Upgrade to curl 8.2.1
curl is currently too old and is thus beginning to accumulate CVE
warnings. This change merges 8.2.1.
Bug: b/297571335
Bug: b/297572374
Change-Id: I395ef39d12da257390ef6f0f67b8a49803c9e067
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 171a650..ec04019 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -21,9 +21,9 @@
# SPDX-License-Identifier: curl
#
###########################################################################
-# Starter pipeline
-# Start with a minimal pipeline that you can customize to build and deploy your code.
-# Add steps that build, run tests, deploy, and more:
+# https://dev.azure.com/daniel0244/curl/_build?view=runs
+#
+# Azure Pipelines configuration:
# https://aka.ms/yaml
trigger:
@@ -31,11 +31,29 @@
include:
- 'master'
- '*/ci'
+ paths:
+ exclude:
+ - '.circleci/*'
+ - '.cirrus.yml'
+ - '.github/*'
+ - '.github/workflows/*'
+ - 'appveyor.yml'
+ - 'packages/*'
+ - 'plan9/*'
pr:
branches:
include:
- 'master'
+ paths:
+ exclude:
+ - '.circleci/*'
+ - '.cirrus.yml'
+ - '.github/*'
+ - '.github/workflows/*'
+ - 'appveyor.yml'
+ - 'packages/*'
+ - 'plan9/*'
stages:
@@ -59,7 +77,7 @@
matrix:
default:
name: default
- install: jsonlint
+ install:
configure: --enable-debug --with-openssl
disable_ipv6:
name: w/o IPv6
@@ -77,7 +95,7 @@
name: torture
install: libnghttp2-dev
configure: --enable-debug --disable-shared --disable-threaded-resolver --with-openssl
- tests: -n -t --shallow=40 !FTP
+ tests: -n -t --shallow=25 !FTP
steps:
- script: sudo apt-get update && sudo apt-get install -y stunnel4 python3-impacket libzstd-dev libbrotli-dev $(install)
displayName: 'apt install'
@@ -95,7 +113,7 @@
displayName: 'test'
env:
AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "-r $(tests)"
+ TFLAGS: "-ac /usr/bin/curl -r $(tests)"
- stage: distcheck
dependsOn: []
@@ -158,23 +176,23 @@
pool:
vmImage: 'ubuntu-latest'
steps:
- - script: sudo apt-get update && sudo apt-get install -y clang-tools-10 clang-9 libssl-dev libssh2-1-dev libpsl-dev libbrotli-dev libzstd-dev
+ - script: sudo apt-get update && sudo apt-get install -y clang-tools clang libssl-dev libssh2-1-dev libpsl-dev libbrotli-dev libzstd-dev
displayName: 'apt install'
retryCountOnTaskFailure: 3
- script: autoreconf -fi
displayName: 'autoreconf'
- - script: scan-build-10 ./configure --enable-debug --enable-werror --with-openssl --with-libssh2
+ - script: scan-build ./configure --enable-debug --enable-werror --with-openssl --with-libssh2
displayName: 'configure'
env:
- CC: "clang-9"
- CCX: "clang++-9"
+ CC: "clang"
+ CCX: "clang++"
- - script: scan-build-10 --status-bugs make
+ - script: scan-build --status-bugs make
displayName: 'make'
- - script: scan-build-10 --status-bugs make examples
+ - script: scan-build --status-bugs make examples
displayName: 'make examples'
##########################################
@@ -223,7 +241,7 @@
name: 32-bit (legacy)
container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys1-mingw:ltsc2019
container_cmd: C:\MinGW\msys\1.0\bin\sh
- configure: --host=i686-pc-mingw32 --build=i686-pc-mingw32 --prefix=/mingw --enable-debug --without-ssl
+ configure: --host=i686-pc-mingw32 --build=i686-pc-mingw32 --prefix=/mingw --enable-debug --without-ssl --with-mingw1-deprecated
tests: "!203 !1143"
v1_mingw32:
name: 32-bit w/o zlib
@@ -255,7 +273,7 @@
name: 32-bit Schannel/SSPI/WinIDN (legacy)
container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys1-mingw:ltsc2019
container_cmd: C:\MinGW\msys\1.0\bin\sh
- configure: --host=i686-pc-mingw32 --build=i686-pc-mingw32 --prefix=/mingw --enable-debug --enable-sspi --with-schannel --with-winidn
+ configure: --host=i686-pc-mingw32 --build=i686-pc-mingw32 --prefix=/mingw --enable-debug --enable-sspi --with-schannel --with-winidn --with-mingw1-deprecated
tests: "!203 !305 !311 !312 !313 !404 !1143 !2033 !2035 !2038 !2041 !2042 !2048 !2070 !2079 !2087 !3023 !3024"
v1_mingw32_schannel:
name: 32-bit Schannel/SSPI/WinIDN w/o zlib
@@ -294,4 +312,4 @@
displayName: 'test'
env:
AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "!IDN !SCP ~612 ~1056 $(tests)"
+ TFLAGS: "-ac /usr/bin/curl.exe !IDN !SCP ~612 ~1056 $(tests)"
diff --git a/.circleci/config.yml b/.circleci/config.yml
index ac10f1f..51dc39a 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2021, 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -65,7 +65,8 @@
steps:
- run:
command: |
- sudo apt-get update && sudo apt-get install -y libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev
+ sudo apt-get update && sudo apt-get install -y libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev python3-pip
+ sudo python3 -m pip install impacket
configure-libssh:
steps:
@@ -78,23 +79,25 @@
steps:
- run:
command: |
- curl -LO https://github.com/wolfSSL/wolfssl/archive/v5.1.1-stable.tar.gz
- tar -xzf v5.1.1-stable.tar.gz
- cd wolfssl-5.1.1-stable
+ WOLFSSL_VER=5.6.0
+ curl -LOsSf --retry 6 --retry-connrefused --max-time 999 https://github.com/wolfSSL/wolfssl/archive/v$WOLFSSL_VER-stable.tar.gz
+ tar -xzf v$WOLFSSL_VER-stable.tar.gz
+ cd wolfssl-$WOLFSSL_VER-stable
./autogen.sh
./configure --enable-tls13 --enable-all --enable-harden --prefix=$HOME/wssl
- make && make install
+ make install
install-wolfssh:
steps:
- run:
command: |
- curl -LO https://github.com/wolfSSL/wolfssh/archive/v1.4.8-stable.tar.gz
- tar -xzf v1.4.8-stable.tar.gz
- cd wolfssh-1.4.8-stable
+ WOLFSSH_VER=1.4.12
+ curl -LOsSf --retry 6 --retry-connrefused --max-time 999 https://github.com/wolfSSL/wolfssh/archive/v$WOLFSSH_VER-stable.tar.gz
+ tar -xzf v$WOLFSSH_VER-stable.tar.gz
+ cd wolfssh-$WOLFSSH_VER-stable
./autogen.sh
./configure --with-wolfssl=$HOME/wssl --prefix=$HOME/wssh --enable-scp --enable-sftp --disable-examples
- make && make install
+ make install
configure-cares:
steps:
@@ -119,12 +122,12 @@
build:
steps:
- - run: make V=1
- - run: make V=1 examples
+ - run: make -j3 V=1
+ - run: make -j3 V=1 examples
test:
steps:
- - run: make V=1 test-ci
+ - run: make -j3 V=1 test-ci
executors:
ubuntu:
diff --git a/.cirrus.yml b/.cirrus.yml
index 508722f..0738c45 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -21,29 +21,46 @@
# SPDX-License-Identifier: curl
#
###########################################################################
-# Cirrus CI configuration
# https://cirrus-ci.com/github/curl/curl
+#
+# Cirrus CI configuration:
+# https://cirrus-ci.org/guide/writing-tasks/
freebsd_task:
+ skip: "changesIncludeOnly(
+ '**/CMakeLists.txt',
+ '.azure-pipelines.yml',
+ '.circleci/**',
+ '.github/**',
+ 'appveyor.yml',
+ 'CMake/**',
+ 'packages/**',
+ 'plan9/**',
+ 'projects/**',
+ 'winbuild/**'
+ )"
+
name: FreeBSD
matrix:
- - name: FreeBSD 13.1
+ - name: FreeBSD 13.2
freebsd_instance:
- image_family: freebsd-13-1
- - name: FreeBSD 12.3
+ image_family: freebsd-13-2
+ - name: FreeBSD 12.4
freebsd_instance:
- image_family: freebsd-12-3
+ image_family: freebsd-12-4
env:
CIRRUS_CLONE_DEPTH: 10
CRYPTOGRAPHY_DONT_BUILD_RUST: 1
- MAKE_FLAGS: -j 2
+ MAKE_FLAGS: -j 3
pkginstall_script:
- pkg update -f
- - pkg install -y autoconf automake libtool pkgconf brotli openldap24-client heimdal libpsl libssh2 openssh-portable libidn2 librtmp libnghttp2 nghttp2 stunnel py38-pip
+ - pkg install -y autoconf automake libtool pkgconf brotli openldap24-client heimdal libpsl libssh2 openssh-portable libidn2 librtmp libnghttp2 nghttp2 stunnel
- pkg delete -y curl
+ - python -m ensurepip --default-pip
+ - python -m pip install --upgrade pip
- pip install "cryptography<3.2"
- pip install "pyOpenSSL<20.0"
- pip install "impacket"
@@ -75,6 +92,15 @@
- make V=1 install
windows_task:
+ skip: "changesIncludeOnly(
+ '.azure-pipelines.yml',
+ '.circleci/**',
+ '.github/**',
+ 'appveyor.yml',
+ 'packages/**',
+ 'plan9/**'
+ )"
+
name: Windows
timeout_in: 120m
windows_container:
@@ -88,44 +114,181 @@
prepare: pacman -S --needed --noconfirm --noprogressbar libssh2-devel mingw-w64-i686-libssh2 mingw-w64-i686-python-pip mingw-w64-i686-python-wheel mingw-w64-i686-python-pyopenssl && python3 -m pip install --prefer-binary impacket
configure: --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-werror --enable-sspi --with-schannel --with-winidn --with-libssh2
tests: "~571"
+ make_cmd: make V=1
- name: Windows 32-bit static/release Schannel/SSPI/WinIDN/libssh2
env:
container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw32:ltsc2019
container_cmd: C:\msys64\usr\bin\sh
prepare: pacman -S --needed --noconfirm --noprogressbar libssh2-devel mingw-w64-i686-libssh2 mingw-w64-i686-python-pip mingw-w64-i686-python-wheel mingw-w64-i686-python-pyopenssl && python3 -m pip install --prefer-binary impacket
- configure: --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-werror --enable-sspi --with-schannel --with-winidn --with-libssh2 --disable-shared --enable-static
+ configure: --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-werror --enable-sspi --with-schannel --with-winidn --with-libssh2 --disable-shared --enable-static --enable-websockets
tests: "~571"
- curl_LDFLAGS: -all-static
+ make_cmd: make LDFLAGS=-all-static V=1
PKG_CONFIG: pkg-config --static
- name: Windows 64-bit shared/release Schannel/SSPI/WinIDN/libssh2
env:
container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw64:ltsc2019
container_cmd: C:\msys64\usr\bin\sh
prepare: pacman -S --needed --noconfirm --noprogressbar libssh2-devel mingw-w64-x86_64-libssh2 mingw-w64-x86_64-python-pip mingw-w64-x86_64-python-wheel mingw-w64-x86_64-python-pyopenssl && python3 -m pip install --prefer-binary impacket
- configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-werror --enable-sspi --with-schannel --with-winidn --with-libssh2
+ configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-werror --enable-sspi --with-schannel --with-winidn --with-libssh2 --enable-websockets
tests: "~571"
+ make_cmd: make V=1
- name: Windows 64-bit static/release Schannel/SSPI/WinIDN/libssh2
env:
container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw64:ltsc2019
container_cmd: C:\msys64\usr\bin\sh
prepare: pacman -S --needed --noconfirm --noprogressbar libssh2-devel mingw-w64-x86_64-libssh2 mingw-w64-x86_64-python-pip mingw-w64-x86_64-python-wheel mingw-w64-x86_64-python-pyopenssl && python3 -m pip install --prefer-binary impacket
- configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-werror --enable-sspi --with-schannel --with-winidn --with-libssh2 --disable-shared --enable-static
+ configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-werror --enable-sspi --with-schannel --with-winidn --with-libssh2 --disable-shared --enable-static --enable-websockets
tests: "~571"
- curl_LDFLAGS: -all-static
+ make_cmd: make LDFLAGS=-all-static V=1
PKG_CONFIG: pkg-config --static
env:
CIRRUS_CLONE_DEPTH: 10
MSYS2_PATH_TYPE: inherit
- MAKEFLAGS: -j 2
+ MAKEFLAGS: -j 3
prepare_script: |
%container_cmd% -l -c "cd $(echo '%cd%') && %prepare%"
configure_script: |
%container_cmd% -l -c "cd $(echo '%cd%') && autoreconf -fi && ./configure %configure%"
compile_script: |
- %container_cmd% -l -c "cd $(echo '%cd%') && make V=1 && make V=1 examples && cd tests && make V=1"
+ %container_cmd% -l -c "cd $(echo '%cd%') && %make_cmd% && %make_cmd% examples && cd tests && %make_cmd%"
install_script: |
- %container_cmd% -l -c "cd $(echo '%cd%') && make V=1 install && PATH=/usr/bin:/bin find . -type f -path '*/.libs/*.exe' -print -execdir mv -t .. {} \;"
+ %container_cmd% -l -c "cd $(echo '%cd%') && %make_cmd% install && PATH=/usr/bin:/bin find . -type f -path '*/.libs/*.exe' -print -execdir mv -t .. {} \;"
test_script: |
- %container_cmd% -l -c "cd $(echo '%cd%') && make V=1 TFLAGS='!IDN !SCP ~612 ~1056 %tests%' test-ci"
+ %container_cmd% -l -c "cd $(echo '%cd%') && %make_cmd% TFLAGS='!IDN !SCP ~612 ~1056 %tests%' test-ci"
+
+macos_task:
+ skip: "changesIncludeOnly(
+ '.azure-pipelines.yml',
+ '.circleci/**',
+ '.github/**',
+ 'appveyor.yml',
+ 'packages/**',
+ 'plan9/**',
+ 'projects/**',
+ 'winbuild/**'
+ )"
+
+ name: macOS arm64
+ macos_instance:
+ image: ghcr.io/cirruslabs/macos-ventura-xcode:latest
+
+ matrix:
+ - name: macOS arm64 normal
+ env:
+ CFLAGS: -Wno-vla -mmacosx-version-min=10.9
+ install_packages: nghttp2
+ configure: --without-ssl
+ - name: macOS arm64 debug
+ env:
+ CFLAGS: -Wno-vla -mmacosx-version-min=10.9
+ install_packages: nghttp2
+ configure: --without-ssl --enable-debug
+ - name: macOS arm64 libssh2
+ env:
+ CFLAGS: -Wno-vla -mmacosx-version-min=10.9
+ install_packages: nghttp2 libssh2
+ configure: --without-ssl --enable-debug --with-libssh2=/opt/homebrew/opt/libssh2
+ TFLAGS: -n !SFTP !SCP
+ - name: macOS arm64 libssh-c-ares
+ env:
+ CFLAGS: -Wno-vla -mmacosx-version-min=10.9
+ install_packages: nghttp2 openssl libssh
+ configure: --enable-debug --with-openssl=/opt/homebrew/opt/openssl --with-libssh --enable-ares
+ - name: macOS arm64 libssh
+ env:
+ CFLAGS: -Wno-vla -mmacosx-version-min=10.9
+ install_packages: nghttp2 openssl libssh
+ configure: --enable-debug --with-openssl=/opt/homebrew/opt/openssl --with-libssh
+ - name: macOS arm64 c-ares
+ env:
+ CFLAGS: -Wno-vla -mmacosx-version-min=10.9
+ install_packages: nghttp2
+ configure: --without-ssl --enable-debug --enable-ares
+ - name: macOS arm64 HTTP only
+ env:
+ CFLAGS: -Wno-vla -mmacosx-version-min=10.15
+ install_packages: nghttp2
+ configure: --enable-debug --enable-maintainer-mode --disable-dict --disable-file --disable-ftp --disable-gopher --disable-imap --disable-ldap --disable-pop3 --disable-rtmp --disable-rtsp --disable-scp --disable-sftp --disable-smb --disable-smtp --disable-telnet --disable-tftp --disable-unix-sockets --disable-shared --without-brotli --without-gssapi --without-libidn2 --without-libpsl --without-librtmp --without-libssh2 --without-nghttp2 --without-ntlm-auth --without-ssl --without-zlib
+ - name: macOS arm64 SecureTransport http2
+ env:
+ CFLAGS: -Wno-vla -mmacosx-version-min=10.8
+ install_packages: nghttp2
+ configure: --with-secure-transport
+ - name: macOS arm64 OpenSSL http2
+ env:
+ CFLAGS: -Wno-vla -mmacosx-version-min=10.9
+ install_packages: nghttp2 openssl
+ configure: --enable-debug --with-openssl=/opt/homebrew/opt/openssl
+ - name: macOS arm64 LibreSSL http2
+ env:
+ CFLAGS: -Wno-vla -mmacosx-version-min=10.9
+ install_packages: nghttp2 libressl
+ configure: --enable-debug --with-openssl=/opt/homebrew/opt/libressl
+ - name: macOS arm64 torture
+ env:
+ CFLAGS: -Wno-vla -mmacosx-version-min=10.9
+ install_packages: nghttp2 openssl
+ configure: --enable-debug --disable-shared --disable-threaded-resolver --with-openssl=/opt/homebrew/opt/openssl
+ TFLAGS: -n -t --shallow=25 !FTP
+ - name: macOS arm64 torture-ftp
+ env:
+ CFLAGS: -Wno-vla -mmacosx-version-min=10.9
+ install_packages: nghttp2 openssl
+ configure: --enable-debug --disable-shared --disable-threaded-resolver --with-openssl=/opt/homebrew/opt/openssl
+ TFLAGS: -n -t --shallow=20 FTP
+
+ env:
+ CIRRUS_CLONE_DEPTH: 10
+ MAKE_FLAGS: -j 12
+
+ pkginstall_script:
+ - echo libtool autoconf automake pkg-config ${install_packages} | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
+ - "while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done"
+ - sudo -H python3 -m pip install --upgrade pip
+ - sudo -H python3 -m pip install impacket
+ configure_script:
+ - autoreconf -fi
+ - ./configure --enable-warnings --enable-werror --enable-websockets ${configure}
+ compile_script:
+ - make V=1 && make V=1 examples && cd tests && make V=1
+ test_script:
+ - make V=1 test-ci
+ install_script:
+ - sudo -H make V=1 install
+
+linux_musl_task:
+ skip: "changesIncludeOnly(
+ '**/CMakeLists.txt',
+ '.azure-pipelines.yml',
+ '.circleci/**',
+ '.github/**',
+ 'appveyor.yml',
+ 'CMake/**',
+ 'packages/**',
+ 'plan9/**',
+ 'projects/**',
+ 'winbuild/**'
+ )"
+ name: Linux MUSL
+ container:
+ image: alpine:3.18
+ memory: 800M
+
+ env:
+ CIRRUS_CLONE_DEPTH: 10
+ MAKEFLAGS: -j 3
+
+ pkginstall_script:
+ - apk add --no-cache build-base autoconf automake libtool perl openssl-dev libssh2-dev zlib-dev brotli-dev zstd-dev libidn2-dev openldap-dev heimdal-dev libpsl-dev py3-impacket py3-asn1 py3-six py3-pycryptodomex perl-time-hires openssh stunnel sudo
+ configure_script:
+ - autoreconf -fi
+ - ./configure --enable-warnings --enable-debug --enable-websockets --with-ssl --with-libssh2 --with-libidn2 --with-gssapi --enable-ldap --with-libpsl
+ compile_script:
+ - make V=1 && make V=1 examples && make -C tests V=1
+ test_script:
+ # TODO: ssh tests don't work, likely because we're running as root
+ - USER=nobody make V=1 test-ci
+ install_script:
+ - make V=1 install
diff --git a/.dcignore b/.dcignore
index 2d835fe..e33af3e 100644
--- a/.dcignore
+++ b/.dcignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/.dir-locals.el b/.dir-locals.el
index 0cc71f7..f6248c2e 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -5,7 +5,7 @@
;;; | (__| |_| | _ <| |___
;;; \___|\___/|_| \_\_____|
;;;
-;;; Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+;;; Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
;;;
;;; This software is licensed as described in the file COPYING, which
;;; you should have received as part of this distribution. The terms
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 75611b6..c627bfd 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -1,4 +1,4 @@
-# Copyright (C) 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/.gitattributes b/.gitattributes
index eccad57..481fd5c 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..9e7b6e3
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,3 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 60f77c7..18be9ed 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 0b38c2b..f02b2d3 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 2c1baec..0000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: ''
-labels: ''
-assignees: ''
-
----
-
-<!-- Only file bugs here! Ask questions on the mailing lists https://curl.se/mail/
-
- SECURITY RELATED? Post it here: https://hackerone.com/curl
-
- There are collections of known issues to be aware of:
- https://curl.se/docs/knownbugs.html
- https://curl.se/docs/todo.html -->
-
-### I did this
-
-### I expected the following
-
-### curl/libcurl version
-
-[curl -V output]
-
-### operating system
-
-<!-- On Unix please post the output of "uname -a" -->
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000..3172306
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,55 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: Bug Report
+description: Create a report to help us improve
+
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to fill out this bug report!
+
+ Only file bugs here! Ask questions on the mailing lists https://curl.se/mail/
+
+ **SECURITY RELATED?** Post it here: https://hackerone.com/curl
+
+ There are collections of known issues to be aware of:
+
+ - https://curl.se/docs/knownbugs.html
+ - https://curl.se/docs/todo.html
+
+ - type: textarea
+ id: reproducer
+ attributes:
+ label: I did this
+ validations:
+ required: false
+
+ - type: textarea
+ id: expected-behaviour
+ attributes:
+ label: I expected the following
+ validations:
+ required: false
+
+ - type: input
+ id: version
+ attributes:
+ label: curl/libcurl version
+ description: |
+ Please paste the output of `curl -V` here.
+ placeholder: 'curl 8.2.0'
+ validations:
+ required: false
+
+ - type: input
+ id: os
+ attributes:
+ label: operating system
+ description: |
+ On Unix please post the output of `uname -a` here.
+ placeholder: 'Fedora Linux 38'
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index eb314f9..9ca2c8f 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/.github/labeler.yml b/.github/labeler.yml
new file mode 100644
index 0000000..58b97e9
--- /dev/null
+++ b/.github/labeler.yml
@@ -0,0 +1,302 @@
+# Copyright (C) Daniel Fandrich, <dan@coneharvesters.com>, et al.
+#
+# SPDX-License-Identifier: curl
+
+# The workflow configures the .github/workflows/label.yml action
+# to add labels to pull requests. This is not (yet?) a replacement for human
+# triaging, but is intended to add labels to the easy cases. If the matching
+# language becomes more powerful, more cases should be able to be handled.
+#
+# The biggest low-hanging problem is this:
+# It looks like there's no way of specifying that a label be added if *all* the
+# files match *any* one of a number of globs. This feature request is tracked
+# in https://github.com/actions/labeler/issues/423
+
+authentication:
+- all: ['docs/mk-ca-bundle.1']
+- all: ['docs/libcurl/opts/CURLINFO_HTTPAUTH*']
+- all: ['docs/libcurl/opts/CURLINFO_PROXYAUTH*']
+- all: ['docs/libcurl/opts/CURLOPT_KRB*']
+- all: ['docs/libcurl/opts/CURLOPT_SASL*']
+- all: ['docs/libcurl/opts/CURLOPT_SERVICE_NAME*']
+- all: ['docs/libcurl/opts/CURLOPT_USERNAME*']
+- all: ['docs/libcurl/opts/CURLOPT_USERPWD*']
+- all: ['docs/libcurl/opts/CURLOPT_XOAUTH*']
+- all: ['lib/*gssapi*']
+- all: ['lib/*krb5*']
+- all: ['lib/*ntlm*']
+- all: ['lib/curl_sasl.*']
+- all: ['lib/http_aws*']
+- all: ['lib/http_digest.*']
+- all: ['lib/http_negotiate.*']
+- all: ['lib/vauth/**']
+- all: ['tests/server/fake_ntlm.c']
+
+build:
+- all: ['**/CMakeLists.txt']
+- all: ['**/Makefile.am']
+- all: ['**/Makefile.inc']
+- all: ['**/Makefile.mk']
+- all: ['**/*.m4']
+- all: ['**/*.mk']
+- all: ['lib/libcurl*.in']
+- all: ['CMake/**']
+- all: ['configure.ac']
+- all: ['m4/**']
+- all: ['MacOSX-Framework']
+- all: ['packages/**']
+- all: ['plan9/**']
+- all: ['projects/**']
+- all: ['winbuild/**']
+
+CI:
+- any: ['.azure-pipelines.yml']
+- any: ['.circleci/**']
+- any: ['.cirrus.yml']
+- any: ['.github/**']
+- any: ['appveyor.yml']
+- any: ['tests/azure.pm']
+- any: ['tests/appveyor.pm']
+- any: ['tests/CI.pm']
+
+cmake:
+- all: ['**/CMakeLists.txt']
+- all: ['CMake/**']
+
+cmdline tool:
+- any: ['docs/cmdline-opts/**']
+- any: ['src/**']
+
+connecting & proxies:
+- all: ['docs/CONNECTION-FILTERS.md']
+- all: ['docs/libcurl/opts/CURLINFO_CONNECT*']
+- all: ['docs/libcurl/opts/CURLINFO_PROXY*']
+- all: ['docs/libcurl/opts/CURLOPT_ADDRESS*']
+- all: ['docs/libcurl/opts/CURLOPT_CONNECT*']
+- all: ['docs/libcurl/opts/CURLOPT_HAPROXY*']
+- all: ['docs/libcurl/opts/CURLOPT_OPENSOCKET*']
+- all: ['docs/libcurl/opts/CURLOPT_PRE_PROXY*']
+- all: ['docs/libcurl/opts/CURLOPT_PROXY*']
+- all: ['docs/libcurl/opts/CURLOPT_SOCKOPT*']
+- all: ['docs/libcurl/opts/CURLOPT_SOCKS*']
+- all: ['docs/libcurl/opts/CURLOPT_TCP*']
+- all: ['docs/libcurl/opts/CURLOPT_TIMEOUT*']
+- all: ['lib/cf-*proxy.*']
+- all: ['lib/cf-socket.*']
+- all: ['lib/cfilters.*']
+- all: ['lib/conncache.*']
+- all: ['lib/connect.*']
+- all: ['lib/http_proxy.*']
+- all: ['lib/if2ip.*']
+- all: ['lib/noproxy.*']
+- all: ['lib/socks.*']
+- all: ['tests/server/socksd.c']
+
+cookies:
+- all: ['docs/HTTP-COOKIES.md']
+- all: ['docs/libcurl/opts/CURLINFO_COOKIE*']
+- all: ['docs/libcurl/opts/CURLOPT_COOKIE*']
+- all: ['lib/cookie.*']
+- all: ['lib/psl.*']
+
+cryptography:
+- all: ['docs/CIPHERS.md']
+- all: ['docs/RUSTLS.md']
+- all: ['docs/libcurl/opts/CURLOPT_EGDSOCKET*']
+- all: ['lib/*sha256*']
+- all: ['lib/curl_des.*']
+- all: ['lib/curl_hmac.*']
+- all: ['lib/curl_md?.*']
+- all: ['lib/md?.*']
+- all: ['lib/rand.*']
+
+DICT:
+- all: ['lib/dict.*']
+- all: ['tests/dictserver.py']
+
+documentation:
+- all: ['**/*.md']
+- all: ['**/*.txt', '!**/CMakeLists.txt']
+- all: ['**/*.1']
+- all: ['**/*.3']
+- all: ['CHANGES']
+- all: ['docs/**', '!docs/examples/**']
+- all: ['GIT-INFO']
+- all: ['LICENSES/**']
+- all: ['README']
+- all: ['RELEASE-NOTES']
+
+FTP:
+- all: ['docs/libcurl/opts/CURLINFO_FTP*']
+- all: ['docs/libcurl/opts/CURLOPT_FTP*']
+- all: ['docs/libcurl/opts/CURLOPT_WILDCARDMATCH*']
+- all: ['lib/curl_fnmatch.*']
+- all: ['lib/curl_range.*']
+- all: ['lib/ftp*']
+- all: ['tests/ftp*']
+
+GOPHER:
+- all: ['lib/gopher*']
+
+HTTP:
+- all: ['docs/HSTS.md']
+- all: ['docs/HTTP-COOKIES.md']
+- all: ['docs/libcurl/opts/CURLINFO_COOKIE*']
+- all: ['docs/libcurl/opts/CURLOPT_COOKIE*']
+- all: ['docs/libcurl/opts/CURLINFO_HTTP_**']
+- all: ['docs/libcurl/opts/CURLINFO_REDIRECT*']
+- all: ['docs/libcurl/opts/CURLINFO_REFER*']
+- all: ['docs/libcurl/opts/CURLOPT_FOLLOWLOCATION*']
+- all: ['docs/libcurl/opts/CURLOPT_HSTS*']
+- all: ['docs/libcurl/opts/CURLOPT_HTTP*']
+- all: ['docs/libcurl/opts/CURLOPT_POST.*']
+- all: ['docs/libcurl/opts/CURLOPT_POSTFIELD*']
+- all: ['docs/libcurl/opts/CURLOPT_POSTREDIR*']
+- all: ['docs/libcurl/opts/CURLOPT_REDIR*']
+- all: ['docs/libcurl/opts/CURLOPT_REFER*']
+- all: ['docs/libcurl/opts/CURLOPT_TRAILER*']
+- all: ['docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING*']
+- all: ['lib/cf-https*']
+- all: ['lib/cf-h1*']
+- all: ['lib/cf-h2*']
+- all: ['lib/cookie.*']
+- all: ['lib/http*']
+- all: ['tests/http*']
+- all: ['tests/http-server.pl']
+- all: ['tests/http/*']
+- all: ['tests/nghttp*']
+- all: ['tests/tests-httpd/*']
+
+HTTP/2:
+- all: ['docs/HTTP2.md']
+- all: ['docs/libcurl/opts/CURLOPT_STREAM*']
+- all: ['lib/http2*']
+- all: ['tests/http2-server.pl']
+
+HTTP/3:
+- all: ['.github/workflows/ngtcp2*']
+- all: ['.github/workflows/pytest.yml']
+- all: ['docs/HTTP3.md']
+- all: ['lib/vquic/**']
+- all: ['tests/http3-server.pl']
+- all: ['tests/nghttpx.conf']
+
+Hyper:
+- all: ['lib/c-hyper.*']
+
+IMAP:
+- all: ['lib/imap*']
+
+LDAP:
+- all: ['lib/*ldap*']
+
+libcurl API:
+- all: ['docs/libcurl/ABI.md']
+- any: ['include/curl/**']
+
+MIME:
+- all: ['docs/libcurl/curl_mime_*']
+- all: ['docs/libcurl/opts/CURLOPT_MIME*']
+- all: ['lib/mime*']
+
+MQTT:
+- all: ['docs/MQTT.md']
+- all: ['lib/mqtt*']
+- all: ['tests/server/mqttd.c']
+
+name lookup:
+- all: ['docs/libcurl/opts/CURLINFO_NAMELOOKUP*']
+- all: ['docs/libcurl/opts/CURLOPT_DNS*']
+- all: ['docs/libcurl/opts/CURLOPT_DOH*']
+- all: ['docs/libcurl/opts/CURLOPT_RESOLVE*']
+- all: ['lib/asyn*']
+- all: ['lib/curl_gethostname.*']
+- all: ['lib/doh*']
+- all: ['lib/host*']
+- all: ['lib/idn*']
+- all: ['lib/inet_pton.*']
+- all: ['lib/socketpair*']
+- all: ['tests/server/resolve.c']
+
+POP3:
+- all: ['lib/pop3.*']
+
+RTMP:
+- all: ['lib/curl_rtmp.*']
+
+RTSP:
+- all: ['docs/libcurl/opts/CURLINFO_RTSP*']
+- all: ['docs/libcurl/opts/CURLOPT_RTSP*']
+- all: ['lib/rtsp.*']
+- all: ['tests/rtspserver.pl']
+- all: ['tests/server/rtspd.c']
+
+SCP/SFTP:
+- all: ['docs/libcurl/opts/CURLOPT_SSH*']
+- all: ['lib/vssh/**']
+- all: ['tests/sshhelp.pm']
+- all: ['tests/sshserver.pl']
+
+script:
+- all: ['**/*.pl']
+- all: ['**/*.sh']
+- all: ['curl-config.in']
+- all: ['docs/curl-config.1']
+- all: ['docs/mk-ca-bundle.1']
+- all: ['docs/THANKS-filter']
+- all: ['scripts/**']
+
+SMB:
+- all: ['lib/smb.*']
+- all: ['tests/smbserver.py']
+
+SMTP:
+- all: ['docs/libcurl/opts/CURLOPT_MAIL*']
+- all: ['lib/smtp.*']
+
+tests:
+- any: ['tests/**']
+
+TFTP:
+- all: ['lib/tftp.*']
+- all: ['tests/tftpserver.pl']
+- all: ['tests/server/tftp*']
+
+TLS:
+- all: ['docs/HYPER.md']
+- all: ['docs/SSL*']
+- all: ['docs/libcurl/opts/CURLINFO_CA*']
+- all: ['docs/libcurl/opts/CURLINFO_CERT*']
+- all: ['docs/libcurl/opts/CURLINFO_SSL*']
+- all: ['docs/libcurl/opts/CURLINFO_TLS*']
+- all: ['docs/libcurl/opts/CURLOPT_CA*']
+- all: ['docs/libcurl/opts/CURLOPT_CERT*']
+- all: ['docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY*']
+- all: ['docs/libcurl/opts/CURLOPT_SSL*']
+- all: ['docs/libcurl/opts/CURLOPT_TLS*']
+- all: ['docs/libcurl/opts/CURLOPT_USE_SSL*']
+- all: ['lib/vtls/**']
+
+URL:
+- all: ['docs/libcurl/curl_url*']
+- all: ['docs/URL-SYNTAX.md']
+- all: ['include/curl/urlapi.h']
+- all: ['lib/urlapi*']
+
+WebSocket:
+- all: ['docs/WEBSOCKET.md*']
+- all: ['docs/libcurl/opts/CURLOPT_WS_*']
+- all: ['docs/libcurl/curl_ws_*']
+- all: ['include/curl/websockets.h']
+- all: ['lib/ws.*']
+
+Windows:
+- all: ['CMake/Platforms/WindowsCache.cmake']
+- all: ['lib/*win32*']
+- all: ['lib/curl_multibyte.*']
+- all: ['lib/rename.*']
+- all: ['lib/vtls/schannel*']
+- all: ['m4/curl-schannel.m4']
+- all: ['projects/**']
+- all: ['src/tool_doswin.c']
+- all: ['winbuild/**']
diff --git a/.github/lock.yml b/.github/lock.yml
index 41b9947..ab30d2a 100644
--- a/.github/lock.yml
+++ b/.github/lock.yml
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/.github/scripts/cleanspell.pl b/.github/scripts/cleanspell.pl
new file mode 100755
index 0000000..3e4b9ec
--- /dev/null
+++ b/.github/scripts/cleanspell.pl
@@ -0,0 +1,80 @@
+#!/usr/bin/perl
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+#
+# Input: a libcurl nroff man page
+# Output: the same file, minus the SYNOPSIS and the EXAMPLE sections
+#
+
+my $f = $ARGV[0];
+my $o = $ARGV[1];
+
+open(F, "<$f") or die;
+open(O, ">$o") or die;
+
+my $ignore = 0;
+while(<F>) {
+ if($_ =~ /^.SH (SYNOPSIS|EXAMPLE|\"SEE ALSO\"|SEE ALSO)/) {
+ $ignore = 1;
+ }
+ elsif($ignore && ($_ =~ /^.SH/)) {
+ $ignore = 0;
+ }
+ elsif(!$ignore) {
+ # filter out mentioned CURLE_ names
+ $_ =~ s/CURL(M|SH|U|H)code//g;
+ $_ =~ s/CURL_(READ|WRITE)FUNC_[A-Z0-9_]*//g;
+ $_ =~ s/CURL_CSELECT_[A-Z0-9_]*//g;
+ $_ =~ s/CURL_DISABLE_[A-Z0-9_]*//g;
+ $_ =~ s/CURL_FORMADD_[A-Z0-9_]*//g;
+ $_ =~ s/CURL_HET_DEFAULT//g;
+ $_ =~ s/CURL_IPRESOLVE_[A-Z0-9_]*//g;
+ $_ =~ s/CURL_PROGRESSFUNC_CONTINUE//g;
+ $_ =~ s/CURL_REDIR_[A-Z0-9_]*//g;
+ $_ =~ s/CURL_RTSPREQ_[A-Z0-9_]*//g;
+ $_ =~ s/CURL_TIMECOND_[A-Z0-9_]*//g;
+ $_ =~ s/CURL_VERSION_[A-Z0-9_]*//g;
+ $_ =~ s/CURLALTSVC_[A-Z0-9_]*//g;
+ $_ =~ s/CURLAUTH_[A-Z0-9_]*//g;
+ $_ =~ s/CURLE_[A-Z0-9_]*//g;
+ $_ =~ s/CURLFORM_[A-Z0-9_]*//g;
+ $_ =~ s/CURLFTP_[A-Z0-9_]*//g;
+ $_ =~ s/CURLFTPAUTH_[A-Z0-9_]*//g;
+ $_ =~ s/CURLFTPMETHOD_[A-Z0-9_]*//g;
+ $_ =~ s/CURLFTPSSL_[A-Z0-9_]*//g;
+ $_ =~ s/CURLGSSAPI_[A-Z0-9_]*//g;
+ $_ =~ s/CURLHEADER_[A-Z0-9_]*//g;
+ $_ =~ s/CURLINFO_[A-Z0-9_]*//g;
+ $_ =~ s/CURLM_[A-Z0-9_]*//g;
+ $_ =~ s/CURLMIMEOPT_[A-Z0-9_]*//g;
+ $_ =~ s/CURLMOPT_[A-Z0-9_]*//g;
+ $_ =~ s/CURLOPT_[A-Z0-9_]*//g;
+ $_ =~ s/CURLPIPE_[A-Z0-9_]*//g;
+ $_ =~ s/CURLPROTO_[A-Z0-9_]*//g;
+ $_ =~ s/CURLPROXY_[A-Z0-9_]*//g;
+ $_ =~ s/CURLPX_[A-Z0-9_]*//g;
+ $_ =~ s/CURLSHE_[A-Z0-9_]*//g;
+ $_ =~ s/CURLSHOPT_[A-Z0-9_]*//g;
+ $_ =~ s/CURLSSH_[A-Z0-9_]*//g;
+ $_ =~ s/CURLSSLBACKEND_[A-Z0-9_]*//g;
+ $_ =~ s/CURLU_[A-Z0-9_]*//g;
+ $_ =~ s/CURLUE_[A-Z0-9_]*//g;
+ $_ =~ s/CURLUPART_[A-Z0-9_]*//g;
+ $_ =~ s/CURLUSESSL_[A-Z0-9_]*//g;
+ $_ =~ s/curl_global_(init_mem|sslset|cleanup)//g;
+ $_ =~ s/curl_(strequal|strnequal|formadd|waitfd|formget|getdate|formfree)//g;
+ $_ =~ s/curl_easy_(nextheader|duphandle)//g;
+ $_ =~ s/curl_multi_fdset//g;
+ $_ =~ s/curl_mime_(subparts|addpart|filedata|data_cb)//g;
+ $_ =~ s/curl_ws_(send|recv|meta)//g;
+ $_ =~ s/curl_url_(dup)//g;
+ $_ =~ s/curl_pushheader_by(name|num)//g;
+ $_ =~ s/libcurl-(env|ws)//g;
+ $_ =~ s/(^|\W)((tftp|https|http|ftp):\/\/[a-z0-9\-._~%:\/?\#\[\]\@!\$&'()*+,;=]+)//gi;
+ print O $_;
+ }
+}
+close(F);
+close(O);
+
diff --git a/.github/scripts/spellcheck.words b/.github/scripts/spellcheck.words
new file mode 100644
index 0000000..a9e2a7a
--- /dev/null
+++ b/.github/scripts/spellcheck.words
@@ -0,0 +1,884 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+#
+ABI
+accessor
+ACK
+AES
+AIA
+AIX
+al
+Alessandro
+allocator
+alnum
+ALPN
+Altera
+ALTSVC
+amiga
+AmigaOS
+AmiSSL
+anyauth
+anycast
+apache
+Apache
+API
+APIs
+APOP
+AppVeyor
+archivers
+Archos
+Arntsen
+Aros
+ascii
+asynch
+AsynchDNS
+atime
+auth
+autobuild
+autobuilds
+Autoconf
+Automake
+Autotools
+autotools
+AVR
+AWS
+AWS-LC
+axTLS
+backend
+backends
+backoff
+backticks
+Baratov
+basename
+bashrc
+BDFL
+BearSSL
+Benoit
+BeOS
+bitmask
+bitwise
+Björn
+Bjørn
+bool
+boolean
+BoringSSL
+boringssl
+Boukris
+Broadcom
+brotli
+bufq
+bufref
+bugfix
+bugfixes
+buildable
+buildbot
+buildconf
+Caddy
+calloc
+CAPA
+CCC
+CDN
+CentOS
+CFLAGS
+CGI's
+CHACHA
+chacha
+Chaffraix
+changelog
+changeset
+CharConv
+charset
+charsets
+checksrc
+checksums
+chgrp
+chmod
+chown
+ChromeOS
+CI's
+CIDR
+CIFS
+CLA
+CLAs
+cleartext
+CLI
+clientp
+cliget
+closesocket
+CMake
+cmake
+cmake's
+CMakeLists
+CodeQL
+codeql
+CODESET
+codeset
+Comcast
+Config
+config
+conncache
+connectdata
+CookieInfo
+Coverity
+CPUs
+CR
+CRL
+CRLF
+crt
+crypto
+cryptographic
+cryptographically
+CSEQ
+CSeq
+csh
+cshrc
+CTRL
+cURL
+CURLcode
+CURLE
+CURLH
+curlimages
+curlrc
+curltest
+customizable
+CVE
+CVSS
+CWD
+CWE
+cyassl
+Cygwin
+daniel
+datatracker
+decrypt
+deepcode
+DELE
+DER
+deselectable
+destructor
+detections
+dev
+devcpp
+DevOps
+devtools
+DHCP
+dir
+distro
+distro's
+distros
+DJGPP
+dlist
+DLL
+dll
+DLLs
+DNS
+dns
+dnsop
+DoH
+doxygen
+drftpd
+dsa
+Dudka
+Dymond
+dynbuf
+EAGAIN
+EBCDIC
+ECC
+ECDHE
+ECH
+eCOS
+EFnet
+EGD
+EHLO
+EINTR
+else's
+encodings
+enctype
+endianness
+Engler
+enum
+epoll
+EPRT
+EPSV
+ERRNO
+errno
+ESNI
+et
+etag
+ETag
+ETags
+exe
+executables
+EXPN
+extensibility
+failsafe
+Falkeborn
+Fandrich
+Fastly
+fcpp
+Feltzing
+ffi
+filesize
+filesystem
+FLOSS
+fnmatch
+formpost
+formposts
+Fortnite
+FOSS
+FPL
+fread
+FreeBSD
+FreeDOS
+FreeRTOS
+freshmeat
+Frexx
+FS
+fseek
+FTPing
+fuzzer
+fwrite
+Garmin
+gcc
+GCM
+gdb
+Genode
+Gergely
+getaddrinfo
+getenv
+gethostbyname
+gethostname
+Getinfo
+getinfo
+GETing
+getpwuid
+ggcov
+Ghedini
+Gisle
+Glesys
+globbing
+gmail
+GnuTLS
+gnutls
+Golemon
+GOST
+GPG
+GPL
+GPLed
+Greear
+groff
+GSKit
+gskit
+GSS
+GSSAPI
+GTFO
+Guenter
+Gunderson
+Gustafsson
+gzip
+Gzipped
+gzipped
+HackerOne
+HackerOne's
+HAProxy
+HardenedBSD
+Hards
+Haxx
+haxx
+Heimdal
+HELO
+HH
+HMAC
+Hoersken
+Holme
+homebrew
+hostname
+hostnames
+Housley
+Hruska
+HSTS
+hsts
+HTC
+html
+http
+httpd
+HTTPD
+HTTPAUTH
+httpget
+HttpGet
+HTTPS
+https
+hyper's
+Högskolan
+IANA
+Icecast
+ICONV
+iconv
+IDN
+IDNA
+IETF
+ietf
+ifdef
+ifdefed
+Ifdefs
+ifdefs
+ILE
+Illumos
+IMAP
+imap
+IMAPS
+imaps
+impacket
+init
+initializer
+inlined
+interoperable
+interoperates
+IoT
+ipadOS
+IPCXN
+IPv
+IPv4
+IPv4/6
+IPv6
+IRIs
+IRIX
+Itanium
+iX
+Jakub
+Jiri
+jo
+jpeg
+jq
+JSON
+json
+Julien
+Kamil
+Kaufmann
+kB
+KDE
+keepalive
+Keil
+kerberos
+Keychain
+KiB
+kickstart
+Kirei
+Knauf
+kqueue
+Krb
+krb
+Kubernetes
+Kuhrt
+Kungliga
+Largefile
+LDAP
+ldap
+LDAPS
+ldaps
+LF
+LGTM
+libbrotlidec
+libc
+libcurl
+libcurl's
+libcurls
+libera
+libev
+libevent
+libgsasl
+libidn
+libnssckbi
+libnsspem
+libpsl
+Libre
+libre
+LibreSSL
+libressl
+librtmp
+libs
+libssh
+libSSH
+libssh2
+Libtool
+libuv
+libWebSocket
+libz
+libzstd
+LineageOS
+linux
+ln
+localhost
+LOGDIR
+logfile
+lookups
+loopback
+LPRT
+LSB
+lseek
+Lua
+lwIP
+macdef
+macOS
+macos
+Makefile
+makefiles
+malloc
+mallocs
+maprintf
+Marek
+Mavrogiannopoulos
+Mbed
+mbedTLS
+Meglio
+memdebug
+MesaLink
+mesalink
+Metalink
+mfprintf
+Michal
+Micrium
+MicroBlaze
+MicroOS
+mingw
+MinGW
+MINIX
+misconfigured
+Mishyn
+mitigations
+MITM
+mk
+mkdir
+mktime
+Monnerat
+monospace
+MorphOS
+MPE
+MPL
+mprintf
+MQTT
+mqtt
+mqtts
+MSB
+MSGSENT
+msh
+MSIE
+msnprintf
+msprintf
+msquic
+mstate
+MSVC
+MSYS
+msys
+mtime
+mTLS
+MUA
+multicwd
+multiparts
+MultiSSL
+mumbo
+musedev
+mutex
+mvaprintf
+mvfprintf
+mvprintf
+mvsnprintf
+mvsprintf
+MX
+Nagel
+Nagle
+NAMELOOKUP
+Natively
+NATs
+nc
+NCR
+NDK
+NEC
+Necko
+NetBSD
+netrc
+Netware
+NFS
+nghttp
+nghttpx
+ngtcp
+Nikos
+Nios
+nitems
+NixOS
+NLST
+nmake
+nmemb
+nocwd
+NODELAY
+NonStop
+NOOP
+Novell
+NPN
+nroff
+nslookup
+NSS
+nss
+NTLM
+NTLMUSER
+NTLMv
+NUM
+NuttX
+OAuth
+objcopy
+OCSP
+Ok
+OpenBSD
+OpenLDAP
+OpenRISC
+OpenSSF
+OpenSSF's
+OpenSSH
+OpenSSL
+OpenStep
+openSUSE
+openwall
+Orbis
+ORing
+Osipov
+OSS
+pac
+pacman
+parser's
+parsers
+PASE
+PASV
+PEM
+pem
+perl
+permafailing
+PINGs
+pipelining
+PKCS
+PKGBUILD
+PKI
+pluggable
+PolarSSL
+Polhem
+pollset
+POSIX
+Postfix
+POSTing
+POSTs
+PowerShell
+pre
+prebuilt
+precompiled
+prepend
+prepended
+prepending
+prepends
+preprocess
+preprocessed
+Preprocessing
+preprocessor
+Prereq
+PRET
+pretransfer
+printf
+printf's
+PSL
+pthreads
+PTR
+ptr
+punycode
+PWD
+py
+pycurl
+pytest
+Pytest
+QNX
+QoS
+Qubes
+QUIC
+quictls
+quicwg
+Raad
+radix
+RAS
+RBS
+ReactOS
+README
+realloc
+rebase
+RECV
+recv
+Redhat
+redirections
+redirs
+redistributable
+Redox
+reentrant
+Referer
+referer
+reinitializes
+Relatedly
+repo
+reprioritized
+resending
+RETR
+retransmit
+retrigger
+RICS
+Rikard
+rmdir
+ROADMAP
+Roadmap
+Rockbox
+roffit
+RPG
+RSA
+RTMP
+rtmp
+RTMPE
+RTMPS
+RTMPT
+RTMPTE
+RTMPTS
+RTOS
+RTP
+RTSP
+rtsp
+RTT
+runtests
+runtime
+Ruslan
+rustc
+rustls
+Sagula
+SanDisk
+SAS
+SASL
+Satiro
+Schannel
+Schindelin
+SCO
+SCP
+scp
+SDK
+se
+SEB
+SEK
+selectable
+Serv
+setopt
+setsockopt
+setuid
+SFTP
+sftp
+sha
+SHOUTcast
+SIGALRM
+SIGCHLD
+SIGPIPE
+singlecwd
+SINIX
+Sintonen
+sizeof
+SLE
+slist
+sln
+SMB
+smb
+SMBS
+smbs
+SMBv
+SMTP
+smtp
+smtps
+SMTPS
+SNI
+socketopen
+socketpair
+sockopt
+SOCKOPT
+SOCKSv
+Solaris
+SONAME
+Soref
+SPARC
+SPDX
+SPNEGO
+Spotify
+sprintf
+src
+SRP
+SRWLOCK
+SSL
+ssl
+SSLeay
+SSLKEYLOGFILE
+sslv
+SSLv
+SSLVERSION
+SSPI
+stackoverflow
+STARTTLS
+STARTTRANSFER
+stateful
+statvfs
+stderr
+stdin
+stdout
+Steinar
+Stenberg
+STOR
+strcat
+strcpy
+strdup
+strerror
+strlen
+strncat
+struct
+structs
+Structs
+stunnel
+subdirectories
+subdirectory
+submitters
+substring
+substrings
+SunOS
+SunSSH
+superset
+svc
+svcb
+Svyatoslav
+Swisscom
+sws
+Symbian
+symlink
+symlinks
+syntaxes
+Szakats
+TABs
+Tatsuhiro
+TBD
+TCP
+tcpdump
+Tekniska
+testability
+TFTP
+tftp
+Tizen
+TLS
+tlsv
+TLSv
+TODO
+Tomtom
+toolchain
+toolchains
+toolset
+toplevel
+TPF
+TrackMemory
+Tru
+Tse
+Tsujikawa
+TTL
+tvOS
+txt
+typedef
+typedefed
+ucLinux
+UDP
+UI
+UID
+UIDL
+Ultrix
+Unary
+unassign
+uncompress
+unencrypted
+unescape
+UNICOS
+unix
+UnixSockets
+UnixWare
+unlink
+unpause
+unpaused
+unpauses
+unpausing
+unsanitized
+Unshare
+unsharing
+untrusted
+UPN
+upstreaming
+URI
+URIs
+url
+URL's
+urlencoded
+urlget
+USD
+userdata
+Userinfo
+userinfo
+UTF
+UX
+valgrind
+Vanem
+vararg
+VC
+vcpkg
+vexxhost
+Viktor
+VM
+VMS
+VMware
+VSE
+vsprintf
+vt
+vtls
+vxWorks
+wakeup
+Warta
+watchOS
+WAV
+WB
+web page
+WebOS
+WebSocket
+WEBSOCKET
+WHATWG
+whitespace
+Whitespaces
+winbind
+WinBind
+winbuild
+winidn
+WinIDN
+WinLDAP
+WinSock
+winsock
+WinSSL
+winssl
+Wireshark
+wolfSSH
+wolfSSL
+WS
+WSS
+www
+Xbox
+xdigit
+Xilinx
+XP
+Xtensa
+XYZ
+Youtube
+YYYY
+YYYYMMDD
+Zakrzewski
+Zitzmann
+zlib
+zsh
+zstd
+Zuul
+zuul
diff --git a/.github/scripts/spellcheck.yaml b/.github/scripts/spellcheck.yaml
new file mode 100644
index 0000000..4e4e13d
--- /dev/null
+++ b/.github/scripts/spellcheck.yaml
@@ -0,0 +1,32 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+#
+# Docs: https://github.com/UnicornGlobal/spellcheck-github-actions
+matrix:
+- name: Markdown
+ expect_match: false
+ apsell:
+ mode: en
+ dictionary:
+ wordlists:
+ - wordlist.txt
+ output: wordlist.dic
+ encoding: utf-8
+ pipeline:
+ - pyspelling.filters.markdown:
+ markdown_extensions:
+ - markdown.extensions.extra:
+ - pyspelling.filters.html:
+ comments: true
+ attributes:
+ - title
+ - alt
+ ignores:
+ - ':matches(code, pre)'
+ - 'code'
+ - 'pre'
+ - 'strong'
+ - 'em'
+ sources:
+ - '**/*.md|!docs/BINDINGS.md'
diff --git a/.github/stale.yml b/.github/stale.yml
index ae4b35a..dc239b5 100644
--- a/.github/stale.yml
+++ b/.github/stale.yml
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/.github/workflows/appveyor-status.yml b/.github/workflows/appveyor-status.yml
new file mode 100644
index 0000000..9b638b5
--- /dev/null
+++ b/.github/workflows/appveyor-status.yml
@@ -0,0 +1,41 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: AppVeyor Status Report
+
+on:
+ status
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.sha }}-${{ github.event.target_url }}
+ cancel-in-progress: true
+
+permissions: {}
+
+jobs:
+ split:
+ runs-on: ubuntu-latest
+ if: ${{ github.event.sender.login == 'appveyor[bot]' }}
+ permissions:
+ statuses: write
+ steps:
+ - name: Create individual AppVeyor build statuses
+ if: ${{ github.event.sha && github.event.target_url }}
+ env:
+ APPVEYOR_COMMIT_SHA: ${{ github.event.sha }}
+ APPVEYOR_TARGET_URL: ${{ github.event.target_url }}
+ APPVEYOR_REPOSITORY: ${{ github.event.repository.full_name }}
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ echo ${APPVEYOR_TARGET_URL} | sed 's/\/project\//\/api\/projects\//' | xargs -t -n1 curl -s | \
+ jq -c '.build.jobs[] | {target_url: ($target_url + "/job/" + .jobId),
+ context: (.name | sub("^(Environment: )?"; "AppVeyor / ")),
+ state: (.status | sub("queued"; "pending")
+ | sub("starting"; "pending")
+ | sub("running"; "pending")
+ | sub("failed"; "failure")
+ | sub("cancelled"; "error")),
+ description: .status}' \
+ --arg target_url ${APPVEYOR_TARGET_URL} | tee /dev/stderr | parallel --pipe -j 1 -N 1 \
+ gh api --silent --input - repos/${APPVEYOR_REPOSITORY}/statuses/${APPVEYOR_COMMIT_SHA}
diff --git a/.github/workflows/awslc.yml b/.github/workflows/awslc.yml
new file mode 100644
index 0000000..f9bc563
--- /dev/null
+++ b/.github/workflows/awslc.yml
@@ -0,0 +1,129 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: Linux AWS-LC
+
+on:
+ push:
+ branches:
+ - master
+ - '*/ci'
+ paths-ignore:
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+ pull_request:
+ branches:
+ - master
+ paths-ignore:
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+
+concurrency:
+ # Hardcoded workflow filename as workflow name above is just Linux again
+ group: awslc-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
+
+env:
+ MAKEFLAGS: -j 3
+
+jobs:
+ autoconf:
+ name: awslc (autoconf)
+ runs-on: 'ubuntu-latest'
+ timeout-minutes: 30
+
+ steps:
+ - run: |
+ sudo apt-get update --yes
+ sudo apt-get install --yes libtool autoconf automake pkg-config stunnel4
+ # ensure we don't pick up openssl in this build
+ sudo apt remove --yes libssl-dev
+ sudo python3 -m pip install impacket
+ name: 'install prereqs and impacket'
+
+ - run: |
+ curl -LOsSf --retry 6 --retry-connrefused --max-time 999 https://github.com/awslabs/aws-lc/archive/refs/tags/v1.3.0.tar.gz
+ tar xzf v1.3.0.tar.gz
+ mkdir aws-lc-1.3.0-build
+ cd aws-lc-1.3.0-build
+ cmake -DCMAKE_INSTALL_PREFIX=$HOME/awslc ../aws-lc-1.3.0
+ cmake --build . --parallel
+ cmake --install .
+ name: 'install awslc'
+
+ - uses: actions/checkout@v3
+
+ - run: autoreconf -fi
+ name: 'autoreconf'
+
+ - run: |
+ mkdir build
+ cd build
+ ../configure --enable-warnings --enable-werror --with-openssl=$HOME/awslc
+ cd ..
+ name: 'configure out-of-tree'
+
+ - run: make -C build V=1
+ name: 'make'
+
+ - run: make -C build V=1 examples
+ name: 'make examples'
+
+ - run: make -C build V=1 -C tests
+ name: 'make tests'
+
+ - run: make -C build V=1 test-ci
+ name: 'run tests'
+
+ cmake:
+ name: awslc (cmake)
+ runs-on: 'ubuntu-latest'
+ timeout-minutes: 15
+
+ steps:
+ - run: |
+ sudo apt-get update
+ sudo apt-get install cmake stunnel4
+ # ensure we don't pick up openssl in this build
+ sudo apt remove --yes libssl-dev
+ sudo python3 -m pip install impacket
+ name: 'install prereqs and impacket'
+
+ - run: |
+ curl -LOsSf --retry 6 --retry-connrefused --max-time 999 https://github.com/awslabs/aws-lc/archive/refs/tags/v1.3.0.tar.gz
+ tar xzf v1.3.0.tar.gz
+ mkdir aws-lc-1.3.0-build
+ cd aws-lc-1.3.0-build
+ cmake -DCMAKE_INSTALL_PREFIX=$HOME/awslc ../aws-lc-1.3.0
+ cmake --build . --parallel
+ cmake --install .
+ name: 'install awslc'
+
+ - uses: actions/checkout@v3
+
+ # CMAKE_COMPILE_WARNING_AS_ERROR is available in cmake 3.24 or later
+ - run: cmake -Bbuild -DOPENSSL_ROOT_DIR=$HOME/awslc -DBUILD_SHARED_LIBS=ON -DCMAKE_COMPILE_WARNING_AS_ERROR=ON .
+ name: 'cmake generate out-of-tree'
+
+ - run: cmake --build build --parallel
+ name: 'cmake build'
+
+ - run: cmake --install build --prefix $HOME/curl --strip
+ name: 'cmake install'
diff --git a/.github/workflows/bearssl.yml b/.github/workflows/bearssl.yml
deleted file mode 100644
index 7c20f88..0000000
--- a/.github/workflows/bearssl.yml
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# SPDX-License-Identifier: curl
-
-name: Linux
-
-on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
- push:
- branches:
- - master
- - '*/ci'
- pull_request:
- branches:
- - master
-
-jobs:
- autotools:
- name: ${{ matrix.build.name }}
- runs-on: 'ubuntu-latest'
- timeout-minutes: 60
- strategy:
- fail-fast: false
- matrix:
- build:
- - name: bearssl
- install: libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev
- configure: LDFLAGS="-Wl,-rpath,$HOME/bear/lib" --with-bearssl=$HOME/bear --enable-debug
- - name: bearssl-clang
- install: libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev clang
- configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/bear/lib" --with-bearssl=$HOME/bear --enable-debug
-
- steps:
- - run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
-
- - run: |
- curl -LO https://bearssl.org/bearssl-0.6.tar.gz
- tar -xzf bearssl-0.6.tar.gz
- cd bearssl-0.6
- make
- mkdir -p $HOME/bear/lib $HOME/bear/include
- cp inc/*.h $HOME/bear/include
- cp build/libbearssl.* $HOME/bear/lib
- name: 'install bearssl'
-
- - uses: actions/checkout@v3
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
-
- - run: make V=1
- name: 'make'
-
- - run: make V=1 examples
- name: 'make examples'
-
- - run: make V=1 test-ci
- name: 'test'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 7309753..e5f38cc 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -1,28 +1,54 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
name: CodeQL
on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
push:
branches:
- master
- '*/ci'
+ paths-ignore:
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'docs/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'tests/data/**'
+ - 'winbuild/**'
pull_request:
branches:
- master
+ paths-ignore:
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'docs/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'tests/data/**'
+ - 'winbuild/**'
schedule:
- cron: '0 0 * * 4'
-permissions:
- security-events: write
+concurrency:
+ group: ${{ github.workflow }}
+
+permissions: {}
jobs:
codeql:
runs-on: ubuntu-latest
+ permissions:
+ security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
diff --git a/.github/workflows/event-based.yml b/.github/workflows/event-based.yml
deleted file mode 100644
index e4f83bc..0000000
--- a/.github/workflows/event-based.yml
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# SPDX-License-Identifier: curl
-
-name: Linux
-
-on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
- push:
- branches:
- - master
- - '*/ci'
- pull_request:
- branches:
- - master
-
-jobs:
- autotools:
- name: ${{ matrix.build.name }}
- runs-on: 'ubuntu-latest'
- timeout-minutes: 60
- strategy:
- fail-fast: false
- matrix:
- build:
- - name: event-based
- install: libpsl-dev libbrotli-dev libzstd-dev libssh-dev
- configure: --enable-debug --disable-shared --disable-threaded-resolver --with-libssh --with-openssl
- tflags: -n -e '!TLS-SRP'
-
- steps:
- - run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
-
- - uses: actions/checkout@v3
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
-
- - run: make V=1
- name: 'make'
-
- - run: make V=1 examples
- name: 'make examples'
-
- - run: make V=1 test-ci
- name: 'test'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml
index c6512fa..695e0de 100644
--- a/.github/workflows/fuzz.yml
+++ b/.github/workflows/fuzz.yml
@@ -1,40 +1,50 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
name: Fuzzer
on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
push:
branches:
- master
- '*/ci'
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'tests/data/**'
+ - 'winbuild/**'
pull_request:
branches:
- master
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'tests/data/**'
+ - 'winbuild/**'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
jobs:
- fuzzing:
- runs-on: ubuntu-latest
- steps:
- - name: Build Fuzzers
- uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
- with:
- oss-fuzz-project-name: 'curl'
- dry-run: false
-
- - name: Run Fuzzers
- uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
- with:
- oss-fuzz-project-name: 'curl'
- fuzz-seconds: 2400
- dry-run: false
-
- - name: Upload Crash
- uses: actions/upload-artifact@v3
- if: failure()
- with:
- name: artifacts
- path: ./out/artifacts
+ Fuzzing:
+ uses: curl/curl-fuzzer/.github/workflows/ci.yml@master
diff --git a/.github/workflows/hacktoberfest-accepted.yml b/.github/workflows/hacktoberfest-accepted.yml
index fa17339..c78ff4e 100644
--- a/.github/workflows/hacktoberfest-accepted.yml
+++ b/.github/workflows/hacktoberfest-accepted.yml
@@ -1,25 +1,30 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
name: Hacktoberfest
on:
- # run for all pushes to master branch
+ # this must not ever run on any other branch than master
push:
branches:
- master
-permissions:
- # requires issues AND pull-requests write permissions to edit labels on PRs!
- issues: write
- pull-requests: write
+concurrency:
+ # this should not run in parallel, so just run one at a time
+ group: ${{ github.workflow }}
+
+permissions: {}
jobs:
# add hacktoberfest-accepted label to PRs opened starting from September 30th
# till November 1st which are closed via commit reference from master branch.
merged:
runs-on: ubuntu-latest
+ permissions:
+ # requires issues AND pull-requests write permissions to edit labels on PRs!
+ issues: write
+ pull-requests: write
steps:
- uses: actions/checkout@v3
with:
@@ -27,8 +32,8 @@
- name: Check whether repo participates in Hacktoberfest
run: |
- gh config set prompt disabled && echo "::set-output name=label::$(
- gh repo view --json repositoryTopics --jq '.repositoryTopics[].name' | grep '^hacktoberfest$')"
+ gh config set prompt disabled && echo "label=$(
+ gh repo view --json repositoryTopics --jq '.repositoryTopics[].name' | grep '^hacktoberfest$')" >> $GITHUB_OUTPUT
id: check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -36,15 +41,15 @@
- name: Search relevant commit message lines starting with Closes/Merges
run: |
git log --format=email ${{ github.event.before }}..${{ github.event.after }} | \
- egrep -i "^Close[sd]? " | sort | uniq | tee log
+ grep -Ei "^Close[sd]? " | sort | uniq | tee log
if: steps.check.outputs.label == 'hacktoberfest'
- name: Search for Number-based PR references
run: |
- egrep -o "#([0-9]+)" log | cut -d# -f2 | sort | uniq | xargs -t -n1 -I{} \
+ grep -Eo "#([0-9]+)" log | cut -d# -f2 | sort | uniq | xargs -t -n1 -I{} \
gh pr view {} --json number,createdAt \
--jq '{number, opened: .createdAt} | [.number, .opened] | join(":")' | tee /dev/stderr | \
- egrep -o '^([0-9]+):[0-9]{4}-(09-30T|10-|11-01T)' | cut -d: -f1 | sort | uniq | xargs -t -n1 -I {} \
+ grep -Eo '^([0-9]+):[0-9]{4}-(09-30T|10-|11-01T)' | cut -d: -f1 | sort | uniq | xargs -t -n1 -I {} \
gh pr edit {} --add-label 'hacktoberfest-accepted'
if: steps.check.outputs.label == 'hacktoberfest'
env:
@@ -52,10 +57,10 @@
- name: Search for URL-based PR references
run: |
- egrep -o "github.com/(.+)/(.+)/pull/([0-9]+)" log | sort | uniq | xargs -t -n1 -I{} \
+ grep -Eo "github.com/(.+)/(.+)/pull/([0-9]+)" log | sort | uniq | xargs -t -n1 -I{} \
gh pr view "https://{}" --json number,createdAt \
--jq '{number, opened: .createdAt} | [.number, .opened] | join(":")' | tee /dev/stderr | \
- egrep -o '^([0-9]+):[0-9]{4}-(09-30T|10-|11-01T)' | cut -d: -f1 | sort | uniq | xargs -t -n1 -I {} \
+ grep -Eo '^([0-9]+):[0-9]{4}-(09-30T|10-|11-01T)' | cut -d: -f1 | sort | uniq | xargs -t -n1 -I {} \
gh pr edit {} --add-label 'hacktoberfest-accepted'
if: steps.check.outputs.label == 'hacktoberfest'
env:
diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml
new file mode 100644
index 0000000..baab1e4
--- /dev/null
+++ b/.github/workflows/label.yml
@@ -0,0 +1,28 @@
+# Copyright (C) Daniel Fandrich, <dan@coneharvesters.com>, et al.
+#
+# SPDX-License-Identifier: curl
+
+# This workflow will triage pull requests and apply a label based on the
+# paths that are modified in the pull request.
+#
+# To use this workflow, you will need to set up a .github/labeler.yml
+# file with configuration. For more information, see:
+# https://github.com/actions/labeler
+
+name: Labeler
+on: [pull_request_target]
+
+jobs:
+ label:
+
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: write
+
+ steps:
+ - uses: actions/labeler@v4
+ with:
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
+ # Workaround for actions/labeler#112
+ sync-labels: ''
diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml
index cad6fbc..18d1299 100644
--- a/.github/workflows/linkcheck.yml
+++ b/.github/workflows/linkcheck.yml
@@ -1,19 +1,29 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
name: Markdown links
on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
push:
branches:
- master
- '*/ci'
+ paths:
+ - '.github/workflows/linkcheck.yml'
+ - '**.md'
pull_request:
branches:
- master
+ paths:
+ - '.github/workflows/linkcheck.yml'
+ - '**.md'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
jobs:
# Docs: https://github.com/marketplace/actions/markdown-link-check
diff --git a/.github/workflows/linux-hyper.yml b/.github/workflows/linux-hyper.yml
deleted file mode 100644
index a9c50d7..0000000
--- a/.github/workflows/linux-hyper.yml
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# SPDX-License-Identifier: curl
-
-name: Linux
-
-on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
- push:
- branches:
- - master
- - '*/ci'
- pull_request:
- branches:
- - master
-
-jobs:
- autotools:
- name: ${{ matrix.build.name }}
- runs-on: 'ubuntu-latest'
- timeout-minutes: 90
- strategy:
- fail-fast: false
- matrix:
- build:
- - name: hyper
- install:
- configure: LDFLAGS="-Wl,-rpath,$HOME/hyper/target/debug" --with-openssl --with-hyper=$HOME/hyper --enable-debug
-
- steps:
- - run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
-
- - run: |
- cd $HOME
- git clone --depth=1 https://github.com/hyperium/hyper.git
- curl https://sh.rustup.rs -sSf | sh -s -- -y
- source $HOME/.cargo/env
- rustup toolchain install nightly
- name: 'install rust'
-
- - run: |
- cd $HOME/hyper
- RUSTFLAGS="--cfg hyper_unstable_ffi" cargo +nightly rustc --features client,http1,http2,ffi -Z unstable-options --crate-type cdylib
- name: 'install hyper'
-
- - uses: actions/checkout@v3
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
-
- - run: make V=1
- name: 'make'
-
- - run: make V=1 examples
- name: 'make examples'
-
- - run: make V=1 test-ci
- name: 'test'
- env:
- LD_LIBRARY_PATH: $HOME/hyper/target/debug:/usr/local/lib
- TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
new file mode 100644
index 0000000..0940bb3
--- /dev/null
+++ b/.github/workflows/linux.yml
@@ -0,0 +1,333 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: Linux
+
+on:
+ push:
+ branches:
+ - master
+ - '*/ci'
+ paths-ignore:
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+ pull_request:
+ branches:
+ - master
+ paths-ignore:
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
+
+env:
+ MAKEFLAGS: -j 3
+
+jobs:
+ autotools:
+ name: ${{ matrix.build.name }}
+ runs-on: 'ubuntu-latest'
+ container: ${{ matrix.build.container }}
+ timeout-minutes: 90
+ strategy:
+ fail-fast: false
+ matrix:
+ build:
+ - name: quiche
+ install_packages: zlib1g-dev valgrind
+ install_steps: quiche pytest
+ configure: LDFLAGS="-Wl,-rpath,/home/runner/work/curl/curl/quiche/target/release" --with-openssl=/home/runner/work/curl/curl/quiche/quiche/deps/boringssl/src --enable-debug --with-quiche=/home/runner/work/curl/curl/quiche/target/release
+
+ - name: bearssl
+ install_packages: zlib1g-dev valgrind
+ install_steps: bearssl pytest
+ configure: LDFLAGS="-Wl,-rpath,$HOME/bear/lib" --with-bearssl=$HOME/bear --enable-debug
+
+ - name: bearssl-clang
+ install_packages: zlib1g-dev clang
+ install_steps: bearssl
+ configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/bear/lib" --with-bearssl=$HOME/bear --enable-debug
+
+ - name: libressl
+ install_packages: zlib1g-dev valgrind
+ install_steps: libressl pytest
+ configure: LDFLAGS="-Wl,-rpath,$HOME/libressl/lib" --with-openssl=$HOME/libressl --enable-debug
+
+ - name: libressl-clang
+ install_packages: zlib1g-dev clang
+ install_steps: libressl
+ configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/libressl/lib" --with-openssl=$HOME/libressl --enable-debug
+
+ - name: mbedtls
+ install_packages: libnghttp2-dev valgrind
+ install_steps: mbedtls pytest
+ configure: LDFLAGS="-Wl,-rpath,$HOME/mbed/lib" --with-mbedtls=$HOME/mbed --enable-debug
+
+ - name: mbedtls-clang
+ install_packages: libnghttp2-dev clang
+ install_steps: mbedtls
+ configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/mbed/lib" --with-mbedtls=$HOME/mbed --enable-debug
+
+ - name: msh3
+ install_packages: zlib1g-dev valgrind
+ install_steps: quictls msh3
+ configure: LDFLAGS="-Wl,-rpath,$HOME/msh3/lib -Wl,-rpath,$HOME/quictls/lib" --with-msh3=$HOME/msh3 --with-openssl=$HOME/quictls --enable-debug
+
+ - name: openssl3
+ install_packages: zlib1g-dev valgrind
+ install_steps: gcc-11 openssl3 pytest
+ configure: LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib64" --with-openssl=$HOME/openssl3 --enable-debug --enable-websockets
+
+ - name: openssl3-O3
+ install_packages: zlib1g-dev valgrind
+ install_steps: gcc-11 openssl3
+ configure: CFLAGS=-O3 LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib64" --with-openssl=$HOME/openssl3 --enable-debug --enable-websockets
+
+ - name: openssl3-clang
+ install_packages: zlib1g-dev clang
+ install_steps: openssl3
+ configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib64" --with-openssl=$HOME/openssl3 --enable-debug --enable-websockets
+
+ - name: address-sanitizer
+ install_packages: zlib1g-dev libssh2-1-dev clang libssl-dev libubsan1 libasan8 libtsan2
+ install_steps: pytest
+ configure: >
+ CC=clang
+ CFLAGS="-fsanitize=address,undefined,signed-integer-overflow -fno-sanitize-recover=undefined,integer -Wformat -Werror=format-security -Werror=array-bounds -g"
+ LDFLAGS="-fsanitize=address,undefined -fno-sanitize-recover=undefined,integer"
+ LIBS="-ldl -lubsan"
+ --with-openssl --enable-debug --enable-websockets
+
+ - name: memory-sanitizer
+ install_packages: clang
+ install_steps:
+ configure: >
+ CC=clang
+ CFLAGS="-fsanitize=memory -Wformat -Werror=format-security -Werror=array-bounds -g"
+ LDFLAGS="-fsanitize=memory"
+ LIBS="-ldl"
+ --without-ssl --without-zlib --without-brotli --without-zstd --without-libpsl --without-nghttp2 --enable-debug --enable-websocketsx
+
+ - name: event-based
+ install_packages: libssh-dev valgrind
+ configure: --enable-debug --disable-shared --disable-threaded-resolver --with-libssh --with-openssl
+ tflags: -n -e '!TLS-SRP'
+
+ - name: hyper
+ install_steps: rust hyper valgrind
+ configure: LDFLAGS="-Wl,-rpath,$HOME/hyper/target/debug" --with-openssl --with-hyper=$HOME/hyper --enable-debug --enable-websockets
+
+ - name: rustls
+ install_steps: rust rustls pytest valgrind
+ configure: --with-rustls=$HOME/rustls --enable-debug
+
+ - name: Intel compiler - without SSL
+ install_packages: zlib1g-dev valgrind
+ install_steps: intel
+ configure: CC=icc --enable-debug --without-ssl
+
+ - name: Intel compiler - OpenSSL
+ install_packages: zlib1g-dev libssl-dev valgrind
+ install_steps: intel
+ configure: CC=icc --enable-debug --with-openssl
+
+ - name: NSS
+ install_packages: clang libnss3-dev libnghttp2-dev nss-plugin-pem
+ configure: CC=clang CPPFLAGS="-isystem /usr/include/nss" --with-nss --enable-debug --with-nss-deprecated
+
+ - name: Slackware-openssl-with-gssapi-gcc
+ # These are essentially the same flags used to build the curl Slackware package
+ # https://ftpmirror.infania.net/slackware/slackware64-current/source/n/curl/curl.SlackBuild
+ configure: --with-openssl --with-libssh2 --with-gssapi --enable-ares --enable-static=no --without-ca-bundle --with-ca-path=/etc/ssl/certs
+ # Docker Hub image that `container-job` executes in
+ container: 'andy5995/slackware-build-essential:15.0'
+
+ steps:
+ - if: ${{ matrix.build.container == null }}
+ run: |
+ sudo apt-get update
+ sudo apt-get install libtool autoconf automake pkg-config stunnel4 libpsl-dev libbrotli-dev libzstd-dev ${{ matrix.build.install_packages }}
+ sudo python3 -m pip install impacket
+ name: 'install prereqs and impacket'
+
+ - uses: actions/checkout@v3
+
+ - if: ${{ contains(matrix.build.install_steps, 'gcc-11') }}
+ run: |
+ sudo add-apt-repository ppa:ubuntu-toolchain-r/ppa
+ sudo apt-get update
+ sudo apt-get install gcc-11
+ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 100
+ sudo update-alternatives --set gcc /usr/bin/gcc-11
+ gcc --version
+ name: 'install gcc-11'
+
+ - if: ${{ contains(matrix.build.install_steps, 'bearssl') }}
+ run: |
+ curl -LOsSf --retry 6 --retry-connrefused --max-time 999 https://bearssl.org/bearssl-0.6.tar.gz
+ tar -xzf bearssl-0.6.tar.gz
+ cd bearssl-0.6
+ make
+ mkdir -p $HOME/bear/lib $HOME/bear/include
+ cp inc/*.h $HOME/bear/include
+ cp build/libbearssl.* $HOME/bear/lib
+ name: 'install bearssl'
+
+ - if: ${{ contains(matrix.build.install_steps, 'libressl') }}
+ run: |
+ git clone --quiet --depth=1 -b v3.6.1 https://github.com/libressl-portable/portable.git libressl-git
+ cd libressl-git
+ ./autogen.sh
+ ./configure --prefix=$HOME/libressl
+ make install
+ name: 'install libressl'
+
+ - if: ${{ contains(matrix.build.install_steps, 'quiche') }}
+ run: |
+ git clone --quiet --depth=1 --recursive https://github.com/cloudflare/quiche.git
+ cd quiche
+ #### Work-around https://github.com/curl/curl/issues/7927 #######
+ #### See https://github.com/alexcrichton/cmake-rs/issues/131 ####
+ sed -i -e 's/cmake = "0.1"/cmake = "=0.1.45"/' quiche/Cargo.toml
+
+ # /home/runner/work/curl/curl/boringssl
+
+ cargo build -v --package quiche --release --features ffi,pkg-config-meta,qlog --verbose
+ mkdir -v quiche/deps/boringssl/src/lib
+ ln -vnf $(find target/release -name libcrypto.a -o -name libssl.a) quiche/deps/boringssl/src/lib/
+
+ # include dir
+ # /home/runner/work/curl/curl/quiche/quiche/deps/boringssl/src/include
+ # lib dir
+ # /home/runner/work/curl/curl/quiche/quiche/deps/boringssl/src/lib
+
+ name: 'build quiche and boringssl'
+
+ - if: ${{ contains(matrix.build.install_steps, 'mbedtls') }}
+ run: |
+ git clone --quiet --depth=1 -b v3.3.0 https://github.com/ARMmbed/mbedtls
+ cd mbedtls
+ make DESTDIR=$HOME/mbed install
+ name: 'install mbedtls'
+
+ - if: ${{ contains(matrix.build.install_steps, 'openssl3') }}
+ run: |
+ git clone --quiet --depth=1 https://github.com/openssl/openssl
+ cd openssl
+ ./config enable-tls1_3 --prefix=$HOME/openssl3
+ make -j1 install_sw
+ name: 'install openssl'
+
+ - if: ${{ contains(matrix.build.install_steps, 'quictls') }}
+ run: |
+ git clone --quiet --depth=1 -b OpenSSL_1_1_1t+quic https://github.com/quictls/openssl
+ cd openssl
+ ./config enable-tls1_3 --prefix=$HOME/quictls
+ make -j1 install_sw
+ name: 'install quictls'
+
+ - if: ${{ contains(matrix.build.install_steps, 'msh3') }}
+ run: |
+ git clone --quiet -b v0.6.0 --depth=1 --recursive https://github.com/nibanks/msh3
+ cd msh3 && mkdir build && cd build
+ cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=$HOME/msh3 ..
+ cmake --build .
+ cmake --install .
+ name: 'install msh3'
+
+ - if: ${{ contains(matrix.build.install_steps, 'rust') }}
+ run: |
+ cd $HOME
+ curl -sSf --compressed https://sh.rustup.rs/ | sh -s -- -y
+ source $HOME/.cargo/env
+ rustup toolchain install nightly
+ name: 'install rust'
+
+ - if: ${{ contains(matrix.build.install_steps, 'rustls') }}
+ run: |
+ git clone --quiet --depth=1 -b v0.10.0 --recursive https://github.com/rustls/rustls-ffi.git
+ cd rustls-ffi
+ make DESTDIR=$HOME/rustls install
+ name: 'install rustls'
+
+ - if: ${{ contains(matrix.build.install_steps, 'hyper') }}
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 https://github.com/hyperium/hyper.git
+ cd $HOME/hyper
+ RUSTFLAGS="--cfg hyper_unstable_ffi" cargo +nightly rustc --features client,http1,http2,ffi -Z unstable-options --crate-type cdylib
+ echo "LD_LIBRARY_PATH=$HOME/hyper/target/debug:/usr/local/lib" >> $GITHUB_ENV
+ name: 'install hyper'
+
+ - if: ${{ contains(matrix.build.install_steps, 'intel') }}
+ run: |
+ cd /tmp
+ curl -sSf --compressed https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | sudo apt-key add -
+ sudo add-apt-repository "deb https://apt.repos.intel.com/oneapi all main"
+ sudo apt install --no-install-recommends intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
+ source /opt/intel/oneapi/setvars.sh
+ printenv >> $GITHUB_ENV
+ name: 'install Intel compilers'
+
+ - if: ${{ contains(matrix.build.install_steps, 'pytest') }}
+ run: |
+ sudo apt-get install apache2 apache2-dev libnghttp2-dev
+ sudo python3 -m pip install -r tests/http/requirements.txt
+ git clone --quiet --depth=1 -b master https://github.com/icing/mod_h2
+ cd mod_h2
+ autoreconf -fi
+ ./configure PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig"
+ make
+ sudo make install
+ name: 'install pytest and apach2-dev mod-h2'
+
+ - run: autoreconf -fi
+ name: 'autoreconf'
+
+ - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
+ name: 'configure'
+
+ - run: make V=1
+ name: 'make'
+
+ - run: ./src/curl -V
+ name: 'check curl -V output'
+
+ - run: make V=1 examples
+ name: 'make examples'
+
+ - run: make V=1 -C tests
+ name: 'make tests'
+
+ - run: make V=1 test-ci
+ name: 'run tests'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
+
+ - if: ${{ contains(matrix.build.install_steps, 'pytest') }}
+ # run for `tests` directory, so pytest does not pick up any other
+ # packages we might have built here
+ run:
+ pytest -v tests
+ name: 'run pytest'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 6ebd57a..2b382dd 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -1,19 +1,47 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
name: macOS
on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
push:
branches:
- master
- '*/ci'
+ paths-ignore:
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
pull_request:
branches:
- master
+ paths-ignore:
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
+
+env:
+ DEVELOPER_DIR: /Applications/Xcode_14.0.1.app/Contents/Developer
+ MAKEFLAGS: -j 5
jobs:
autotools:
@@ -56,6 +84,9 @@
install: nghttp2
configure: --enable-debug --with-secure-transport
macosx-version-min: 10.8
+ - name: gcc SecureTransport
+ configure: CC=gcc-12 --enable-debug --with-secure-transport
+ macosx-version-min: 10.8
- name: OpenSSL http2
install: nghttp2 openssl
configure: --enable-debug --with-openssl=/usr/local/opt/openssl
@@ -85,9 +116,20 @@
# Run this command with retries because of spurious failures seen
# while running the tests, for example
# https://github.com/curl/curl/runs/4095721123?check_suite_focus=true
- - run: brew update && for i in 1 2 3; do brew bundle install --no-lock --file /tmp/Brewfile && break || sleep 1; done
+ - run: "while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done"
name: 'brew install'
+ - run: |
+ case "${{ matrix.build.install }}" in
+ *openssl*)
+ ;;
+ *)
+ if test -d /usr/local/include/openssl; then
+ brew unlink openssl
+ fi;;
+ esac
+ name: 'brew unlink openssl'
+
- run: python3 -m pip install impacket
name: 'pip3 install'
@@ -96,11 +138,10 @@
- run: autoreconf -fi
name: 'autoreconf'
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
+ - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }} --enable-websockets
name: 'configure'
env:
- # -Wvla is caused by brotli
- CFLAGS: "-Wno-vla -mmacosx-version-min=${{ matrix.build.macosx-version-min }}"
+ CFLAGS: "-mmacosx-version-min=${{ matrix.build.macosx-version-min }}"
- run: make V=1
name: 'make'
@@ -108,8 +149,11 @@
- run: make V=1 examples
name: 'make examples'
+ - run: make V=1 -C tests
+ name: 'make tests'
+
- run: make V=1 test-ci
- name: 'test'
+ name: 'run tests'
env:
TFLAGS: "${{ matrix.build.tflags }} ~1452"
@@ -124,8 +168,8 @@
- CC: clang
CXX: clang++
CFLAGS: "-mmacosx-version-min=10.15 -Wno-deprecated-declarations"
- - CC: gcc-9
- CXX: g++-9
+ - CC: gcc-12
+ CXX: g++-12
CFLAGS: "-mmacosx-version-min=10.15 -Wno-error=undef -Wno-error=conversion"
build:
- name: OpenSSL
@@ -133,7 +177,7 @@
generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DCURL_DISABLE_LDAP=ON -DCURL_DISABLE_LDAPS=ON
- name: LibreSSL
install: nghttp2 libressl
- generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/libressl -DCURL_DISABLE_LDAP=ON -DCURL_DISABLE_LDAPS=ON
+ generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/libressl -DCURL_DISABLE_LDAP=ON -DCURL_DISABLE_LDAPS=ON -DCMAKE_UNITY_BUILD=ON
- name: libssh2
install: nghttp2 openssl libssh2
generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DCURL_USE_LIBSSH2=ON
@@ -141,11 +185,19 @@
- run: echo libtool autoconf automake pkg-config ${{ matrix.build.install }} | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
name: 'brew bundle'
- - run: brew update && brew bundle install --no-lock --file /tmp/Brewfile
+ - run: "while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done"
name: 'brew install'
- - run: python3 -m pip install impacket
- name: 'pip3 install'
+ - run: |
+ case "${{ matrix.build.install }}" in
+ *openssl*)
+ ;;
+ *)
+ if test -d /usr/local/include/openssl; then
+ brew unlink openssl
+ fi;;
+ esac
+ name: 'brew unlink openssl'
- uses: actions/checkout@v3
diff --git a/.github/workflows/mbedtls.yml b/.github/workflows/mbedtls.yml
deleted file mode 100644
index 85ae4b8..0000000
--- a/.github/workflows/mbedtls.yml
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# SPDX-License-Identifier: curl
-
-name: Linux
-
-on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
- push:
- branches:
- - master
- - '*/ci'
- pull_request:
- branches:
- - master
-
-jobs:
- autotools:
- name: ${{ matrix.build.name }}
- runs-on: 'ubuntu-latest'
- timeout-minutes: 60
- strategy:
- fail-fast: false
- matrix:
- build:
- - name: mbedtls
- install: libpsl-dev libbrotli-dev libzstd-dev libnghttp2-dev
- configure: LDFLAGS="-Wl,-rpath,$HOME/mbed/lib" --with-mbedtls=$HOME/mbed --enable-debug
- - name: mbedtls-clang
- install: libpsl-dev libbrotli-dev libzstd-dev libnghttp2-dev clang
- configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/mbed/lib" --with-mbedtls=$HOME/mbed --enable-debug
-
- steps:
- - run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
-
- - run: |
- git clone --depth=1 -b v3.1.0 https://github.com/ARMmbed/mbedtls
- cd mbedtls
- make
- make DESTDIR=$HOME/mbed install
- name: 'install mbedtls'
-
- - uses: actions/checkout@v3
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
-
- - run: make V=1
- name: 'make'
-
- - run: make V=1 examples
- name: 'make examples'
-
- - run: make V=1 test-ci
- name: 'test'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/msh3.yml b/.github/workflows/msh3.yml
deleted file mode 100644
index b326478..0000000
--- a/.github/workflows/msh3.yml
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# SPDX-License-Identifier: curl
-
-name: Linux
-
-on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
- push:
- branches:
- - master
- - '*/ci'
- pull_request:
- branches:
- - master
-
-jobs:
- autotools:
- name: ${{ matrix.build.name }}
- runs-on: 'ubuntu-latest'
- timeout-minutes: 60
- strategy:
- fail-fast: false
- matrix:
- build:
- - name: msh3
- install: libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev
- configure: LDFLAGS="-Wl,-rpath,$HOME/msh3/lib -Wl,-rpath,$HOME/quictls/lib" --with-msh3=$HOME/msh3 --enable-debug --enable-werror --with-openssl=$HOME/quictls
-
- steps:
- - run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
-
- - run: |
- git clone --depth 1 -b OpenSSL_1_1_1j+quic https://github.com/quictls/openssl ossl
- cd ossl
- ./config enable-tls1_3 --prefix=$HOME/quictls
- make
- make install_sw
- name: 'install quictls'
-
- - run: |
- git clone --depth 1 --recursive https://github.com/nibanks/msh3
- cd msh3 && mkdir build && cd build
- cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=$HOME/msh3 ..
- cmake --build .
- cmake --install .
- name: 'install msh3'
-
- - uses: actions/checkout@v3
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
-
- - run: make V=1
- name: 'make'
-
- - run: make V=1 examples
- name: 'make examples'
-
- - run: make V=1 test-ci
- name: 'test'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/ngtcp2-gnutls.yml b/.github/workflows/ngtcp2-gnutls.yml
new file mode 100644
index 0000000..960837e
--- /dev/null
+++ b/.github/workflows/ngtcp2-gnutls.yml
@@ -0,0 +1,168 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: ngtcp2 GnuTLS
+
+on:
+ push:
+ branches:
+ - master
+ - '*/ci'
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+ pull_request:
+ branches:
+ - master
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+
+concurrency:
+ # Hardcoded workflow filename as workflow name above is just Linux again
+ group: ngtcp2-gnutls-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
+
+env:
+ MAKEFLAGS: -j 3
+
+jobs:
+ autotools:
+ name: ${{ matrix.build.name }}
+ runs-on: 'ubuntu-latest'
+ timeout-minutes: 60
+ strategy:
+ fail-fast: false
+ matrix:
+ build:
+ - name: gnutls
+ install: >-
+ libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libev-dev libc-ares-dev
+ nettle-dev libp11-kit-dev libtspi-dev libunistring-dev guile-2.2-dev libtasn1-bin
+ libtasn1-6-dev libidn2-0-dev gawk gperf libtss2-dev dns-root-data bison gtk-doc-tools
+ texinfo texlive texlive-extra-utils autopoint libev-dev
+ configure: >-
+ PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/all/lib"
+ --with-ngtcp2=$HOME/all --enable-warnings --enable-werror --enable-debug
+ --with-test-nghttpx="$HOME/all/bin/nghttpx"
+ ngtcp2-configure: >-
+ --prefix=$HOME/all PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" --enable-lib-only
+ gnutls-configure: >-
+ PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/all/lib -L$HOME/all/lib"
+ --with-included-libtasn1 --with-included-unistring
+ --disable-guile --disable-doc --disable-tests --disable-tools
+
+ steps:
+ - run: |
+ sudo apt-get update
+ sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
+ sudo apt-get install apache2 apache2-dev
+ name: 'install prereqs and impacket, pytest, crypto'
+
+ - run: |
+ git clone --quiet --depth=1 -b openssl-3.0.9+quic https://github.com/quictls/openssl
+ cd openssl
+ ./config --prefix=$HOME/all --libdir=$HOME/all/lib
+ make -j1 install_sw
+ name: 'install quictls'
+
+ - run: |
+ git clone --quiet --depth=1 https://gitlab.com/gnutls/nettle.git
+ cd nettle
+ ./.bootstrap
+ ./configure LDFLAGS="-Wl,-rpath,$HOME/all/lib" ${{ matrix.build.nettle-configure }} --prefix=$HOME/all --libdir=$HOME/all/lib --disable-documentation
+ make install
+ name: 'install nettle'
+
+ - run: |
+ git clone --quiet --depth=1 -b 3.8.0 https://github.com/gnutls/gnutls.git
+ cd gnutls
+ ./bootstrap
+ ./configure ${{ matrix.build.gnutls-configure }} --prefix=$HOME/all
+ make install
+ name: 'install gnutls'
+
+ - run: |
+ git clone --quiet --depth=1 -b v0.13.0 https://github.com/ngtcp2/nghttp3
+ cd nghttp3
+ autoreconf -fi
+ ./configure --prefix=$HOME/all PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" --enable-lib-only
+ make install
+ name: 'install nghttp3'
+
+ - run: |
+ git clone --quiet --depth=1 -b v0.17.0 https://github.com/ngtcp2/ngtcp2
+ cd ngtcp2
+ autoreconf -fi
+ ./configure ${{ matrix.build.ngtcp2-configure }} --with-openssl --with-gnutls
+ make install
+ name: 'install ngtcp2'
+
+ - run: |
+ git clone --quiet --depth=1 -b v1.55.1 https://github.com/nghttp2/nghttp2
+ cd nghttp2
+ autoreconf -fi
+ ./configure --prefix=$HOME/all PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" --enable-http3
+ make install
+ name: 'install nghttp2'
+
+ - run: |
+ git clone --quiet --depth=1 -b master https://github.com/icing/mod_h2
+ cd mod_h2
+ autoreconf -fi
+ ./configure PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig"
+ make
+ sudo make install
+ name: 'install mod_h2'
+
+ - uses: actions/checkout@v3
+
+ - run: |
+ sudo python3 -m pip install -r tests/requirements.txt -r tests/http/requirements.txt
+ name: 'install python test prereqs'
+
+ - run: autoreconf -fi
+ name: 'autoreconf'
+
+ - run: ./configure --with-gnutls=$HOME/all ${{ matrix.build.configure }}
+ name: 'configure'
+
+ - run: make V=1
+ name: 'make'
+
+ - run: make V=1 examples
+ name: 'make examples'
+
+ - run: make V=1 -C tests
+ name: 'make tests'
+
+ - run: make V=1 test-ci
+ name: 'run tests'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
+
+ - run: pytest -v
+ name: 'run pytest'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/ngtcp2-quictls.yml b/.github/workflows/ngtcp2-quictls.yml
new file mode 100644
index 0000000..5423b17
--- /dev/null
+++ b/.github/workflows/ngtcp2-quictls.yml
@@ -0,0 +1,145 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: ngtcp2 quictls
+
+on:
+ push:
+ branches:
+ - master
+ - '*/ci'
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+ pull_request:
+ branches:
+ - master
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+
+concurrency:
+ # Hardcoded workflow filename as workflow name above is just Linux again
+ group: ngtcp2-openssl-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
+
+env:
+ MAKEFLAGS: -j 3
+
+jobs:
+ autotools:
+ name: ${{ matrix.build.name }}
+ runs-on: 'ubuntu-latest'
+ timeout-minutes: 60
+ strategy:
+ fail-fast: false
+ matrix:
+ build:
+ - name: quictls
+ install: >-
+ libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libev-dev libc-ares-dev
+ configure: >-
+ PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/all/lib"
+ --with-ngtcp2=$HOME/all --enable-warnings --enable-werror --enable-debug
+ --with-test-nghttpx="$HOME/all/bin/nghttpx"
+ ngtcp2-configure: >-
+ --prefix=$HOME/all PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" --enable-lib-only
+
+ steps:
+ - run: |
+ sudo apt-get update
+ sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
+ sudo apt-get install apache2 apache2-dev
+ name: 'install prereqs and impacket, pytest, crypto'
+
+ - run: |
+ git clone --quiet --depth=1 -b openssl-3.0.9+quic https://github.com/quictls/openssl
+ cd openssl
+ ./config --prefix=$HOME/all --libdir=$HOME/all/lib
+ make -j1 install_sw
+ name: 'install quictls'
+
+ - run: |
+ git clone --quiet --depth=1 -b v0.13.0 https://github.com/ngtcp2/nghttp3
+ cd nghttp3
+ autoreconf -fi
+ ./configure --prefix=$HOME/all PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" --enable-lib-only
+ make install
+ name: 'install nghttp3'
+
+ - run: |
+ git clone --quiet --depth=1 -b v0.17.0 https://github.com/ngtcp2/ngtcp2
+ cd ngtcp2
+ autoreconf -fi
+ ./configure ${{ matrix.build.ngtcp2-configure }} --with-openssl
+ make install
+ name: 'install ngtcp2'
+
+ - run: |
+ git clone --quiet --depth=1 -b v1.55.1 https://github.com/nghttp2/nghttp2
+ cd nghttp2
+ autoreconf -fi
+ ./configure --prefix=$HOME/all PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" --enable-http3
+ make install
+ name: 'install nghttp2'
+
+ - run: |
+ git clone --quiet --depth=1 -b master https://github.com/icing/mod_h2
+ cd mod_h2
+ autoreconf -fi
+ ./configure PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig"
+ make
+ sudo make install
+ name: 'install mod_h2'
+
+ - uses: actions/checkout@v3
+
+ - run: |
+ sudo python3 -m pip install -r tests/requirements.txt -r tests/http/requirements.txt
+ name: 'install python test prereqs'
+
+ - run: autoreconf -fi
+ name: 'autoreconf'
+
+ - run: ./configure --with-openssl=$HOME/all ${{ matrix.build.configure }}
+ name: 'configure'
+
+ - run: make V=1
+ name: 'make'
+
+ - run: make V=1 examples
+ name: 'make examples'
+
+ - run: make V=1 -C tests
+ name: 'make tests'
+
+ - run: make V=1 test-ci
+ name: 'run tests'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
+
+ - run: pytest -v
+ name: 'run pytest'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/ngtcp2-wolfssl.yml b/.github/workflows/ngtcp2-wolfssl.yml
new file mode 100644
index 0000000..6c8b983
--- /dev/null
+++ b/.github/workflows/ngtcp2-wolfssl.yml
@@ -0,0 +1,158 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: ngtcp2 wolfSSL
+
+on:
+ push:
+ branches:
+ - master
+ - '*/ci'
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+ pull_request:
+ branches:
+ - master
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+
+concurrency:
+ # Hardcoded workflow filename as workflow name above is just Linux again
+ group: ngtcp2-wolfssl-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
+
+env:
+ MAKEFLAGS: -j 3
+
+jobs:
+ autotools:
+ name: ${{ matrix.build.name }}
+ runs-on: 'ubuntu-latest'
+ timeout-minutes: 60
+ strategy:
+ fail-fast: false
+ matrix:
+ build:
+ - name: wolfssl
+ install: >-
+ libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libev-dev libc-ares-dev
+ configure: >-
+ PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/all/lib"
+ --with-ngtcp2=$HOME/all --enable-warnings --enable-werror --enable-debug
+ --with-test-nghttpx="$HOME/all/bin/nghttpx"
+ ngtcp2-configure: >-
+ --prefix=$HOME/all PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" --enable-lib-only
+ wolfssl-configure: >-
+ --enable-all --enable-quic
+
+ steps:
+ - run: |
+ sudo apt-get update
+ sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
+ sudo apt-get install apache2 apache2-dev
+ name: 'install prereqs'
+
+ - run: |
+ WOLFSSL_VER=v5.6.3-stable
+ git clone --quiet --depth=1 -b $WOLFSSL_VER https://github.com/wolfSSL/wolfssl.git
+ cd wolfssl
+ ./autogen.sh
+ ./configure ${{ matrix.build.wolfssl-configure }} --prefix=$HOME/all
+ make install
+ name: 'install wolfssl'
+
+ - run: |
+ git clone --quiet --depth=1 -b openssl-3.0.9+quic https://github.com/quictls/openssl
+ cd openssl
+ ./config --prefix=$HOME/all --libdir=$HOME/all/lib
+ make -j1 install_sw
+ name: 'install quictls'
+
+ - run: |
+ git clone --quiet --depth=1 -b v0.13.0 https://github.com/ngtcp2/nghttp3
+ cd nghttp3
+ autoreconf -fi
+ ./configure --prefix=$HOME/all PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" --enable-lib-only
+ make install
+ name: 'install nghttp3'
+
+ - run: |
+ git clone --quiet --depth=1 -b v0.17.0 https://github.com/ngtcp2/ngtcp2
+ cd ngtcp2
+ autoreconf -fi
+ ./configure ${{ matrix.build.ngtcp2-configure }} --with-openssl --with-wolfssl
+ make install
+ name: 'install ngtcp2'
+
+ - run: |
+ git clone --quiet --depth=1 -b v1.55.1 https://github.com/nghttp2/nghttp2
+ cd nghttp2
+ autoreconf -fi
+ ./configure --prefix=$HOME/all PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig" --enable-http3
+ make install
+ name: 'install nghttp2'
+
+ - run: |
+ git clone --quiet --depth=1 -b master https://github.com/icing/mod_h2
+ cd mod_h2
+ autoreconf -fi
+ ./configure PKG_CONFIG_PATH="$HOME/all/lib/pkgconfig"
+ make
+ sudo make install
+ name: 'install mod_h2'
+
+ - uses: actions/checkout@v3
+
+ - run: |
+ sudo python3 -m pip install -r tests/requirements.txt -r tests/http/requirements.txt
+ name: 'install python test prereqs'
+
+ - run: autoreconf -fi
+ name: 'autoreconf'
+
+ - run: ./configure --with-wolfssl=$HOME/all ${{ matrix.build.configure }}
+ name: 'configure'
+
+ - run: make V=1
+ name: 'make'
+
+ - run: make V=1 examples
+ name: 'make examples'
+
+ - run: make V=1 -C tests
+ name: 'make tests'
+
+ - run: make V=1 test-ci
+ name: 'run tests'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
+
+ # Disabled for now, we see spurious SSL_connect() errors when talking
+ # http/1.1 to apache and this, so far, is not reproducable in local testing
+ #- run: pytest -v
+ # name: 'run pytest'
+ # env:
+ # TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/nss.yml b/.github/workflows/nss.yml
deleted file mode 100644
index 92d0007..0000000
--- a/.github/workflows/nss.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# SPDX-License-Identifier: curl
-
-name: Linux
-
-on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
- push:
- branches:
- - master
- - '*/ci'
- pull_request:
- branches:
- - master
-
-jobs:
- autotools:
- name: ${{ matrix.build.name }}
- runs-on: 'ubuntu-latest'
- timeout-minutes: 60
- strategy:
- fail-fast: false
- matrix:
- build:
- - name: NSS
- install: clang-9 libnss3-dev libpsl-dev libbrotli-dev libzstd-dev libnghttp2-dev nss-plugin-pem
- configure: CC=clang-9 CPPFLAGS="-isystem /usr/include/nss" --with-nss --enable-debug --with-nss-deprecated
-
- steps:
- - run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
-
- - uses: actions/checkout@v3
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure with clang'
-
- - run: make V=1
- name: 'make'
-
- - run: make V=1 examples
- name: 'make examples'
-
- - run: make V=1 test-ci
- name: 'test'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/openssl3.yml b/.github/workflows/openssl3.yml
deleted file mode 100644
index 961090d..0000000
--- a/.github/workflows/openssl3.yml
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# SPDX-License-Identifier: curl
-
-name: Linux
-
-on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
- push:
- branches:
- - master
- - '*/ci'
- pull_request:
- branches:
- - master
-
-jobs:
- autotools:
- name: ${{ matrix.build.name }}
- runs-on: 'ubuntu-latest'
- timeout-minutes: 60
- strategy:
- fail-fast: false
- matrix:
- build:
- - name: openssl3
- install: libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev
- configure: LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib64" --with-openssl=$HOME/openssl3 --enable-debug
- - name: openssl3-clang
- install: libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev clang
- configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib64" --with-openssl=$HOME/openssl3 --enable-debug
-
- steps:
- - run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
-
- - run: |
- git clone --depth=1 https://github.com/openssl/openssl
- cd openssl
- ./config enable-tls1_3 --prefix=$HOME/openssl3
- make && make install_sw
- name: 'install openssl3'
-
- - uses: actions/checkout@v3
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
-
- - run: make V=1
- name: 'make'
-
- - run: make V=1 examples
- name: 'make examples'
-
- - run: make V=1 test-ci
- name: 'test'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/proselint.yml b/.github/workflows/proselint.yml
new file mode 100644
index 0000000..01a7cf5
--- /dev/null
+++ b/.github/workflows/proselint.yml
@@ -0,0 +1,68 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: proselint
+
+on:
+ push:
+ branches:
+ - master
+ - '*/ci'
+ paths:
+ - '.github/workflows/proselint.yml'
+ - '**.md'
+ pull_request:
+ branches:
+ - master
+ paths:
+ - '.github/workflows/proselint.yml'
+ - '**.md'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
+
+jobs:
+ check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: install prereqs
+ run: sudo apt-get install python3-proselint
+
+ # config file help: https://github.com/amperser/proselint/
+ - name: create proselint config
+ run: |
+ cat <<JSON > $HOME/.proselintrc
+ {
+ "checks": {
+ "typography.diacritical_marks": false,
+ "typography.symbols": false,
+ "annotations.misc": false
+ }
+ }
+ JSON
+
+ - name: check prose
+ run: a=`git ls-files '*.md' | grep -v docs/CHECKSRC.md` && proselint $a README
+
+ # This is for CHECKSRC and files with aggressive exclamation mark needs
+ - name: create second proselint config
+ run: |
+ cat <<JSON > $HOME/.proselintrc
+ {
+ "checks": {
+ "typography.diacritical_marks": false,
+ "typography.symbols": false,
+ "typography.exclamation": false,
+ "annotations.misc": false
+ }
+ }
+ JSON
+
+ - name: check special prose
+ run: a=docs/CHECKSRC.md && proselint $a
diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml
index 23e019f..95ad6e9 100644
--- a/.github/workflows/reuse.yml
+++ b/.github/workflows/reuse.yml
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
# SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. <https://fsfe.org>
#
# SPDX-License-Identifier: curl
@@ -6,8 +6,6 @@
name: REUSE compliance
on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
push:
branches:
- master
@@ -16,6 +14,12 @@
branches:
- master
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
+
jobs:
check:
runs-on: ubuntu-latest
diff --git a/.github/workflows/rustls.yml b/.github/workflows/rustls.yml
deleted file mode 100644
index 348c896..0000000
--- a/.github/workflows/rustls.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# SPDX-License-Identifier: curl
-
-name: Linux
-
-on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
- push:
- branches:
- - master
- - '*/ci'
- pull_request:
- branches:
- - master
-
-jobs:
- autotools:
- name: ${{ matrix.build.name }}
- runs-on: 'ubuntu-latest'
- timeout-minutes: 60
- strategy:
- fail-fast: false
- matrix:
- build:
- - name: rustls
- install: libpsl-dev libbrotli-dev libzstd-dev
- configure: --with-rustls=$HOME/rustls --enable-debug
-
- steps:
- - run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
-
- - run: |
- git clone --depth=1 --recursive https://github.com/rustls/rustls-ffi.git -b v0.8.2
- curl https://sh.rustup.rs -sSf | sh -s -- -y
- source $HOME/.cargo/env
- cd rustls-ffi
- make
- make DESTDIR=$HOME/rustls install
- name: 'install rustls'
-
- - uses: actions/checkout@v3
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
-
- - run: make V=1
- name: 'make'
-
- - run: make V=1 examples
- name: 'make examples'
-
- - run: make V=1 test-ci
- name: 'test'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml
new file mode 100644
index 0000000..65a7da1
--- /dev/null
+++ b/.github/workflows/spellcheck.yml
@@ -0,0 +1,54 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: spell
+on:
+ push:
+ branches:
+ - master
+ paths:
+ - '**.md'
+ - '**.3'
+ - '**.1'
+ - '**/spellcheck.yml'
+ - '**/spellcheck.yaml'
+ - '**/wordlist.txt'
+ pull_request:
+ branches:
+ - master
+ paths:
+ - '**.md'
+ - '**.3'
+ - '**.1'
+ - '**/spellcheck.yml'
+ - '**/spellcheck.yaml'
+ - '**/wordlist.txt'
+
+permissions: {}
+
+jobs:
+ check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: install pandoc
+ run: sudo apt-get install pandoc
+
+ - name: strip "uncheckable" sections from .3 pages
+ run: find docs -name "*.3" -size +40c | sed 's/\.3//' | xargs -t -n1 -I OO ./.github/scripts/cleanspell.pl OO.3 OO.33
+
+ - name: convert .3 man pages to markdown
+ run: find docs -name "*.33" -size +40c | sed 's/\.33//' | xargs -t -n1 -I OO pandoc -f man -t markdown OO.33 -o OO.md
+
+ - name: convert .1 man pages to markdown
+ run: find docs -name "*.1" -size +40c | sed 's/\.1//' | xargs -t -n1 -I OO pandoc OO.1 -o OO.md
+
+ - name: setup the custom wordlist
+ run: grep -v '^#' .github/scripts/spellcheck.words > wordlist.txt
+
+ - name: Check Spelling
+ uses: rojopolis/spellcheck-github-actions@v0
+ with:
+ config_path: .github/scripts/spellcheck.yaml
diff --git a/.github/workflows/torture.yml b/.github/workflows/torture.yml
new file mode 100644
index 0000000..cb639a5
--- /dev/null
+++ b/.github/workflows/torture.yml
@@ -0,0 +1,92 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: Linux torture
+
+on:
+ push:
+ branches:
+ - master
+ - '*/ci'
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+ pull_request:
+ branches:
+ - master
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+
+concurrency:
+ # Hardcoded workflow filename as workflow name above is just Linux again
+ group: torture-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
+
+env:
+ MAKEFLAGS: -j 3
+
+jobs:
+ autotools:
+ name: ${{ matrix.build.name }}
+ runs-on: 'ubuntu-latest'
+ timeout-minutes: 90
+ strategy:
+ fail-fast: false
+ matrix:
+ build:
+ - name: torture
+ install: libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libnghttp2-dev libssh2-1-dev libc-ares-dev
+ configure: --with-openssl --enable-debug --enable-ares --enable-websockets
+ tflags: -n -t --shallow=25 !FTP
+ - name: torture-ftp
+ install: libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libnghttp2-dev libssh2-1-dev libc-ares-dev
+ configure: --with-openssl --enable-debug --enable-ares
+ tflags: -n -t --shallow=20 FTP
+
+ steps:
+ - run: |
+ sudo apt-get update
+ sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
+ sudo python3 -m pip install impacket
+ name: 'install prereqs and impacket'
+
+ - uses: actions/checkout@v3
+
+ - run: autoreconf -fi
+ name: 'autoreconf'
+
+ - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
+ name: 'configure'
+
+ - run: make V=1
+ name: 'make'
+
+ - run: make V=1 -C tests
+ name: 'make tests'
+
+ - run: make V=1 test-torture
+ name: 'run tests'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/wolfssl.yml b/.github/workflows/wolfssl.yml
index a92f2d3..53ed0cc 100644
--- a/.github/workflows/wolfssl.yml
+++ b/.github/workflows/wolfssl.yml
@@ -1,19 +1,51 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
-name: Linux
+name: Linux wolfSSL
on:
- # Trigger the workflow on push or pull requests, but only for the
- # master branch
push:
branches:
- master
- '*/ci'
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
pull_request:
branches:
- master
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.yml'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+
+concurrency:
+ # Hardcoded workflow filename as workflow name above is just Linux again
+ group: wolfssl-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
+
+env:
+ MAKEFLAGS: -j 3
jobs:
autotools:
@@ -41,12 +73,13 @@
name: 'install prereqs and impacket'
- run: |
- curl -LO https://github.com/wolfSSL/wolfssl/archive/v5.0.0-stable.tar.gz
- tar -xzf v5.0.0-stable.tar.gz
- cd wolfssl-5.0.0-stable
+ WOLFSSL_VER=5.6.3
+ curl -LOsSf --retry 6 --retry-connrefused --max-time 999 https://github.com/wolfSSL/wolfssl/archive/v$WOLFSSL_VER-stable.tar.gz
+ tar -xzf v$WOLFSSL_VER-stable.tar.gz
+ cd wolfssl-$WOLFSSL_VER-stable
./autogen.sh
./configure --enable-tls13 ${{ matrix.build.wolfssl-configure }} --enable-harden --prefix=$HOME/wssl
- make && make install
+ make install
name: 'install wolfssl'
- uses: actions/checkout@v3
@@ -63,7 +96,10 @@
- run: make V=1 examples
name: 'make examples'
+ - run: make V=1 -C tests
+ name: 'make tests'
+
- run: make V=1 test-ci
- name: 'test'
+ name: 'run tests'
env:
TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.gitignore b/.gitignore
index 973e868..7ac6cc2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
@@ -64,3 +64,5 @@
curl_fuzzer_seed_corpus.zip
libstandaloneengine.a
tests/string
+tests/config
+
diff --git a/.lgtm.yml b/.lgtm.yml
deleted file mode 100644
index b428410..0000000
--- a/.lgtm.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-extraction:
- cpp:
- prepare:
- packages: # to avoid confusion with libopenafs-dev which also provides a des.h
- - libssl-dev
- after_prepare: # make sure lgtm.com doesn't use CMake (which generates and runs tests)
- - rm -f CMakeLists.txt
- - autoreconf -fi
- configure: # enable as many optional features as possible
- command: ./configure --enable-ares --with-libssh2 --with-gssapi --with-librtmp --with-openssl
diff --git a/.lift/config.toml b/.lift/config.toml
index 66bcb5e..a57f3ba 100644
--- a/.lift/config.toml
+++ b/.lift/config.toml
@@ -1,7 +1,8 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
-ignoreRules = [ "DEAD_STORE" ]
+ignoreRules = [ "DEAD_STORE", "subprocess_without_shell_equals_true" ]
+ignoreFiles = [ "tests/http/**" ]
build = "make"
setup = ".lift/setup.sh"
diff --git a/.lift/setup.sh b/.lift/setup.sh
index 226d585..aa6ff4f 100755
--- a/.lift/setup.sh
+++ b/.lift/setup.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
autoreconf -fi
diff --git a/.mailmap b/.mailmap
index 54dd31a..55ba214 100644
--- a/.mailmap
+++ b/.mailmap
@@ -48,7 +48,8 @@
Daniel Jelinski <daniel.jelinski@thomsonreuters.com> <30433125+djelinski@users.noreply.github.com>
Amit Katyal <amkatyal@cisco.com>
Giorgos Oikonomou <giorgos.n.oikonomou@gmail.com>
-Evgeny Grin <k2k@narod.ru>
+Evgeny Grin (Karlson2k) <k2k@narod.ru> <k2k@yandex.ru>
+Evgeny Grin (Karlson2k) <k2k@narod.ru>
Peter Pih <railsnewbie257@gmail.com>
Anton Malov <malov.anton@gmail.com>
Marquis de Muesli <marquis.de.muesli@gmail.com>
@@ -90,3 +91,17 @@
Henrik Holst <henrik.holst@millistream.com>
Christian Schmitz <support@monkeybreadsoftware.de>
Max Mehl <max.mehl@fsfe.org>
+rzrymiak on github <106121613+rzrymiak@users.noreply.github.com>
+Oliver Roberts <oliver@futaura.co.uk>
+opensignature on github <antonio@piumarossa.it>
+Cering on github <gfypm@qq.com>
+a1346054 on github <36859588+a1346054@users.noreply.github.com>
+zhanghu on xiaomi <zhanghu6@xiaomi.com>
+Philip Heiduck <pheiduck@Philips-MBP.lan> <47042125+pheiduck@users.noreply.github.com>
+bsergean on github <bsergean@gmail.com>
+Stefan Eissing <stefan@eissing.org> <stefan.eissing@greenbytes.de>
+Michael Musset <mickamusset@gmail.com>
+Andy Alt <arch_stanton5995@protonmail.com>
+Thomas1664 on github <46387399+Thomas1664@users.noreply.github.com>
+dengjfzh on github <dengjfzh@gmail.com>
+Brad Harder <brad.harder@gmail.com>
diff --git a/.reuse/dep5 b/.reuse/dep5
index c73508d..0766738 100644
--- a/.reuse/dep5
+++ b/.reuse/dep5
@@ -5,102 +5,90 @@
# Tests
Files: tests/data/test* tests/certs/* tests/stunnel.pem tests/valgrind.supp
-Copyright: 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
# Markdown documentation in docs/
Files: docs/*.md
-Copyright: 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
# Docs in docs/
Files: docs/FAQ docs/INSTALL docs/INSTALL.cmake docs/KNOWN_BUGS docs/MAIL-ETIQUETTE docs/THANKS docs/TODO docs/cmdline-opts/page-footer docs/libcurl/curl_multi_socket_all.3 docs/libcurl/curl_strnequal.3 docs/libcurl/symbols-in-versions docs/options-in-versions
-Copyright: 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
# Windows
Files: projects/Windows/*
-Copyright: 2014 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
# Single files we do not want to edit directly
Files: CHANGES
-Copyright: 2019 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: GIT-INFO
-Copyright: 2010 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: RELEASE-NOTES
-Copyright: 2003 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
# checksrc control files
Files: lib/.checksrc docs/examples/.checksrc tests/libtest/.checksrc
-Copyright: 2021 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: lib/libcurl.plist.in
-Copyright: 2022 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: lib/libcurl.vers.in
-Copyright: 2011 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
-License: curl
-
-Files: mlc_config.json
-Copyright: 2022 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
-License: curl
-
-Files: packages/DOS/README
-Copyright: 2003 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: packages/OS400/README.OS400
-Copyright: 2007 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
-License: curl
-
-Files: packages/README
-Copyright: 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: packages/vms/build_vms.com
-Copyright: 2004 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: packages/vms/curl_release_note_start.txt
-Copyright: 2013 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: packages/vms/curlmsg.sdl
-Copyright: 2004 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: packages/vms/macro32_exactcase.patch
-Copyright: 2013 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: packages/vms/readme
-Copyright: 2004 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: plan9/README
-Copyright: 2020 - 2020 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: projects/wolfssl_override.props
-Copyright: 2015 - 2018 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: README
-Copyright: 1999 - 2021 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: .github/ISSUE_TEMPLATE/bug_report.md
-Copyright: 2020 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
Files: .mailmap
-Copyright: 2017 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
diff --git a/CMake/CMakeConfigurableFile.in b/CMake/CMakeConfigurableFile.in
index b93e753..a3d2bc4 100644
--- a/CMake/CMakeConfigurableFile.in
+++ b/CMake/CMakeConfigurableFile.in
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/CurlSymbolHiding.cmake b/CMake/CurlSymbolHiding.cmake
index 75215a1..142e919 100644
--- a/CMake/CurlSymbolHiding.cmake
+++ b/CMake/CurlSymbolHiding.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/CurlTests.c b/CMake/CurlTests.c
index cf76fb7..3dbba3c 100644
--- a/CMake/CurlTests.c
+++ b/CMake/CurlTests.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -184,28 +184,6 @@
#include <float.h>
int main() { return 0; }
#endif
-#ifdef HAVE_GETADDRINFO
-#include <netdb.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-int main(void) {
- struct addrinfo hints, *ai;
- int error;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
-#ifndef getaddrinfo
- (void)getaddrinfo;
-#endif
- error = getaddrinfo("127.0.0.1", "8080", &hints, &ai);
- if (error) {
- return 1;
- }
- return 0;
-}
-#endif
#ifdef HAVE_FILE_OFFSET_BITS
#ifdef _FILE_OFFSET_BITS
#undef _FILE_OFFSET_BITS
@@ -516,3 +494,39 @@
return 0;
}
#endif
+#ifdef HAVE_ATOMIC
+/* includes start */
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_STDATOMIC_H
+# include <stdatomic.h>
+#endif
+/* includes end */
+
+int
+main() {
+ _Atomic int i = 1;
+ i = 0; // Force an atomic-write operation.
+ return i;
+}
+#endif
+#ifdef HAVE_WIN32_WINNT
+/* includes start */
+#ifdef WIN32
+# include "../lib/setup-win32.h"
+#endif
+/* includes end */
+
+#define enquote(x) #x
+#define expand(x) enquote(x)
+#pragma message("_WIN32_WINNT=" expand(_WIN32_WINNT))
+
+int
+main() {
+ return 0;
+}
+#endif
diff --git a/CMake/FindBearSSL.cmake b/CMake/FindBearSSL.cmake
index 88d5e87..56a064e 100644
--- a/CMake/FindBearSSL.cmake
+++ b/CMake/FindBearSSL.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/FindBrotli.cmake b/CMake/FindBrotli.cmake
index 833e181..11ab7f8 100644
--- a/CMake/FindBrotli.cmake
+++ b/CMake/FindBrotli.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -28,7 +28,7 @@
find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon)
find_library(BROTLIDEC_LIBRARY NAMES brotlidec)
-find_package_handle_standard_args(BROTLI
+find_package_handle_standard_args(Brotli
FOUND_VAR
BROTLI_FOUND
REQUIRED_VARS
@@ -36,7 +36,7 @@
BROTLICOMMON_LIBRARY
BROTLI_INCLUDE_DIR
FAIL_MESSAGE
- "Could NOT find BROTLI"
+ "Could NOT find Brotli"
)
set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR})
diff --git a/CMake/FindCARES.cmake b/CMake/FindCARES.cmake
index 99cf31d..fa75891 100644
--- a/CMake/FindCARES.cmake
+++ b/CMake/FindCARES.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/FindGSS.cmake b/CMake/FindGSS.cmake
index ec2bd57..b244e61 100644
--- a/CMake/FindGSS.cmake
+++ b/CMake/FindGSS.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -181,14 +181,14 @@
set(GSS_FLAVOUR "MIT")
else()
# prevent compiling the header - just check if we can include it
- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__")
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -D__ROKEN_H__)
check_include_file( "roken.h" _GSS_HAVE_ROKEN_H)
check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H)
if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H)
set(GSS_FLAVOUR "Heimdal")
endif()
- set(CMAKE_REQUIRED_DEFINITIONS "")
+ list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D__ROKEN_H__)
endif()
else()
# I'm not convinced if this is the right way but this is what autotools do at the moment
diff --git a/CMake/FindLibPSL.cmake b/CMake/FindLibPSL.cmake
index 66abdd7..e3bd68d 100644
--- a/CMake/FindLibPSL.cmake
+++ b/CMake/FindLibPSL.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/FindLibSSH2.cmake b/CMake/FindLibSSH2.cmake
index 0ec7f7e..a0c251a 100644
--- a/CMake/FindLibSSH2.cmake
+++ b/CMake/FindLibSSH2.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/FindMSH3.cmake b/CMake/FindMSH3.cmake
index 96477e2..7d9c6b6 100644
--- a/CMake/FindMSH3.cmake
+++ b/CMake/FindMSH3.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/FindMbedTLS.cmake b/CMake/FindMbedTLS.cmake
index fcd6717..814bd97 100644
--- a/CMake/FindMbedTLS.cmake
+++ b/CMake/FindMbedTLS.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/FindNGHTTP2.cmake b/CMake/FindNGHTTP2.cmake
index 6d70c4a..3957646 100644
--- a/CMake/FindNGHTTP2.cmake
+++ b/CMake/FindNGHTTP2.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/FindNGHTTP3.cmake b/CMake/FindNGHTTP3.cmake
index 8d8ebc1..9b13e6c 100644
--- a/CMake/FindNGHTTP3.cmake
+++ b/CMake/FindNGHTTP3.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/FindNGTCP2.cmake b/CMake/FindNGTCP2.cmake
index 37b060e..ae92e41 100644
--- a/CMake/FindNGTCP2.cmake
+++ b/CMake/FindNGTCP2.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
This module accepts optional COMPONENTS to control the crypto library (these are
mutually exclusive)::
- OpenSSL: Use libngtcp2_crypto_openssl
+ OpenSSL: Use libngtcp2_crypto_quictls
GnuTLS: Use libngtcp2_crypto_gnutls
Result Variables
@@ -71,7 +71,7 @@
if(NGTCP2_FIND_COMPONENTS)
set(NGTCP2_CRYPTO_BACKEND "")
foreach(component IN LISTS NGTCP2_FIND_COMPONENTS)
- if(component MATCHES "^(OpenSSL|GnuTLS)")
+ if(component MATCHES "^(BoringSSL|quictls|wolfSSL|GnuTLS)")
if(NGTCP2_CRYPTO_BACKEND)
message(FATAL_ERROR "NGTCP2: Only one crypto library can be selected")
endif()
diff --git a/CMake/FindNSS.cmake b/CMake/FindNSS.cmake
index 6742dda..ccddf42 100644
--- a/CMake/FindNSS.cmake
+++ b/CMake/FindNSS.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/FindQUICHE.cmake b/CMake/FindQUICHE.cmake
index fc47027..0488463 100644
--- a/CMake/FindQUICHE.cmake
+++ b/CMake/FindQUICHE.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/FindWolfSSL.cmake b/CMake/FindWolfSSL.cmake
index 986f01e..d67c0eb 100644
--- a/CMake/FindWolfSSL.cmake
+++ b/CMake/FindWolfSSL.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/FindZstd.cmake b/CMake/FindZstd.cmake
index 2d65404..973e6ad 100644
--- a/CMake/FindZstd.cmake
+++ b/CMake/FindZstd.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/Macros.cmake b/CMake/Macros.cmake
index 4d7380e..e12bf30 100644
--- a/CMake/Macros.cmake
+++ b/CMake/Macros.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/OtherTests.cmake b/CMake/OtherTests.cmake
index 9f62c9d..fa1e458 100644
--- a/CMake/OtherTests.cmake
+++ b/CMake/OtherTests.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -48,158 +48,6 @@
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
-function(curl_cv_func_recv_run_test recv_retv recv_arg1 recv_arg2 recv_arg3 recv_arg4)
- unset(curl_cv_func_recv_test CACHE)
- check_c_source_compiles("
- ${_source_epilogue}
- #ifdef WINSOCK_API_LINKAGE
- WINSOCK_API_LINKAGE
- #endif
- extern ${recv_retv} ${signature_call_conv}
- recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4});
- int main(void) {
- ${recv_arg1} s=0;
- ${recv_arg2} buf=0;
- ${recv_arg3} len=0;
- ${recv_arg4} flags=0;
- ${recv_retv} res = recv(s, buf, len, flags);
- (void) res;
- return 0;
- }"
- curl_cv_func_recv_test)
- message(STATUS
- "Tested: ${recv_retv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})")
- if(curl_cv_func_recv_test)
- set(curl_cv_func_recv_args
- "${recv_arg1},${recv_arg2},${recv_arg3},${recv_arg4},${recv_retv}" PARENT_SCOPE)
- set(RECV_TYPE_ARG1 "${recv_arg1}" PARENT_SCOPE)
- set(RECV_TYPE_ARG2 "${recv_arg2}" PARENT_SCOPE)
- set(RECV_TYPE_ARG3 "${recv_arg3}" PARENT_SCOPE)
- set(RECV_TYPE_ARG4 "${recv_arg4}" PARENT_SCOPE)
- set(RECV_TYPE_RETV "${recv_retv}" PARENT_SCOPE)
- set(HAVE_RECV 1 PARENT_SCOPE)
- set(curl_cv_func_recv_done 1 PARENT_SCOPE)
- endif()
-endfunction()
-
-check_c_source_compiles("${_source_epilogue}
-int main(void) {
- recv(0, 0, 0, 0);
- return 0;
-}" curl_cv_recv)
-if(curl_cv_recv)
- if(NOT DEFINED curl_cv_func_recv_args OR curl_cv_func_recv_args STREQUAL "unknown")
- if(APPLE)
- curl_cv_func_recv_run_test("ssize_t" "int" "void *" "size_t" "int")
- endif()
- foreach(recv_retv "int" "ssize_t" )
- foreach(recv_arg1 "SOCKET" "int" )
- foreach(recv_arg2 "char *" "void *" )
- foreach(recv_arg3 "int" "size_t" "socklen_t" "unsigned int")
- foreach(recv_arg4 "int" "unsigned int")
- if(NOT curl_cv_func_recv_done)
- curl_cv_func_recv_run_test(${recv_retv} ${recv_arg1} ${recv_arg2} ${recv_arg3} ${recv_arg4})
- endif()
- endforeach()
- endforeach()
- endforeach()
- endforeach()
- endforeach()
- else()
- string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG1 "${curl_cv_func_recv_args}")
- string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG2 "${curl_cv_func_recv_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG3 "${curl_cv_func_recv_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" RECV_TYPE_ARG4 "${curl_cv_func_recv_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" RECV_TYPE_RETV "${curl_cv_func_recv_args}")
- endif()
-
- if(curl_cv_func_recv_args STREQUAL "unknown")
- message(FATAL_ERROR "Cannot find proper types to use for recv args")
- endif()
-else()
- message(FATAL_ERROR "Unable to link function recv")
-endif()
-set(curl_cv_func_recv_args "${curl_cv_func_recv_args}" CACHE INTERNAL "Arguments for recv")
-set(HAVE_RECV 1)
-
-function(curl_cv_func_send_run_test send_retv send_arg1 send_arg2 send_arg3 send_arg4)
- unset(curl_cv_func_send_test CACHE)
- check_c_source_compiles("
- ${_source_epilogue}
- #ifdef WINSOCK_API_LINKAGE
- WINSOCK_API_LINKAGE
- #endif
- extern ${send_retv} ${signature_call_conv}
- send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4});
- int main(void) {
- ${send_arg1} s=0;
- ${send_arg2} buf=0;
- ${send_arg3} len=0;
- ${send_arg4} flags=0;
- ${send_retv} res = send(s, buf, len, flags);
- (void) res;
- return 0;
- }"
- curl_cv_func_send_test)
- message(STATUS
- "Tested: ${send_retv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})")
- if(curl_cv_func_send_test)
- string(REGEX REPLACE "(const) .*" "\\1" send_qual_arg2 "${send_arg2}")
- string(REGEX REPLACE "const (.*)" "\\1" send_arg2 "${send_arg2}")
- set(curl_cv_func_send_args
- "${send_arg1},${send_arg2},${send_arg3},${send_arg4},${send_retv},${send_qual_arg2}" PARENT_SCOPE)
- set(SEND_TYPE_ARG1 "${send_arg1}" PARENT_SCOPE)
- set(SEND_TYPE_ARG2 "${send_arg2}" PARENT_SCOPE)
- set(SEND_TYPE_ARG3 "${send_arg3}" PARENT_SCOPE)
- set(SEND_TYPE_ARG4 "${send_arg4}" PARENT_SCOPE)
- set(SEND_TYPE_RETV "${send_retv}" PARENT_SCOPE)
- set(HAVE_SEND 1 PARENT_SCOPE)
- set(curl_cv_func_send_done 1 PARENT_SCOPE)
- endif()
-endfunction()
-
-check_c_source_compiles("${_source_epilogue}
-int main(void) {
- send(0, 0, 0, 0);
- return 0;
-}" curl_cv_send)
-if(curl_cv_send)
- if(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown")
- if(APPLE)
- curl_cv_func_send_run_test("ssize_t" "int" "const void *" "size_t" "int")
- endif()
- foreach(send_retv "int" "ssize_t" )
- foreach(send_arg1 "SOCKET" "int" "ssize_t" )
- foreach(send_arg2 "const char *" "const void *" "void *" "char *")
- foreach(send_arg3 "int" "size_t" "socklen_t" "unsigned int")
- foreach(send_arg4 "int" "unsigned int")
- if(NOT curl_cv_func_send_done)
- curl_cv_func_send_run_test("${send_retv}" "${send_arg1}" "${send_arg2}" "${send_arg3}" "${send_arg4}")
- endif()
- endforeach()
- endforeach()
- endforeach()
- endforeach()
- endforeach()
- else()
- string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG1 "${curl_cv_func_send_args}")
- string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG2 "${curl_cv_func_send_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG3 "${curl_cv_func_send_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG4 "${curl_cv_func_send_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" SEND_TYPE_RETV "${curl_cv_func_send_args}")
- string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" SEND_QUAL_ARG2 "${curl_cv_func_send_args}")
- endif()
-
- if("${curl_cv_func_send_args}" STREQUAL "unknown")
- message(FATAL_ERROR "Cannot find proper types to use for send args")
- endif()
- set(SEND_QUAL_ARG2 "const")
-else()
- message(FATAL_ERROR "Unable to link function send")
-endif()
-set(curl_cv_func_send_args "${curl_cv_func_send_args}" CACHE INTERNAL "Arguments for send")
-set(HAVE_SEND 1)
-
check_c_source_compiles("${_source_epilogue}
int main(void) {
int flag = MSG_NOSIGNAL;
@@ -237,51 +85,51 @@
unset(CMAKE_TRY_COMPILE_TARGET_TYPE)
-if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
+if(NOT CMAKE_CROSSCOMPILING)
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "iOS")
- # only try this on non-apple platforms
+ # only try this on non-apple platforms
- # if not cross-compilation...
- include(CheckCSourceRuns)
- set(CMAKE_REQUIRED_FLAGS "")
- if(HAVE_SYS_POLL_H)
- set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
- elseif(HAVE_POLL_H)
- set(CMAKE_REQUIRED_FLAGS "-DHAVE_POLL_H")
- endif()
- check_c_source_runs("
- #include <stdlib.h>
- #include <sys/time.h>
+ # if not cross-compilation...
+ include(CheckCSourceRuns)
+ set(CMAKE_REQUIRED_FLAGS "")
+ if(HAVE_SYS_POLL_H)
+ set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
+ elseif(HAVE_POLL_H)
+ set(CMAKE_REQUIRED_FLAGS "-DHAVE_POLL_H")
+ endif()
+ check_c_source_runs("
+ #include <stdlib.h>
+ #include <sys/time.h>
- #ifdef HAVE_SYS_POLL_H
- # include <sys/poll.h>
- #elif HAVE_POLL_H
- # include <poll.h>
- #endif
+ #ifdef HAVE_SYS_POLL_H
+ # include <sys/poll.h>
+ #elif HAVE_POLL_H
+ # include <poll.h>
+ #endif
- int main(void)
- {
- if(0 != poll(0, 0, 10)) {
- return 1; /* fail */
- }
- else {
- /* detect the 10.12 poll() breakage */
- struct timeval before, after;
- int rc;
- size_t us;
-
- gettimeofday(&before, NULL);
- rc = poll(NULL, 0, 500);
- gettimeofday(&after, NULL);
-
- us = (after.tv_sec - before.tv_sec) * 1000000 +
- (after.tv_usec - before.tv_usec);
-
- if(us < 400000) {
- return 1;
+ int main(void)
+ {
+ if(0 != poll(0, 0, 10)) {
+ return 1; /* fail */
}
- }
- return 0;
+ else {
+ /* detect the 10.12 poll() breakage */
+ struct timeval before, after;
+ int rc;
+ size_t us;
+
+ gettimeofday(&before, NULL);
+ rc = poll(NULL, 0, 500);
+ gettimeofday(&after, NULL);
+
+ us = (after.tv_sec - before.tv_sec) * 1000000 +
+ (after.tv_usec - before.tv_usec);
+
+ if(us < 400000) {
+ return 1;
+ }
+ }
+ return 0;
}" HAVE_POLL_FINE)
endif()
endif()
diff --git a/CMake/PickyWarnings.cmake b/CMake/PickyWarnings.cmake
new file mode 100644
index 0000000..1310cb4
--- /dev/null
+++ b/CMake/PickyWarnings.cmake
@@ -0,0 +1,197 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the 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(CheckCCompilerFlag)
+
+if(PICKY_COMPILER)
+ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+
+ # https://clang.llvm.org/docs/DiagnosticsReference.html
+ # https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
+
+ # WPICKY_ENABLE = Options we want to enable as-is.
+ # WPICKY_DETECT = Options we want to test first and enable if available.
+
+ # Prefer the -Wextra alias with clang.
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ set(WPICKY_ENABLE "-Wextra")
+ else()
+ set(WPICKY_ENABLE "-W")
+ endif()
+
+ list(APPEND WPICKY_ENABLE
+ -Wall -pedantic
+ )
+
+ # ----------------------------------
+ # Add new options here, if in doubt:
+ # ----------------------------------
+ set(WPICKY_DETECT
+ )
+
+ # Assume these options always exist with both clang and gcc.
+ # Require clang 3.0 / gcc 2.95 or later.
+ list(APPEND WPICKY_ENABLE
+ -Wbad-function-cast # clang 3.0 gcc 2.95
+ -Wconversion # clang 3.0 gcc 2.95
+ -Winline # clang 1.0 gcc 1.0
+ -Wmissing-declarations # clang 1.0 gcc 2.7
+ -Wmissing-prototypes # clang 1.0 gcc 1.0
+ -Wnested-externs # clang 1.0 gcc 2.7
+ -Wno-long-long # clang 1.0 gcc 2.95
+ -Wno-multichar # clang 1.0 gcc 2.95
+ -Wpointer-arith # clang 1.0 gcc 1.4
+ -Wshadow # clang 1.0 gcc 2.95
+ -Wsign-compare # clang 1.0 gcc 2.95
+ -Wundef # clang 1.0 gcc 2.95
+ -Wunused # clang 1.1 gcc 2.95
+ -Wwrite-strings # clang 1.0 gcc 1.4
+ )
+
+ # Always enable with clang, version dependent with gcc
+ set(WPICKY_COMMON_OLD
+ -Wcast-align # clang 1.0 gcc 4.2
+ -Wdeclaration-after-statement # clang 1.0 gcc 3.4
+ -Wempty-body # clang 3.0 gcc 4.3
+ -Wendif-labels # clang 1.0 gcc 3.3
+ -Wfloat-equal # clang 1.0 gcc 2.96 (3.0)
+ -Wignored-qualifiers # clang 3.0 gcc 4.3
+ -Wno-format-nonliteral # clang 1.0 gcc 2.96 (3.0)
+ -Wno-sign-conversion # clang 3.0 gcc 4.3
+ -Wno-system-headers # clang 1.0 gcc 3.0
+ -Wstrict-prototypes # clang 1.0 gcc 3.3
+ -Wtype-limits # clang 3.0 gcc 4.3
+ -Wvla # clang 2.8 gcc 4.3
+ )
+
+ set(WPICKY_COMMON
+ -Wdouble-promotion # clang 3.6 gcc 4.6 appleclang 6.3
+ -Wenum-conversion # clang 3.2 gcc 10.0 appleclang 4.6 g++ 11.0
+ -Wunused-const-variable # clang 3.4 gcc 6.0 appleclang 5.1
+ )
+
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ list(APPEND WPICKY_ENABLE
+ ${WPICKY_COMMON_OLD}
+ -Wshift-sign-overflow # clang 2.9
+ -Wshorten-64-to-32 # clang 1.0
+ )
+ # Enable based on compiler version
+ if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6) OR
+ (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.3))
+ list(APPEND WPICKY_ENABLE
+ ${WPICKY_COMMON}
+ )
+ endif()
+ if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.9) OR
+ (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.3))
+ list(APPEND WPICKY_ENABLE
+ -Wcomma # clang 3.9 appleclang 8.3
+ -Wmissing-variable-declarations # clang 3.2 appleclang 4.6
+ )
+ endif()
+ if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 7.0) OR
+ (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.3))
+ list(APPEND WPICKY_ENABLE
+ -Wassign-enum # clang 7.0 appleclang 10.3
+ -Wextra-semi-stmt # clang 7.0 appleclang 10.3
+ )
+ endif()
+ else() # gcc
+ list(APPEND WPICKY_DETECT
+ ${WPICKY_COMMON}
+ )
+ # Enable based on compiler version
+ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.3)
+ list(APPEND WPICKY_ENABLE
+ ${WPICKY_COMMON_OLD}
+ -Wmissing-parameter-type # gcc 4.3
+ -Wold-style-declaration # gcc 4.3
+ -Wstrict-aliasing=3 # gcc 4.0
+ )
+ endif()
+ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5 AND MINGW)
+ list(APPEND WPICKY_ENABLE
+ -Wno-pedantic-ms-format # gcc 4.5 (mingw-only)
+ )
+ endif()
+ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.8)
+ list(APPEND WPICKY_ENABLE
+ -Wformat=2 # clang 3.0 gcc 4.8 (clang part-default, enabling it fully causes -Wformat-nonliteral warnings)
+ )
+ endif()
+ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0)
+ list(APPEND WPICKY_ENABLE
+ -Warray-bounds=2 -ftree-vrp # clang 3.0 gcc 5.0 (clang default: -Warray-bounds)
+ )
+ endif()
+ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.0)
+ list(APPEND WPICKY_ENABLE
+ -Wduplicated-cond # gcc 6.0
+ -Wnull-dereference # clang 3.0 gcc 6.0 (clang default)
+ -fdelete-null-pointer-checks
+ -Wshift-negative-value # clang 3.7 gcc 6.0 (clang default)
+ -Wshift-overflow=2 # clang 3.0 gcc 6.0 (clang default: -Wshift-overflow)
+ )
+ endif()
+ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 7.0)
+ list(APPEND WPICKY_ENABLE
+ -Walloc-zero # gcc 7.0
+ -Wduplicated-branches # gcc 7.0
+ -Wformat-overflow=2 # gcc 7.0
+ -Wformat-truncation=1 # gcc 7.0
+ -Wrestrict # gcc 7.0
+ )
+ endif()
+ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.0)
+ list(APPEND WPICKY_ENABLE
+ -Warith-conversion # gcc 10.0
+ )
+ endif()
+ endif()
+
+ #
+
+ unset(WPICKY)
+
+ foreach(_CCOPT ${WPICKY_ENABLE})
+ set(WPICKY "${WPICKY} ${_CCOPT}")
+ endforeach()
+
+ foreach(_CCOPT ${WPICKY_DETECT})
+ # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
+ # test result in.
+ string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
+ # GCC only warns about unknown -Wno- options if there are also other diagnostic messages,
+ # so test for the positive form instead
+ string(REPLACE "-Wno-" "-W" _CCOPT_ON "${_CCOPT}")
+ check_c_compiler_flag(${_CCOPT_ON} ${_optvarname})
+ if(${_optvarname})
+ set(WPICKY "${WPICKY} ${_CCOPT}")
+ endif()
+ endforeach()
+
+ message(STATUS "Picky compiler options:${WPICKY}")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WPICKY}")
+ endif()
+endif()
diff --git a/CMake/Platforms/WindowsCache.cmake b/CMake/Platforms/WindowsCache.cmake
index 6043e72..3771237 100644
--- a/CMake/Platforms/WindowsCache.cmake
+++ b/CMake/Platforms/WindowsCache.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,34 +23,19 @@
###########################################################################
if(NOT UNIX)
if(WIN32)
- set(HAVE_LIBDL 0)
- set(HAVE_LIBUCB 0)
set(HAVE_LIBSOCKET 0)
- set(NOT_NEED_LIBNSL 0)
- set(HAVE_LIBNSL 0)
set(HAVE_GETHOSTNAME 1)
set(HAVE_LIBZ 0)
- set(HAVE_DLOPEN 0)
-
- set(HAVE_ALLOCA_H 0)
set(HAVE_ARPA_INET_H 0)
- set(HAVE_DLFCN_H 0)
set(HAVE_FCNTL_H 1)
- set(HAVE_INTTYPES_H 0)
set(HAVE_IO_H 1)
- set(HAVE_MALLOC_H 1)
- set(HAVE_MEMORY_H 1)
set(HAVE_NETDB_H 0)
- set(HAVE_NETINET_IF_ETHER_H 0)
set(HAVE_NETINET_IN_H 0)
set(HAVE_NET_IF_H 0)
- set(HAVE_PROCESS_H 1)
set(HAVE_PWD_H 0)
set(HAVE_SETJMP_H 1)
set(HAVE_SIGNAL_H 1)
- set(HAVE_SOCKIO_H 0)
- set(HAVE_STDINT_H 0)
set(HAVE_STDLIB_H 1)
set(HAVE_STRINGS_H 0)
set(HAVE_STRING_H 1)
@@ -66,43 +51,25 @@
set(HAVE_TERMIOS_H 0)
set(HAVE_TERMIO_H 0)
set(HAVE_TIME_H 1)
- set(HAVE_UNISTD_H 0)
set(HAVE_UTIME_H 0)
- set(HAVE_X509_H 0)
- set(HAVE_ZLIB_H 0)
-
- set(HAVE_SIZEOF_LONG_DOUBLE 1)
- set(SIZEOF_LONG_DOUBLE 8)
set(HAVE_SOCKET 1)
- set(HAVE_POLL 0)
set(HAVE_SELECT 1)
set(HAVE_STRDUP 1)
- set(HAVE_STRSTR 1)
- set(HAVE_STRTOK_R 0)
- set(HAVE_STRFTIME 1)
- set(HAVE_UNAME 0)
- set(HAVE_STRCASECMP 0)
set(HAVE_STRICMP 1)
set(HAVE_STRCMPI 1)
set(HAVE_GETTIMEOFDAY 0)
- set(HAVE_INET_ADDR 1)
set(HAVE_CLOSESOCKET 1)
- set(HAVE_SETVBUF 0)
set(HAVE_SIGSETJMP 0)
+ set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1)
set(HAVE_GETPASS_R 0)
- set(HAVE_STRLCAT 0)
set(HAVE_GETPWUID 0)
set(HAVE_GETEUID 0)
set(HAVE_UTIME 1)
set(HAVE_RAND_EGD 0)
- set(HAVE_RAND_SCREEN 0)
- set(HAVE_RAND_STATUS 0)
set(HAVE_GMTIME_R 0)
- set(HAVE_LOCALTIME_R 0)
set(HAVE_GETHOSTBYNAME_R 0)
- set(HAVE_SIGNAL_FUNC 1)
- set(HAVE_SIGNAL_MACRO 0)
+ set(HAVE_SIGNAL 1)
set(HAVE_GETHOSTBYNAME_R_3 0)
set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
@@ -114,11 +81,6 @@
set(TIME_WITH_SYS_TIME 0)
set(HAVE_O_NONBLOCK 0)
set(HAVE_IN_ADDR_T 0)
- if(ENABLE_IPV6)
- set(HAVE_GETADDRINFO 1)
- else()
- set(HAVE_GETADDRINFO 0)
- endif()
set(STDC_HEADERS 1)
set(HAVE_SIGACTION 0)
diff --git a/CMake/Utilities.cmake b/CMake/Utilities.cmake
index 78bfd6f..9ff38e3 100644
--- a/CMake/Utilities.cmake
+++ b/CMake/Utilities.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/cmake_uninstall.cmake.in b/CMake/cmake_uninstall.cmake.in
index 55801f5..47aec8d 100644
--- a/CMake/cmake_uninstall.cmake.in
+++ b/CMake/cmake_uninstall.cmake.in
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMake/curl-config.cmake.in b/CMake/curl-config.cmake.in
index 496a92d..dbe4ed2 100644
--- a/CMake/curl-config.cmake.in
+++ b/CMake/curl-config.cmake.in
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ad20777..7a4c36f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -39,7 +39,29 @@
# To check:
# (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my box while the plain configure script did not.
# (From Daniel Stenberg) The gcc command line use neither -g nor any -O options. As a developer, I also treasure our configure scripts's --enable-debug option that sets a long range of "picky" compiler options.
-cmake_minimum_required(VERSION 3.2...3.16 FATAL_ERROR)
+
+# Note: By default this CMake build script detects the version of some
+# dependencies using `check_symbol_exists`. Those checks do not work
+# in the case that both CURL and its dependency are included as
+# sub-projects in a larger build using `FetchContent`. To support
+# that case, additional variables may be defined by the parent
+# project, ideally in the "extra" find package redirect file:
+# https://cmake.org/cmake/help/latest/module/FetchContent.html#integrating-with-find-package
+#
+# The following variables are available:
+# HAVE_RAND_EGD: `RAND_egd` present in OpenSSL
+# HAVE_AWSLC: OpenSSL is AWS-LC
+# HAVE_BORINGSSL: OpenSSL is BoringSSL
+# HAVE_PK11_CREATEMANAGEDGENERICOBJECTL: `PK11_CreateManagedGenericObject` present in NSS
+# HAVE_SSL_CTX_SET_QUIC_METHOD: `SSL_CTX_set_quic_method` present in OpenSSL/wolfSSL
+# HAVE_QUICHE_CONN_SET_QLOG_FD: `quiche_conn_set_qlog_fd` present in QUICHE
+# HAVE_ZSTD_CREATEDSTREAM: `ZSTD_createDStream` present in Zstd
+#
+# For each of the above variables, if the variable is DEFINED (either
+# to ON or OFF), the symbol detection will be skipped. If the
+# variable is NOT DEFINED, the symbol detection will be performed.
+
+cmake_minimum_required(VERSION 3.7...3.16 FATAL_ERROR)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
include(Utilities)
@@ -67,10 +89,16 @@
# SET(PACKAGE_STRING "curl-")
# SET(PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.se/mail/")
set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
-set(OS "\"${CMAKE_SYSTEM_NAME}${CURL_OS_SUFFIX}\"")
+if(CMAKE_C_COMPILER_TARGET)
+ set(OS "\"${CMAKE_C_COMPILER_TARGET}\"")
+else()
+ set(OS "\"${CMAKE_SYSTEM_NAME}\"")
+endif()
include_directories(${CURL_SOURCE_DIR}/include)
+set(CMAKE_UNITY_BUILD_BATCH_SIZE 0)
+
option(CURL_WERROR "Turn compiler warnings into errors" OFF)
option(PICKY_COMPILER "Enable picky compiler options" ON)
option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
@@ -78,20 +106,12 @@
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
if(WIN32)
option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
- option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON)
option(ENABLE_UNICODE "Set to ON to use the Unicode version of the Windows API functions" OFF)
set(CURL_TARGET_WINDOWS_VERSION "" CACHE STRING "Minimum target Windows version as hex string")
if(CURL_TARGET_WINDOWS_VERSION)
add_definitions(-D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION})
- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}")
- elseif(ENABLE_INET_PTON)
- # _WIN32_WINNT_VISTA (0x0600)
- add_definitions(-D_WIN32_WINNT=0x0600)
- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=0x0600")
- else()
- # _WIN32_WINNT_WINXP (0x0501)
- add_definitions(-D_WIN32_WINNT=0x0501)
- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=0x0501")
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION})
+ set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}")
endif()
if(ENABLE_UNICODE)
add_definitions(-DUNICODE -D_UNICODE)
@@ -109,28 +129,7 @@
option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF)
option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF)
-if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
- if(PICKY_COMPILER)
- foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wfloat-equal -Wsign-compare -Wundef -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wvla -Wdouble-promotion -Wenum-conversion -Warith-conversion)
- # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
- # test result in.
- string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
- check_c_compiler_flag(${_CCOPT} ${_optvarname})
- if(${_optvarname})
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}")
- endif()
- endforeach()
- foreach(_CCOPT long-long multichar format-nonliteral sign-conversion system-headers pedantic-ms-format)
- # GCC only warns about unknown -Wno- options if there are also other diagnostic messages,
- # so test for the positive form instead
- string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
- check_c_compiler_flag("-W${_CCOPT}" ${_optvarname})
- if(${_optvarname})
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-${_CCOPT}")
- endif()
- endforeach()
- endif()
-endif()
+include(PickyWarnings)
if(ENABLE_DEBUG)
# DEBUGBUILD will be defined only for Debug builds
@@ -304,6 +303,11 @@
set(_ALL_SOURCE 1)
endif()
+# If we are on Haiku, make sure that the network library is brought in.
+if(${CMAKE_SYSTEM_NAME} MATCHES Haiku)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lnetwork")
+endif()
+
# Include all the necessary files for macros
include(CMakePushCheckState)
include(CheckFunctionExists)
@@ -316,7 +320,7 @@
# On windows preload settings
if(WIN32)
- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_=")
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_WINSOCKAPI_=)
include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
endif()
@@ -332,37 +336,26 @@
endif()
# Check for all needed libraries
-check_library_exists_concat("${CMAKE_DL_LIBS}" dlopen HAVE_LIBDL)
check_library_exists_concat("socket" connect HAVE_LIBSOCKET)
-check_library_exists("c" gethostbyname "" NOT_NEED_LIBNSL)
-
-if(NOT NOT_NEED_LIBNSL)
- check_library_exists_concat("nsl" gethostbyname HAVE_LIBNSL)
-endif()
check_function_exists(gethostname HAVE_GETHOSTNAME)
if(WIN32)
check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32)
check_library_exists_concat("winmm" getch HAVE_LIBWINMM)
-endif()
-# This check below for use of deprecated symbols is only temporary and is to
-# be removed again after a year's service. Remove after November 25, 2022.
-set(CURL_RECONFIG_REQUIRED 0)
-foreach(_LIB GSSAPI OPENLDAP LIBSSH LIBSSH2 BEARSSL MBEDTLS NSS OPENSSL
- SCHANNEL SECTRANSP WOLFSSL)
- if(CMAKE_USE_${_LIB})
- set(CURL_RECONFIG_REQUIRED 1)
- message(SEND_ERROR "The option CMAKE_USE_${_LIB} was renamed to CURL_USE_${_LIB}.")
+ # Matching logic used for Curl_win32_random()
+ if(MINGW)
+ check_c_source_compiles("
+ #include <_mingw.h>
+ #if defined(__MINGW64_VERSION_MAJOR)
+ #error
+ #endif
+ int main(void) {
+ return 0;
+ }"
+ HAVE_MINGW_ORIGINAL)
endif()
-endforeach()
-if(CMAKE_USE_WINSSL)
- set(CURL_RECONFIG_REQUIRED 1)
- message(SEND_ERROR "The option CMAKE_USE_WINSSL was renamed to CURL_USE_SCHANNEL.")
-endif()
-if(CURL_RECONFIG_REQUIRED)
- message(FATAL_ERROR "Reconfig required")
endif()
# check SSL libraries
@@ -374,7 +367,7 @@
endif()
if(WIN32)
cmake_dependent_option(CURL_USE_SCHANNEL "enable Windows native SSL/TLS" OFF CURL_ENABLE_SSL OFF)
- cmake_dependent_option(CURL_WINDOWS_SSPI "Use windows libraries to allow NTLM authentication without openssl" ON
+ cmake_dependent_option(CURL_WINDOWS_SSPI "Use windows libraries to allow NTLM authentication without OpenSSL" ON
CURL_USE_SCHANNEL OFF)
endif()
cmake_dependent_option(CURL_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
@@ -409,7 +402,6 @@
endif()
if(CURL_WINDOWS_SSPI)
set(USE_WINDOWS_SSPI ON)
- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DSECURITY_WIN32")
endif()
if(CURL_USE_SECTRANSP)
@@ -449,19 +441,23 @@
include_directories(${OPENSSL_INCLUDE_DIR})
endif()
- set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
- check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H)
- check_include_file("openssl/err.h" HAVE_OPENSSL_ERR_H)
- check_include_file("openssl/pem.h" HAVE_OPENSSL_PEM_H)
- check_include_file("openssl/rsa.h" HAVE_OPENSSL_RSA_H)
- check_include_file("openssl/ssl.h" HAVE_OPENSSL_SSL_H)
- check_include_file("openssl/x509.h" HAVE_OPENSSL_X509_H)
- check_include_file("openssl/rand.h" HAVE_OPENSSL_RAND_H)
- check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS)
- check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN)
- check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD)
+ if(WIN32)
+ list(APPEND CURL_LIBS "ws2_32")
+ if(NOT HAVE_MINGW_ORIGINAL)
+ list(APPEND CURL_LIBS "bcrypt") # for OpenSSL/LibreSSL
+ endif()
+ endif()
- add_definitions(-DOPENSSL_SUPPRESS_DEPRECATED)
+ set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
+ if(NOT DEFINED HAVE_RAND_EGD)
+ check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD)
+ endif()
+ if(NOT DEFINED HAVE_BORINGSSL)
+ check_symbol_exists(OPENSSL_IS_BORINGSSL "openssl/base.h" HAVE_BORINGSSL)
+ endif()
+ if(NOT DEFINED HAVE_AWSLC)
+ check_symbol_exists(OPENSSL_IS_AWSLC "openssl/base.h" HAVE_AWSLC)
+ endif()
endif()
if(CURL_USE_MBEDTLS)
@@ -494,11 +490,66 @@
list(APPEND CURL_LIBS ${NSS_LIBRARIES})
set(SSL_ENABLED ON)
set(USE_NSS ON)
- cmake_push_check_state()
- set(CMAKE_REQUIRED_INCLUDES ${NSS_INCLUDE_DIRS})
- set(CMAKE_REQUIRED_LIBRARIES ${NSS_LIBRARIES})
- check_symbol_exists(PK11_CreateManagedGenericObject "pk11pub.h" HAVE_PK11_CREATEMANAGEDGENERICOBJECT)
- cmake_pop_check_state()
+ if(NOT DEFINED HAVE_PK11_CREATEMANAGEDGENERICOBJECT)
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_INCLUDES ${NSS_INCLUDE_DIRS})
+ set(CMAKE_REQUIRED_LIBRARIES ${NSS_LIBRARIES})
+ check_symbol_exists(PK11_CreateManagedGenericObject "pk11pub.h" HAVE_PK11_CREATEMANAGEDGENERICOBJECT)
+ cmake_pop_check_state()
+ endif()
+endif()
+
+# Keep ZLIB detection after TLS detection,
+# and before calling CheckQuicSupportInOpenSSL.
+
+set(HAVE_LIBZ OFF)
+set(USE_ZLIB OFF)
+optional_dependency(ZLIB)
+if(ZLIB_FOUND)
+ set(HAVE_LIBZ ON)
+ set(USE_ZLIB ON)
+
+ # Depend on ZLIB via imported targets if supported by the running
+ # version of CMake. This allows our dependents to get our dependencies
+ # transitively.
+ if(NOT CMAKE_VERSION VERSION_LESS 3.4)
+ list(APPEND CURL_LIBS ZLIB::ZLIB)
+ else()
+ list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
+ include_directories(${ZLIB_INCLUDE_DIRS})
+ endif()
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
+endif()
+
+option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF)
+set(HAVE_BROTLI OFF)
+if(CURL_BROTLI)
+ find_package(Brotli REQUIRED)
+ if(BROTLI_FOUND)
+ set(HAVE_BROTLI ON)
+ set(CURL_LIBS "${BROTLI_LIBRARIES};${CURL_LIBS}") # For 'ld' linker. Emulate `list(PREPEND ...)` to stay compatible with <v3.15 CMake.
+ list(APPEND CURL_LIBS ${BROTLI_LIBRARIES})
+ include_directories(${BROTLI_INCLUDE_DIRS})
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${BROTLI_INCLUDE_DIRS})
+ endif()
+endif()
+
+option(CURL_ZSTD "Set to ON to enable building curl with zstd support." OFF)
+set(HAVE_ZSTD OFF)
+if(CURL_ZSTD)
+ find_package(Zstd REQUIRED)
+ if (NOT DEFINED HAVE_ZSTD_CREATEDSTREAM)
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_INCLUDES ${Zstd_INCLUDE_DIRS})
+ set(CMAKE_REQUIRED_LIBRARIES ${Zstd_LIBRARIES})
+ check_symbol_exists(ZSTD_createDStream "zstd.h" HAVE_ZSTD_CREATEDSTREAM)
+ cmake_pop_check_state()
+ endif()
+ if(Zstd_FOUND AND HAVE_ZSTD_CREATEDSTREAM)
+ set(HAVE_ZSTD ON)
+ list(APPEND CURL_LIBS ${Zstd_LIBRARIES})
+ include_directories(${Zstd_INCLUDE_DIRS})
+ endif()
endif()
option(USE_NGHTTP2 "Use Nghttp2 library" OFF)
@@ -509,27 +560,58 @@
endif()
function(CheckQuicSupportInOpenSSL)
- # Be sure that the OpenSSL library actually supports QUIC.
- cmake_push_check_state()
- set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}")
- set(CMAKE_REQUIRED_LIBRARIES "${OPENSSL_LIBRARIES}")
- check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
- if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD)
- message(FATAL_ERROR "QUIC support is missing in OpenSSL/boringssl. Try setting -DOPENSSL_ROOT_DIR")
+ # Be sure that the OpenSSL/wolfSSL library actually supports QUIC.
+ if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD)
+ cmake_push_check_state()
+ if(USE_WOLFSSL)
+ set(CMAKE_REQUIRED_INCLUDES "${WolfSSL_INCLUDE_DIRS}")
+ set(CMAKE_REQUIRED_LIBRARIES "${WolfSSL_LIBRARIES}")
+ if(HAVE_LIBZ)
+ list(APPEND CMAKE_REQUIRED_INCLUDES "${ZLIB_INCLUDE_DIRS}") # Public wolfSSL headers require zlib headers
+ list(APPEND CMAKE_REQUIRED_LIBRARIES "${ZLIB_LIBRARIES}")
+ endif()
+ if(WIN32)
+ list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32" "crypt32")
+ endif()
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_UINTPTR_T) # to pull in stdint.h (as of wolfSSL v5.5.4)
+ check_symbol_exists(wolfSSL_set_quic_method "wolfssl/options.h;wolfssl/openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
+ else()
+ set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}")
+ set(CMAKE_REQUIRED_LIBRARIES "${OPENSSL_LIBRARIES}")
+ if(HAVE_LIBZ)
+ list(APPEND CMAKE_REQUIRED_LIBRARIES "${ZLIB_LIBRARIES}")
+ endif()
+ if(WIN32)
+ list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32")
+ if(NOT HAVE_MINGW_ORIGINAL)
+ list(APPEND CMAKE_REQUIRED_LIBRARIES "bcrypt") # for OpenSSL/LibreSSL
+ endif()
+ endif()
+ check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
+ endif()
+ cmake_pop_check_state()
endif()
- cmake_pop_check_state()
+ if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD)
+ message(FATAL_ERROR "QUIC support is missing in OpenSSL/LibreSSL/BoringSSL/wolfSSL. Try setting -DOPENSSL_ROOT_DIR")
+ endif()
endfunction()
option(USE_NGTCP2 "Use ngtcp2 and nghttp3 libraries for HTTP/3 support" OFF)
if(USE_NGTCP2)
- if(USE_OPENSSL)
- find_package(NGTCP2 REQUIRED OpenSSL)
+ if(USE_OPENSSL OR USE_WOLFSSL)
+ if(USE_WOLFSSL)
+ find_package(NGTCP2 REQUIRED wolfSSL)
+ elseif(HAVE_BORINGSSL)
+ find_package(NGTCP2 REQUIRED BoringSSL)
+ else()
+ find_package(NGTCP2 REQUIRED quictls)
+ endif()
CheckQuicSupportInOpenSSL()
elseif(USE_GNUTLS)
# TODO add GnuTLS support as vtls library.
find_package(NGTCP2 REQUIRED GnuTLS)
else()
- message(FATAL_ERROR "ngtcp2 requires OpenSSL or GnuTLS")
+ message(FATAL_ERROR "ngtcp2 requires OpenSSL, wolfSSL or GnuTLS")
endif()
set(USE_NGTCP2 ON)
include_directories(${NGTCP2_INCLUDE_DIRS})
@@ -551,11 +633,13 @@
set(USE_QUICHE ON)
include_directories(${QUICHE_INCLUDE_DIRS})
list(APPEND CURL_LIBS ${QUICHE_LIBRARIES})
- cmake_push_check_state()
- set(CMAKE_REQUIRED_INCLUDES "${QUICHE_INCLUDE_DIRS}")
- set(CMAKE_REQUIRED_LIBRARIES "${QUICHE_LIBRARIES}")
- check_symbol_exists(quiche_conn_set_qlog_fd "quiche.h" HAVE_QUICHE_CONN_SET_QLOG_FD)
- cmake_pop_check_state()
+ if(NOT DEFINED HAVE_QUICHE_CONN_SET_QLOG_FD)
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_INCLUDES "${QUICHE_INCLUDE_DIRS}")
+ set(CMAKE_REQUIRED_LIBRARIES "${QUICHE_LIBRARIES}")
+ check_symbol_exists(quiche_conn_set_qlog_fd "quiche.h" HAVE_QUICHE_CONN_SET_QLOG_FD)
+ cmake_pop_check_state()
+ endif()
endif()
option(USE_MSH3 "Use msquic library for HTTP/3 support" OFF)
@@ -575,6 +659,8 @@
check_library_exists_concat("wldap32" cldap_open HAVE_WLDAP32)
if(NOT HAVE_WLDAP32)
set(USE_WIN32_LDAP OFF)
+ elseif(NOT CURL_DISABLE_LDAPS)
+ set(HAVE_LDAP_SSL ON)
endif()
endif()
endif()
@@ -589,10 +675,7 @@
endif()
# Now that we know, we're not using windows LDAP...
- if(USE_WIN32_LDAP)
- check_include_file_concat("winldap.h" HAVE_WINLDAP_H)
- check_include_file_concat("winber.h" HAVE_WINBER_H)
- else()
+ if(NOT USE_WIN32_LDAP)
# Check for LDAP
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
check_library_exists_concat(${CMAKE_LDAP_LIB} ldap_init HAVE_LIBLDAP)
@@ -647,7 +730,7 @@
return 0;
}"
)
- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DLDAP_DEPRECATED=1")
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -DLDAP_DEPRECATED=1)
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB})
if(HAVE_LIBLBER)
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB})
@@ -674,7 +757,6 @@
if(NOT CURL_DISABLE_LDAPS)
check_include_file_concat("ldap_ssl.h" HAVE_LDAP_SSL_H)
- check_include_file_concat("ldapssl.h" HAVE_LDAPSSL_H)
endif()
# Check for idn2
@@ -688,60 +770,7 @@
if(WIN32)
option(USE_WIN32_IDN "Use WinIDN for IDN support" OFF)
if(USE_WIN32_IDN)
- list(APPEND CURL_LIBS "Normaliz")
- set(WANT_IDN_PROTOTYPES ON)
- endif()
-endif()
-
-# Check for symbol dlopen (same as HAVE_LIBDL)
-check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
-
-set(HAVE_LIBZ OFF)
-set(HAVE_ZLIB_H OFF)
-set(USE_ZLIB OFF)
-optional_dependency(ZLIB)
-if(ZLIB_FOUND)
- set(HAVE_ZLIB_H ON)
- set(HAVE_LIBZ ON)
- set(USE_ZLIB ON)
-
- # Depend on ZLIB via imported targets if supported by the running
- # version of CMake. This allows our dependents to get our dependencies
- # transitively.
- if(NOT CMAKE_VERSION VERSION_LESS 3.4)
- list(APPEND CURL_LIBS ZLIB::ZLIB)
- else()
- list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
- include_directories(${ZLIB_INCLUDE_DIRS})
- endif()
- list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
-endif()
-
-option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF)
-set(HAVE_BROTLI OFF)
-if(CURL_BROTLI)
- find_package(Brotli QUIET)
- if(BROTLI_FOUND)
- set(HAVE_BROTLI ON)
- list(APPEND CURL_LIBS ${BROTLI_LIBRARIES})
- include_directories(${BROTLI_INCLUDE_DIRS})
- list(APPEND CMAKE_REQUIRED_INCLUDES ${BROTLI_INCLUDE_DIRS})
- endif()
-endif()
-
-option(CURL_ZSTD "Set to ON to enable building curl with zstd support." OFF)
-set(HAVE_ZSTD OFF)
-if(CURL_ZSTD)
- find_package(Zstd REQUIRED)
- cmake_push_check_state()
- set(CMAKE_REQUIRED_INCLUDES ${Zstd_INCLUDE_DIRS})
- set(CMAKE_REQUIRED_LIBRARIES ${Zstd_LIBRARIES})
- check_symbol_exists(ZSTD_createDStream "zstd.h" HAVE_ZSTD_CREATEDSTREAM)
- cmake_pop_check_state()
- if(Zstd_FOUND AND HAVE_ZSTD_CREATEDSTREAM)
- set(HAVE_ZSTD ON)
- list(APPEND CURL_LIBS ${Zstd_LIBRARIES})
- include_directories(${Zstd_INCLUDE_DIRS})
+ list(APPEND CURL_LIBS "normaliz")
endif()
endif()
@@ -749,24 +778,14 @@
option(CURL_USE_LIBPSL "Use libPSL" ON)
mark_as_advanced(CURL_USE_LIBPSL)
set(USE_LIBPSL OFF)
-set(HAVE_LIBPSL OFF)
-set(HAVE_LIBSPSL_H OFF)
if(CURL_USE_LIBPSL)
find_package(LibPSL)
if(LIBPSL_FOUND)
list(APPEND CURL_LIBS ${LIBPSL_LIBRARY})
- set(CMAKE_REQUIRED_LIBRARIES ${LIBPSL_LIBRARY})
list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBPSL_INCLUDE_DIR}")
include_directories("${LIBPSL_INCLUDE_DIR}")
- set(HAVE_LIBPSL ON)
set(USE_LIBPSL ON)
-
- # find_package has already found the headers
- set(HAVE_LIBPSL_H ON)
- set(CURL_INCLUDES ${CURL_INCLUDES} "${LIBPSL_INCLUDE_DIR}/libpsl.h")
- set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DHAVE_LIBPSL_H")
- unset(CMAKE_REQUIRED_LIBRARIES)
endif()
endif()
@@ -774,38 +793,27 @@
option(CURL_USE_LIBSSH2 "Use libSSH2" ON)
mark_as_advanced(CURL_USE_LIBSSH2)
set(USE_LIBSSH2 OFF)
-set(HAVE_LIBSSH2 OFF)
-set(HAVE_LIBSSH2_H OFF)
if(CURL_USE_LIBSSH2)
find_package(LibSSH2)
if(LIBSSH2_FOUND)
list(APPEND CURL_LIBS ${LIBSSH2_LIBRARY})
- set(CMAKE_REQUIRED_LIBRARIES ${LIBSSH2_LIBRARY})
list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBSSH2_INCLUDE_DIR}")
include_directories("${LIBSSH2_INCLUDE_DIR}")
- set(HAVE_LIBSSH2 ON)
set(USE_LIBSSH2 ON)
-
- # find_package has already found the headers
- set(HAVE_LIBSSH2_H ON)
- set(CURL_INCLUDES ${CURL_INCLUDES} "${LIBSSH2_INCLUDE_DIR}/libssh2.h")
- set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DHAVE_LIBSSH2_H")
- unset(CMAKE_REQUIRED_LIBRARIES)
endif()
endif()
# libssh
option(CURL_USE_LIBSSH "Use libSSH" OFF)
mark_as_advanced(CURL_USE_LIBSSH)
-if(NOT HAVE_LIBSSH2 AND CURL_USE_LIBSSH)
+if(NOT USE_LIBSSH2 AND CURL_USE_LIBSSH)
find_package(libssh CONFIG)
if(libssh_FOUND)
message(STATUS "Found libssh ${libssh_VERSION}")
# Use imported target for include and library paths.
list(APPEND CURL_LIBS ssh)
set(USE_LIBSSH ON)
- set(HAVE_LIBSSH_LIBSSH_H 1)
endif()
endif()
@@ -847,19 +855,21 @@
set(_LINKER_FLAGS_STR "${_LINKER_FLAGS_STR} -L\"${_dir}\"")
endforeach()
- set(CMAKE_REQUIRED_FLAGS "${_COMPILER_FLAGS_STR} ${_LINKER_FLAGS_STR}")
- set(CMAKE_REQUIRED_LIBRARIES ${GSS_LIBRARIES})
- check_symbol_exists("GSS_C_NT_HOSTBASED_SERVICE" ${_INCLUDE_LIST} HAVE_GSS_C_NT_HOSTBASED_SERVICE)
+ if(NOT DEFINED HAVE_GSS_C_NT_HOSTBASED_SERVICE)
+ set(CMAKE_REQUIRED_FLAGS "${_COMPILER_FLAGS_STR} ${_LINKER_FLAGS_STR}")
+ set(CMAKE_REQUIRED_LIBRARIES ${GSS_LIBRARIES})
+ check_symbol_exists("GSS_C_NT_HOSTBASED_SERVICE" ${_INCLUDE_LIST} HAVE_GSS_C_NT_HOSTBASED_SERVICE)
+ unset(CMAKE_REQUIRED_LIBRARIES)
+ endif()
if(NOT HAVE_GSS_C_NT_HOSTBASED_SERVICE)
set(HAVE_OLD_GSSMIT ON)
endif()
- unset(CMAKE_REQUIRED_LIBRARIES)
-
endif()
include_directories(${GSS_INCLUDE_DIR})
link_directories(${GSS_LINK_DIRECTORIES})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}")
+ string(REPLACE ";" " " GSS_LINKER_FLAGS "${GSS_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
@@ -899,7 +909,9 @@
unset(CURL_CA_BUNDLE CACHE)
elseif("${CURL_CA_BUNDLE}" STREQUAL "auto")
unset(CURL_CA_BUNDLE CACHE)
- set(CURL_CA_BUNDLE_AUTODETECT TRUE)
+ if(NOT CMAKE_CROSSCOMPILING)
+ set(CURL_CA_BUNDLE_AUTODETECT TRUE)
+ endif()
else()
set(CURL_CA_BUNDLE_SET TRUE)
endif()
@@ -910,7 +922,7 @@
unset(CURL_CA_PATH CACHE)
elseif("${CURL_CA_PATH}" STREQUAL "auto")
unset(CURL_CA_PATH CACHE)
- if(NOT USE_NSS)
+ if(NOT CMAKE_CROSSCOMPILING AND NOT USE_NSS)
set(CURL_CA_PATH_AUTODETECT TRUE)
endif()
else()
@@ -966,7 +978,6 @@
check_include_file_concat("wincrypt.h" HAVE_WINCRYPT_H)
endif()
-check_include_file_concat("stdio.h" HAVE_STDIO_H)
check_include_file_concat("inttypes.h" HAVE_INTTYPES_H)
check_include_file_concat("sys/filio.h" HAVE_SYS_FILIO_H)
check_include_file_concat("sys/ioctl.h" HAVE_SYS_IOCTL_H)
@@ -979,20 +990,15 @@
check_include_file_concat("sys/stat.h" HAVE_SYS_STAT_H)
check_include_file_concat("sys/time.h" HAVE_SYS_TIME_H)
check_include_file_concat("sys/types.h" HAVE_SYS_TYPES_H)
-check_include_file_concat("sys/uio.h" HAVE_SYS_UIO_H)
check_include_file_concat("sys/un.h" HAVE_SYS_UN_H)
check_include_file_concat("sys/utime.h" HAVE_SYS_UTIME_H)
check_include_file_concat("sys/xattr.h" HAVE_SYS_XATTR_H)
-check_include_file_concat("alloca.h" HAVE_ALLOCA_H)
check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H)
check_include_file_concat("arpa/tftp.h" HAVE_ARPA_TFTP_H)
-check_include_file_concat("assert.h" HAVE_ASSERT_H)
-check_include_file_concat("errno.h" HAVE_ERRNO_H)
check_include_file_concat("fcntl.h" HAVE_FCNTL_H)
check_include_file_concat("idn2.h" HAVE_IDN2_H)
check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H)
check_include_file_concat("io.h" HAVE_IO_H)
-check_include_file_concat("krb.h" HAVE_KRB_H)
check_include_file_concat("libgen.h" HAVE_LIBGEN_H)
check_include_file_concat("locale.h" HAVE_LOCALE_H)
check_include_file_concat("net/if.h" HAVE_NET_IF_H)
@@ -1001,15 +1007,14 @@
check_include_file_concat("netinet/tcp.h" HAVE_NETINET_TCP_H)
check_include_file("linux/tcp.h" HAVE_LINUX_TCP_H)
-check_include_file_concat("pem.h" HAVE_PEM_H)
check_include_file_concat("poll.h" HAVE_POLL_H)
check_include_file_concat("pwd.h" HAVE_PWD_H)
check_include_file_concat("setjmp.h" HAVE_SETJMP_H)
check_include_file_concat("signal.h" HAVE_SIGNAL_H)
check_include_file_concat("ssl.h" HAVE_SSL_H)
+check_include_file_concat("stdatomic.h" HAVE_STDATOMIC_H)
check_include_file_concat("stdbool.h" HAVE_STDBOOL_H)
check_include_file_concat("stdint.h" HAVE_STDINT_H)
-check_include_file_concat("stdio.h" HAVE_STDIO_H)
check_include_file_concat("stdlib.h" HAVE_STDLIB_H)
check_include_file_concat("string.h" HAVE_STRING_H)
check_include_file_concat("strings.h" HAVE_STRINGS_H)
@@ -1019,26 +1024,16 @@
check_include_file_concat("time.h" HAVE_TIME_H)
check_include_file_concat("unistd.h" HAVE_UNISTD_H)
check_include_file_concat("utime.h" HAVE_UTIME_H)
-check_include_file_concat("x509.h" HAVE_X509_H)
-check_include_file_concat("process.h" HAVE_PROCESS_H)
check_include_file_concat("stddef.h" HAVE_STDDEF_H)
-check_include_file_concat("dlfcn.h" HAVE_DLFCN_H)
-check_include_file_concat("malloc.h" HAVE_MALLOC_H)
-check_include_file_concat("memory.h" HAVE_MEMORY_H)
-check_include_file_concat("netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H)
-check_include_file_concat("stdint.h" HAVE_STDINT_H)
-check_include_file_concat("sockio.h" HAVE_SOCKIO_H)
check_include_file_concat("sys/utsname.h" HAVE_SYS_UTSNAME_H)
check_type_size(size_t SIZEOF_SIZE_T)
check_type_size(ssize_t SIZEOF_SSIZE_T)
check_type_size("long long" SIZEOF_LONG_LONG)
check_type_size("long" SIZEOF_LONG)
-check_type_size("short" SIZEOF_SHORT)
check_type_size("int" SIZEOF_INT)
check_type_size("__int64" SIZEOF___INT64)
-check_type_size("long double" SIZEOF_LONG_DOUBLE)
check_type_size("time_t" SIZEOF_TIME_T)
if(NOT HAVE_SIZEOF_SSIZE_T)
if(SIZEOF_LONG EQUAL SIZEOF_SIZE_T)
@@ -1052,7 +1047,6 @@
if(HAVE_SIZEOF_LONG_LONG)
set(HAVE_LONGLONG 1)
- set(HAVE_LL 1)
endif()
if(NOT CMAKE_CROSSCOMPILING)
@@ -1070,55 +1064,43 @@
check_symbol_exists(fchmod "${CURL_INCLUDES}" HAVE_FCHMOD)
check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME)
check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET)
+check_symbol_exists(socketpair "${CURL_INCLUDES}" HAVE_SOCKETPAIR)
+check_symbol_exists(recv "${CURL_INCLUDES}" HAVE_RECV)
+check_symbol_exists(send "${CURL_INCLUDES}" HAVE_SEND)
+check_symbol_exists(sendmsg "${CURL_INCLUDES}" HAVE_SENDMSG)
check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT)
-check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL)
check_symbol_exists(strdup "${CURL_INCLUDES}" HAVE_STRDUP)
-check_symbol_exists(strstr "${CURL_INCLUDES}" HAVE_STRSTR)
check_symbol_exists(strtok_r "${CURL_INCLUDES}" HAVE_STRTOK_R)
-check_symbol_exists(strftime "${CURL_INCLUDES}" HAVE_STRFTIME)
-check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME)
check_symbol_exists(strcasecmp "${CURL_INCLUDES}" HAVE_STRCASECMP)
check_symbol_exists(stricmp "${CURL_INCLUDES}" HAVE_STRICMP)
check_symbol_exists(strcmpi "${CURL_INCLUDES}" HAVE_STRCMPI)
-check_symbol_exists(strncmpi "${CURL_INCLUDES}" HAVE_STRNCMPI)
check_symbol_exists(alarm "${CURL_INCLUDES}" HAVE_ALARM)
-if(NOT HAVE_STRNCMPI)
- set(HAVE_STRCMPI)
-endif()
check_symbol_exists(getppid "${CURL_INCLUDES}" HAVE_GETPPID)
check_symbol_exists(utimes "${CURL_INCLUDES}" HAVE_UTIMES)
check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
-check_symbol_exists(inet_addr "${CURL_INCLUDES}" HAVE_INET_ADDR)
check_symbol_exists(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET)
check_symbol_exists(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP)
check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R)
check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID)
check_symbol_exists(getpwuid_r "${CURL_INCLUDES}" HAVE_GETPWUID_R)
check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID)
-check_symbol_exists(usleep "${CURL_INCLUDES}" HAVE_USLEEP)
check_symbol_exists(utime "${CURL_INCLUDES}" HAVE_UTIME)
check_symbol_exists(gmtime_r "${CURL_INCLUDES}" HAVE_GMTIME_R)
-check_symbol_exists(localtime_r "${CURL_INCLUDES}" HAVE_LOCALTIME_R)
-check_symbol_exists(gethostbyname "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME)
check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R)
-check_symbol_exists(signal "${CURL_INCLUDES}" HAVE_SIGNAL_FUNC)
-check_symbol_exists(SIGALRM "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO)
-if(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
- set(HAVE_SIGNAL 1)
-endif()
-check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME)
+check_symbol_exists(signal "${CURL_INCLUDES}" HAVE_SIGNAL)
check_symbol_exists(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL)
-check_symbol_exists(_strtoi64 "${CURL_INCLUDES}" HAVE__STRTOI64)
check_symbol_exists(strerror_r "${CURL_INCLUDES}" HAVE_STRERROR_R)
check_symbol_exists(siginterrupt "${CURL_INCLUDES}" HAVE_SIGINTERRUPT)
check_symbol_exists(getaddrinfo "${CURL_INCLUDES}" HAVE_GETADDRINFO)
+if(WIN32)
+ set(HAVE_GETADDRINFO_THREADSAFE ${HAVE_GETADDRINFO})
+endif()
check_symbol_exists(freeaddrinfo "${CURL_INCLUDES}" HAVE_FREEADDRINFO)
check_symbol_exists(pipe "${CURL_INCLUDES}" HAVE_PIPE)
check_symbol_exists(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE)
-check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
check_symbol_exists(getpeername "${CURL_INCLUDES}" HAVE_GETPEERNAME)
check_symbol_exists(getsockname "${CURL_INCLUDES}" HAVE_GETSOCKNAME)
check_symbol_exists(if_nametoindex "${CURL_INCLUDES}" HAVE_IF_NAMETOINDEX)
@@ -1126,10 +1108,16 @@
check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE)
check_symbol_exists(setmode "${CURL_INCLUDES}" HAVE_SETMODE)
check_symbol_exists(setrlimit "${CURL_INCLUDES}" HAVE_SETRLIMIT)
-check_symbol_exists(fcntl "${CURL_INCLUDES}" HAVE_FCNTL)
-check_symbol_exists(ioctl "${CURL_INCLUDES}" HAVE_IOCTL)
-check_symbol_exists(setsockopt "${CURL_INCLUDES}" HAVE_SETSOCKOPT)
+
+if(NOT MSVC OR (MSVC_VERSION GREATER_EQUAL 1900))
+ # earlier MSVC compilers had faulty snprintf implementations
+ check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
+endif()
check_function_exists(mach_absolute_time HAVE_MACH_ABSOLUTE_TIME)
+check_symbol_exists(inet_ntop "${CURL_INCLUDES}" HAVE_INET_NTOP)
+if(MSVC AND (MSVC_VERSION LESS_EQUAL 1600))
+ set(HAVE_INET_NTOP OFF)
+endif()
check_symbol_exists(inet_pton "${CURL_INCLUDES}" HAVE_INET_PTON)
check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR)
@@ -1179,7 +1167,6 @@
HAVE_IOCTL_FIONBIO
HAVE_IOCTL_SIOCGIFADDR
HAVE_SETSOCKOPT_SO_NONBLOCK
- HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
TIME_WITH_SYS_TIME
HAVE_O_NONBLOCK
HAVE_GETHOSTBYNAME_R_3
@@ -1191,10 +1178,10 @@
HAVE_IN_ADDR_T
HAVE_BOOL_T
STDC_HEADERS
- HAVE_GETADDRINFO
HAVE_FILE_OFFSET_BITS
HAVE_VARIADIC_MACROS_C99
HAVE_VARIADIC_MACROS_GCC
+ HAVE_ATOMIC
)
curl_internal_test(${CURL_TEST})
endforeach()
@@ -1209,10 +1196,34 @@
set(CMAKE_REQUIRED_INCLUDES "${CURL_SOURCE_DIR}/include")
set(CMAKE_EXTRA_INCLUDE_FILES "curl/system.h")
check_type_size("curl_off_t" SIZEOF_CURL_OFF_T)
+set(CMAKE_EXTRA_INCLUDE_FILES "curl/curl.h")
+check_type_size("curl_socket_t" SIZEOF_CURL_SOCKET_T)
set(CMAKE_EXTRA_INCLUDE_FILES "")
+if(WIN32)
+ # detect actual value of _WIN32_WINNT and store as HAVE_WIN32_WINNT
+ curl_internal_test(HAVE_WIN32_WINNT)
+ if(HAVE_WIN32_WINNT)
+ string(REGEX MATCH ".*_WIN32_WINNT=0x[0-9a-fA-F]+" OUTPUT "${OUTPUT}")
+ string(REGEX REPLACE ".*_WIN32_WINNT=" "" HAVE_WIN32_WINNT "${OUTPUT}")
+ message(STATUS "Found _WIN32_WINNT=${HAVE_WIN32_WINNT}")
+ endif()
+ # avoid storing HAVE_WIN32_WINNT in CMake cache
+ unset(HAVE_WIN32_WINNT CACHE)
+endif()
+
set(CMAKE_REQUIRED_FLAGS)
+option(ENABLE_WEBSOCKETS "Set to ON to enable EXPERIMENTAL websockets" OFF)
+
+if(ENABLE_WEBSOCKETS)
+ if(${SIZEOF_CURL_OFF_T} GREATER "4")
+ set(USE_WEBSOCKETS ON)
+ else()
+ message(WARNING "curl_off_t is too small to enable WebSockets")
+ endif()
+endif()
+
foreach(CURL_TEST
HAVE_GLIBC_STRERROR_R
HAVE_POSIX_STRERROR_R
@@ -1256,18 +1267,6 @@
set(in_addr_t "unsigned long")
endif()
-# Fix libz / zlib.h
-
-if(NOT CURL_SPECIAL_LIBZ)
- if(NOT HAVE_LIBZ)
- set(HAVE_ZLIB_H 0)
- endif()
-
- if(NOT HAVE_ZLIB_H)
- set(HAVE_LIBZ 0)
- endif()
-endif()
-
# Check for nonblocking
set(HAVE_DISABLED_NONBLOCKING 1)
if(HAVE_FIONBIO OR
@@ -1301,8 +1300,6 @@
set(CURL_PULL_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H})
set(CURL_PULL_SYS_POLL_H ${HAVE_SYS_POLL_H})
endif()
-set(CURL_PULL_STDINT_H ${HAVE_STDINT_H})
-set(CURL_PULL_INTTYPES_H ${HAVE_INTTYPES_H})
include(CMake/OtherTests.cmake)
@@ -1317,7 +1314,7 @@
# Check if crypto functions in wincrypt.h are actually available
if(HAVE_WINCRYPT_H)
- check_symbol_exists(CryptAcquireContext "${CURL_INCLUDES}" USE_WINCRYPT)
+ check_symbol_exists(CryptAcquireContext "windows.h;wincrypt.h" USE_WINCRYPT)
endif()
if(USE_WINCRYPT)
set(USE_WIN32_CRYPTO ON)
@@ -1327,6 +1324,12 @@
if(USE_WIN32_CRYPTO OR USE_SCHANNEL)
list(APPEND CURL_LIBS "advapi32" "crypt32")
endif()
+
+ if(NOT HAVE_MINGW_ORIGINAL)
+ list(APPEND CURL_LIBS "bcrypt")
+ else()
+ set(HAVE_FTRUNCATE OFF)
+ endif()
endif()
if(MSVC)
@@ -1465,8 +1468,14 @@
_add_if("HTTP2" USE_NGHTTP2)
_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE)
_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
-_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS))
+# TODO wolfSSL only support this from v5.0.0 onwards
+_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS
+ OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR
+ USE_MBEDTLS OR USE_SECTRANSP))
_add_if("unicode" ENABLE_UNICODE)
+_add_if("threadsafe" HAVE_ATOMIC OR (WIN32 AND
+ HAVE_WIN32_WINNT GREATER_EQUAL 0x600))
+_add_if("PSL" USE_LIBPSL)
string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
@@ -1503,6 +1512,8 @@
_add_if("RTSP" NOT CURL_DISABLE_RTSP)
_add_if("RTMP" USE_LIBRTMP)
_add_if("MQTT" NOT CURL_DISABLE_MQTT)
+_add_if("WS" USE_WEBSOCKETS)
+_add_if("WSS" USE_WEBSOCKETS)
if(_items)
list(SORT _items)
endif()
@@ -1605,6 +1616,15 @@
VERSION ${CURL_VERSION}
COMPATIBILITY SameMajorVersion
)
+file(READ "${version_config}" generated_version_config)
+file(WRITE "${version_config}"
+"if(NOT PACKAGE_FIND_VERSION_RANGE AND PACKAGE_FIND_VERSION_MAJOR STREQUAL \"7\")
+ # Version 8 satisfies version 7... requirements
+ set(PACKAGE_FIND_VERSION_MAJOR 8)
+ set(PACKAGE_FIND_VERSION_COUNT 1)
+endif()
+${generated_version_config}"
+)
# Use:
# * TARGETS_EXPORT_NAME
@@ -1636,13 +1656,13 @@
endif()
endif()
-if(NOT TARGET uninstall)
+if(NOT TARGET curl_uninstall)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake
IMMEDIATE @ONLY)
- add_custom_target(uninstall
+ add_custom_target(curl_uninstall
COMMAND ${CMAKE_COMMAND} -P
${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake)
endif()
diff --git a/COPYING b/COPYING
index 90f05ad..d1eab3e 100644
--- a/COPYING
+++ b/COPYING
@@ -1,6 +1,6 @@
COPYRIGHT AND PERMISSION NOTICE
-Copyright (c) 1996 - 2022, Daniel Stenberg, <daniel@haxx.se>, and many
+Copyright (c) 1996 - 2023, Daniel Stenberg, <daniel@haxx.se>, and many
contributors, see the THANKS file.
All rights reserved.
diff --git a/GIT-INFO b/GIT-INFO
index 053369e..62efbd9 100644
--- a/GIT-INFO
+++ b/GIT-INFO
@@ -14,7 +14,7 @@
everything from git, do this:
autoreconf -fi
-./configure
+./configure --with-openssl
make
Daniel uses a ./configure line similar to this for easier development:
diff --git a/LICENSES/GPL-3.0-or-later.txt b/LICENSES/GPL-3.0-or-later.txt
deleted file mode 100644
index d41c0bd..0000000
--- a/LICENSES/GPL-3.0-or-later.txt
+++ /dev/null
@@ -1,232 +0,0 @@
-GNU GENERAL PUBLIC LICENSE
-Version 3, 29 June 2007
-
-Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>
-
-Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
-
-Preamble
-
-The GNU General Public License is a free, copyleft license for software and other kinds of works.
-
-The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.
-
-When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
-
-To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.
-
-For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
-
-Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.
-
-For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.
-
-Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.
-
-Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.
-
-The precise terms and conditions for copying, distribution and modification follow.
-
-TERMS AND CONDITIONS
-
-0. Definitions.
-
-“This License” refers to version 3 of the GNU General Public License.
-
-“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
-
-“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.
-
-To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.
-
-A “covered work” means either the unmodified Program or a work based on the Program.
-
-To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
-
-To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
-
-An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
-
-1. Source Code.
-The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.
-
-A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
-
-The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
-
-The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
-
-The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
-
-The Corresponding Source for a work in source code form is that same work.
-
-2. Basic Permissions.
-All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
-
-You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
-
-Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
-
-3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
-
-When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
-
-4. Conveying Verbatim Copies.
-You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
-
-You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
-
-5. Conveying Modified Source Versions.
-You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.
-
- c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
-
-A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
-
-6. Conveying Non-Source Forms.
-You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
-
- d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
-
-A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
-
-A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
-
-“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
-
-If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
-
-The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
-
-Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
-
-7. Additional Terms.
-“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
-
-When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
-
-Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
-
-All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
-
-If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
-
-Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
-
-8. Termination.
-You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
-
-However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
-
-Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
-
-Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
-
-9. Acceptance Not Required for Having Copies.
-You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
-
-10. Automatic Licensing of Downstream Recipients.
-Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
-
-An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
-
-You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
-
-11. Patents.
-A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”.
-
-A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
-
-Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
-
-In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
-
-If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
-
-If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
-
-A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
-
-Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
-
-12. No Surrender of Others' Freedom.
-If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
-
-13. Use with the GNU Affero General Public License.
-Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
-
-14. Revised Versions of this License.
-The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
-
-If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
-
-Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
-
-15. Disclaimer of Warranty.
-THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-16. Limitation of Liability.
-IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-17. Interpretation of Sections 15 and 16.
-If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
-
-END OF TERMS AND CONDITIONS
-
-How to Apply These Terms to Your New Programs
-
-If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
-
-To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
-
- <program> Copyright (C) <year> <name of author>
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”.
-
-You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <http://www.gnu.org/licenses/>.
-
-The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/LICENSES/LicenseRef-OpenEvidence.txt b/LICENSES/LicenseRef-OpenEvidence.txt
deleted file mode 100644
index 9cc2fd1..0000000
--- a/LICENSES/LicenseRef-OpenEvidence.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions, the following disclaimer,
- and the original OpenSSL and SSLeay Licences below.
-
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions, the following disclaimer
- and the original OpenSSL and SSLeay Licences below in
- the documentation and/or other materials provided with the
- distribution.
-
-3. All advertising materials mentioning features or use of this
- software must display the following acknowledgments:
- "This product includes software developed by the Openevidence Project
- for use in the OpenEvidence Toolkit. (http://www.openevidence.org/)"
- This product includes software developed by the OpenSSL Project
- for use in the OpenSSL Toolkit (https://www.openssl.org/)"
- This product includes cryptographic software written by Eric Young
- (eay@cryptsoft.com). This product includes software written by Tim
- Hudson (tjh@cryptsoft.com)."
-
-4. The names "OpenEvidence Toolkit" and "OpenEvidence Project" must not be
- used to endorse or promote products derived from this software without
- prior written permission. For written permission, please contact
- openevidence-core@openevidence.org.
-
-5. Products derived from this software may not be called "OpenEvidence"
- nor may "OpenEvidence" appear in their names without prior written
- permission of the OpenEvidence Project.
-
-6. Redistributions of any form whatsoever must retain the following
- acknowledgments:
- "This product includes software developed by the OpenEvidence Project
- for use in the OpenEvidence Toolkit (http://www.openevidence.org/)
- This product includes software developed by the OpenSSL Project
- for use in the OpenSSL Toolkit (https://www.openssl.org/)"
- This product includes cryptographic software written by Eric Young
- (eay@cryptsoft.com). This product includes software written by Tim
- Hudson (tjh@cryptsoft.com)."
-
-THIS SOFTWARE IS PROVIDED BY THE OpenEvidence PROJECT ``AS IS'' AND ANY
-EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenEvidence PROJECT OR
-ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-OF THE POSSIBILITY OF SUCH DAMAGE.
-====================================================================
-
-This product includes software developed by the OpenSSL Project
-for use in the OpenSSL Toolkit (https://www.openssl.org/)
-This product includes cryptographic software written by Eric Young
-(eay@cryptsoft.com). This product includes software written by Tim
-Hudson (tjh@cryptsoft.com).
diff --git a/LICENSES/curl.txt b/LICENSES/curl.txt
index 90f05ad..3c1c197 100644
--- a/LICENSES/curl.txt
+++ b/LICENSES/curl.txt
@@ -1,6 +1,6 @@
COPYRIGHT AND PERMISSION NOTICE
-Copyright (c) 1996 - 2022, Daniel Stenberg, <daniel@haxx.se>, and many
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, and many
contributors, see the THANKS file.
All rights reserved.
diff --git a/MacOSX-Framework b/MacOSX-Framework
index 97cd00b..5ac5376 100755
--- a/MacOSX-Framework
+++ b/MacOSX-Framework
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -83,12 +83,12 @@
then
SDK64=10.5
ARCHES64='-arch x86_64 -arch ppc64'
- SDK64=`ls $SDK_PATH|grep 10.5|head -1`
+ SDK64=`ls $SDK_PATH | grep "10\.5" | head -1`
else
ARCHES64='-arch x86_64'
#We "know" that 10.4 and earlier do not support 64bit
- OLD_SDK64=`ls $SDK_PATH|egrep -v "10.[0-4]"|head -1`
- NEW_SDK64=`ls -r $SDK_PATH|egrep -v "10.[0-4][^0-9]" | head -1`
+ OLD_SDK64=`ls $SDK_PATH | grep -v "10\.[0-4]" | head -1`
+ NEW_SDK64=`ls -r $SDK_PATH | grep -v "10\.[0-4][^0-9]" | head -1`
if test $USE_OLD -gt 0
then
SDK64=$OLD_SDK64
diff --git a/Makefile.am b/Makefile.am
index 40771ed..f25e4e2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -49,6 +49,7 @@
CMake/FindZstd.cmake \
CMake/Macros.cmake \
CMake/OtherTests.cmake \
+ CMake/PickyWarnings.cmake \
CMake/Platforms/WindowsCache.cmake \
CMake/Utilities.cmake \
CMakeLists.txt
diff --git a/Makefile.dist b/Makefile.dist
index ab5a9b5..a5818e1 100644
--- a/Makefile.dist
+++ b/Makefile.dist
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -31,25 +31,25 @@
make
mingw32:
- $(MAKE) -C lib -f Makefile.m32
- $(MAKE) -C src -f Makefile.m32
+ $(MAKE) -C lib -f Makefile.mk
+ $(MAKE) -C src -f Makefile.mk
mingw32-clean:
- $(MAKE) -C lib -f Makefile.m32 clean
- $(MAKE) -C src -f Makefile.m32 clean
- $(MAKE) -C docs/examples -f Makefile.m32 clean
+ $(MAKE) -C lib -f Makefile.mk clean
+ $(MAKE) -C src -f Makefile.mk clean
+ $(MAKE) -C docs/examples -f Makefile.mk clean
mingw32-vclean mingw32-distclean:
- $(MAKE) -C lib -f Makefile.m32 vclean
- $(MAKE) -C src -f Makefile.m32 vclean
- $(MAKE) -C docs/examples -f Makefile.m32 vclean
+ $(MAKE) -C lib -f Makefile.mk vclean
+ $(MAKE) -C src -f Makefile.mk vclean
+ $(MAKE) -C docs/examples -f Makefile.mk vclean
mingw32-examples%:
- $(MAKE) -C docs/examples -f Makefile.m32 CFG=$@
+ $(MAKE) -C docs/examples -f Makefile.mk CFG=$@
mingw32%:
- $(MAKE) -C lib -f Makefile.m32 CFG=$@
- $(MAKE) -C src -f Makefile.m32 CFG=$@
+ $(MAKE) -C lib -f Makefile.mk CFG=$@
+ $(MAKE) -C src -f Makefile.mk CFG=$@
vc:
cd winbuild
@@ -59,9 +59,9 @@
cd winbuild
nmake /f Makefile.vc MACHINE=x64
-djgpp:
- $(MAKE) -C lib -f Makefile.dj
- $(MAKE) -C src -f Makefile.dj
+djgpp%:
+ $(MAKE) -C lib -f Makefile.mk CFG=$@ CROSSPREFIX=i586-pc-msdosdjgpp-
+ $(MAKE) -C src -f Makefile.mk CFG=$@ CROSSPREFIX=i586-pc-msdosdjgpp-
cygwin:
./configure
@@ -71,9 +71,9 @@
./configure --with-openssl
make
-amiga:
- cd ./lib && make -f makefile.amiga
- cd ./src && make -f makefile.amiga
+amiga%:
+ $(MAKE) -C lib -f Makefile.mk CFG=$@ CROSSPREFIX=m68k-amigaos-
+ $(MAKE) -C src -f Makefile.mk CFG=$@ CROSSPREFIX=m68k-amigaos-
unix: all
diff --git a/README b/README
index 9705f41..f5efbd7 100644
--- a/README
+++ b/README
@@ -13,7 +13,7 @@
libcurl is the library curl is using to do its job. It is readily
available to be used by your software. Read the libcurl.3 man page to
- learn how!
+ learn how.
You find answers to the most frequent questions we get in the FAQ document.
@@ -36,7 +36,7 @@
GIT
- To download the very latest source off the GIT server do this:
+ To download the latest source code off the GIT server, do this:
git clone https://github.com/curl/curl.git
@@ -44,7 +44,7 @@
SECURITY PROBLEMS
- Report suspected security problems via our HackerOne page and not in public!
+ Report suspected security problems via our HackerOne page and not in public.
https://hackerone.com/curl
diff --git a/README.md b/README.md
index 2743982..e2b1352 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,10 @@
<!--
-Copyright (C) 1998 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
-# 
-
-[](https://bestpractices.coreinfrastructure.org/projects/63)
-[](https://scan.coverity.com/projects/curl)
-[](https://ci.appveyor.com/project/curlorg/curl)
-[](https://dev.azure.com/daniel0244/curl/_build/latest?definitionId=1&branchName=master)
-[](https://cirrus-ci.com/github/curl/curl)
-[](#backers)
-[](#sponsors)
-[](https://lgtm.com/projects/g/curl/curl/context:cpp)
-[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:curl)
-[](https://api.reuse.software/info/github.com/curl/curl)
+# [](https://curl.se/)
Curl is a command-line tool for transferring data specified with URL
syntax. Find out how to use curl by reading [the curl.1 man
@@ -53,7 +42,7 @@
## Git
-To download the latest source from the Git server do this:
+To download the latest source from the Git server, do this:
git clone https://github.com/curl/curl.git
@@ -62,7 +51,7 @@
## Security problems
Report suspected security problems via [our HackerOne
-page](https://hackerone.com/curl) and not in public!
+page](https://hackerone.com/curl) and not in public.
## Notice
@@ -72,22 +61,9 @@
## Backers
-Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/curl#backer)]
-
-[](https://opencollective.com/curl#backers)
+Thank you to all our backers! 🙏 [Become a backer](https://opencollective.com/curl#section-contribute).
## Sponsors
-Support this project by becoming a sponsor. Your logo will show up here with a
-link to your website. [[Become a sponsor](https://opencollective.com/curl#sponsor)]
-<!-- markdown-link-check-disable -->
-[](https://opencollective.com/curl/sponsor/0/website)
-[](https://opencollective.com/curl/sponsor/1/website)
-[](https://opencollective.com/curl/sponsor/2/website)
-[](https://opencollective.com/curl/sponsor/3/website)
-[](https://opencollective.com/curl/sponsor/4/website)
-[](https://opencollective.com/curl/sponsor/5/website)
-[](https://opencollective.com/curl/sponsor/6/website)
-[](https://opencollective.com/curl/sponsor/7/website)
-[](https://opencollective.com/curl/sponsor/8/website)
-[](https://opencollective.com/curl/sponsor/9/website)
+Support this project by becoming a [sponsor](https://curl.se/sponsors.html).
+
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 5bc5055..4720b47 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,288 +1,93 @@
-curl and libcurl 7.84.0
+curl and libcurl 8.2.1
- Public curl releases: 209
- Command line options: 248
- curl_easy_setopt() options: 297
- Public functions in libcurl: 88
- Contributors: 2652
+ Public curl releases: 221
+ Command line options: 255
+ curl_easy_setopt() options: 303
+ Public functions in libcurl: 91
+ Contributors: 2927
This release includes the following changes:
- o curl: add --rate to set max request rate per time unit [69]
- o curl: deprecate --random-file and --egd-file [12]
- o curl_version_info: add CURL_VERSION_THREADSAFE [100]
- o CURLINFO_CAPATH/CAINFO: get the default CA paths from libcurl [9]
- o lib: make curl_global_init() threadsafe when possible [101]
- o libssh2: add CURLOPT_SSH_HOSTKEYFUNCTION [78]
- o opts: deprecate RANDOM_FILE and EGDSOCKET [13]
- o socks: support unix sockets for socks proxy [2]
This release includes the following bugfixes:
- o aws-sigv4: fix potentional NULL pointer arithmetic [48]
- o bindlocal: don't use a random port if port number would wrap [14]
- o c-hyper: mark status line as status for Curl_client_write() [58]
- o ci: avoid `cmake -Hpath` [114]
- o CI: bump FreeBSD 13.0 to 13.1 [127]
- o ci: update github actions [36]
- o cmake: add libpsl support [3]
- o cmake: do not add libcurl.rc to the static libcurl library [53]
- o cmake: enable curl.rc for all Windows targets [55]
- o cmake: fix detecting libidn2 [56]
- o cmake: support adding a suffix to the OS value [54]
- o configure: skip libidn2 detection when winidn is used [89]
- o configure: use the SED value to invoke sed [28]
- o configure: warn about rustls being experimental [103]
- o content_encoding: return error on too many compression steps [106]
- o cookie: address secure domain overlay [7]
- o cookie: apply limits [83]
- o copyright.pl: parse and use .reuse/dep5 for skips [105]
- o copyright: make repository REUSE compliant [119]
- o curl.1: add a few see also --tls-max [52]
- o curl.1: mention exit code zero too [44]
- o curl: re-enable --no-remote-name [31]
- o curl_easy_pause.3: remove explanation of progress function [97]
- o curl_getdate.3: document that some illegal dates pass through [34]
- o Curl_parsenetrc: don't access local pwbuf outside of scope [27]
- o curl_url_set.3: clarify by default using known schemes only [120]
- o CURLOPT_ALTSVC.3: document the file format [118]
- o CURLOPT_FILETIME.3: fix the protocols this works with
- o CURLOPT_HTTPHEADER.3: improve comment in example [66]
- o CURLOPT_NETRC.3: document the .netrc file format
- o CURLOPT_PORT.3: We discourage using this option [92]
- o CURLOPT_RANGE.3: remove ranged upload advice [99]
- o digest: added detection of more syntax error in server headers [81]
- o digest: tolerate missing "realm" [80]
- o digest: unquote realm and nonce before processing [82]
- o DISABLED: disable 1021 for hyper again
- o docs/cmdline-opts: add copyright and license identifier to each file [112]
- o docs/CONTRIBUTE.md: document the 'needs-votes' concept [79]
- o docs: clarify data replacement policy for MIME API [16]
- o doh: remove UNITTEST macro definition [67]
- o examples/crawler.c: use the curl license [73]
- o examples: remove fopen.c and rtsp.c [76]
- o FAQ: Clarify Windows double quote usage [42]
- o fopen: add Curl_fopen() for better overwriting of files [72]
- o ftp: restore protocol state after http proxy CONNECT [110]
- o ftp: when failing to do a secure GSSAPI login, fail hard [62]
- o GHA/hyper: enable debug in the build
- o gssapi: improve handling of errors from gss_display_status [45]
- o gssapi: initialize gss_buffer_desc strings
- o headers api: remove EXPERIMENTAL tag [35]
- o http2: always debug print stream id in decimal with %u [46]
- o http2: reject overly many push-promise headers [63]
- o http: restore header folding behavior [64]
- o hyper: use 'alt-used' [71]
- o krb5: return error properly on decode errors [107]
- o lib: make more protocol specific struct fields #ifdefed [84]
- o libcurl-security.3: add "Secrets in memory" [30]
- o libcurl-security.3: document CRLF header injection [98]
- o libssh: skip the fake-close when libssh does the right thing [102]
- o links: update dead links to the curl-wiki [21]
- o log2changes: do not indent empty lines [ci skip] [37]
- o macos9: remove partial support [22]
- o Makefile.am: fix portability issues [1]
- o Makefile.m32: delete obsolete options, improve -On [ci skip] [65]
- o Makefile.m32: delete two obsolete OpenSSL options [ci skip] [39]
- o Makefile.m32: stop forcing XP target with ipv6 enabled [ci skip] [116]
- o max-time.d: clarify max-time sets max transfer time [70]
- o mprintf: ignore clang non-literal format string [19]
- o netrc: check %USERPROFILE% as well on Windows [77]
- o netrc: support quoted strings [33]
- o ngtcp2: allow curl to send larger UDP datagrams [29]
- o ngtcp2: correct use of ngtcp2 and nghttp3 signed integer types [25]
- o ngtcp2: enable Linux GSO [91]
- o ngtcp2: extend QUIC transport parameters buffer [4]
- o ngtcp2: fix alert_read_func return value [26]
- o ngtcp2: fix typo in preprocessor condition [121]
- o ngtcp2: handle error from ngtcp2_conn_submit_crypto_data [5]
- o ngtcp2: send appropriate connection close error code [6]
- o ngtcp2: support boringssl crypto backend [17]
- o ngtcp2: use helper funcs to simplify TLS handshake integration [68]
- o ntlm: provide a fixed fake host name [32]
- o projects: fix third-party SSL library build paths for Visual Studio [125]
- o quic: add Curl_quic_idle [18]
- o quiche: support ca-fallback [49]
- o rand: stop detecting /dev/urandom in cross-builds [113]
- o remote-name.d: mention --output-dir [88]
- o runtests.pl: add the --repeat parameter to the --help output [43]
- o runtests: fix skipping tests not done event-based [95]
- o runtests: skip starting the ssh server if user name is lacking [104]
- o scripts/copyright.pl: fix the exclusion to not ignore man pages [75]
- o sectransp: check for a function defined when __BLOCKS__ is undefined [20]
- o select: return error from "lethal" poll/select errors [93]
- o server/sws: support spaces in the HTTP request path
- o speed-limit/time.d: mention these affect transfers in either direction [74]
- o strcase: some optimisations [8]
- o test 2081: add a valid reply for the second request [60]
- o test 675: add missing CR so the test passes when run through Privoxy [61]
- o test414: add the '--resolve' keyword [23]
- o test681: verify --no-remote-name [90]
- o tests 266, 116 and 1540: add a small write delay
- o tests/data/test1501: kill ftp server after slow LIST response [59]
- o tests/getpart: fix getpartattr to work with "data" and "data2"
- o tests/server/sws.c: change the HTTP writedelay unit to milliseconds [47]
- o test{440,441,493,977}: add "HTTP proxy" keywords [40]
- o tool_getparam: fix --parallel-max maximum value constraint [51]
- o tool_operate: make sure --fail-with-body works with --retry [24]
- o transfer: fix potential NULL pointer dereference [15]
- o transfer: maintain --path-as-is after redirects [96]
- o transfer: upload performance; avoid tiny send [124]
- o url: free old conn better on reuse [41]
- o url: remove redundant #ifdefs in allocate_conn()
- o url: URL encode the path when extracted, if spaces were set
- o urlapi: make curl_url_set(url, CURLUPART_URL, NULL, 0) clear all parts [126]
- o urlapi: support CURLU_URLENCODE for curl_url_get()
- o urldata: reduce size of a few struct fields [86]
- o urldata: remove three unused booleans from struct UserDefined [87]
- o urldata: store tcp_keepidle and tcp_keepintvl as ints [85]
- o version: allow stricmp() for sorting the feature list [57]
- o vtls: make curl_global_sslset thread-safe [94]
- o wolfssh.h: removed [10]
- o wolfssl: correct the failf() message when a handle can't be made [38]
- o wolfSSL: explicitly use compatibility layer [11]
- o x509asn1: mark msnprintf return as unchecked [50]
+ o amigaos: fix sys/mbuf.h m_len macro clash [9]
+ o amissl: add missing signal.h include [8]
+ o amissl: fix AmiSSL v5 detection [2]
+ o cfilters: rename close/connect functions to avoid clashes [12]
+ o ciphers.d: put URL in first column [1]
+ o cmake: add `libcurlu`/`libcurltool` for unit tests [5]
+ o cmake: update ngtcp2 detection [4]
+ o configure: check for nghttp2_session_get_stream_local_window_size [14]
+ o CONTRIBUTE: drop mention of copyright year ranges [20]
+ o CONTRIBUTE: fix syntax in commit message description [21]
+ o curl_multi_wait.3: fix arg quoting to doc macro .BR [27]
+ o docs: mark two TLS options for TLS, not SSL [26]
+ o docs: provide more see also for cipher options [23]
+ o hostip: return IPv6 first for localhost resolves [16]
+ o http2: fix regression on upload EOF handling [13]
+ o http: VLH, very large header test and fixes [19]
+ o libcurl-errors.3: add CURLUE_OK [11]
+ o os400: correct EXPECTED_STRING_LASTZEROTERMINATED [7]
+ o quiche: fix lookup of transfer at multi [18]
+ o quiche: fix segfault and other things [15]
+ o rustls: update rustls-ffi 0.10.0 [24]
+ o socks: print ipv6 address within brackets [10]
+ o src/mkhelp: strip off escape sequences [22]
+ o tool: fix tool_seek_cb build when SIZEOF_CURL_OFF_T > SIZEOF_OFF_T [17]
+ o transfer: do not clear the credentials on redirect to absolute URL [6]
+ o unittest: remove unneeded *_LDADD [3]
+ o websocket: rename arguments/variables to match docs [25]
This release includes the following known bugs:
o see docs/KNOWN_BUGS (https://curl.se/docs/knownbugs.html)
+Planned upcoming removals include:
+
+ o gskit
+ o NSS
+ o support for space-separated NOPROXY patterns
+ o support for the original legacy mingw version 1
+
+ See https://curl.se/dev/deprecate.html for details
+
This release would not have looked like this without help, code, reports and
advice from friends like these:
- Andrea Pappacoda, Balakrishnan Balasubramanian, Boris Verkhovskiy,
- Carlo Alberto, Christian Weisgerber, Dan Fandrich, Daniel Gustafsson,
- Daniel Stenberg, Egor Pugin, Emanuele Torre, Emil Engler, Evgeny Grin,
- Fabian Keil, Frank Gevaerts, Frazer Smith, Gisle Vanem, Glenn Strauss,
- Gregor Jasny, Harry Sintonen, Illarion Taev, ImpatientHippo on GitHub,
- Jakub Bochenski, Kamil Dudka, Karlson2k on github, KotlinIsland on github,
- Ladar Levison, Marcel Raad, Marc Hörsken, Marcus T, Max Mehl, michael musset,
- Nick Zitzmann, Nuru on github, Patrick Monnerat, Petr Pisar, Philip H,
- Pierrick Charron, Ray Satiro, Ricardo M. Correia, Simon Berger,
- Stefan Eissing, Steve Holme, Tatsuhiro Tsujikawa, Thomas Guillem, Tom Eccles,
- Viktor Szakats, Vincent Torri, vvb2060 on github, Willem Hoek,
- Wolf Vollprecht, Elms
- (51 contributors)
+ Aleksander Mazur, Alois Klink, Andrei Rybak, Brad Harder,
+ Chilledheart on github, Christian Schmitz, Cloudogu Siebels, Daniel Stenberg,
+ Harry Sintonen, Jacob Hoffman-Andrews, Jan Macku, John Haugabook, Jon Rumsey,
+ Oliver Roberts, Paul Howarth, Stefan Eissing, VictorVG on github,
+ Viktor Szakats, Yair Lenga, ウさん
+ (20 contributors)
References to bug reports and discussions on issues:
- [1] = https://curl.se/mail/lib-2022-05/0024.html
- [2] = https://curl.se/bug/?i=8668
- [3] = https://curl.se/bug/?i=8865
- [4] = https://curl.se/bug/?i=8872
- [5] = https://curl.se/bug/?i=8871
- [6] = https://curl.se/bug/?i=8870
- [7] = https://hackerone.com/reports/1560324
- [8] = https://curl.se/bug/?i=8875
- [9] = https://curl.se/bug/?i=8888
- [10] = https://curl.se/bug/?i=8863
- [11] = https://curl.se/bug/?i=8864
- [12] = https://curl.se/bug/?i=8670
- [13] = https://curl.se/bug/?i=8670
- [14] = https://curl.se/bug/?i=8862
- [15] = https://curl.se/bug/?i=8857
- [16] = https://curl.se/bug/?i=8860
- [17] = https://curl.se/bug/?i=8789
- [18] = https://curl.se/bug/?i=8698
- [19] = https://curl.se/bug/?i=8740
- [20] = https://curl.se/bug/?i=8846
- [21] = https://curl.se/bug/?i=8897
- [22] = https://curl.se/bug/?i=8836
- [23] = https://curl.se/bug/?i=8959
- [24] = https://curl.se/bug/?i=8845
- [25] = https://curl.se/bug/?i=8851
- [26] = https://curl.se/bug/?i=8852
- [27] = https://curl.se/bug/?i=8850
- [28] = https://curl.se/bug/?i=8891
- [29] = https://curl.se/bug/?i=8883
- [30] = https://curl.se/bug/?i=8881
- [31] = https://curl.se/bug/?i=8931
- [32] = https://curl.se/bug/?i=8859
- [33] = https://curl.se/bug/?i=8908
- [34] = https://curl.se/bug/?i=8938
- [35] = https://curl.se/bug/?i=8900
- [36] = https://curl.se/bug/?i=8843
- [37] = https://curl.se/bug/?i=8887
- [38] = https://curl.se/bug/?i=8885
- [39] = https://curl.se/bug/?i=8884
- [40] = https://curl.se/bug/?i=8959
- [41] = https://curl.se/bug/?i=8841
- [42] = https://curl.se/bug/?i=8823
- [43] = https://curl.se/bug/?i=8959
- [44] = https://curl.se/bug/?i=8833
- [45] = https://curl.se/bug/?i=8832
- [46] = https://curl.se/bug/?i=8808
- [47] = https://curl.se/bug/?i=8827
- [48] = https://curl.se/bug/?i=8814
- [49] = https://curl.se/bug/?i=8696
- [50] = https://curl.se/bug/?i=8831
- [51] = https://curl.se/bug/?i=8930
- [52] = https://curl.se/bug/?i=8929
- [53] = https://curl.se/bug/?i=8918
- [54] = https://curl.se/bug/?i=8919
- [55] = https://curl.se/bug/?i=8918
- [56] = https://curl.se/bug/?i=8917
- [57] = https://curl.se/bug/?i=8916
- [58] = https://curl.se/bug/?i=8894
- [59] = https://curl.se/bug/?i=8907
- [60] = https://curl.se/bug/?i=8959
- [61] = https://curl.se/bug/?i=8959
- [62] = https://hackerone.com/reports/1590102
- [63] = https://hackerone.com/reports/1589847
- [64] = https://curl.se/bug/?i=8844
- [65] = https://curl.se/bug/?i=8904
- [66] = https://curl.se/bug/?i=9025
- [67] = https://curl.se/bug/?i=8902
- [68] = https://curl.se/bug/?i=8968
- [69] = https://curl.se/bug/?i=8671
- [70] = https://curl.se/bug/?i=8877
- [71] = https://curl.se/bug/?i=8898
- [72] = https://curl.se/docs/CVE-2022-32207.html
- [73] = https://curl.se/bug/?i=8950
- [74] = https://curl.se/bug/?i=8948
- [75] = https://curl.se/bug/?i=8952
- [76] = https://curl.se/bug/?i=8949
- [77] = https://curl.se/bug/?i=8855
- [78] = https://curl.se/bug/?i=7959
- [79] = https://curl.se/bug/?i=8910
- [80] = https://curl.se/bug/?i=8912
- [81] = https://curl.se/bug/?i=8912
- [82] = https://curl.se/bug/?i=8912
- [83] = https://curl.se/docs/CVE-2022-32205.html
- [84] = https://curl.se/bug/?i=8944
- [85] = https://curl.se/bug/?i=8940
- [86] = https://curl.se/bug/?i=8940
- [87] = https://curl.se/bug/?i=8940
- [88] = https://curl.se/bug/?i=8945
- [89] = https://curl.se/bug/?i=8934
- [90] = https://curl.se/bug/?i=8942
- [91] = https://curl.se/bug/?i=8909
- [92] = https://curl.se/bug/?i=8941
- [93] = https://curl.se/bug/?i=8921
- [94] = https://curl.se/bug/?i=9016
- [95] = https://curl.se/bug/?i=8977
- [96] = https://curl.se/bug/?i=8974
- [97] = https://curl.se/bug/?i=9015
- [98] = https://curl.se/bug/?i=8964
- [99] = https://curl.se/bug/?i=8969
- [100] = https://curl.se/bug/?i=8680
- [101] = https://curl.se/bug/?i=8680
- [102] = https://curl.se/bug/?i=9021
- [103] = https://curl.se/bug/?i=9019
- [104] = https://curl.se/bug/?i=9013
- [105] = https://curl.se/bug/?i=9006
- [106] = https://curl.se/docs/CVE-2022-32206.html
- [107] = https://curl.se/docs/CVE-2022-32208.html
- [110] = https://curl.se/bug/?i=8737
- [112] = https://curl.se/bug/?i=9002
- [113] = https://curl.se/bug/?i=9038
- [114] = https://curl.se/bug/?i=9008
- [116] = https://curl.se/bug/?i=9035
- [118] = https://curl.se/bug/?i=9033
- [119] = https://curl.se/bug/?i=8869
- [120] = https://curl.se/bug/?i=8994
- [121] = https://curl.se/bug/?i=8981
- [124] = https://curl.se/bug/?i=8965
- [125] = https://curl.se/bug/?i=8991
- [126] = https://curl.se/bug/?i=9028
- [127] = https://curl.se/bug/?i=8815
+ [1] = https://curl.se/bug/?i=11464
+ [2] = https://curl.se/bug/?i=11477
+ [3] = https://curl.se/bug/?i=11494
+ [4] = https://curl.se/bug/?i=11508
+ [5] = https://curl.se/bug/?i=11446
+ [6] = https://curl.se/bug/?i=11486
+ [7] = https://curl.se/bug/?i=11476
+ [8] = https://curl.se/bug/?i=11478
+ [9] = https://curl.se/bug/?i=11479
+ [10] = https://curl.se/bug/?i=11483
+ [11] = https://curl.se/bug/?i=11488
+ [12] = https://curl.se/bug/?i=11491
+ [13] = https://curl.se/bug/?i=11485
+ [14] = https://curl.se/bug/?i=11470
+ [15] = https://curl.se/bug/?i=11449
+ [16] = https://curl.se/bug/?i=11465
+ [17] = https://curl.se/bug/?i=11468
+ [18] = https://curl.se/bug/?i=11462
+ [19] = https://curl.se/bug/?i=11509
+ [20] = https://curl.se/bug/?i=11504
+ [21] = https://curl.se/bug/?i=11504
+ [22] = https://curl.se/bug/?i=11501
+ [23] = https://curl.se/bug/?i=11513
+ [24] = https://curl.se/bug/?i=10865
+ [25] = https://curl.se/bug/?i=11493
+ [26] = https://curl.se/bug/?i=11514
+ [27] = https://curl.se/bug/?i=11511
diff --git a/SECURITY.md b/SECURITY.md
index e0d4cfb..b76da78 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,16 +1,16 @@
<!--
-Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
# Security Policy
-See [docs/SECURITY-PROCESS.md](docs/SECURITY-PROCESS.md) for full details.
+See [SECURITY-PROCESS](docs/SECURITY-PROCESS.md) for full details.
## Reporting a Vulnerability
-If you have found or just suspect a security problem somewhere in curl or libcurl,
-report it on [https://hackerone.com/curl](https://hackerone.com/curl).
+If you have found or just suspect a security problem somewhere in curl or
+libcurl, report it on [HackerOne](https://hackerone.com/curl).
We treat security issues with confidentiality until controlled and disclosed responsibly.
diff --git a/acinclude.m4 b/acinclude.m4
index 313f4c6..df20049 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -345,88 +345,6 @@
])
-dnl CURL_CHECK_HEADER_WINLDAP
-dnl -------------------------------------------------
-dnl Check for compilable and valid winldap.h header
-
-AC_DEFUN([CURL_CHECK_HEADER_WINLDAP], [
- AC_REQUIRE([CURL_CHECK_HEADER_WINDOWS])dnl
- AC_CACHE_CHECK([for winldap.h], [curl_cv_header_winldap_h], [
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#undef inline
-#ifdef HAVE_WINDOWS_H
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#endif
-#include <winldap.h>
- ]],[[
-#if defined(__CYGWIN__) || defined(__CEGCC__)
- HAVE_WINLDAP_H shall not be defined.
-#else
- LDAP *ldp = ldap_init("dummy", LDAP_PORT);
- ULONG res = ldap_unbind(ldp);
-#endif
- ]])
- ],[
- curl_cv_header_winldap_h="yes"
- ],[
- curl_cv_header_winldap_h="no"
- ])
- ])
- case "$curl_cv_header_winldap_h" in
- yes)
- AC_DEFINE_UNQUOTED(HAVE_WINLDAP_H, 1,
- [Define to 1 if you have the winldap.h header file.])
- ;;
- esac
-])
-
-
-dnl CURL_CHECK_HEADER_WINBER
-dnl -------------------------------------------------
-dnl Check for compilable and valid winber.h header
-
-AC_DEFUN([CURL_CHECK_HEADER_WINBER], [
- AC_REQUIRE([CURL_CHECK_HEADER_WINLDAP])dnl
- AC_CACHE_CHECK([for winber.h], [curl_cv_header_winber_h], [
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#undef inline
-#ifdef HAVE_WINDOWS_H
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#endif
-#include <winldap.h>
-#include <winber.h>
- ]],[[
-#if defined(__CYGWIN__) || defined(__CEGCC__)
- HAVE_WINBER_H shall not be defined.
-#else
- BERVAL *bvp = NULL;
- BerElement *bep = ber_init(bvp);
- ber_free(bep, 1);
-#endif
- ]])
- ],[
- curl_cv_header_winber_h="yes"
- ],[
- curl_cv_header_winber_h="no"
- ])
- ])
- case "$curl_cv_header_winber_h" in
- yes)
- AC_DEFINE_UNQUOTED(HAVE_WINBER_H, 1,
- [Define to 1 if you have the winber.h header file.])
- ;;
- esac
-])
-
-
dnl CURL_CHECK_HEADER_LBER
dnl -------------------------------------------------
dnl Check for compilable and valid lber.h header,
@@ -602,58 +520,6 @@
])
-dnl CURL_CHECK_HEADER_LDAPSSL
-dnl -------------------------------------------------
-dnl Check for compilable and valid ldapssl.h header
-
-AC_DEFUN([CURL_CHECK_HEADER_LDAPSSL], [
- AC_REQUIRE([CURL_CHECK_HEADER_LDAP])dnl
- AC_CACHE_CHECK([for ldapssl.h], [curl_cv_header_ldapssl_h], [
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#undef inline
-#ifdef HAVE_WINDOWS_H
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#else
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#endif
-#ifndef NULL
-#define NULL (void *)0
-#endif
-#ifndef LDAP_DEPRECATED
-#define LDAP_DEPRECATED 1
-#endif
-#ifdef NEED_LBER_H
-#include <lber.h>
-#endif
-#ifdef HAVE_LDAP_H
-#include <ldap.h>
-#endif
-#include <ldapssl.h>
- ]],[[
- char *cert_label = NULL;
- LDAP *ldp = ldap_ssl_init("dummy", LDAPS_PORT, cert_label);
- ]])
- ],[
- curl_cv_header_ldapssl_h="yes"
- ],[
- curl_cv_header_ldapssl_h="no"
- ])
- ])
- case "$curl_cv_header_ldapssl_h" in
- yes)
- AC_DEFINE_UNQUOTED(HAVE_LDAPSSL_H, 1,
- [Define to 1 if you have the ldapssl.h header file.])
- ;;
- esac
-])
-
-
dnl CURL_CHECK_LIBS_WINLDAP
dnl -------------------------------------------------
dnl Check for libraries needed for WINLDAP support,
@@ -706,9 +572,7 @@
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
-#ifdef HAVE_WINLDAP_H
#include <winldap.h>
-#endif
#ifdef HAVE_WINBER_H
#include <winber.h>
#endif
@@ -858,108 +722,6 @@
])
-dnl CURL_CHECK_HEADER_MALLOC
-dnl -------------------------------------------------
-dnl Check for compilable and valid malloc.h header,
-dnl and check if it is needed even with stdlib.h
-
-AC_DEFUN([CURL_CHECK_HEADER_MALLOC], [
- AC_CACHE_CHECK([for malloc.h], [curl_cv_header_malloc_h], [
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#include <malloc.h>
- ]],[[
- void *p = malloc(10);
- void *q = calloc(10,10);
- free(p);
- free(q);
- ]])
- ],[
- curl_cv_header_malloc_h="yes"
- ],[
- curl_cv_header_malloc_h="no"
- ])
- ])
- if test "$curl_cv_header_malloc_h" = "yes"; then
- AC_DEFINE_UNQUOTED(HAVE_MALLOC_H, 1,
- [Define to 1 if you have the malloc.h header file.])
- #
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#include <stdlib.h>
- ]],[[
- void *p = malloc(10);
- void *q = calloc(10,10);
- free(p);
- free(q);
- ]])
- ],[
- curl_cv_need_header_malloc_h="no"
- ],[
- curl_cv_need_header_malloc_h="yes"
- ])
- #
- case "$curl_cv_need_header_malloc_h" in
- yes)
- AC_DEFINE_UNQUOTED(NEED_MALLOC_H, 1,
- [Define to 1 if you need the malloc.h header file even with stdlib.h])
- ;;
- esac
- fi
-])
-
-
-dnl CURL_CHECK_HEADER_MEMORY
-dnl -------------------------------------------------
-dnl Check for compilable and valid memory.h header,
-dnl and check if it is needed even with stdlib.h for
-dnl memory related functions.
-
-AC_DEFUN([CURL_CHECK_HEADER_MEMORY], [
- AC_CACHE_CHECK([for memory.h], [curl_cv_header_memory_h], [
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#include <memory.h>
- ]],[[
- void *p = malloc(10);
- void *q = calloc(10,10);
- free(p);
- free(q);
- ]])
- ],[
- curl_cv_header_memory_h="yes"
- ],[
- curl_cv_header_memory_h="no"
- ])
- ])
- if test "$curl_cv_header_memory_h" = "yes"; then
- AC_DEFINE_UNQUOTED(HAVE_MEMORY_H, 1,
- [Define to 1 if you have the memory.h header file.])
- #
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#include <stdlib.h>
- ]],[[
- void *p = malloc(10);
- void *q = calloc(10,10);
- free(p);
- free(q);
- ]])
- ],[
- curl_cv_need_header_memory_h="no"
- ],[
- curl_cv_need_header_memory_h="yes"
- ])
- #
- case "$curl_cv_need_header_memory_h" in
- yes)
- AC_DEFINE_UNQUOTED(NEED_MEMORY_H, 1,
- [Define to 1 if you need the memory.h header file even with stdlib.h])
- ;;
- esac
- fi
-])
-
dnl TYPE_SOCKADDR_STORAGE
dnl -------------------------------------------------
dnl Check for struct sockaddr_storage. Most IPv6-enabled
@@ -1000,15 +762,10 @@
dnl CURL_CHECK_FUNC_RECV
dnl -------------------------------------------------
dnl Test if the socket recv() function is available,
-dnl and check its return type and the types of its
-dnl arguments. If the function succeeds HAVE_RECV
-dnl will be defined, defining the types of the arguments
-dnl in RECV_TYPE_ARG1, RECV_TYPE_ARG2, RECV_TYPE_ARG3
-dnl and RECV_TYPE_ARG4, defining the type of the function
-dnl return value in RECV_TYPE_RETV.
AC_DEFUN([CURL_CHECK_FUNC_RECV], [
AC_REQUIRE([CURL_CHECK_HEADER_WINSOCK2])dnl
+ AC_REQUIRE([CURL_INCLUDES_BSDSOCKET])dnl
AC_CHECK_HEADERS(sys/types.h sys/socket.h)
#
AC_MSG_CHECKING([for recv])
@@ -1024,10 +781,7 @@
#include <winsock2.h>
#endif
#else
-#ifdef HAVE_PROTO_BSDSOCKET_H
-#include <proto/bsdsocket.h>
-struct Library *SocketBase = NULL;
-#endif
+$curl_includes_bsdsocket
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -1047,84 +801,9 @@
])
#
if test "$curl_cv_recv" = "yes"; then
- AC_CACHE_CHECK([types of args and return type for recv],
- [curl_cv_func_recv_args], [
- curl_cv_func_recv_args="unknown"
- for recv_retv in 'int' 'ssize_t'; do
- for recv_arg1 in 'int' 'ssize_t' 'SOCKET'; do
- for recv_arg2 in 'char *' 'void *'; do
- for recv_arg3 in 'size_t' 'int' 'socklen_t' 'unsigned int'; do
- for recv_arg4 in 'int' 'unsigned int'; do
- if test "$curl_cv_func_recv_args" = "unknown"; then
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#undef inline
-#ifdef HAVE_WINDOWS_H
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-#define RECVCALLCONV PASCAL
-#else
-#ifdef HAVE_PROTO_BSDSOCKET_H
-#include <proto/bsdsocket.h>
-struct Library *SocketBase = NULL;
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#define RECVCALLCONV
-#endif
-#ifndef HAVE_PROTO_BSDSOCKET_H
- extern $recv_retv RECVCALLCONV
- recv($recv_arg1, $recv_arg2, $recv_arg3, $recv_arg4);
-#endif
- ]],[[
- $recv_arg1 s=0;
- $recv_arg2 buf=0;
- $recv_arg3 len=0;
- $recv_arg4 flags=0;
- $recv_retv res = recv(s, buf, len, flags);
- ]])
- ],[
- curl_cv_func_recv_args="$recv_arg1,$recv_arg2,$recv_arg3,$recv_arg4,$recv_retv"
- ])
- fi
- done
- done
- done
- done
- done
- ]) # AC-CACHE-CHECK
- if test "$curl_cv_func_recv_args" = "unknown"; then
- AC_MSG_ERROR([Cannot find proper types to use for recv args])
- else
- recv_prev_IFS=$IFS; IFS=','
- set dummy `echo "$curl_cv_func_recv_args" | sed 's/\*/\*/g'`
- IFS=$recv_prev_IFS
- shift
- #
- AC_DEFINE_UNQUOTED(RECV_TYPE_ARG1, $[1],
- [Define to the type of arg 1 for recv.])
- AC_DEFINE_UNQUOTED(RECV_TYPE_ARG2, $[2],
- [Define to the type of arg 2 for recv.])
- AC_DEFINE_UNQUOTED(RECV_TYPE_ARG3, $[3],
- [Define to the type of arg 3 for recv.])
- AC_DEFINE_UNQUOTED(RECV_TYPE_ARG4, $[4],
- [Define to the type of arg 4 for recv.])
- AC_DEFINE_UNQUOTED(RECV_TYPE_RETV, $[5],
- [Define to the function return type for recv.])
- #
AC_DEFINE_UNQUOTED(HAVE_RECV, 1,
[Define to 1 if you have the recv function.])
curl_cv_func_recv="yes"
- fi
else
AC_MSG_ERROR([Unable to link function recv])
fi
@@ -1134,16 +813,10 @@
dnl CURL_CHECK_FUNC_SEND
dnl -------------------------------------------------
dnl Test if the socket send() function is available,
-dnl and check its return type and the types of its
-dnl arguments. If the function succeeds HAVE_SEND
-dnl will be defined, defining the types of the arguments
-dnl in SEND_TYPE_ARG1, SEND_TYPE_ARG2, SEND_TYPE_ARG3
-dnl and SEND_TYPE_ARG4, defining the type of the function
-dnl return value in SEND_TYPE_RETV, and also defining the
-dnl type qualifier of second argument in SEND_QUAL_ARG2.
AC_DEFUN([CURL_CHECK_FUNC_SEND], [
AC_REQUIRE([CURL_CHECK_HEADER_WINSOCK2])dnl
+ AC_REQUIRE([CURL_INCLUDES_BSDSOCKET])dnl
AC_CHECK_HEADERS(sys/types.h sys/socket.h)
#
AC_MSG_CHECKING([for send])
@@ -1159,10 +832,7 @@
#include <winsock2.h>
#endif
#else
-#ifdef HAVE_PROTO_BSDSOCKET_H
-#include <proto/bsdsocket.h>
-struct Library *SocketBase = NULL;
-#endif
+$curl_includes_bsdsocket
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -1182,117 +852,9 @@
])
#
if test "$curl_cv_send" = "yes"; then
- AC_CACHE_CHECK([types of args and return type for send],
- [curl_cv_func_send_args], [
- curl_cv_func_send_args="unknown"
- for send_retv in 'int' 'ssize_t'; do
- for send_arg1 in 'int' 'ssize_t' 'SOCKET'; do
- for send_arg2 in 'char *' 'void *' 'const char *' 'const void *'; do
- for send_arg3 in 'size_t' 'int' 'socklen_t' 'unsigned int'; do
- for send_arg4 in 'int' 'unsigned int'; do
- if test "$curl_cv_func_send_args" = "unknown"; then
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#undef inline
-#ifdef HAVE_WINDOWS_H
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-#define SENDCALLCONV PASCAL
-#else
-#ifdef HAVE_PROTO_BSDSOCKET_H
-#include <proto/bsdsocket.h>
-struct Library *SocketBase = NULL;
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#define SENDCALLCONV
-#endif
-#ifndef HAVE_PROTO_BSDSOCKET_H
- extern $send_retv SENDCALLCONV
- send($send_arg1, $send_arg2, $send_arg3, $send_arg4);
-#endif
- ]],[[
- $send_arg1 s=0;
- $send_arg3 len=0;
- $send_arg4 flags=0;
- $send_retv res = send(s, 0, len, flags);
- ]])
- ],[
- curl_cv_func_send_args="$send_arg1,$send_arg2,$send_arg3,$send_arg4,$send_retv"
- ])
- fi
- done
- done
- done
- done
- done
- ]) # AC-CACHE-CHECK
- if test "$curl_cv_func_send_args" = "unknown"; then
- AC_MSG_ERROR([Cannot find proper types to use for send args])
- else
- send_prev_IFS=$IFS; IFS=','
- set dummy `echo "$curl_cv_func_send_args" | sed 's/\*/\*/g'`
- IFS=$send_prev_IFS
- shift
- #
- send_qual_type_arg2=$[2]
- #
- AC_DEFINE_UNQUOTED(SEND_TYPE_ARG1, $[1],
- [Define to the type of arg 1 for send.])
- AC_DEFINE_UNQUOTED(SEND_TYPE_ARG3, $[3],
- [Define to the type of arg 3 for send.])
- AC_DEFINE_UNQUOTED(SEND_TYPE_ARG4, $[4],
- [Define to the type of arg 4 for send.])
- AC_DEFINE_UNQUOTED(SEND_TYPE_RETV, $[5],
- [Define to the function return type for send.])
- #
- prev_sh_opts=$-
- #
- case $prev_sh_opts in
- *f*)
- ;;
- *)
- set -f
- ;;
- esac
- #
- case "$send_qual_type_arg2" in
- const*)
- send_qual_arg2=const
- send_type_arg2=`echo $send_qual_type_arg2 | sed 's/^const //'`
- ;;
- *)
- send_qual_arg2=
- send_type_arg2=$send_qual_type_arg2
- ;;
- esac
- #
- AC_DEFINE_UNQUOTED(SEND_QUAL_ARG2, $send_qual_arg2,
- [Define to the type qualifier of arg 2 for send.])
- AC_DEFINE_UNQUOTED(SEND_TYPE_ARG2, $send_type_arg2,
- [Define to the type of arg 2 for send.])
- #
- case $prev_sh_opts in
- *f*)
- ;;
- *)
- set +f
- ;;
- esac
- #
- AC_DEFINE_UNQUOTED(HAVE_SEND, 1,
- [Define to 1 if you have the send function.])
- curl_cv_func_send="yes"
- fi
+ AC_DEFINE_UNQUOTED(HAVE_SEND, 1,
+ [Define to 1 if you have the send function.])
+ curl_cv_func_send="yes"
else
AC_MSG_ERROR([Unable to link function send])
fi
@@ -1317,10 +879,6 @@
#include <winsock2.h>
#endif
#else
-#ifdef HAVE_PROTO_BSDSOCKET_H
-#include <proto/bsdsocket.h>
-struct Library *SocketBase = NULL;
-#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -1514,6 +1072,38 @@
dnl until library linking and run-time checks for clock_gettime succeed.
])
+dnl CURL_CHECK_FUNC_CLOCK_GETTIME_MONOTONIC_RAW
+dnl -------------------------------------------------
+dnl Check if monotonic clock_gettime is available.
+
+AC_DEFUN([CURL_CHECK_FUNC_CLOCK_GETTIME_MONOTONIC_RAW], [
+ AC_CHECK_HEADERS(sys/types.h sys/time.h)
+ AC_MSG_CHECKING([for raw monotonic clock_gettime])
+ #
+ if test "x$dontwant_rt" = "xno" ; then
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <time.h>
+ ]],[[
+ struct timespec ts;
+ (void)clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+ ]])
+ ],[
+ AC_MSG_RESULT([yes])
+ AC_DEFINE_UNQUOTED(HAVE_CLOCK_GETTIME_MONOTONIC_RAW, 1,
+ [Define to 1 if you have the clock_gettime function and raw monotonic timer.])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+ fi
+])
+
dnl CURL_CHECK_LIBS_CLOCK_GETTIME_MONOTONIC
dnl -------------------------------------------------
@@ -1728,18 +1318,11 @@
dnl CURL_CHECK_FUNC_SELECT
dnl -------------------------------------------------
-dnl Test if the socket select() function is available,
-dnl and check its return type and the types of its
-dnl arguments. If the function succeeds HAVE_SELECT
-dnl will be defined, defining the types of the
-dnl arguments in SELECT_TYPE_ARG1, SELECT_TYPE_ARG234
-dnl and SELECT_TYPE_ARG5, defining the type of the
-dnl function return value in SELECT_TYPE_RETV, and
-dnl also defining the type qualifier of fifth argument
-dnl in SELECT_QUAL_ARG5.
+dnl Test if the socket select() function is available.
AC_DEFUN([CURL_CHECK_FUNC_SELECT], [
AC_REQUIRE([CURL_CHECK_STRUCT_TIMEVAL])dnl
+ AC_REQUIRE([CURL_INCLUDES_BSDSOCKET])dnl
AC_CHECK_HEADERS(sys/select.h sys/socket.h)
#
AC_MSG_CHECKING([for select])
@@ -1771,11 +1354,7 @@
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
-#ifdef HAVE_PROTO_BSDSOCKET_H
-#include <proto/bsdsocket.h>
-struct Library *SocketBase = NULL;
-#define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
-#endif
+$curl_includes_bsdsocket
#endif
]],[[
select(0, 0, 0, 0, 0);
@@ -1789,136 +1368,9 @@
])
#
if test "$curl_cv_select" = "yes"; then
- AC_CACHE_CHECK([types of args and return type for select],
- [curl_cv_func_select_args], [
- curl_cv_func_select_args="unknown"
- for sel_retv in 'int' 'ssize_t'; do
- for sel_arg1 in 'int' 'ssize_t' 'size_t' 'unsigned long int' 'unsigned int'; do
- for sel_arg234 in 'fd_set *' 'int *' 'void *'; do
- for sel_arg5 in 'struct timeval *' 'const struct timeval *'; do
- if test "$curl_cv_func_select_args" = "unknown"; then
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#undef inline
-#ifdef HAVE_WINDOWS_H
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-#define SELECTCALLCONV PASCAL
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <time.h>
-#ifndef HAVE_WINDOWS_H
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#elif defined(HAVE_UNISTD_H)
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_PROTO_BSDSOCKET_H
-#include <proto/bsdsocket.h>
-struct Library *SocketBase = NULL;
-#define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
-#endif
-#define SELECTCALLCONV
-#endif
-#ifndef HAVE_STRUCT_TIMEVAL
- struct timeval {
- long tv_sec;
- long tv_usec;
- };
-#endif
-#ifndef HAVE_PROTO_BSDSOCKET_H
- extern $sel_retv SELECTCALLCONV
- select($sel_arg1,
- $sel_arg234,
- $sel_arg234,
- $sel_arg234,
- $sel_arg5);
-#endif
- ]],[[
- $sel_arg1 nfds=0;
- $sel_arg234 rfds=0;
- $sel_arg234 wfds=0;
- $sel_arg234 efds=0;
- $sel_retv res = select(nfds, rfds, wfds, efds, 0);
- ]])
- ],[
- curl_cv_func_select_args="$sel_arg1,$sel_arg234,$sel_arg5,$sel_retv"
- ])
- fi
- done
- done
- done
- done
- ]) # AC-CACHE-CHECK
- if test "$curl_cv_func_select_args" = "unknown"; then
- AC_MSG_WARN([Cannot find proper types to use for select args])
- AC_MSG_WARN([HAVE_SELECT will not be defined])
- else
- select_prev_IFS=$IFS; IFS=','
- set dummy `echo "$curl_cv_func_select_args" | sed 's/\*/\*/g'`
- IFS=$select_prev_IFS
- shift
- #
- sel_qual_type_arg5=$[3]
- #
- AC_DEFINE_UNQUOTED(SELECT_TYPE_ARG1, $[1],
- [Define to the type of arg 1 for select.])
- AC_DEFINE_UNQUOTED(SELECT_TYPE_ARG234, $[2],
- [Define to the type of args 2, 3 and 4 for select.])
- AC_DEFINE_UNQUOTED(SELECT_TYPE_RETV, $[4],
- [Define to the function return type for select.])
- #
- prev_sh_opts=$-
- #
- case $prev_sh_opts in
- *f*)
- ;;
- *)
- set -f
- ;;
- esac
- #
- case "$sel_qual_type_arg5" in
- const*)
- sel_qual_arg5=const
- sel_type_arg5=`echo $sel_qual_type_arg5 | sed 's/^const //'`
- ;;
- *)
- sel_qual_arg5=
- sel_type_arg5=$sel_qual_type_arg5
- ;;
- esac
- #
- AC_DEFINE_UNQUOTED(SELECT_QUAL_ARG5, $sel_qual_arg5,
- [Define to the type qualifier of arg 5 for select.])
- AC_DEFINE_UNQUOTED(SELECT_TYPE_ARG5, $sel_type_arg5,
- [Define to the type of arg 5 for select.])
- #
- case $prev_sh_opts in
- *f*)
- ;;
- *)
- set +f
- ;;
- esac
- #
- AC_DEFINE_UNQUOTED(HAVE_SELECT, 1,
- [Define to 1 if you have the select function.])
- curl_cv_func_select="yes"
- fi
+ AC_DEFINE_UNQUOTED(HAVE_SELECT, 1,
+ [Define to 1 if you have the select function.])
+ curl_cv_func_select="yes"
fi
])
diff --git a/appveyor.yml b/appveyor.yml
index f886ea8..fda46e6 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -21,13 +21,18 @@
# SPDX-License-Identifier: curl
#
###########################################################################
+# https://ci.appveyor.com/project/curlorg/curl/history
+# Appveyor configuration
+# https://www.appveyor.com/docs/appveyor-yml/
version: 7.50.0.{build}
environment:
+ UNITY: "OFF"
matrix:
# generated CMake-based Visual Studio Release builds
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
+ - job_name: "CMake, VS2008, Release x86, Schannel"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
BUILD_SYSTEM: CMake
PRJ_GEN: "Visual Studio 9 2008"
PRJ_CFG: Release
@@ -38,7 +43,8 @@
TESTING: OFF
SHARED: ON
DISABLED_TESTS: ""
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
+ - job_name: "CMake, VS2022, Release x64, OpenSSL, WebSockets, Unity"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
BUILD_SYSTEM: CMake
PRJ_GEN: "Visual Studio 17 2022"
TARGET: "-A x64"
@@ -50,7 +56,10 @@
TESTING: OFF
SHARED: ON
DISABLED_TESTS: ""
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
+ WEBSOCKETS: ON
+ UNITY: "ON"
+ - job_name: "CMake, VS2022, Release arm64, Schannel, Static"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
BUILD_SYSTEM: CMake
PRJ_GEN: "Visual Studio 17 2022"
TARGET: "-A ARM64"
@@ -63,7 +72,8 @@
SHARED: OFF
DISABLED_TESTS: ""
# generated CMake-based Visual Studio Debug builds
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
+ - job_name: "CMake, VS2010, Debug x64, no SSL, Static"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
BUILD_SYSTEM: CMake
PRJ_GEN: "Visual Studio 10 2010 Win64"
PRJ_CFG: Debug
@@ -73,9 +83,10 @@
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "!1139 !1501"
+ DISABLED_TESTS: "!1139 !1501 ~1056"
ADD_PATH: "C:\\msys64\\usr\\bin"
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
+ - job_name: "CMake, VS2022, Debug x64, Schannel, Static, Unicode"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
BUILD_SYSTEM: CMake
PRJ_GEN: "Visual Studio 17 2022"
TARGET: "-A x64"
@@ -86,9 +97,10 @@
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "~571 !1139 !1501 "
+ DISABLED_TESTS: "~571 !1139 !1501 ~1056"
ADD_PATH: "C:\\msys64\\usr\\bin"
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
+ - job_name: "CMake, VS2022, Debug x64, no SSL, Static"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
BUILD_SYSTEM: CMake
PRJ_GEN: "Visual Studio 17 2022"
TARGET: "-A x64"
@@ -99,9 +111,10 @@
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "~571 !1139 !1501"
+ DISABLED_TESTS: "~571 !1139 !1501 ~1056"
ADD_PATH: "C:\\msys64\\usr\\bin"
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
+ - job_name: "CMake, VS2022, Debug x64, no SSL, Static, HTTP only"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
BUILD_SYSTEM: CMake
PRJ_GEN: "Visual Studio 17 2022"
TARGET: "-A x64"
@@ -112,10 +125,11 @@
HTTP_ONLY: ON
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "!1139 !1501"
+ DISABLED_TESTS: "!1139 !1501 ~1056"
ADD_PATH: "C:\\msys64\\usr\\bin"
# generated CMake-based MSYS Makefiles builds (mingw cross-compiling)
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
+ - job_name: "CMake, mingw-w64, gcc 8, Debug x64, Schannel, Static, Unicode"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
BUILD_SYSTEM: CMake
PRJ_GEN: "MSYS Makefiles"
PRJ_CFG: Debug
@@ -125,11 +139,12 @@
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "!1139 !1501"
+ DISABLED_TESTS: "!1139 !1501 ~1056"
ADD_PATH: "C:\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin;C:\\msys64\\usr\\bin"
MSYS2_ARG_CONV_EXCL: "/*"
BUILD_OPT: -k
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
+ - job_name: "CMake, mingw-w64, gcc 7, Debug x64, Schannel, Static, Unicode"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
BUILD_SYSTEM: CMake
PRJ_GEN: "MSYS Makefiles"
PRJ_CFG: Debug
@@ -139,11 +154,27 @@
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "!1139 !1501"
+ DISABLED_TESTS: "!1139 !1501 ~1056"
ADD_PATH: "C:\\mingw-w64\\x86_64-7.2.0-posix-seh-rt_v5-rev1\\mingw64\\bin;C:\\msys64\\usr\\bin"
MSYS2_ARG_CONV_EXCL: "/*"
BUILD_OPT: -k
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
+ - job_name: "CMake, mingw-w64, Debug x64, Schannel, Static, Unity"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
+ BUILD_SYSTEM: CMake
+ PRJ_GEN: "MSYS Makefiles"
+ PRJ_CFG: Debug
+ OPENSSL: OFF
+ SCHANNEL: ON
+ ENABLE_UNICODE: OFF
+ HTTP_ONLY: OFF
+ TESTING: OFF
+ SHARED: OFF
+ ADD_PATH: "C:\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin;C:\\msys64\\usr\\bin"
+ MSYS2_ARG_CONV_EXCL: "/*"
+ BUILD_OPT: -k
+ UNITY: "ON"
+ - job_name: "CMake, mingw-w64, Debug x86, Schannel, Static"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
BUILD_SYSTEM: CMake
PRJ_GEN: "MSYS Makefiles"
PRJ_CFG: Debug
@@ -153,11 +184,12 @@
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "!1139 !1501"
+ DISABLED_TESTS: "!1139 !1501 ~1056"
ADD_PATH: "C:\\mingw-w64\\i686-6.3.0-posix-dwarf-rt_v5-rev1\\mingw32\\bin;C:\\msys64\\usr\\bin"
MSYS2_ARG_CONV_EXCL: "/*"
BUILD_OPT: -k
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
+ - job_name: "CMake, mingw, Debug x86, no SSL, Static"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
BUILD_SYSTEM: CMake
PRJ_GEN: "MSYS Makefiles"
PRJ_CFG: Debug
@@ -167,91 +199,104 @@
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "!1139 !1501"
+ DISABLED_TESTS: "!1139 !1501 ~1056"
ADD_PATH: "C:\\MinGW\\bin;C:\\msys64\\usr\\bin"
MSYS2_ARG_CONV_EXCL: "/*"
BUILD_OPT: -k
# winbuild-based builds
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
+ - job_name: "winbuild, VS2015, Debug"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
BUILD_SYSTEM: winbuild_vs2015
DEBUG: yes
PATHPART: debug
TESTING: OFF
ENABLE_UNICODE: no
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
+ - job_name: "winbuild, VS2015, Release"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
BUILD_SYSTEM: winbuild_vs2015
DEBUG: no
PATHPART: release
TESTING: OFF
ENABLE_UNICODE: no
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
+ - job_name: "winbuild, VS2017, Debug"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
BUILD_SYSTEM: winbuild_vs2017
DEBUG: yes
PATHPART: debug
TESTING: OFF
ENABLE_UNICODE: no
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
+ - job_name: "winbuild, VS2017, Release"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
BUILD_SYSTEM: winbuild_vs2017
DEBUG: no
PATHPART: release
TESTING: OFF
ENABLE_UNICODE: no
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
+ - job_name: "winbuild, VS2015, Debug, Unicode"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
BUILD_SYSTEM: winbuild_vs2015
DEBUG: yes
PATHPART: debug
TESTING: OFF
ENABLE_UNICODE: yes
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
+ - job_name: "winbuild, VS2015, Release, Unicode"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
BUILD_SYSTEM: winbuild_vs2015
DEBUG: no
PATHPART: release
TESTING: OFF
ENABLE_UNICODE: yes
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
+ - job_name: "winbuild, VS2017, Debug, Unicode"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
BUILD_SYSTEM: winbuild_vs2017
DEBUG: yes
PATHPART: debug
TESTING: OFF
ENABLE_UNICODE: yes
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
+ - job_name: "winbuild, VS2017, Release, Unicode"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
BUILD_SYSTEM: winbuild_vs2017
DEBUG: no
PATHPART: release
TESTING: OFF
ENABLE_UNICODE: yes
# generated VisualStudioSolution-based builds
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
+ - job_name: "VisualStudioSolution, VS2017, Debug"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
BUILD_SYSTEM: VisualStudioSolution
PRJ_CFG: "DLL Debug - DLL Windows SSPI - DLL WinIDN"
TESTING: OFF
VC_VERSION: VC14.10
# autotools-based builds (NOT mingw cross-compiling, but msys2 native)
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
+ - job_name: "autotools, msys2, Debug, no Proxy, no SSL"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
BUILD_SYSTEM: autotools
TESTING: ON
DISABLED_TESTS: "!19 ~1056 !1233"
ADD_PATH: "C:\\msys64\\usr\\bin"
- CONFIG_ARGS: "--enable-debug --enable-werror --disable-threaded-resolver --disable-proxy --with-schannel"
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
+ CONFIG_ARGS: "--enable-debug --enable-werror --disable-threaded-resolver --disable-proxy --without-ssl --enable-websockets"
+ - job_name: "autotools, msys2, Debug, no SSL"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
BUILD_SYSTEM: autotools
TESTING: ON
DISABLED_TESTS: "!19 !504 !704 !705 ~1056 !1233"
ADD_PATH: "C:\\msys64\\usr\\bin"
- CONFIG_ARGS: "--enable-debug --enable-werror --disable-threaded-resolver --with-schannel"
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
+ CONFIG_ARGS: "--enable-debug --enable-werror --disable-threaded-resolver --without-ssl --enable-websockets"
+ - job_name: "autotools, msys2, Release, no SSL"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
BUILD_SYSTEM: autotools
TESTING: ON
DISABLED_TESTS: "!19 !504 !704 !705 ~1056 !1233"
ADD_PATH: "C:\\msys64\\usr\\bin"
- CONFIG_ARGS: "--enable-warnings --enable-werror --with-schannel"
+ CONFIG_ARGS: "--enable-warnings --enable-werror --without-ssl --enable-websockets"
# autotools-based Cygwin build
- - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
+ - job_name: "autotools, cygwin, Debug, no SSL"
+ APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2022"
BUILD_SYSTEM: autotools
TESTING: ON
DISABLED_TESTS: "~1056"
ADD_PATH: "C:\\cygwin64\\bin"
- CONFIG_ARGS: "--enable-debug --enable-werror --disable-threaded-resolver --without-ssl"
+ CONFIG_ARGS: "--enable-debug --enable-werror --disable-threaded-resolver --without-ssl --enable-websockets"
POSIX_PATH_PREFIX: "/cygdrive"
install:
@@ -268,6 +313,8 @@
-DHTTP_ONLY=%HTTP_ONLY%
-DBUILD_SHARED_LIBS=%SHARED%
-DBUILD_TESTING=%TESTING%
+ -DENABLE_WEBSOCKETS=%WEBSOCKETS%
+ -DCMAKE_UNITY_BUILD=%UNITY%
-DCURL_WERROR=ON
-DENABLE_DEBUG=ON
-DENABLE_UNICODE=%ENABLE_UNICODE%
@@ -306,15 +353,19 @@
))
test_script:
+ - if exist C:/msys64/usr/bin/curl.exe (
+ set ACURL=-ac %POSIX_PATH_PREFIX%/c/msys64/usr/bin/curl.exe )
+ - if exist C:/Windows/System32/curl.exe (
+ set ACURL=-ac %POSIX_PATH_PREFIX%/c/Windows/System32/curl.exe )
- if %TESTING%==ON (
if %BUILD_SYSTEM%==CMake (
- set TFLAGS=%DISABLED_TESTS% &&
+ set TFLAGS=%ACURL% %DISABLED_TESTS% &&
cmake --build . --config %PRJ_CFG% --target test-ci
) else (
if %BUILD_SYSTEM%==autotools (
- bash.exe -e -l -c "cd %POSIX_PATH_PREFIX%/c/projects/curl && make V=1 TFLAGS='%DISABLED_TESTS%' test-ci"
+ bash.exe -e -l -c "cd %POSIX_PATH_PREFIX%/c/projects/curl && make V=1 TFLAGS='%ACURL% %DISABLED_TESTS%' test-ci"
) else (
- bash.exe -e -l -c "cd %POSIX_PATH_PREFIX%/c/projects/curl/tests && ./runtests.pl -a -p !flaky -r -rm %DISABLED_TESTS%"
+ bash.exe -e -l -c "cd %POSIX_PATH_PREFIX%/c/projects/curl/tests && ./runtests.pl -a -p !flaky -r -rm %ACURL% %DISABLED_TESTS%"
))
)
@@ -324,8 +375,17 @@
- master
- /\/ci$/
+skip_commits:
+ files:
+ - '.azure-pipelines.yml'
+ - '.circleci/**/*'
+ - '.cirrus.yml'
+ - '.github/**/*'
+ - 'packages/**/*'
+ - 'plan9/**/*'
+
artifacts:
- path: '**/curl.exe'
name: curl
- path: '**/*curl*.dll'
- name: libcurl
+ name: libcurl dll
diff --git a/buildconf b/buildconf
index 16fc8a7..ee6a280 100755
--- a/buildconf
+++ b/buildconf
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/buildconf.bat b/buildconf.bat
index d779795..6153661 100644
--- a/buildconf.bat
+++ b/buildconf.bat
@@ -6,7 +6,7 @@
rem * | (__| |_| | _ <| |___
rem * \___|\___/|_| \_\_____|
rem *
-rem * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+rem * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
rem *
rem * This software is licensed as described in the file COPYING, which
rem * you should have received as part of this distribution. The terms
diff --git a/configure.ac b/configure.ac
index de2dee5..71b9f5b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -33,7 +33,7 @@
CURL_OVERRIDE_AUTOCONF
dnl configure script copyright
-AC_COPYRIGHT([Copyright (c) 1998 - 2022 Daniel Stenberg, <daniel@haxx.se>
+AC_COPYRIGHT([Copyright (C) Daniel Stenberg, <daniel@haxx.se>
This configure script may be copied, distributed and modified under the
terms of the curl license; see COPYING for more details])
@@ -85,21 +85,22 @@
fi
AC_SUBST([GREP])
-dnl EGREP is mandatory for configure process and libtool.
+dnl 'grep -E' is mandatory for configure process and libtool.
dnl Set it now, allowing it to be changed later.
if test -z "$EGREP"; then
dnl allow it to be overridden
+ AC_MSG_CHECKING([that grep -E works])
if echo a | ($GREP -E '(a|b)') >/dev/null 2>&1; then
- AC_MSG_CHECKING([for egrep])
EGREP="$GREP -E"
- AC_MSG_RESULT([$EGREP])
+ AC_MSG_RESULT([yes])
else
+ AC_MSG_RESULT([no])
AC_PATH_PROG([EGREP], [egrep], [not_found],
[$PATH:/usr/bin:/usr/local/bin])
fi
fi
if test -z "$EGREP" || test "$EGREP" = "not_found"; then
- AC_MSG_ERROR([egrep not found in PATH. Cannot continue without egrep.])
+ AC_MSG_ERROR([grep -E is not working and egrep is not found in PATH. Cannot continue.])
fi
AC_SUBST([EGREP])
@@ -170,10 +171,11 @@
curl_altsvc_msg="enabled (--disable-alt-svc)"
curl_headers_msg="enabled (--disable-headers-api)"
curl_hsts_msg="enabled (--disable-hsts)"
+ curl_ws_msg="no (--enable-websockets)"
ssl_backends=
curl_h1_msg="enabled (internal)"
curl_h2_msg="no (--with-nghttp2, --with-hyper)"
- curl_h3_msg="no (--with-ngtcp2, --with-quiche --with-msh3)"
+ curl_h3_msg="no (--with-ngtcp2 --with-nghttp3, --with-quiche, --with-msh3)"
enable_altsvc="yes"
hsts="yes"
@@ -184,6 +186,25 @@
INITIAL_LDFLAGS=$LDFLAGS
INITIAL_LIBS=$LIBS
+dnl
+dnl Generates a shell script to run the compiler with LD_LIBRARY_PATH set to
+dnl the value used right now. This lets CURL_RUN_IFELSE set LD_LIBRARY_PATH to
+dnl something different but only have that affect the execution of the results
+dnl of the compile, not change the libraries for the compiler itself.
+dnl
+compilersh="run-compiler"
+CURL_SAVED_CC="$CC"
+export CURL_SAVED_CC
+CURL_SAVED_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
+export CURL_SAVED_LD_LIBRARY_PATH
+cat <<\EOF > "$compilersh"
+CC="$CURL_SAVED_CC"
+export CC
+LD_LIBRARY_PATH="$CURL_SAVED_LD_LIBRARY_PATH"
+export LD_LIBRARY_PATH
+exec $CC "$@"
+EOF
+
dnl **********************************************************************
dnl See which TLS backend(s) that are requested. Just do all the
dnl TLS AC_ARG_WITH() invokes here and do the checks later
@@ -196,76 +217,86 @@
OPT_SECURETRANSPORT=no
AC_ARG_WITH(secure-transport,dnl
-AS_HELP_STRING([--with-secure-transport],[enable Apple OS native SSL/TLS]),
+AS_HELP_STRING([--with-secure-transport],[enable Apple OS native SSL/TLS]),[
OPT_SECURETRANSPORT=$withval
- test -z "TLSCHOICE" || TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }Secure-Transport"
-)
+ TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }Secure-Transport"
+])
OPT_AMISSL=no
AC_ARG_WITH(amissl,dnl
-AS_HELP_STRING([--with-amissl],[enable Amiga native SSL/TLS (AmiSSL)]),
+AS_HELP_STRING([--with-amissl],[enable Amiga native SSL/TLS (AmiSSL)]),[
OPT_AMISSL=$withval
- test -z "TLSCHOICE" || TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }AmiSSL")
+ TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }AmiSSL"
+])
OPT_OPENSSL=no
dnl Default to no CA bundle
ca="no"
AC_ARG_WITH(ssl,dnl
AS_HELP_STRING([--with-ssl=PATH],[old version of --with-openssl])
-AS_HELP_STRING([--without-ssl], [build without any TLS library]),
+AS_HELP_STRING([--without-ssl], [build without any TLS library]),[
OPT_SSL=$withval
OPT_OPENSSL=$withval
if test X"$withval" != Xno; then
- test -z "TLSCHOICE" || TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }OpenSSL")
+ TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }OpenSSL"
+ else
+ SSL_DISABLED="D"
fi
+])
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]),
+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
- test -z "TLSCHOICE" || TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }OpenSSL")
+ TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }OpenSSL"
fi
+])
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]),
+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
- test -z "TLSCHOICE" || TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }GnuTLS")
+ TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }GnuTLS"
fi
+])
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]),
+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
- test -z "TLSCHOICE" || TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }mbedTLS")
+ TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }mbedTLS"
fi
+])
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)]),
+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
- test -z "TLSCHOICE" || TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }wolfSSL")
+ TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }wolfSSL"
fi
+])
OPT_BEARSSL=no
AC_ARG_WITH(bearssl,dnl
-AS_HELP_STRING([--with-bearssl=PATH],[where to look for BearSSL, PATH points to the installation root]),
+AS_HELP_STRING([--with-bearssl=PATH],[where to look for BearSSL, PATH points to the installation root]),[
OPT_BEARSSL=$withval
if test X"$withval" != Xno; then
- test -z "TLSCHOICE" || TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }BearSSL")
+ TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }BearSSL"
fi
+])
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]),
+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
- test -z "TLSCHOICE" || TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }rustls")
+ TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }rustls"
experimental="$experimental rustls"
fi
+])
OPT_NSS_AWARE=no
AC_ARG_WITH(nss-deprecated,dnl
@@ -285,10 +316,105 @@
AC_MSG_ERROR([NSS use must be confirmed using --with-nss-deprecated. NSS support will be dropped from curl in August 2022. See docs/DEPRECATE.md])
fi
- test -z "TLSCHOICE" || TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }NSS"
+ [TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }NSS"]
fi
)
+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"$OPT_TEST_NGHTTPX" = "Xno" ; then
+ TEST_NGHTTPX=""
+ fi
+)
+AC_SUBST(TEST_NGHTTPX)
+
+CADDY=caddy
+AC_ARG_WITH(test-caddy,dnl
+AS_HELP_STRING([--with-test-caddy=PATH],[where to find caddy for testing]),
+ CADDY=$withval
+ if test X"$OPT_CADDY" = "Xno" ; then
+ CADDY=""
+ fi
+)
+AC_SUBST(CADDY)
+
+dnl we'd like a httpd+apachectl 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 "/usr/sbin/apache2" -a -x "/usr/sbin/apache2ctl"; then
+ # common location on distros (debian/ubuntu)
+ HTTPD="/usr/sbin/apache2"
+ APACHECTL="/usr/sbin/apache2ctl"
+ AC_PATH_PROG([APXS], [apxs])
+ if test "x$APXS" = "x"; 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
+ AC_PATH_PROG([HTTPD], [apache2])
+ fi
+ AC_PATH_PROG([APACHECTL], [apachectl])
+ AC_PATH_PROG([APXS], [apxs])
+ if test "x$HTTPD" = "x" -o "x$APACHECTL" = "x"; then
+ AC_MSG_NOTICE([httpd/apache2 not in PATH, http tests disabled])
+ HTTPD_ENABLED="no"
+ fi
+ if test "x$APXS" = "x"; then
+ AC_MSG_NOTICE([apxs not in PATH, http tests disabled])
+ HTTPD_ENABLED="no"
+ fi
+ fi
+elif test x"$request_httpd" != "xno"; then
+ HTTPD="${request_httpd}/bin/httpd"
+ APACHECTL="${request_httpd}/bin/apachectl"
+ APXS="${request_httpd}/bin/apxs"
+ if test ! -x "${HTTPD}"; then
+ AC_MSG_NOTICE([httpd not found as ${HTTPD}, http tests disabled])
+ HTTPD_ENABLED="no"
+ elif test ! -x "${APACHECTL}"; then
+ AC_MSG_NOTICE([apachectl not found as ${APACHECTL}, http tests disabled])
+ HTTPD_ENABLED="no"
+ elif test ! -x "${APXS}"; then
+ AC_MSG_NOTICE([apxs not found as ${APXS}, http tests disabled])
+ HTTPD_ENABLED="no"
+ else
+ AC_MSG_NOTICE([using HTTPD=$HTTPD for tests])
+ fi
+fi
+if test x"$HTTPD_ENABLED" = "xno"; then
+ HTTPD=""
+ APACHECTL=""
+ APXS=""
+fi
+AC_SUBST(HTTPD)
+AC_SUBST(APACHECTL)
+AC_SUBST(APXS)
+
+dnl the nghttpx we might use in httpd testing
+if test "x$TEST_NGHTTPX" != "x" -a "x$TEST_NGHTTPX" != "xnghttpx"; then
+ HTTPD_NGHTTPX="$TEST_NGHTTPX"
+else
+ AC_PATH_PROG([HTTPD_NGHTTPX], [nghttpx], [],
+ [$PATH:/usr/bin:/usr/local/bin])
+fi
+AC_SUBST(HTTPD_NGHTTPX)
+
+dnl the Caddy server we might use in testing
+if test "x$TEST_CADDY" != "x"; then
+ CADDY="$TEST_CADDY"
+else
+ AC_PATH_PROG([CADDY], [caddy])
+fi
+AC_SUBST(CADDY)
+
dnl If no TLS choice has been made, check if it was explicitly disabled or
dnl error out to force the user to decide.
if test -z "$TLSCHOICE"; then
@@ -312,7 +438,7 @@
fi
AC_ARG_WITH(darwinssl,,
- AC_MSG_ERROR([--with-darwin-ssl no longer works!]))
+ AC_MSG_ERROR([--with-darwin-ssl and --without-darwin-ssl no longer work!]))
dnl
dnl Detect the canonical host and target build environment
@@ -337,6 +463,8 @@
XC_LIBTOOL
+LT_LANG([Windows Resource])
+
#
# Automake conditionals based on libtool related checks
#
@@ -500,6 +628,41 @@
;;
esac
+# Detect original MinGW (not MinGW-w64)
+curl_mingw_original=no
+case $host in
+ *-*-mingw32*)
+ AC_MSG_CHECKING([using original MinGW (not MinGW-w64)])
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+#include <_mingw.h>
+ ]],[[
+#if defined(__MINGW64_VERSION_MAJOR)
+#error
+#endif
+ ]])
+ ],[
+ curl_mingw_original=yes
+ curl_mingw_die=yes
+ AC_MSG_RESULT([yes])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+ ;;
+esac
+
+
+AC_ARG_WITH(mingw1-deprecated,dnl
+AS_HELP_STRING([--with-mingw1-deprecated],[confirm you realize support for mingw v1 is dying]),
+ if test X"$withval" != Xno; then
+ curl_mingw_die=
+ fi
+)
+
+if test -n "$curl_mingw_die"; then
+ AC_MSG_ERROR([support for mingw v1 is going away, enable temporarily with --with-mingw1-deprecated])
+fi
+
dnl **********************************************************************
dnl Compilation based checks should not be done before this point.
dnl **********************************************************************
@@ -518,15 +681,11 @@
CURL_CHECK_HEADER_WINSOCK2
CURL_CHECK_HEADER_WS2TCPIP
CURL_CHECK_HEADER_WINCRYPT
- CURL_CHECK_HEADER_WINLDAP
- CURL_CHECK_HEADER_WINBER
;;
*)
curl_cv_header_winsock2_h="no"
curl_cv_header_ws2tcpip_h="no"
curl_cv_header_wincrypt_h="no"
- curl_cv_header_winldap_h="no"
- curl_cv_header_winber_h="no"
;;
esac
CURL_CHECK_WIN32_LARGEFILE
@@ -536,6 +695,13 @@
CURL_DARWIN_SYSTEMCONFIGURATION
CURL_SUPPORTS_BUILTIN_AVAILABLE
+AM_CONDITIONAL([HAVE_WINDRES],
+ [test "$curl_cv_native_windows" = "yes" && test -n "${RC}"])
+
+if test "$curl_cv_native_windows" = "yes"; then
+ AM_COND_IF([HAVE_WINDRES],,
+ [AC_MSG_ERROR([windres not found in PATH. Windows builds require windres. Cannot continue.])])
+fi
dnl ************************************************************
dnl switch off particular protocols
@@ -746,13 +912,11 @@
AC_MSG_NOTICE([Disable RTSP support with hyper])
AC_DEFINE(CURL_DISABLE_RTSP, 1, [to disable RTSP])
AC_SUBST(CURL_DISABLE_RTSP, [1])
-
else
-
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]),
+AS_HELP_STRING([--enable-rtsp],[Enable RTSP support])
+AS_HELP_STRING([--disable-rtsp],[Disable RTSP support]),
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
@@ -1131,8 +1295,13 @@
AC_MSG_CHECKING([for gethostbyname for AmigaOS bsdsocket.library])
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
+ #define __USE_INLINE__
#include <proto/bsdsocket.h>
+ #ifdef __amigaos4__
+ struct SocketIFace *ISocket = NULL;
+ #else
struct Library *SocketBase = NULL;
+ #endif
]],[[
gethostbyname("www.dummysite.com");
]])
@@ -1170,6 +1339,9 @@
dnl **********************************************************************
CURL_CHECK_LIBS_CLOCK_GETTIME_MONOTONIC
+dnl Check for even better option
+CURL_CHECK_FUNC_CLOCK_GETTIME_MONOTONIC_RAW
+
dnl **********************************************************************
dnl The preceding library checks are all potentially useful for test
dnl servers and libtest cases which require networking and clock_gettime
@@ -1270,7 +1442,6 @@
then
dnl both header and lib were found!
AC_SUBST(HAVE_LIBZ)
- AC_DEFINE(HAVE_ZLIB_H, 1, [if you have the zlib.h header file])
AC_DEFINE(HAVE_LIBZ, 1, [if zlib is available])
ZLIB_LIBS="-lz"
@@ -1480,7 +1651,6 @@
CURL_CHECK_HEADER_LBER
CURL_CHECK_HEADER_LDAP
- CURL_CHECK_HEADER_LDAPSSL
CURL_CHECK_HEADER_LDAP_SSL
if test -z "$LDAPLIBNAME" ; then
@@ -1536,16 +1706,19 @@
fi
if test x$CURL_DISABLE_LDAP != x1 ; then
- AC_CHECK_FUNCS([ldap_url_parse ldap_init_fd])
+ AC_CHECK_FUNCS([ldap_url_parse \
+ ldap_init_fd])
if test "$LDAPLIBNAME" = "wldap32"; then
curl_ldap_msg="enabled (winldap)"
AC_DEFINE(USE_WIN32_LDAP, 1, [Use Windows LDAP implementation])
else
- curl_ldap_msg="enabled (OpenLDAP)"
if test "x$ac_cv_func_ldap_init_fd" = "xyes"; then
+ curl_ldap_msg="enabled (OpenLDAP)"
AC_DEFINE(USE_OPENLDAP, 1, [Use OpenLDAP-specific code])
AC_SUBST(USE_OPENLDAP, [1])
+ else
+ curl_ldap_msg="enabled (ancient OpenLDAP)"
fi
fi
fi
@@ -1642,9 +1815,17 @@
CURL_RUN_IFELSE([[
int main(int argc, char **argv)
{
+#ifdef _WIN32
+ /* on Windows, writing to the argv does not hide the argument in
+ process lists so it can just be skipped */
+ (void)argc;
+ (void)argv;
+ return 1;
+#else
(void)argc;
argv[0][0] = ' ';
return (argv[0][0] == ' ')?0:1;
+#endif
}
]],[
curl_cv_writable_argv=yes
@@ -1917,11 +2098,17 @@
LIBS="-ladvapi32 -lcrypt32 $LIBS"
fi
-case "x$OPENSSL_ENABLED$GNUTLS_ENABLED$NSS_ENABLED$MBEDTLS_ENABLED$WOLFSSL_ENABLED$SCHANNEL_ENABLED$SECURETRANSPORT_ENABLED$BEARSSL_ENABLED$AMISSL_ENABLED$RUSTLS_ENABLED"
+dnl link bcrypt for BCryptGenRandom() (used when building for Vista or newer)
+if test "x$curl_cv_native_windows" = "xyes" &&
+ test "x$curl_mingw_original" = "xno"; then
+ LIBS="-lbcrypt $LIBS"
+fi
+
+case "x$SSL_DISABLED$OPENSSL_ENABLED$GNUTLS_ENABLED$NSS_ENABLED$MBEDTLS_ENABLED$WOLFSSL_ENABLED$SCHANNEL_ENABLED$SECURETRANSPORT_ENABLED$BEARSSL_ENABLED$RUSTLS_ENABLED"
in
x)
- AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more.])
- AC_MSG_WARN([Use --with-openssl, --with-gnutls, --with-wolfssl, --with-mbedtls, --with-nss, --with-schannel, --with-secure-transport, --with-amissl, --with-bearssl or --with-rustls to address this.])
+ AC_MSG_ERROR([TLS not detected, you will not be able to use HTTPS, FTPS, NTLM and more.
+Use --with-openssl, --with-gnutls, --with-wolfssl, --with-mbedtls, --with-nss, --with-schannel, --with-secure-transport, --with-amissl, --with-bearssl or --with-rustls to address this.])
;;
x1)
# one SSL backend is enabled
@@ -1929,6 +2116,14 @@
SSL_ENABLED="1"
AC_MSG_NOTICE([built with one SSL backend])
;;
+xD)
+ # explicitly built without TLS
+ ;;
+xD*)
+ AC_MSG_ERROR([--without-ssl has been set together with an explicit option to use an ssl library
+(e.g. --with-openssl, --with-gnutls, --with-wolfssl, --with-mbedtls, --with-nss, --with-schannel, --with-secure-transport, --with-amissl, --with-bearssl, --with-rustls).
+Since these are conflicting parameters, verify which is the desired one and drop the other.])
+ ;;
*)
# more than one SSL backend is enabled
AC_SUBST(SSL_ENABLED)
@@ -2009,7 +2204,7 @@
AM_CONDITIONAL([USE_GSASL], [test "$curl_gsasl_msg" = "enabled"])
AC_ARG_WITH(libmetalink,,
- AC_MSG_ERROR([--with-libmetalink no longer works!]))
+ AC_MSG_ERROR([--with-libmetalink and --without-libmetalink no longer work!]))
dnl **********************************************************************
dnl Check for the presence of LIBSSH2 libraries and headers
@@ -2079,7 +2274,7 @@
dnl check for function added in libssh2 version 1.0
AC_CHECK_LIB(ssh2, libssh2_session_block_directions)
- AC_CHECK_HEADERS(libssh2.h,
+ AC_CHECK_HEADER(libssh2.h,
curl_ssh_msg="enabled (libSSH2)"
LIBSSH2_ENABLED=1
AC_DEFINE(USE_LIBSSH2, 1, [if libSSH2 is in use])
@@ -2152,7 +2347,7 @@
AC_CHECK_LIB(ssh, ssh_new)
- AC_CHECK_HEADERS(libssh/libssh.h,
+ AC_CHECK_HEADER(libssh/libssh.h,
curl_ssh_msg="enabled (libSSH)"
LIBSSH_ENABLED=1
AC_DEFINE(USE_LIBSSH, 1, [if libSSH is in use])
@@ -2427,7 +2622,6 @@
#
if test "$tst_links_winidn" = "yes"; then
AC_DEFINE(USE_WIN32_IDN, 1, [Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz).])
- AC_DEFINE(WANT_IDN_PROTOTYPES, 1, [Define to 1 to provide own prototypes.])
AC_SUBST([IDN_ENABLED], [1])
curl_idn_msg="enabled (Windows-native)"
else
@@ -2633,15 +2827,17 @@
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.])
+ else
+ LIB_H2="-lnghttp2"
fi
LDFLAGS="$LDFLAGS $LD_H2"
CPPFLAGS="$CPPFLAGS $CPP_H2"
LIBS="$LIB_H2 $LIBS"
- # use nghttp2_session_set_local_window_size to require nghttp2
- # >= 1.12.0
- AC_CHECK_LIB(nghttp2, nghttp2_session_set_local_window_size,
+ # use nghttp2_session_get_stream_local_window_size to require nghttp2
+ # >= 1.15.0
+ AC_CHECK_LIB(nghttp2, nghttp2_session_get_stream_local_window_size,
[
AC_CHECK_HEADERS(nghttp2/nghttp2.h,
curl_h2_msg="enabled (nghttp2)"
@@ -2665,7 +2861,7 @@
dnl Check for ngtcp2 (QUIC)
dnl **********************************************************************
-OPT_TCP2="yes"
+OPT_TCP2="no"
if test "x$disable_http" = "xyes"; then
# without HTTP, ngtcp2 is no use
@@ -2751,42 +2947,42 @@
fi
if test "x$NGTCP2_ENABLED" = "x1" -a "x$OPENSSL_ENABLED" = "x1"; then
- dnl backup the pre-ngtcp2_crypto_openssl variables
+ dnl backup the pre-ngtcp2_crypto_quictls variables
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
CLEANLIBS="$LIBS"
- CURL_CHECK_PKGCONFIG(libngtcp2_crypto_openssl, $want_tcp2_path)
+ CURL_CHECK_PKGCONFIG(libngtcp2_crypto_quictls, $want_tcp2_path)
if test "$PKGCONFIG" != "no" ; then
- LIB_NGTCP2_CRYPTO_OPENSSL=`CURL_EXPORT_PCDIR([$want_tcp2_path])
- $PKGCONFIG --libs-only-l libngtcp2_crypto_openssl`
- AC_MSG_NOTICE([-l is $LIB_NGTCP2_CRYPTO_OPENSSL])
+ LIB_NGTCP2_CRYPTO_QUICTLS=`CURL_EXPORT_PCDIR([$want_tcp2_path])
+ $PKGCONFIG --libs-only-l libngtcp2_crypto_quictls`
+ AC_MSG_NOTICE([-l is $LIB_NGTCP2_CRYPTO_QUICTLS])
- CPP_NGTCP2_CRYPTO_OPENSSL=`CURL_EXPORT_PCDIR([$want_tcp2_path]) dnl
- $PKGCONFIG --cflags-only-I libngtcp2_crypto_openssl`
- AC_MSG_NOTICE([-I is $CPP_NGTCP2_CRYPTO_OPENSSL])
+ CPP_NGTCP2_CRYPTO_QUICTLS=`CURL_EXPORT_PCDIR([$want_tcp2_path]) dnl
+ $PKGCONFIG --cflags-only-I libngtcp2_crypto_quictls`
+ AC_MSG_NOTICE([-I is $CPP_NGTCP2_CRYPTO_QUICTLS])
- LD_NGTCP2_CRYPTO_OPENSSL=`CURL_EXPORT_PCDIR([$want_tcp2_path])
- $PKGCONFIG --libs-only-L libngtcp2_crypto_openssl`
- AC_MSG_NOTICE([-L is $LD_NGTCP2_CRYPTO_OPENSSL])
+ LD_NGTCP2_CRYPTO_QUICTLS=`CURL_EXPORT_PCDIR([$want_tcp2_path])
+ $PKGCONFIG --libs-only-L libngtcp2_crypto_quictls`
+ AC_MSG_NOTICE([-L is $LD_NGTCP2_CRYPTO_QUICTLS])
- LDFLAGS="$LDFLAGS $LD_NGTCP2_CRYPTO_OPENSSL"
- CPPFLAGS="$CPPFLAGS $CPP_NGTCP2_CRYPTO_OPENSSL"
- LIBS="$LIB_NGTCP2_CRYPTO_OPENSSL $LIBS"
+ LDFLAGS="$LDFLAGS $LD_NGTCP2_CRYPTO_QUICTLS"
+ CPPFLAGS="$CPPFLAGS $CPP_NGTCP2_CRYPTO_QUICTLS"
+ LIBS="$LIB_NGTCP2_CRYPTO_QUICTLS $LIBS"
if test "x$cross_compiling" != "xyes"; then
- DIR_NGTCP2_CRYPTO_OPENSSL=`echo $LD_NGTCP2_CRYPTO_OPENSSL | $SED -e 's/^-L//'`
+ DIR_NGTCP2_CRYPTO_QUICTLS=`echo $LD_NGTCP2_CRYPTO_QUICTLS | $SED -e 's/^-L//'`
fi
- AC_CHECK_LIB(ngtcp2_crypto_openssl, ngtcp2_crypto_recv_client_initial_cb,
+ AC_CHECK_LIB(ngtcp2_crypto_quictls, ngtcp2_crypto_recv_client_initial_cb,
[
AC_CHECK_HEADERS(ngtcp2/ngtcp2_crypto.h,
NGTCP2_ENABLED=1
- AC_DEFINE(USE_NGTCP2_CRYPTO_OPENSSL, 1, [if ngtcp2_crypto_openssl is in use])
- AC_SUBST(USE_NGTCP2_CRYPTO_OPENSSL, [1])
- CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_NGTCP2_CRYPTO_OPENSSL"
+ AC_DEFINE(USE_NGTCP2_CRYPTO_QUICTLS, 1, [if ngtcp2_crypto_quictls is in use])
+ AC_SUBST(USE_NGTCP2_CRYPTO_QUICTLS, [1])
+ CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_NGTCP2_CRYPTO_QUICTLS"
export CURL_LIBRARY_PATH
- AC_MSG_NOTICE([Added $DIR_NGTCP2_CRYPTO_OPENSSL to CURL_LIBRARY_PATH])
+ AC_MSG_NOTICE([Added $DIR_NGTCP2_CRYPTO_QUICTLS to CURL_LIBRARY_PATH])
)
],
dnl not found, revert back to clean variables
@@ -2796,11 +2992,11 @@
)
else
- dnl no ngtcp2_crypto_openssl pkg-config found, deal with it
+ dnl no ngtcp2_crypto_quictls pkg-config found, deal with it
if test X"$want_tcp2" != Xdefault; then
dnl To avoid link errors, we do not allow --with-ngtcp2 without
dnl a pkgconfig file
- AC_MSG_ERROR([--with-ngtcp2 was specified but could not find ngtcp2_crypto_openssl pkg-config file.])
+ AC_MSG_ERROR([--with-ngtcp2 was specified but could not find ngtcp2_crypto_quictls pkg-config file.])
fi
fi
fi
@@ -2860,6 +3056,61 @@
fi
fi
+if test "x$NGTCP2_ENABLED" = "x1" -a "x$WOLFSSL_ENABLED" = "x1"; then
+ dnl backup the pre-ngtcp2_crypto_wolfssl variables
+ CLEANLDFLAGS="$LDFLAGS"
+ CLEANCPPFLAGS="$CPPFLAGS"
+ CLEANLIBS="$LIBS"
+
+ CURL_CHECK_PKGCONFIG(libngtcp2_crypto_wolfssl, $want_tcp2_path)
+
+ if test "$PKGCONFIG" != "no" ; then
+ LIB_NGTCP2_CRYPTO_WOLFSSL=`CURL_EXPORT_PCDIR([$want_tcp2_path])
+ $PKGCONFIG --libs-only-l libngtcp2_crypto_wolfssl`
+ AC_MSG_NOTICE([-l is $LIB_NGTCP2_CRYPTO_WOLFSSL])
+
+ CPP_NGTCP2_CRYPTO_WOLFSSL=`CURL_EXPORT_PCDIR([$want_tcp2_path]) dnl
+ $PKGCONFIG --cflags-only-I libngtcp2_crypto_wolfssl`
+ AC_MSG_NOTICE([-I is $CPP_NGTCP2_CRYPTO_WOLFSSL])
+
+ LD_NGTCP2_CRYPTO_WOLFSSL=`CURL_EXPORT_PCDIR([$want_tcp2_path])
+ $PKGCONFIG --libs-only-L libngtcp2_crypto_wolfssl`
+ AC_MSG_NOTICE([-L is $LD_NGTCP2_CRYPTO_WOLFSSL])
+
+ LDFLAGS="$LDFLAGS $LD_NGTCP2_CRYPTO_WOLFSSL"
+ CPPFLAGS="$CPPFLAGS $CPP_NGTCP2_CRYPTO_WOLFSSL"
+ LIBS="$LIB_NGTCP2_CRYPTO_WOLFSSL $LIBS"
+
+ if test "x$cross_compiling" != "xyes"; 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,
+ [
+ AC_CHECK_HEADERS(ngtcp2/ngtcp2_crypto.h,
+ NGTCP2_ENABLED=1
+ AC_DEFINE(USE_NGTCP2_CRYPTO_WOLFSSL, 1, [if ngtcp2_crypto_wolfssl is in use])
+ AC_SUBST(USE_NGTCP2_CRYPTO_WOLFSSL, [1])
+ CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_NGTCP2_CRYPTO_WOLFSSL"
+ export CURL_LIBRARY_PATH
+ AC_MSG_NOTICE([Added $DIR_NGTCP2_CRYPTO_WOLFSSL to CURL_LIBRARY_PATH])
+ )
+ ],
+ dnl not found, revert back to clean variables
+ LDFLAGS=$CLEANLDFLAGS
+ CPPFLAGS=$CLEANCPPFLAGS
+ LIBS=$CLEANLIBS
+ )
+
+ else
+ dnl no ngtcp2_crypto_wolfssl pkg-config found, deal with it
+ if test X"$want_tcp2" != Xdefault; then
+ dnl To avoid link errors, we do not allow --with-ngtcp2 without
+ dnl a pkgconfig file
+ AC_MSG_ERROR([--with-ngtcp2 was specified but could not find ngtcp2_crypto_wolfssl pkg-config file.])
+ fi
+ fi
+fi
+
dnl **********************************************************************
dnl Check for nghttp3 (HTTP/3 with ngtcp2)
dnl **********************************************************************
@@ -3016,7 +3267,7 @@
if test "x$cross_compiling" != "xyes"; then
DIR_QUICHE=`echo $LD_QUICHE | $SED -e 's/^-L//'`
fi
- AC_CHECK_LIB(quiche, quiche_connect,
+ AC_CHECK_LIB(quiche, quiche_conn_send_ack_eliciting,
[
AC_CHECK_HEADERS(quiche.h,
experimental="$experimental HTTP3"
@@ -3176,9 +3427,6 @@
;;
esac
-CURL_CHECK_HEADER_MALLOC
-CURL_CHECK_HEADER_MEMORY
-
dnl Now check for the very most basic headers. Then we can use these
dnl ones as default-headers when checking for the rest!
AC_CHECK_HEADERS(
@@ -3188,13 +3436,12 @@
sys/socket.h \
sys/ioctl.h \
sys/uio.h \
- assert.h \
unistd.h \
stdlib.h \
arpa/inet.h \
net/if.h \
netinet/in.h \
- netinet/in6.h \
+ netinet/in6.h \
sys/un.h \
linux/tcp.h \
netinet/tcp.h \
@@ -3206,7 +3453,6 @@
termios.h \
termio.h \
fcntl.h \
- alloca.h \
io.h \
pwd.h \
utime.h \
@@ -3217,7 +3463,6 @@
sys/resource.h \
libgen.h \
locale.h \
- errno.h \
stdbool.h \
arpa/tftp.h \
sys/filio.h \
@@ -3264,18 +3509,20 @@
CURL_CHECK_STRUCT_TIMEVAL
CURL_VERIFY_RUNTIMELIBS
-AX_COMPILE_CHECK_SIZEOF(size_t)
-AX_COMPILE_CHECK_SIZEOF(long)
-AX_COMPILE_CHECK_SIZEOF(int)
-AX_COMPILE_CHECK_SIZEOF(short)
-AX_COMPILE_CHECK_SIZEOF(time_t)
-AX_COMPILE_CHECK_SIZEOF(off_t)
+CURL_SIZEOF(size_t)
+CURL_SIZEOF(long)
+CURL_SIZEOF(int)
+CURL_SIZEOF(time_t)
+CURL_SIZEOF(off_t)
o=$CPPFLAGS
CPPFLAGS="-I$srcdir/include $CPPFLAGS"
-AX_COMPILE_CHECK_SIZEOF(curl_off_t, [
+CURL_SIZEOF(curl_off_t, [
#include <curl/system.h>
])
+CURL_SIZEOF(curl_socket_t, [
+#include <curl/curl.h>
+])
CPPFLAGS=$o
AC_CHECK_TYPE(long long,
@@ -3284,22 +3531,10 @@
longlong="yes"
)
-if test "xyes" = "x$longlong"; then
- AC_MSG_CHECKING([if numberLL works])
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- ]],[[
- long long val = 1000LL;
- ]])
- ],[
- AC_MSG_RESULT([yes])
- AC_DEFINE(HAVE_LL, 1, [if your compiler supports LL])
- ],[
- AC_MSG_RESULT([no])
- ])
+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
AC_CHECK_TYPE(ssize_t, ,
AC_DEFINE(ssize_t, int, [the signed version of size_t]))
@@ -3399,13 +3634,10 @@
CURL_CHECK_FUNC_GMTIME_R
CURL_CHECK_FUNC_INET_NTOP
CURL_CHECK_FUNC_INET_PTON
-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_POLL
-CURL_CHECK_FUNC_SETSOCKOPT
CURL_CHECK_FUNC_SIGACTION
CURL_CHECK_FUNC_SIGINTERRUPT
CURL_CHECK_FUNC_SIGNAL
@@ -3417,12 +3649,8 @@
CURL_CHECK_FUNC_STRDUP
CURL_CHECK_FUNC_STRERROR_R
CURL_CHECK_FUNC_STRICMP
-CURL_CHECK_FUNC_STRNCMPI
-CURL_CHECK_FUNC_STRNICMP
-CURL_CHECK_FUNC_STRSTR
CURL_CHECK_FUNC_STRTOK_R
CURL_CHECK_FUNC_STRTOLL
-CURL_CHECK_FUNC_WRITEV
case $host in
*msdosdjgpp)
@@ -3439,6 +3667,7 @@
AC_CHECK_FUNCS([fnmatch \
fchmod \
+ fork \
geteuid \
getpass_r \
getppid \
@@ -3454,9 +3683,10 @@
setlocale \
setmode \
setrlimit \
- usleep \
+ snprintf \
utime \
- utimes
+ utimes \
+ arc4random
],[
],[
func="$ac_func"
@@ -3619,6 +3849,9 @@
dnl if it wasn't found without lib, search for it in pthread lib
if test "$USE_THREADS_POSIX" != "1"
then
+ # assign PTHREAD for pkg-config use
+ PTHREAD=" -pthread"
+
case $host in
*-ibm-aix*)
dnl Check if compiler is xlC
@@ -3629,12 +3862,14 @@
CFLAGS="$CFLAGS -qthreaded"
fi
;;
+ powerpc-*amigaos*)
+ dnl No -pthread option, but link with -lpthread
+ PTHREAD=" -lpthread"
+ ;;
*)
CFLAGS="$CFLAGS -pthread"
;;
esac
- # assign PTHREAD for pkg-config use
- PTHREAD=" -pthread"
AC_CHECK_LIB(pthread, pthread_create,
[USE_THREADS_POSIX=1],
[ CFLAGS="$save_CFLAGS"])
@@ -3808,17 +4043,23 @@
]
)
if test "x$want_unix_sockets" != "xno"; then
- AC_CHECK_MEMBER([struct sockaddr_un.sun_path], [
+ if test "x$curl_cv_native_windows" = "xyes"; then
+ USE_UNIX_SOCKETS=1
AC_DEFINE(USE_UNIX_SOCKETS, 1, [Use Unix domain sockets])
- AC_SUBST(USE_UNIX_SOCKETS, [1])
curl_unix_sockets_msg="enabled"
- ], [
- if test "x$want_unix_sockets" = "xyes"; then
- AC_MSG_ERROR([--enable-unix-sockets is not available on this platform!])
- fi
- ], [
- #include <sys/un.h>
- ])
+ else
+ AC_CHECK_MEMBER([struct sockaddr_un.sun_path], [
+ AC_DEFINE(USE_UNIX_SOCKETS, 1, [Use Unix domain sockets])
+ AC_SUBST(USE_UNIX_SOCKETS, [1])
+ curl_unix_sockets_msg="enabled"
+ ], [
+ if test "x$want_unix_sockets" = "xyes"; then
+ AC_MSG_ERROR([--enable-unix-sockets is not available on this platform!])
+ fi
+ ], [
+ #include <sys/un.h>
+ ])
+ fi
fi
dnl ************************************************************
@@ -4029,27 +4270,26 @@
AS_HELP_STRING([--enable-headers-api],[Enable headers-api support])
AS_HELP_STRING([--disable-headers-api],[Disable headers-api support]),
[ case "$enableval" in
- *)
- AC_MSG_RESULT(yes)
- ;;
no) AC_MSG_RESULT(no)
curl_headers_msg="no (--enable-headers-api)"
AC_DEFINE(CURL_DISABLE_HEADERS_API, 1, [disable headers-api])
;;
+ *)
+ AC_MSG_RESULT(yes)
+ ;;
esac ],
AC_MSG_RESULT(yes)
)
dnl only check for HSTS if there's SSL present
if test -n "$SSL_ENABLED"; then
-
dnl ************************************************************
dnl switch on/off hsts
dnl
AC_MSG_CHECKING([whether to support HSTS])
AC_ARG_ENABLE(hsts,
- AS_HELP_STRING([--enable-hsts],[Enable HSTS support])
- AS_HELP_STRING([--disable-hsts],[Disable HSTS support]),
+AS_HELP_STRING([--enable-hsts],[Enable HSTS support])
+AS_HELP_STRING([--disable-hsts],[Disable HSTS support]),
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
@@ -4100,6 +4340,45 @@
fi
fi
+dnl *************************************************************
+dnl check whether OpenSSL (lookalikes) have SSL_set0_wbio
+dnl
+if test "x$OPENSSL_ENABLED" = "x1"; then
+ AC_CHECK_FUNCS([SSL_set0_wbio])
+fi
+
+dnl *************************************************************
+dnl WebSockets
+dnl
+AC_MSG_CHECKING([whether to support WebSockets])
+AC_ARG_ENABLE(websockets,
+AS_HELP_STRING([--enable-websockets],[Enable WebSockets support])
+AS_HELP_STRING([--disable-websockets],[Disable WebSockets support]),
+[ case "$enableval" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ if test ${ac_cv_sizeof_curl_off_t} -gt 4; then
+ AC_MSG_RESULT(yes)
+ curl_ws_msg="enabled"
+ AC_DEFINE_UNQUOTED(USE_WEBSOCKETS, [1], [enable websockets support])
+ SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS WS"
+ if test "x$SSL_ENABLED" = "x1"; then
+ SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS WSS"
+ fi
+ experimental="$experimental Websockets"
+ else
+ 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])
+ fi
+ ;;
+ esac ],
+ AC_MSG_RESULT(no)
+)
+
+
dnl ************************************************************
dnl hiding of library internal symbols
dnl
@@ -4139,6 +4418,8 @@
fi
AC_SUBST(LIBCURL_NO_SHARED)
+rm $compilersh
+
dnl
dnl For keeping supported features and protocols also in pkg-config file
dnl since it is more cross-compile friendly than curl-config
@@ -4246,8 +4527,17 @@
dnl if not explicitly turned off, HTTPS-proxy comes with some TLS backends
if test "x$https_proxy" != "xno"; then
- if test "x$OPENSSL_ENABLED" = "x1" -o "x$GNUTLS_ENABLED" = "x1" \
- -o "x$NSS_ENABLED" = "x1"; then
+ if test "x$OPENSSL_ENABLED" = "x1" \
+ -o "x$GNUTLS_ENABLED" = "x1" \
+ -o "x$NSS_ENABLED" = "x1" \
+ -o "x$SECURETRANSPORT_ENABLED" = "x1" \
+ -o "x$RUSTLS_ENABLED" = "x1" \
+ -o "x$BEARSSL_ENABLED" = "x1" \
+ -o "x$SCHANNEL_ENABLED" = "x1" \
+ -o "x$GNUTLS_ENABLED" = "x1" \
+ -o "x$MBEDTLS_ENABLED" = "x1"; then
+ SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy"
+ elif test "x$WOLFSSL_ENABLED" = "x1" -a "x$WOLFSSL_FULL_BIO" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy"
fi
fi
@@ -4418,12 +4708,16 @@
lib/libcurl.vers \
lib/libcurl.plist \
tests/Makefile \
+ tests/config \
tests/certs/Makefile \
tests/certs/scripts/Makefile \
tests/data/Makefile \
tests/server/Makefile \
tests/libtest/Makefile \
tests/unit/Makefile \
+ tests/http/config.ini \
+ tests/http/Makefile \
+ tests/http/clients/Makefile \
packages/Makefile \
packages/vms/Makefile \
curl-config \
@@ -4433,8 +4727,6 @@
CURL_GENERATE_CONFIGUREHELP_PM
-XC_AMEND_DISTCLEAN([lib src tests/unit tests/server tests/libtest docs/examples])
-
AC_MSG_NOTICE([Configured to build curl/libcurl:
Host setup: ${host}
@@ -4479,6 +4771,7 @@
HTTP2: ${curl_h2_msg}
HTTP3: ${curl_h3_msg}
ECH: ${curl_ech_msg}
+ WebSockets: ${curl_ws_msg}
Protocols: ${SUPPORT_PROTOCOLS}
Features: ${SUPPORT_FEATURES}
])
diff --git a/curl-config.in b/curl-config.in
index aaf2b8a..54f92d9 100644
--- a/curl-config.in
+++ b/curl-config.in
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2001 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
#
###########################################################################
-prefix=@prefix@
+prefix="@prefix@"
exec_prefix=@exec_prefix@
includedir=@includedir@
cppflag_curl_staticlib=@CPPFLAG_CURL_STATICLIB@
@@ -174,7 +174,7 @@
--static-libs)
if test "X@ENABLE_STATIC@" != "Xno" ; then
- echo @libdir@/libcurl.@libext@ @LDFLAGS@ @LIBCURL_LIBS@
+ echo "@libdir@/libcurl.@libext@" @LDFLAGS@ @LIBCURL_LIBS@
else
echo "curl was built with static libraries disabled" >&2
exit 1
diff --git a/docs/.gitignore b/docs/.gitignore
index df26524..8d0bfb3 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/docs/ALTSVC.md b/docs/ALTSVC.md
index d347f6e..560b437 100644
--- a/docs/ALTSVC.md
+++ b/docs/ALTSVC.md
@@ -14,7 +14,7 @@
# Alt-Svc cache file format
-This a text based file with one line per entry and each line consists of nine
+This is a text based file with one line per entry and each line consists of nine
space separated fields.
## Example
diff --git a/docs/BINDINGS.md b/docs/BINDINGS.md
index b9f68ea..7be5387 100644
--- a/docs/BINDINGS.md
+++ b/docs/BINDINGS.md
@@ -20,7 +20,7 @@
[curlcpp](https://github.com/JosephP91/curlcpp) by Giuseppe Persico and [C++
Requests](https://github.com/libcpr/cpr) by Huu Nguyen
-[Ch](https://chcurl.sourceforge.io/) Written by Stephen Nestinger and Jonathan Rogado
+[Ch](https://chcurl.sourceforge.net/) Written by Stephen Nestinger and Jonathan Rogado
Cocoa: [BBHTTP](https://github.com/biasedbit/BBHTTP) written by Bruno de Carvalho
[curlhandle](https://github.com/karelia/curlhandle) Written by Dan Wood
@@ -31,7 +31,7 @@
[Delphi](https://github.com/Mercury13/curl4delphi) Written by Mikhail Merkuryev
-[Dylan](https://dylanlibs.sourceforge.io/) Written by Chris Double
+[Dylan](https://dylanlibs.sourceforge.net/) Written by Chris Double
[Eiffel](https://iron.eiffel.com/repository/20.11/package/ABEF6975-37AC-45FD-9C67-52D10BA0669B) Written by Eiffel Software
@@ -41,7 +41,9 @@
[Ferite](https://web.archive.org/web/20150102192018/ferite.org/) Written by Paul Querna
-[Gambas](https://gambas.sourceforge.io/)
+[Fortran](https://github.com/interkosmos/fortran-curl) Written by Philipp Engel
+
+[Gambas](https://gambas.sourceforge.net/)
[glib/GTK+](https://web.archive.org/web/20100526203452/atterer.net/glibcurl) Written by Richard Atterer
@@ -94,11 +96,11 @@
[Python](http://pycurl.io/) PycURL by Kjetil Jacobsen
-[Q](https://q-lang.sourceforge.io/) The libcurl module is part of the default install
+[Q](https://q-lang.sourceforge.net/) The libcurl module is part of the default install
[R](https://cran.r-project.org/package=curl)
-[Rexx](https://rexxcurl.sourceforge.io/) Written Mark Hessling
+[Rexx](https://rexxcurl.sourceforge.net/) Written Mark Hessling
[Ring](https://ring-lang.sourceforge.io/doc1.3/libcurl.html) RingLibCurl by Mahmoud Fayed
@@ -119,7 +121,7 @@
[SP-Forth](https://sourceforge.net/p/spf/spf/ci/master/tree/devel/~ac/lib/lin/curl/) Written by Andrey Cherezov
-[SPL](https://web.archive.org/web/20210203022158/http://www.clifford.at/spl/spldoc/curl.html) Written by Clifford Wolf
+[SPL](https://web.archive.org/web/20210203022158/www.clifford.at/spl/spldoc/curl.html) Written by Clifford Wolf
[Tcl](https://web.archive.org/web/20160826011806/mirror.yellow5.com/tclcurl/) Tclcurl by Andrés García
@@ -127,7 +129,7 @@
[Visual Foxpro](https://web.archive.org/web/20130730181523/www.ctl32.com.ar/libcurl.asp) by Carlos Alloatti
-[wxWidgets](https://wxcode.sourceforge.io/components/wxcurl/) Written by Casey O'Donnell
+[wxWidgets](https://wxcode.sourceforge.net/components/wxcurl/) Written by Casey O'Donnell
[XBLite](https://web.archive.org/web/20060426150418/perso.wanadoo.fr/xblite/libraries.html) Written by David Szafranski
diff --git a/docs/BUFQ.md b/docs/BUFQ.md
new file mode 100644
index 0000000..c5ff92e
--- /dev/null
+++ b/docs/BUFQ.md
@@ -0,0 +1,144 @@
+# bufq
+
+This is an internal module for managing I/O buffers. A `bufq` can be written
+to and read from. It manages read and write positions and has a maximum size.
+
+## read/write
+
+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);
+
+- returns the length written into `q` or -1 on error.
+- writing to a full `q` will return -1 and set *err to CURLE_AGAIN
+
+ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len, CURLcode *err);
+
+- returns the length read from `q` or -1 on error.
+- reading from an empty `q` will return -1 and set *err to CURLE_AGAIN
+
+```
+
+To pass data into a `bufq` without an extra copy, read callbacks can be used.
+
+```
+typedef ssize_t Curl_bufq_reader(void *reader_ctx, unsigned char *buf, size_t len,
+ CURLcode *err);
+
+ssize_t Curl_bufq_slurp(struct bufq *q, Curl_bufq_reader *reader, void *reader_ctx,
+ CURLcode *err);
+
+```
+
+`Curl_bufq_slurp()` will invoke the given `reader` callback, passing it its own internal
+buffer memory to write to. It may invoke the `reader` several times, as long as it has space
+and while the `reader` always returns the length that was requested. There are variations of `slurp` that call the `reader` at most once or only read in a
+maximum amount of bytes.
+
+The analog mechanism for write out buffer data is:
+
+```
+typedef ssize_t Curl_bufq_writer(void *writer_ctx, const unsigned char *buf, size_t len,
+ CURLcode *err);
+
+ssize_t Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer, void *writer_ctx,
+ CURLcode *err);
+```
+
+`Curl_bufq_pass()` will invoke the `writer`, passing its internal memory and remove the
+amount that `writer` reports.
+
+## peek and skip
+
+It is possible to get access to the memory of data stored in a `bufq` with:
+
+```
+bool Curl_bufq_peek(const struct bufq *q, const unsigned char **pbuf, size_t *plen);
+```
+
+On returning TRUE, `pbuf` will point to internal memory with `plen` bytes that one may read. This will only
+be valid until another operation on `bufq` is performed.
+
+Instead of reading `bufq` data, one may simply skip it:
+
+```
+void Curl_bufq_skip(struct bufq *q, size_t amount);
+```
+
+This will remove `amount` number of bytes from the `bufq`.
+
+
+## lifetime
+
+`bufq` is initialized and freed similar to the `dynbuf` module. Code using `bufq` will
+hold a `struct bufq` somewhere. Before it uses it, it invokes:
+
+```
+void Curl_bufq_init(struct bufq *q, size_t chunk_size, size_t max_chunks);
+```
+
+The `bufq` is told how many "chunks" of data it shall hold at maximum and how large those
+"chunks" should be. There are some variants of this, allowing for more options. How "chunks" are handled in a `bufq` is presented in the section about memory management.
+
+The user of the `bufq` has the responsibility to call:
+
+```
+void Curl_bufq_free(struct bufq *q);
+```
+to free all resources held by `q`. It is possible to reset a `bufq` to empty via:
+
+```
+void Curl_bufq_reset(struct bufq *q);
+```
+
+## memory management
+
+Internally, a `bufq` uses allocation of fixed size, e.g. the "chunk_size", up to a maximum number, e.g. "max_chunks". These chunks are allocated on demand, therefore writing to a `bufq` may return `CURLE_OUT_OF_MEMORY`. Once the max number of chunks are used, the `bufq` will report that it is "full".
+
+Each chunks has a `read` and `write` index. A `bufq` keeps its chunks in a list. Reading happens always at the head chunk, writing always goes to the tail chunk. When the head chunk becomes empty, it is removed. When the tail chunk becomes full, another chunk is added to the end of the list, becoming the new tail.
+
+Chunks that are no longer used are returned to a `spare` list by default. If the `bufq` is created with option `BUFQ_OPT_NO_SPARES` those chunks will be freed right away.
+
+If a `bufq` is created with a `bufc_pool`, the no longer used chunks are returned to the pool. Also `bufq` will ask the pool for a chunk when it needs one. More in section "pools".
+
+## empty, full and overflow
+
+One can ask about the state of a `bufq` with methods such as `Curl_bufq_is_empty(q)`,
+`Curl_bufq_is_full(q)`, etc. The amount of data held by a `bufq` is the sum of the data in all its chunks. This is what is reported by `Curl_bufq_len(q)`.
+
+Note that a `bufq` length and it being "full" are only loosely related. A simple example:
+
+* create a `bufq` with chunk_size=1000 and max_chunks=4.
+* write 4000 bytes to it, it will report "full"
+* read 1 bytes from it, it will still report "full"
+* read 999 more bytes from it, and it will no longer be "full"
+
+The reason for this is that full really means: *bufq uses max_chunks and the last one cannot be written to*.
+
+So when you read 1 byte from the head chunk in the example above, the head still hold 999 unread bytes. Only when those are also read, can the head chunk be removed and a new tail be added.
+
+There is another variation to this. If you initialized a `bufq` with option `BUFQ_OPT_SOFT_LIMIT`, it will allow writes **beyond** the `max_chunks`. It will report **full**, but one can **still** write. This option is necessary, if partial writes need to be avoided. But it means that you will need other checks to keep the `bufq` from growing ever larger and larger.
+
+
+## pools
+
+A `struct bufc_pool` may be used to create chunks for a `bufq` and keep spare ones around. It is initialized
+and used via:
+
+```
+void Curl_bufcp_init(struct bufc_pool *pool, size_t chunk_size, size_t spare_max);
+
+void Curl_bufq_initp(struct bufq *q, struct bufc_pool *pool, size_t max_chunks, int opts);
+```
+
+The pool gets the size and the mount of spares to keep. The `bufq` gets the pool and the `max_chunks`. It no longer needs to know the chunk sizes, as those are managed by the pool.
+
+A pool can be shared between many `bufq`s, as long as all of them operate in the same thread. In curl that would be true for all transfers using the same multi handle. The advantages of a pool are:
+
+* when all `bufq`s are empty, only memory for `max_spare` chunks in the pool is used. Empty `bufq`s will hold no memory.
+* the latest spare chunk is the first to be handed out again, no matter which `bufq` needs it. This keeps the footprint of "recently used" memory smaller.
+
+
diff --git a/docs/BUFREF.md b/docs/BUFREF.md
index 35c5342..14f41b3 100644
--- a/docs/BUFREF.md
+++ b/docs/BUFREF.md
@@ -12,13 +12,13 @@
that structure **MUST NOT** be accessed or modified without using the dedicated
bufref API.
-## init
+## `init`
```c
void Curl_bufref_init(struct bufref *br);
```
-Initialises a `bufref` structure. This function **MUST** be called before any
+Initializes a `bufref` structure. This function **MUST** be called before any
other operation is performed on the structure.
Upon completion, the referenced buffer is `NULL` and length is zero.
@@ -26,16 +26,16 @@
This function may also be called to bypass referenced buffer destruction while
invalidating the current reference.
-## free
+## `free`
```c
void Curl_bufref_free(struct bufref *br);
```
Destroys the previously referenced buffer using its destructor and
-reinitialises the structure for a possible subsequent reuse.
+reinitializes the structure for a possible subsequent reuse.
-## set
+## `set`
```c
void Curl_bufref_set(struct bufref *br, const void *buffer, size_t length,
@@ -47,9 +47,9 @@
specified as `NULL`: this will be the case when the referenced buffer is
static.
-if `buffer` is NULL, `length`must be zero.
+if `buffer` is NULL, `length` must be zero.
-## memdup
+## `memdup`
```c
CURLcode Curl_bufref_memdup(struct bufref *br, const void *data, size_t length);
@@ -59,12 +59,12 @@
`data` into a buffer allocated via `malloc()` and references the latter
associated with destructor `curl_free()`.
-An additional trailing byte is allocated and set to zero as a possible
-string zero-terminator; it is not counted in the stored length.
+An additional trailing byte is allocated and set to zero as a possible string
+null-terminator; it is not counted in the stored length.
Returns `CURLE_OK` if successful, else `CURLE_OUT_OF_MEMORY`.
-## ptr
+## `ptr`
```c
const unsigned char *Curl_bufref_ptr(const struct bufref *br);
@@ -72,7 +72,7 @@
Returns a `const unsigned char *` to the referenced buffer.
-## len
+## `len`
```c
size_t Curl_bufref_len(const struct bufref *br);
diff --git a/docs/BUGS.md b/docs/BUGS.md
index 584c67f..9d18ffe 100644
--- a/docs/BUGS.md
+++ b/docs/BUGS.md
@@ -3,7 +3,7 @@
## There are still bugs
Curl and libcurl keep being developed. Adding features and changing code
- means that bugs will sneak in, no matter how hard we try not to.
+ means that bugs will sneak in, no matter how hard we try to keep them out.
Of course there are lots of bugs left. And lots of misfeatures.
@@ -44,7 +44,7 @@
## What to report
When reporting a bug, you should include all information that will help us
- understand what's wrong, what you expected to happen and how to repeat the
+ understand what is wrong, what you expected to happen and how to repeat the
bad behavior. You therefore need to tell us:
- your operating system's name and version number
@@ -162,7 +162,7 @@
experimental build or similar, to get this confirmed or not.
At times people insist that they cannot upgrade to a modern curl version, but
- instead they "just want the bug fixed". That is fine, just do not count on us
+ instead, they "just want the bug fixed". That is fine, just do not count on us
spending many cycles on trying to identify which single commit, if that is
even possible, that at some point in the past fixed the problem you are now
experiencing.
@@ -181,7 +181,7 @@
maybe they are off in the woods hunting. Have patience. Allow at least a few
days before expecting someone to have responded.
- In the issue tracker you can expect that some labels will be set on the issue
+ In the issue tracker, you can expect that some labels will be set on the issue
to help categorize it.
## First response
@@ -199,14 +199,13 @@
## Not reproducible
- For problems that we cannot reproduce and cannot understand even after having
- gotten all the info we need and having studied the source code over again,
- are really hard to solve so then we may require further work from you who
- actually see or experience the problem.
+ We may require further work from you who actually see or experience the
+ problem if we cannot reproduce it and cannot understand it even after having
+ gotten all the info we need and having studied the source code over again.
## Unresponsive
- If the problem have not been understood or reproduced, and there's nobody
+ If the problem have not been understood or reproduced, and there is nobody
responding to follow-up questions or questions asking for clarifications or
for discussing possible ways to move forward with the task, we take that as a
strong suggestion that the bug is unimportant.
@@ -246,7 +245,7 @@
tracker.
The `TODO` document is full of ideas and suggestions of what we can add or
- fix one day. you are always encouraged and free to grab one of those items and
+ fix one day. You are always encouraged and free to grab one of those items and
take up a discussion with the curl development team on how that could be
implemented or provided in the project so that you can work on ticking it odd
that document.
diff --git a/docs/CHECKSRC.md b/docs/CHECKSRC.md
index 58a33d7..0406a7f 100644
--- a/docs/CHECKSRC.md
+++ b/docs/CHECKSRC.md
@@ -16,9 +16,9 @@
`-h` shows the help output, that also lists all recognized warnings
-## What does checksrc warn for?
+## What does `checksrc` warn for?
-checksrc does not check and verify the code against the entire style guide.
+`checksrc` does not check and verify the code against the entire style guide.
The script is an effort to detect the most common mistakes and syntax mistakes
that contributors make before they get accustomed to our code style. Heck,
many of us regulars do the mistakes too and this script helps us keep the code
@@ -27,7 +27,7 @@
checksrc.pl -h
Lists how to use the script and it lists all existing warnings it has and
-problems it detects. At the time of this writing, the existing checksrc
+problems it detects. At the time of this writing, the existing `checksrc`
warnings are:
- `ASSIGNWITHINCONDITION`: Assignment within a conditional expression. The
@@ -41,7 +41,7 @@
more appropriate `char *name` style. The asterisk should sit right next to
the name without a space in between.
-- `BADCOMMAND`: There's a bad `!checksrc!` instruction in the code. See the
+- `BADCOMMAND`: There's a bad `checksrc` instruction in the code. See the
**Ignore certain warnings** section below for details.
- `BANNEDFUNC`: A banned function was used. The functions sprintf, vsprintf,
@@ -56,7 +56,7 @@
- `COMMANOSPACE`: a comma without following space
-- `COPYRIGHT`: the file is missing a copyright statement!
+- `COPYRIGHT`: the file is missing a copyright statement
- `CPPCOMMENTS`: `//` comment detected, that is not C89 compliant
@@ -113,14 +113,14 @@
- `SPACESEMICOLON`: there was a space before semicolon, ` ;`.
-- `TABS`: TAB characters are not allowed!
+- `TABS`: TAB characters are not allowed
- `TRAILINGSPACE`: Trailing whitespace on the line
- `TYPEDEFSTRUCT`: we frown upon (most) typedefed structs
-- `UNUSEDIGNORE`: a checksrc inlined warning ignore was asked for but not used,
- that is an ignore that should be removed or changed to get used.
+- `UNUSEDIGNORE`: a `checksrc` inlined warning ignore was asked for but not
+ used, that is an ignore that should be removed or changed to get used.
### Extended warnings
@@ -139,17 +139,16 @@
## Ignore certain warnings
-Due to the nature of the source code and the flaws of the checksrc tool, there
-is sometimes a need to ignore specific warnings. checksrc allows a few
+Due to the nature of the source code and the flaws of the `checksrc` tool,
+there is sometimes a need to ignore specific warnings. `checksrc` allows a few
different ways to do this.
### Inline ignore
You can control what to ignore within a specific source file by providing
-instructions to checksrc in the source code itself. You need a magic marker
-that is `!checksrc!` followed by the instruction. The instruction can ask to
-ignore a specific warning N number of times or you ignore all of them until
-you mark the end of the ignored section.
+instructions to `checksrc` in the source code itself. See examples below. The
+instruction can ask to ignore a specific warning a specific number of times or
+you ignore all of them until you mark the end of the ignored section.
Inline ignores are only done for that single specific source code file.
diff --git a/docs/CIPHERS.md b/docs/CIPHERS.md
index e1df764..6029378 100644
--- a/docs/CIPHERS.md
+++ b/docs/CIPHERS.md
@@ -6,7 +6,8 @@
[`--ciphers`](https://curl.se/docs/manpage.html#--ciphers)
users can control which ciphers to consider when negotiating TLS connections.
-TLS 1.3 ciphers are supported since curl 7.61 for OpenSSL 1.1.1+ with options
+TLS 1.3 ciphers are supported since curl 7.61 for OpenSSL 1.1.1+, and since
+curl 7.85 for Schannel with options
[`CURLOPT_TLS13_CIPHERS`](https://curl.se/libcurl/c/CURLOPT_TLS13_CIPHERS.html)
and
[`--tls13-ciphers`](https://curl.se/docs/manpage.html#--tls13-ciphers)
@@ -50,7 +51,7 @@
`ADH-RC4-MD5`
`ADH-DES-CBC3-SHA`
-### AES ciphersuites from RFC3268, extending TLS v1.0
+### AES cipher suites from RFC 3268, extending TLS v1.0
`AES128-SHA`
`AES256-SHA`
@@ -65,7 +66,7 @@
`ADH-AES128-SHA`
`ADH-AES256-SHA`
-### SEED ciphersuites from RFC4162, extending TLS v1.0
+### SEED cipher suites from RFC 4162, extending TLS v1.0
`SEED-SHA`
`DH-DSS-SEED-SHA`
@@ -74,7 +75,7 @@
`DHE-RSA-SEED-SHA`
`ADH-SEED-SHA`
-### GOST ciphersuites, extending TLS v1.0
+### GOST cipher suites, extending TLS v1.0
`GOST94-GOST89-GOST89`
`GOST2001-GOST89-GOST89`
@@ -147,7 +148,7 @@
`ECDHE-ECDSA-AES128-CCM8`
`ECDHE-ECDSA-AES256-CCM8`
-### Camellia HMAC-Based ciphersuites from RFC6367, extending TLS v1.2
+### Camellia HMAC-Based cipher suites from RFC 6367, extending TLS v1.2
`ECDHE-ECDSA-CAMELLIA128-SHA256`
`ECDHE-ECDSA-CAMELLIA256-SHA384`
@@ -176,7 +177,7 @@
`des`
`desede3`
-### SSL3/TLS cipher suites
+### SSL3/TLS cipher suites
`rsa_rc4_128_md5`
`rsa_rc4_128_sha`
@@ -457,7 +458,7 @@
## Schannel
Schannel allows the enabling and disabling of encryption algorithms, but not
-specific ciphersuites. They are
+specific cipher suites. They are
[defined](https://docs.microsoft.com/windows/desktop/SecCrypto/alg-id) by
Microsoft.
@@ -516,11 +517,21 @@
`CALG_ECDH_EPHEM`,
As of curl 7.77.0, you can also pass `SCH_USE_STRONG_CRYPTO` as a cipher name
-to [constrain the set of available ciphers as specified in the schannel
+to [constrain the set of available ciphers as specified in the Schannel
documentation](https://docs.microsoft.com/en-us/windows/win32/secauthn/tls-cipher-suites-in-windows-server-2022).
Note that the supported ciphers in this case follow the OS version, so if you
are running an outdated OS you might still be supporting weak ciphers.
+### TLS 1.3 cipher suites
+
+(Note these ciphers are set with `CURLOPT_TLS13_CIPHERS` and `--tls13-ciphers`)
+
+`TLS_AES_256_GCM_SHA384`
+`TLS_AES_128_GCM_SHA256`
+`TLS_CHACHA20_POLY1305_SHA256`
+`TLS_AES_128_CCM_8_SHA256`
+`TLS_AES_128_CCM_SHA256`
+
## BearSSL
BearSSL ciphers can be specified by either the OpenSSL name (`ECDHE-RSA-AES128-GCM-SHA256`) or the IANA name (`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`).
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
index 97101a4..dd2c6dc 100644
--- a/docs/CMakeLists.txt
+++ b/docs/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/docs/CODE_REVIEW.md b/docs/CODE_REVIEW.md
index 20d1be8..0776d30 100644
--- a/docs/CODE_REVIEW.md
+++ b/docs/CODE_REVIEW.md
@@ -70,7 +70,7 @@
Can the mallocs be avoided? Do not introduce mallocs in any hot paths. If
there are (new) mallocs, can they be combined into fewer calls?
-Are all allocations handled in errorpaths to avoid leaks and crashes?
+Are all allocations handled in error paths to avoid leaks and crashes?
## Thread-safety
@@ -151,12 +151,12 @@
Do not allow new code that grows buffers without using dynbuf.
Use of C functions that rely on a terminating zero must only be used on data
-that really do have a zero terminating zero.
+that really do have a null-terminating zero.
## Dangerous "data styles"
Make extra precautions and verify that memory buffers that need a terminating
-zero always have exactly that. Buffers *without* a zero terminator must not be
+zero always have exactly that. Buffers *without* a null-terminator must not be
used as input to string functions.
# Commit messages
@@ -164,5 +164,5 @@
Tightly coupled with a code review is making sure that the commit message is
good. It is the responsibility of the person who merges the code to make sure
that the commit message follows our standard (detailed in the
-[CONTRIBUTE.md](CONTRIBUTE.md) document). This includes making sure the PR
+[CONTRIBUTE](CONTRIBUTE.md) document). This includes making sure the PR
identifies related issues and giving credit to reporters and helpers.
diff --git a/docs/CODE_STYLE.md b/docs/CODE_STYLE.md
index 5481aa5..6712de0 100644
--- a/docs/CODE_STYLE.md
+++ b/docs/CODE_STYLE.md
@@ -64,7 +64,7 @@
newspapers have used columns for decades or centuries.
2. Narrower columns allow developers to easier show multiple pieces of code
- next to each other in different windows. I often have two or three source
+ next to each other in different windows. It allows two or three source
code windows next to each other on the same screen - as well as multiple
terminal and debugging windows.
diff --git a/docs/CONNECTION-FILTERS.md b/docs/CONNECTION-FILTERS.md
new file mode 100644
index 0000000..cedd37c
--- /dev/null
+++ b/docs/CONNECTION-FILTERS.md
@@ -0,0 +1,127 @@
+# curl connection filters
+
+Connection filters is a design in the internals of curl, not visible in its public API. They were added
+in curl v7.xx.x. This document describes the concepts, its high level implementation and the motivations.
+
+## Filters
+
+A "connection filter" is a piece of code that is responsible for handling a range of operations
+of curl's connections: reading, writing, waiting on external events, connecting and closing down - to name the most important ones.
+
+The most important feat of connection filters is that they can be stacked on top of each other (or "chained" if you prefer that metaphor). In the common scenario that you want to retrieve a `https:` url with curl, you need 2 basic things to send the request and get the response: a TCP connection, represented by a `socket` and a SSL instance en- and decrypt over that socket. You write your request to the SSL instance, which encrypts and writes that data to the socket, which then sends the bytes over the network.
+
+With connection filters, curl's internal setup will look something like this (cf for connection filter):
+
+```
+Curl_easy *data connectdata *conn cf-ssl cf-socket
++----------------+ +-----------------+ +-------+ +--------+
+|https://curl.se/|----> | properties |----> | keys |---> | socket |--> OS --> network
++----------------+ +-----------------+ +-------+ +--------+
+
+ Curl_write(data, buffer)
+ --> Curl_cfilter_write(data, data->conn, buffer)
+ ---> conn->filter->write(conn->filter, data, buffer)
+```
+
+While connection filters all do different things, they look the same from the "outside". The code in `data` and `conn` does not really know **which** filters are installed. `conn` just writes into the first filter, whatever that is.
+
+Same is true for filters. Each filter has a pointer to the `next` filter. When SSL has encrypted the data, it does not write to a socket, it writes to the next filter. If that is indeed a socket, or a file, or an HTTP/2 connection is of no concern to the SSL filter.
+
+And this allows the stacking, as in:
+
+```
+Direct:
+ http://localhost/ conn -> cf-socket
+ https://curl.se/ conn -> cf-ssl -> cf-socket
+Via http proxy tunnel:
+ http://localhost/ conn -> cf-http-proxy -> cf-socket
+ https://curl.se/ conn -> cf-ssl -> cf-http-proxy -> cf-socket
+Via https proxy tunnel:
+ http://localhost/ conn -> cf-http-proxy -> cf-ssl -> cf-socket
+ https://curl.se/ conn -> cf-ssl -> cf-http-proxy -> cf-ssl -> cf-socket
+Via http proxy tunnel via SOCKS proxy:
+ http://localhost/ conn -> cf-http-proxy -> cf-socks -> cf-socket
+```
+
+### Connecting/Closing
+
+Before `Curl_easy` can send the request, the connection needs to be established. This means that all connection filters have done, whatever they need to do: waiting for the socket to be connected, doing the TLS handshake, performing the HTTP tunnel request, etc. This has to be done in reverse order: the last filter has to do its connect first, then the one above can start, etc.
+
+Each filter does in principle the following:
+
+```
+static CURLcode
+myfilter_cf_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done)
+{
+ CURLcode result;
+
+ if(cf->connected) { /* we and all below are done */
+ *done = TRUE;
+ return CURLE_OK;
+ }
+ /* Let the filters below connect */
+ result = cf->next->cft->connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ return result; /* below errored/not finished yet */
+
+ /* MYFILTER CONNECT THINGS */ /* below connected, do out thing */
+ *done = cf->connected = TRUE; /* done, remember, return */
+ return CURLE_OK;
+}
+```
+
+Closing a connection then works similar. The `conn` tells the first filter to close. Contrary to connecting,
+the filter does its own things first, before telling the next filter to close.
+
+### Efficiency
+
+There are two things curl is concerned about: efficient memory use and fast transfers.
+
+The memory footprint of a filter is relatively small:
+
+```
+struct Curl_cfilter {
+ const struct Curl_cftype *cft; /* the type providing implementation */
+ struct Curl_cfilter *next; /* next filter in chain */
+ void *ctx; /* filter type specific settings */
+ struct connectdata *conn; /* the connection this filter belongs to */
+ int sockindex; /* TODO: like to get rid off this */
+ BIT(connected); /* != 0 iff this filter is connected */
+};
+```
+The filter type `cft` is a singleton, one static struct for each type of filter. The `ctx` is where a filter will hold its specific data. That varies by filter type. An http-proxy filter will keep the ongoing state of the CONNECT here, but free it after its has been established. The SSL filter will keep the `SSL*` (if OpenSSL is used) here until the connection is closed. So, this varies.
+
+`conn` is a reference to the connection this filter belongs to, so nothing extra besides the pointer itself.
+
+Several things, that before were kept in `struct connectdata`, will now go into the `filter->ctx` *when needed*. So, the memory footprint for connections that do *not* use an http proxy, or socks, or https will be lower.
+
+As to transfer efficiency, writing and reading through a filter comes at near zero cost *if the filter does not transform the data*. An http proxy or socks filter, once it is connected, will just pass the calls through. Those filters implementations will look like this:
+
+```
+ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err)
+{
+ return cf->next->cft->do_send(cf->next, data, buf, len, err);
+}
+```
+The `recv` implementation is equivalent.
+
+## Filter Types
+
+The (currently) existing filter types are: SOCKET, SOCKET-ACCEPT, SSL, HTTP-PROXY and SOCKS-PROXY. Vital to establishing and read/writing a connection. But filters are also a good way to implement tasks for *managing* a connection:
+
+* **Statistics**: a filter that counts the number of bytes sent/received. Place one in front of SOCKET and one higher up and get the number of raw and "easy" bytes transferred. They may track the speed as well, or number of partial writes, etc.
+* **Timeout**: enforce timeouts, e.g. fail if a connection cannot be established in a certain amount of time.
+* **Progress**: report progress on a connection.
+* **Pacing**: limit read/write rates.
+* **Testing**: simulate network condition or failures.
+
+As you see, filters are a good way to add functionality to curl's internal handling of transfers without impact on other code.
+
+## Easy Filters?
+
+Some things that curl needs to manage are not directly tied to a specific connection but the property of the `Curl_easy` handle, e.g. a particular transfer. When using HTTP/2 or HTTP/3, many transfers can use the same connection. If one wants to monitor of the transfer itself or restricting its speed alone, a connection filter is not the right place to do this.
+
+So we might add "easy filters" one day. Who knows?
diff --git a/docs/CONTRIBUTE.md b/docs/CONTRIBUTE.md
index 506af9b..16c126b 100644
--- a/docs/CONTRIBUTE.md
+++ b/docs/CONTRIBUTE.md
@@ -148,7 +148,7 @@
### About pull requests
-With github it is easy to send a [pull
+With GitHub it is easy to send a [pull
request](https://github.com/curl/curl/pulls) to the curl project to have
changes merged.
@@ -157,12 +157,12 @@
to lose in the flood of many emails, like they sometimes do on the mailing
lists.
-Every pull request submitted will automatically be
-tested in several different ways. [See CI.md for more
+Every pull request submitted will automatically be tested in several different
+ways. [See the CI document for more
information](https://github.com/curl/curl/blob/master/tests/CI.md).
Sometimes the tests fail due to a dependency service temporarily being offline
-or otherwise unavailable, eg. package downloads. In this case you can just
+or otherwise unavailable, e.g. package downloads. In this case you can just
try to update your pull requests to rerun the tests later as described below.
You can update your pull requests by pushing new commits or force-pushing
@@ -188,34 +188,62 @@
### Commit messages
-A short guide to how to write commit messages in the curl project.
+A short guide to how to write git commit messages in the curl project.
---- start ----
[area]: [short line describing the main effect]
-- empty line --
- [full description, no wider than 72 columns that describe as much as
+ [full description, no wider than 72 columns that describes as much as
possible as to why this change is made, and possibly what things
- it fixes and everything else that is related]
+ it fixes and everything else that is related, with unwieldy URLs replaced
+ with references like [0], [1], etc.]
-- empty line --
- [Closes/Fixes #1234 - if this closes or fixes a github issue]
- [Bug: URL to source of the report or more related discussion]
- [Reported-by: John Doe - credit the reporter]
- [whatever-else-by: credit all helpers, finders, doers]
+ [[0] URL - Reference to a URL in the description, almost like Markdown;
+ the last numbered reference is followed by an -- empty line -- ]
+ [Follow-up to {shorthash} - if this fixes or continues a previous commit;
+ add a Ref: that commit's PR or issue if it's not a small, obvious fix;
+ followed by an -- empty line -- ]
+ [Bug: URL to the source of the report or more related discussion; use Fixes
+ for GitHub issues instead when that is appropriate]
+ [Approved-by: John Doe - credit someone who approved the PR; if you are
+ committing this for someone else using --author=... you don't need this
+ as you are implicitly approving it by committing]
+ [Authored-by: John Doe - credit the original author of the code; only use
+ this if you can't use "git commit --author=..."]
+ [Signed-off-by: John Doe - we don't use this, but don't bother removing it]
+ [whatever-else-by: credit all helpers, finders, doers; try to use one of
+ the following keywords if at all possible, for consistency:
+ Acked-by:, Assisted-by:, Co-authored-by:, Found-by:, Reported-by:,
+ Reviewed-by:, Suggested-by:, Tested-by:]
+ [Ref: #1234 - if this is related to a GitHub issue or PR, possibly one that
+ has already been closed]
+ [Ref: URL to more information about the commit; use Bug: instead for
+ a reference to a bug on another bug tracker]
+ [Fixes #1234 - if this closes a GitHub issue; GitHub will actually
+ close the issue once this commit is merged]
+ [Closes #1234 - if this closes a GitHub PR; GitHub will actually
+ close the PR once this commit is merged]
---- stop ----
The first line is a succinct description of the change:
- use the imperative, present tense: "change" not "changed" nor "changes"
- - do not capitalize first letter
- - no dot (.) at the end
+ - do not capitalize the first letter
+ - no period (.) at the end
The `[area]` in the first line can be `http2`, `cookies`, `openssl` or
similar. There's no fixed list to select from but using the same "area" as
other related changes could make sense.
-Do not forget to use commit --author="" if you commit someone else's work, and
+Do not forget to use commit --author=... if you commit someone else's work, and
make sure that you have your own user and email setup correctly in git before
-you commit
+you commit.
+
+Add whichever header lines as appropriate, with one line per person if more
+than one person was involved. There's no need to credit yourself unless you are
+using --author=... which hides your identity. Don't include people's e-mail
+addresses in headers to avoid spam, unless they're already public from a
+previous commit; saying `{userid} on github` is OK.
### Write Access to git Repository
@@ -245,7 +273,7 @@
git format-patch remotes/origin/master
-This creates files in your local directory named NNNN-[name].patch for each
+This creates files in your local directory named `NNNN-[name].patch` for each
commit.
Now send those patches off to the curl-library list. You can of course opt to
@@ -267,17 +295,7 @@
diff -ur curl-original-dir curl-modified-sources-dir > my-fixes.diff
The GNU diff and GNU patch tools exist for virtually all platforms, including
-all kinds of Unixes and Windows:
-
-For unix-like operating systems:
-
- - [https://savannah.gnu.org/projects/patch/](https://savannah.gnu.org/projects/patch/)
- - [https://www.gnu.org/software/diffutils/](https://www.gnu.org/software/diffutils/)
-
-For Windows:
-
- - [https://gnuwin32.sourceforge.io/packages/patch.htm](https://gnuwin32.sourceforge.io/packages/patch.htm)
- - [https://gnuwin32.sourceforge.io/packages/diffutils.htm](https://gnuwin32.sourceforge.io/packages/diffutils.htm)
+all kinds of Unixes and Windows.
### Useful resources
- [Webinar on getting code into cURL](https://www.youtube.com/watch?v=QmZ3W1d6LQI)
@@ -290,12 +308,9 @@
This means that all files need to have their license and copyright information
clearly stated. Ideally by having the standard curl source code header, with
-an accurate copyright year range and the SPDX-License-Identifier included. If
-the header does not work, you can use a smaller header or as a last resort add
-the information for a specific file to the `.reuse/dep5` file.
-
-We update copyright year ranges to end on the year of the most recent change
-of the individual file.
+the SPDX-License-Identifier included. If the header does not work, you can use a
+smaller header or add the information for a specific file to the `.reuse/dep5`
+file.
You can manually verify the copyright and compliance status by running the
`./scripts/copyright.pl` script in the root of the git repository.
diff --git a/docs/CURL-DISABLE.md b/docs/CURL-DISABLE.md
index 7ece3dc..1548df6 100644
--- a/docs/CURL-DISABLE.md
+++ b/docs/CURL-DISABLE.md
@@ -1,140 +1,140 @@
# Code defines to disable features and protocols
-## CURL_DISABLE_ALTSVC
+## `CURL_DISABLE_ALTSVC`
Disable support for Alt-Svc: HTTP headers.
-## CURL_DISABLE_COOKIES
+## `CURL_DISABLE_COOKIES`
Disable support for HTTP cookies.
-## CURL_DISABLE_CRYPTO_AUTH
+## `CURL_DISABLE_CRYPTO_AUTH`
Disable support for authentication methods using crypto.
-## CURL_DISABLE_DICT
+## `CURL_DISABLE_DICT`
Disable the DICT protocol
-## CURL_DISABLE_DOH
+## `CURL_DISABLE_DOH`
Disable DNS-over-HTTPS
-## CURL_DISABLE_FILE
+## `CURL_DISABLE_FILE`
Disable the FILE protocol
-## CURL_DISABLE_FTP
+## `CURL_DISABLE_FTP`
Disable the FTP (and FTPS) protocol
-## CURL_DISABLE_GETOPTIONS
+## `CURL_DISABLE_GETOPTIONS`
Disable the `curl_easy_options` API calls that lets users get information
about existing options to `curl_easy_setopt`.
-## CURL_DISABLE_GOPHER
+## `CURL_DISABLE_GOPHER`
Disable the GOPHER protocol.
-## CURL_DISABLE_HEADERS_API
+## `CURL_DISABLE_HEADERS_API`
Disable the HTTP header API.
-## CURL_DISABLE_HSTS
+## `CURL_DISABLE_HSTS`
Disable the HTTP Strict Transport Security support.
-## CURL_DISABLE_HTTP
+## `CURL_DISABLE_HTTP`
Disable the HTTP(S) protocols. Note that this then also disable HTTP proxy
support.
-## CURL_DISABLE_HTTP_AUTH
+## `CURL_DISABLE_HTTP_AUTH`
Disable support for all HTTP authentication methods.
-## CURL_DISABLE_IMAP
+## `CURL_DISABLE_IMAP`
Disable the IMAP(S) protocols.
-## CURL_DISABLE_LDAP
+## `CURL_DISABLE_LDAP`
Disable the LDAP(S) protocols.
-## CURL_DISABLE_LDAPS
+## `CURL_DISABLE_LDAPS`
Disable the LDAPS protocol.
-## CURL_DISABLE_LIBCURL_OPTION
+## `CURL_DISABLE_LIBCURL_OPTION`
Disable the --libcurl option from the curl tool.
-## CURL_DISABLE_MIME
+## `CURL_DISABLE_MIME`
Disable MIME support.
-## CURL_DISABLE_MQTT
+## `CURL_DISABLE_MQTT`
Disable MQTT support.
-## CURL_DISABLE_NETRC
+## `CURL_DISABLE_NETRC`
Disable the netrc parser.
-## CURL_DISABLE_NTLM
+## `CURL_DISABLE_NTLM`
Disable support for NTLM.
-## CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
+## `CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG`
Disable the auto load config support in the OpenSSL backend.
-## CURL_DISABLE_PARSEDATE
+## `CURL_DISABLE_PARSEDATE`
Disable date parsing
-## CURL_DISABLE_POP3
+## `CURL_DISABLE_POP3`
Disable the POP3 protocol
-## CURL_DISABLE_PROGRESS_METER
+## `CURL_DISABLE_PROGRESS_METER`
Disable the built-in progress meter
-## CURL_DISABLE_PROXY
+## `CURL_DISABLE_PROXY`
Disable support for proxies
-## CURL_DISABLE_RTSP
+## `CURL_DISABLE_RTSP`
Disable the RTSP protocol.
-## CURL_DISABLE_SHUFFLE_DNS
+## `CURL_DISABLE_SHUFFLE_DNS`
Disable the shuffle DNS feature
-## CURL_DISABLE_SMB
+## `CURL_DISABLE_SMB`
Disable the SMB(S) protocols
-## CURL_DISABLE_SMTP
+## `CURL_DISABLE_SMTP`
Disable the SMTP(S) protocols
-## CURL_DISABLE_SOCKETPAIR
+## `CURL_DISABLE_SOCKETPAIR`
-Disable the use of socketpair internally to allow waking up and canceling
-curl_multi_poll().
+Disable the use of `socketpair()` internally to allow waking up and canceling
+`curl_multi_poll()`.
-## CURL_DISABLE_TELNET
+## `CURL_DISABLE_TELNET`
Disable the TELNET protocol
-## CURL_DISABLE_TFTP
+## `CURL_DISABLE_TFTP`
Disable the TFTP protocol
-## CURL_DISABLE_VERBOSE_STRINGS
+## `CURL_DISABLE_VERBOSE_STRINGS`
Disable verbose strings and error messages.
diff --git a/docs/DEPRECATE.md b/docs/DEPRECATE.md
index 4d58f56..aac9ab8 100644
--- a/docs/DEPRECATE.md
+++ b/docs/DEPRECATE.md
@@ -8,39 +8,64 @@
## NSS
-We remove support for building curl with the NSS TLS library in August 2022.
+We remove support for building curl with the NSS TLS library in August 2023.
-- There are very few users left who use curl+NSS
-- NSS has very few users outside of curl as well (primarily Firefox)
+- There are few users left who use curl+NSS
+- NSS has few users outside of curl as well (primarily Firefox)
- NSS is harder than ever to find documentation for
- NSS was always "best" used with Red Hat Linux when they provided additional
features on top of the regular NSS that is not shipped by the vanilla library
Starting in 7.82.0, building curl to use NSS configure requires the additional
-flag --with-nss-deprecated in an attempt to highlight these plans.
+flag `--with-nss-deprecated` in an attempt to highlight these plans.
-## NPN
+## gskit
-We make selecting NPN a no-op starting in August 2022.
+We remove support for building curl with the gskit TLS library in August 2023.
-**Next Protocol Negotiation** is a TLS extension that was created and used for
-agreeing to use the SPDY protocol (the precursor to HTTP/2) for HTTPS. In the
-early days of HTTP/2, before the spec was finalized and shipped, the protocol
-could be enabled using this extension with some servers.
+- This is a niche TLS library, only running on some IBM systems
+- no regular curl contributors use this backend
+- no CI builds use or verify this backend
+- gskit, or the curl adaption for it, lacks many modern TLS features making it
+ an inferior solution
+- build breakages in this code take weeks or more to get detected
+- fixing gskit code is mostly done "flying blind"
-curl supports the NPN extension with some TLS backends since then, with a
-command line option `--npn` and in libcurl with `CURLOPT_SSL_ENABLE_NPN`.
+## mingw v1
-HTTP/2 proper is made to use the ALPN (Application-Layer Protocol Negotiation)
-extension and the NPN extension has no purposes anymore. The HTTP/2 spec was
-published in May 2015.
+We remove support for building curl with the original legacy mingw version 1
+in September 2023.
-Today, use of NPN in the wild should be extremely rare and most likely totally
-extinct. Chrome removed NPN support in Chrome 51, shipped in
-June 2016. Removed in Firefox 53, April 2017.
+During the deprecation period you can enable the support with the configure
+option `--with-mingw1-deprecated`.
+
+mingw version 1 is old and deprecated software. There are much better and
+still support build environments to use to build curl and other software. For
+example [MinGW-w64](https://www.mingw-w64.org/).
+
+## space-separated `NOPROXY` patterns
+
+When specifying patterns/domain names for curl that should *not* go through a
+proxy, the curl tool features the `--noproxy` command line option and the
+library supports the `NO_PROXY` environment variable and the `CURLOPT_NOPROXY`
+libcurl option.
+
+They all set the same list of patterns. This list is documented to be a set of
+**comma-separated** names, but can also be provided separated with just
+space. The ability to just use spaces for this has never been documented but
+some users may still have come to rely on this.
+
+Several other tools and utilities also parse the `NO_PROXY` environment
+variable but do not consider a space to be a valid separator. Using spaces for
+separator is probably less portable and might cause more friction than commas
+do. Users should use commas for this for greater portability.
+
+curl will remove the support for space-separated names in July 2024.
## past removals
- Pipelining
- axTLS
- PolarSSL
+ - NPN
+ - Support for systems without 64 bit data types
diff --git a/docs/DYNBUF.md b/docs/DYNBUF.md
index a984a41..b0d3929 100644
--- a/docs/DYNBUF.md
+++ b/docs/DYNBUF.md
@@ -9,17 +9,18 @@
buffer. The members of that struct **MUST NOT** be accessed or modified
without using the dedicated dynbuf API.
-## init
+## `Curl_dyn_init`
```c
void Curl_dyn_init(struct dynbuf *s, size_t toobig);
```
-This inits a struct to use for dynbuf and it cannot fail. The `toobig` value
-**must** be set to the maximum size we allow this buffer instance to grow to.
-The functions below will return `CURLE_OUT_OF_MEMORY` when hitting this limit.
+This initializes a struct to use for dynbuf and it cannot fail. The `toobig`
+value **must** be set to the maximum size we allow this buffer instance to
+grow to. The functions below will return `CURLE_OUT_OF_MEMORY` when hitting
+this limit.
-## free
+## `Curl_dyn_free`
```c
void Curl_dyn_free(struct dynbuf *s);
@@ -28,7 +29,7 @@
Free the associated memory and clean up. After a free, the `dynbuf` struct can
be re-used to start appending new data to.
-## addn
+## `Curl_dyn_addn`
```c
CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len);
@@ -36,7 +37,9 @@
Append arbitrary data of a given length to the end of the buffer.
-## add
+If this function fails it calls `Curl_dyn_free` on `dynbuf`.
+
+## `Curl_dyn_add`
```c
CURLcode Curl_dyn_add(struct dynbuf *s, const char *str);
@@ -44,7 +47,9 @@
Append a C string to the end of the buffer.
-## addf
+If this function fails it calls `Curl_dyn_free` on `dynbuf`.
+
+## `Curl_dyn_addf`
```c
CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...);
@@ -52,7 +57,9 @@
Append a `printf()`-style string to the end of the buffer.
-## vaddf
+If this function fails it calls `Curl_dyn_free` on `dynbuf`.
+
+## `Curl_dyn_vaddf`
```c
CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap);
@@ -60,7 +67,9 @@
Append a `vprintf()`-style string to the end of the buffer.
-## reset
+If this function fails it calls `Curl_dyn_free` on `dynbuf`.
+
+## `Curl_dyn_reset`
```c
void Curl_dyn_reset(struct dynbuf *s);
@@ -68,7 +77,7 @@
Reset the buffer length, but leave the allocation.
-## tail
+## `Curl_dyn_tail`
```c
CURLcode Curl_dyn_tail(struct dynbuf *s, size_t length);
@@ -76,9 +85,10 @@
Keep `length` bytes of the buffer tail (the last `length` bytes of the
buffer). The rest of the buffer is dropped. The specified `length` must not be
-larger than the buffer length.
+larger than the buffer length. To instead keep the leading part, see
+`Curl_dyn_setlen()`.
-## ptr
+## `Curl_dyn_ptr`
```c
char *Curl_dyn_ptr(const struct dynbuf *s);
@@ -88,7 +98,7 @@
NULL. Since the buffer may be reallocated, this pointer should not be trusted
or used anymore after the next buffer manipulation call.
-## uptr
+## `Curl_dyn_uptr`
```c
unsigned char *Curl_dyn_uptr(const struct dynbuf *s);
@@ -98,7 +108,7 @@
return NULL. Since the buffer may be reallocated, this pointer should not be
trusted or used anymore after the next buffer manipulation call.
-## len
+## `Curl_dyn_len`
```c
size_t Curl_dyn_len(const struct dynbuf *s);
@@ -106,3 +116,13 @@
Returns the length of the buffer in bytes. Does not include the terminating
zero byte.
+
+## `Curl_dyn_setlen`
+
+```c
+CURLcode Curl_dyn_setlen(struct dynbuf *s, size_t len);
+```
+
+Sets the new shorter length of the buffer in number of bytes. Keeps the
+leftmost set number of bytes, discards the rest. To instead keep the tail part
+of the buffer, see `Curl_dyn_tail()`.
diff --git a/docs/EARLY-RELEASE.md b/docs/EARLY-RELEASE.md
new file mode 100644
index 0000000..989a207
--- /dev/null
+++ b/docs/EARLY-RELEASE.md
@@ -0,0 +1,67 @@
+# How to determine if an early patch release is warranted
+
+In the curl project we do releases every 8 weeks. Unless we break the cycle
+and do an early patch release.
+
+We do frequent releases partly to always have the next release "not too far
+away".
+
+## Bugfix
+
+During the release cycle, and especially in the beginning of a new cycle (the
+so-called "cool down" period), there are times when a bug is reported and
+after it has been subsequently fixed correctly, the question might be asked:
+is this bug and associated fix important enough for an early patch release?
+
+The question can only be properly asked when a fix has been created and landed
+in the git master branch.
+
+## Early release
+
+An early patch release means that we ship a new, complete and full release
+called `major.minor.patch` where the `patch` part is increased by one since
+the previous release. A curl release is a curl release. There is no small or
+big and we never release just a patch. There is only "release".
+
+## Questions to ask
+
+ - Is there a security advisory rated high or critical?
+ - Is there a data corruption bug?
+ - Did the bug cause an API/ABI breakage?
+ - Will the problem annoy a significant share of the user population?
+
+If the answer is yes to one or more of the above, an early release might be
+warranted.
+
+More questions to ask ourselves when doing the assessment if the answers to
+the three ones above are all 'no'.
+
+ - Does the bug cause curl to prematurely terminate?
+ - How common is the affected buggy option/feature/protocol/platform to get
+ used?
+ - How large is the estimated impacted user base?
+ - Does the bug block something crucial for applications or other adoption of
+ curl "out there" ?
+ - Does the bug cause problems for curl developers or others on "the curl
+ team" ?
+ - Is the bug limited to the curl tool only? That might have a smaller impact
+ than a bug also present in libcurl.
+ - Is there a (decent) workaround?
+ - Is it a regression? Is the bug introduced in this release?
+ - Can the bug be fixed "easily" by applying a patch?
+ - Does the bug break the build? Most users don't build curl themselves.
+ - How long is it until the already scheduled next release?
+ - Can affected users safely rather revert to a former release until the next
+ scheduled release?
+ - Is it a performance regression with no functionality side-effects? If so it
+ has to be substantial.
+
+## If an early release is deemed necessary
+
+Unless done for security or similarly important reasons, an early release
+should not be done within a week of the previous release.
+
+This, to enable us to collect and bundle more fixes into the same release to
+make the release more worthwhile for everyone and to allow more time for fixes
+to settle and things to get tested. Getting a release in shape and done in
+style is work that should not be rushed.
diff --git a/docs/EXPERIMENTAL.md b/docs/EXPERIMENTAL.md
index 42b6e21..6b7145d 100644
--- a/docs/EXPERIMENTAL.md
+++ b/docs/EXPERIMENTAL.md
@@ -10,7 +10,7 @@
"carved in stone".
2. You must enable the feature when invoking configure as otherwise curl will
not be built with the feature present.
-3. We strongly advice against using this feature in production.
+3. We strongly advise against using this feature in production.
4. **We reserve the right to change behavior** of the feature without sticking
to our API/ABI rules as we do for regular features, as long as it is marked
experimental.
@@ -20,5 +20,5 @@
- The Hyper HTTP backend
- HTTP/3 support and options
- - `CURLSSLOPT_NATIVE_CA` (No configure option, feature built in when supported)
- The rustls backend
+ - WebSocket
diff --git a/docs/FAQ b/docs/FAQ
index 375715d..78fa9d6 100644
--- a/docs/FAQ
+++ b/docs/FAQ
@@ -136,7 +136,8 @@
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 and TFTP.
+ 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
@@ -421,7 +422,7 @@
backends.
curl can be built to use one of the following SSL alternatives: OpenSSL,
- libressl, BoringSSL, GnuTLS, wolfSSL, NSS, mbedTLS, Secure
+ libressl, BoringSSL, AWS-LC, GnuTLS, wolfSSL, NSS, mbedTLS, Secure
Transport (native iOS/OS X), Schannel (native Windows), GSKit (native IBM
i), BearSSL, 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
@@ -816,7 +817,7 @@
4.5 Why do I get return code XXX from an HTTP server?
- RFC2616 clearly explains the return codes. This is a short transcript. Go
+ 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"
@@ -984,16 +985,15 @@
To use explicit FTPS, you use an FTP:// URL and the --ftp-ssl option (or one
of its related flavors). This is the most common method, and the one
- mandated by RFC4217. This kind of connection will then of course use the
+ 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 POST requests with a
- tiny 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.
+ 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
@@ -1208,7 +1208,7 @@
Target: static lib. import lib for libcurl*.dll.
-----------------------------------------------------------
- MingW: libcurl.a libcurldll.a
+ 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
@@ -1332,7 +1332,7 @@
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 RFC3659 section 7.5.1. If MLSD is not supported
+ 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.
diff --git a/docs/FEATURES.md b/docs/FEATURES.md
index 7451ee6..6f8fa4f 100644
--- a/docs/FEATURES.md
+++ b/docs/FEATURES.md
@@ -7,7 +7,7 @@
- range "globbing" support: [0-13], {one,two,three}
- multiple file upload on a single command line
- custom maximum transfer rate
- - redirectable stderr
+ - redirect stderr
- parallel transfers
## libcurl
@@ -43,7 +43,7 @@
- PUT
- HEAD
- POST
- - multipart formpost (RFC1867-style)
+ - multipart formpost (RFC 1867-style)
- authentication: Basic, Digest, NTLM (9) and Negotiate (SPNEGO) (3)
to server and proxy
- resume (both GET and PUT)
@@ -174,7 +174,7 @@
## POP3S (1)
- implicit `pop3s://` support
- - explicit "STLS" usage to "upgrade" plain `pop3://` connections to use SSL
+ - explicit `STLS` usage to "upgrade" plain `pop3://` connections to use SSL
- via http-proxy
## IMAP
@@ -183,7 +183,7 @@
- SASL based authentication: Plain, Login, CRAM-MD5, Digest-MD5, NTLM (9),
Kerberos 5 (4) and External.
- list the folders of a mailbox
- - select a mailbox with support for verifying the UIDVALIDITY
+ - select a mailbox with support for verifying the `UIDVALIDITY`
- fetch emails with support for specifying the UID and SECTION
- upload emails via the append command
- enhanced command support for: EXAMINE, CREATE, DELETE, RENAME, STATUS,
diff --git a/docs/GOVERNANCE.md b/docs/GOVERNANCE.md
index 0d6c5b2..dd09de4 100644
--- a/docs/GOVERNANCE.md
+++ b/docs/GOVERNANCE.md
@@ -116,7 +116,7 @@
Feltzing serve as backup admins for when Daniel is gone or unable.
The primary server is paid for by Haxx. The machine is physically located in a
-server bunker in Stockholm Sweden, operated by the company Portlane.
+server bunker in Stockholm Sweden, operated by the company Glesys.
The website contents are served to the web via Fastly and Daniel is the
primary curl contact with Fastly.
@@ -152,13 +152,13 @@
### Merge advice
-When you are merging patches/PRs...
+When you are merging patches/pull requests...
- make sure the commit messages follow our template
- squash patch sets into a few logical commits even if the PR did not, if
necessary
- avoid the "merge" button on GitHub, do it "manually" instead to get full
- control and full audit trail (github leaves out you as "Committer:")
+ control and full audit trail (GitHub leaves out you as "Committer:")
- remember to credit the reporter and the helpers.
## Who are maintainers?
diff --git a/docs/HELP-US.md b/docs/HELP-US.md
index eabf808..03a4e3a 100644
--- a/docs/HELP-US.md
+++ b/docs/HELP-US.md
@@ -4,9 +4,11 @@
looking for ways to contribute and help out, this document aims to give a few
good starting points.
-A good idea is to start by subscribing to the [curl-library mailing
+You may subscribe to the [curl-library mailing
list](https://lists.haxx.se/listinfo/curl-library) to keep track of the
-current discussion topics.
+current discussion topics; or if you are registered on GitHub, you can use the
+[Discussions section](https://github.com/curl/curl/discussions) on the main
+curl repository.
## Scratch your own itch
diff --git a/docs/HISTORY.md b/docs/HISTORY.md
index 6268b87..5a142b4 100644
--- a/docs/HISTORY.md
+++ b/docs/HISTORY.md
@@ -24,7 +24,7 @@
HttpGet 0.3 was released in January 1997 and now it accepted HTTP URLs on the
command line.
-HttpGet 1.0 was released on April 8th 1997 with brand new HTTP proxy support.
+HttpGet 1.0 was released on April 8 1997 with brand new HTTP proxy support.
We soon found and fixed support for getting currencies over GOPHER. Once FTP
download support was added, the name of the project was changed and urlget 2.0
@@ -130,7 +130,7 @@
Daniel to discuss "the name issue". After Daniel's reply, they have never
since got back in touch again.
-September: libcurl 7.9 introduces cookie jar and curl_formadd(). During the
+September: libcurl 7.9 introduces cookie jar and `curl_formadd()`. During the
forthcoming 7.9.x releases, we introduced the multi interface slowly and
without many whistles.
@@ -179,16 +179,16 @@
June: curl 7.12.0 introduced IDN support. 10 official web mirrors.
This release bumped the major SONAME to 3 due to the removal of the
-curl_formparse() function
+`curl_formparse()` function
August: Curl and libcurl 7.12.1
Public curl release number: 82
- Releases counted from the very beginning: 109
+ Releases counted from the beginning: 109
Available command line options: 96
Available curl_easy_setopt() options: 120
Number of public functions in libcurl: 36
- Amount of public website mirrors: 12
+ Amount of public website mirrors: 12
Number of known libcurl bindings: 26
2005
@@ -288,7 +288,7 @@
July: Added support for Schannel (native Windows TLS backend) and Darwin SSL
(Native Mac OS X and iOS TLS backend).
- Supports metalink
+ Supports Metalink
October: SSH-agent support.
diff --git a/docs/HSTS.md b/docs/HSTS.md
index cecdc75..e541024 100644
--- a/docs/HSTS.md
+++ b/docs/HSTS.md
@@ -19,7 +19,7 @@
- `CURLOPT_HSTS` - specify file name where to store the HSTS cache on close
(and possibly read from at startup)
-## curl cmdline options
+## curl command line options
- `--hsts [filename]` - enable HSTS, use the file as HSTS cache. If filename
is `""` (no length) then no file will be used, only in-memory cache.
@@ -32,13 +32,11 @@
[host name] "YYYYMMDD HH:MM:SS"
-The `[host name]` is dot-prefixed if it is a includeSubDomain.
+The `[host name]` is dot-prefixed if it includes subdomains.
The time stamp is when the entry expires.
-I considered using wget's file format for the HSTS cache. However, they store the time stamp as the epoch (number of seconds since 1970) and I strongly disagree with using that format. Instead I opted to use a format similar to the curl alt-svc cache file format.
-
## Possible future additions
- - `CURLOPT_HSTS_PRELOAD` - provide a set of preloaded HSTS host names
+ - `CURLOPT_HSTS_PRELOAD` - provide a set of HSTS host names to load first
- ability to save to something else than a file
diff --git a/docs/HTTP-COOKIES.md b/docs/HTTP-COOKIES.md
index 73fa242..d6fd87d 100644
--- a/docs/HTTP-COOKIES.md
+++ b/docs/HTTP-COOKIES.md
@@ -17,7 +17,7 @@
For a long time, the only spec explaining how to use cookies was the
original [Netscape spec from 1994](https://curl.se/rfc/cookie_spec.html).
- In 2011, [RFC6265](https://www.ietf.org/rfc/rfc6265.txt) was finally
+ In 2011, [RFC 6265](https://www.ietf.org/rfc/rfc6265.txt) was finally
published and details how cookies work within HTTP. In 2016, an update which
added support for prefixes was
[proposed](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00),
@@ -25,10 +25,15 @@
[drafted](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-alone-01)
to deprecate modification of 'secure' cookies from non-secure origins. Both
of these drafts have been incorporated into a proposal to
- [replace](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-02)
- RFC6265. Cookie prefixes and secure cookie modification protection has been
+ [replace](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-11)
+ RFC 6265. Cookie prefixes and secure cookie modification protection has been
implemented by curl.
+ curl considers `http://localhost` to be a *secure context*, meaning that it
+ will allow and use cookies marked with the `secure` keyword even when done
+ over plain HTTP for this host. curl does this to match how popular browsers
+ work with secure cookies.
+
## Cookies saved to disk
Netscape once created a file format for storing cookies on disk so that they
@@ -38,15 +43,18 @@
The Netscape cookie file format stores one cookie per physical line in the
file with a bunch of associated meta data, each field separated with
- TAB. That file is called the cookiejar in curl terminology.
+ TAB. That file is called the cookie jar in curl terminology.
- When libcurl saves a cookiejar, it creates a file header of its own in which
- there is a URL mention that will link to the web version of this document.
+ When libcurl saves a cookie jar, it creates a file header of its own in
+ which there is a URL mention that will link to the web version of this
+ document.
## Cookie file format
The cookie file format is text based and stores one cookie per line. Lines
- that start with `#` are treated as comments.
+ that start with `#` are treated as comments. An exception is lines that
+ start with `#HttpOnly_`, which is a prefix for cookies that have the
+ `HttpOnly` attribute set.
Each line that specifies a single cookie consists of seven text fields
separated with TAB characters. A valid line must end with a newline
@@ -74,8 +82,8 @@
`-b, --cookie`
tell curl a file to read cookies from and start the cookie engine, or if it
- is not a file it will pass on the given string. -b name=var works and so does
- -b cookiefile.
+ is not a file it will pass on the given string. `-b name=var` works and so
+ does `-b cookiefile`.
`-j, --junk-session-cookies`
@@ -106,7 +114,7 @@
`CURLOPT_COOKIEJAR`
Tell libcurl to activate the cookie engine, and when the easy handle is
- closed save all known cookies to the given cookiejar file. Write-only.
+ closed save all known cookies to the given cookie jar file. Write-only.
`CURLOPT_COOKIELIST`
@@ -127,7 +135,7 @@
## Cookies with JavaScript
- These days a lot of the web is built up by JavaScript. The webbrowser loads
+ These days a lot of the web is built up by JavaScript. The web browser loads
complete programs that render the page you see. These JavaScript programs
can also set and access cookies.
diff --git a/docs/HTTP2.md b/docs/HTTP2.md
index 35b45ed..a15bb31 100644
--- a/docs/HTTP2.md
+++ b/docs/HTTP2.md
@@ -35,35 +35,16 @@
--------------------
If `CURLOPT_HTTP_VERSION` is set to `CURL_HTTP_VERSION_2_0`, libcurl will use
-ALPN (or NPN) to negotiate which protocol to continue with. Possibly introduce
-an option that will cause libcurl to fail if not possible to use HTTP/2.
+ALPN to negotiate which protocol to continue with. Possibly introduce an
+option that will cause libcurl to fail if not possible to use HTTP/2.
`CURL_HTTP_VERSION_2TLS` was added in 7.47.0 as a way to ask libcurl to prefer
HTTP/2 for HTTPS but stick to 1.1 by default for plain old HTTP connections.
-ALPN is the TLS extension that HTTP/2 is expected to use. The NPN extension is
-for a similar purpose, was made prior to ALPN and is used for SPDY so early
-HTTP/2 servers are implemented using NPN before ALPN support is widespread.
+ALPN is the TLS extension that HTTP/2 is expected to use.
-`CURLOPT_SSL_ENABLE_ALPN` and `CURLOPT_SSL_ENABLE_NPN` are offered to allow
-applications to explicitly disable ALPN or NPN.
-
-SSL libs
---------
-
-The challenge is the ALPN and NPN support and all our different SSL
-backends. You may need a fairly updated SSL library version for it to provide
-the necessary TLS features. Right now we support:
-
- - OpenSSL: ALPN and NPN
- - libressl: ALPN and NPN
- - BoringSSL: ALPN and NPN
- - NSS: ALPN and NPN
- - GnuTLS: ALPN
- - mbedTLS: ALPN
- - Schannel: ALPN
- - wolfSSL: ALPN
- - Secure Transport: ALPN
+`CURLOPT_SSL_ENABLE_ALPN` is offered to allow applications to explicitly
+disable ALPN.
Multiplexing
------------
@@ -78,12 +59,12 @@
that when doing subsequent parallel requests.
While libcurl sets up a connection to an HTTP server there is a period during
-which it does not know if it can pipeline or do multiplexing and if you add new
-transfers in that period, libcurl will default to start new connections for
-those transfers. With the new option `CURLOPT_PIPEWAIT` (added in 7.43.0), you
-can ask that a transfer should rather wait and see in case there's a
+which it does not know if it can pipeline or do multiplexing and if you add
+new transfers in that period, libcurl will default to start new connections
+for those transfers. With the new option `CURLOPT_PIPEWAIT` (added in 7.43.0),
+you can ask that a transfer should rather wait and see in case there's a
connection for the same host in progress that might end up being possible to
-multiplex on. It favours keeping the number of connections low to the cost of
+multiplex on. It favors keeping the number of connections low to the cost of
slightly longer time to first byte transferred.
Applications
diff --git a/docs/HTTP3.md b/docs/HTTP3.md
index 42bc974..87e9e78 100644
--- a/docs/HTTP3.md
+++ b/docs/HTTP3.md
@@ -15,7 +15,7 @@
[quiche](https://github.com/cloudflare/quiche)
-[msquic](https://github.com/microsoft/msquic) & [msh3](https://github.com/nibanks/msh3)
+[msh3](https://github.com/nibanks/msh3) (with [msquic](https://github.com/microsoft/msquic))
## Experimental
@@ -25,13 +25,28 @@
Further development and tweaking of the HTTP/3 support in curl will happen in
the master branch using pull-requests, just like ordinary changes.
+To fix before we remove the experimental label:
+
+ - working multiplexing and GTFO handling
+ - fallback or another flexible way to go (back to) h1/h2 if h3 fails
+ - enough test cases to verify basic HTTP/3 functionality
+ - no "important" bugs left on HTTP/3
+ - it's fine to "leave" individual backends as experimental if necessary
+
# ngtcp2 version
+Building curl with ngtcp2 involves 3 components: `ngtcp2` itself, `nghttp3` and a QUIC supporting TLS library. The supported TLS libraries are covered below.
+
+For now, `ngtcp2` and `nghttp3` are still *experimental* which means their evolution bring breaking changes. Therefore, the proper version of both libraries need to be used when building curl. These are
+
+ * `ngtcp2`: v0.17.0
+ * `nghttp3`: v0.13.0
+
## Build with OpenSSL
Build (patched) OpenSSL
- % git clone --depth 1 -b openssl-3.0.0+quic https://github.com/quictls/openssl
+ % git clone --depth 1 -b openssl-3.0.9+quic https://github.com/quictls/openssl
% cd openssl
% ./config enable-tls1_3 --prefix=<somewhere1>
% make
@@ -40,7 +55,7 @@
Build nghttp3
% cd ..
- % git clone https://github.com/ngtcp2/nghttp3
+ % git clone -b v0.13.0 https://github.com/ngtcp2/nghttp3
% cd nghttp3
% autoreconf -fi
% ./configure --prefix=<somewhere2> --enable-lib-only
@@ -50,7 +65,7 @@
Build ngtcp2
% cd ..
- % git clone https://github.com/ngtcp2/ngtcp2
+ % git clone -b v0.17.0 https://github.com/ngtcp2/ngtcp2
% cd ngtcp2
% autoreconf -fi
% ./configure PKG_CONFIG_PATH=<somewhere1>/lib/pkgconfig:<somewhere2>/lib/pkgconfig LDFLAGS="-Wl,-rpath,<somewhere1>/lib" --prefix=<somewhere3> --enable-lib-only
@@ -83,7 +98,7 @@
Build nghttp3
% cd ..
- % git clone https://github.com/ngtcp2/nghttp3
+ % git clone -b v0.13.0 https://github.com/ngtcp2/nghttp3
% cd nghttp3
% autoreconf -fi
% ./configure --prefix=<somewhere2> --enable-lib-only
@@ -93,7 +108,7 @@
Build ngtcp2
% cd ..
- % git clone https://github.com/ngtcp2/ngtcp2
+ % git clone -b v0.17.0 https://github.com/ngtcp2/ngtcp2
% cd ngtcp2
% autoreconf -fi
% ./configure PKG_CONFIG_PATH=<somewhere1>/lib/pkgconfig:<somewhere2>/lib/pkgconfig LDFLAGS="-Wl,-rpath,<somewhere1>/lib" --prefix=<somewhere3> --enable-lib-only --with-gnutls
@@ -106,12 +121,55 @@
% git clone https://github.com/curl/curl
% cd curl
% autoreconf -fi
- % ./configure --without-openssl --with-gnutls=<somewhere1> --with-nghttp3=<somewhere2> --with-ngtcp2=<somewhere3>
+ % ./configure --with-gnutls=<somewhere1> --with-nghttp3=<somewhere2> --with-ngtcp2=<somewhere3>
+ % make
+ % make install
+
+## Build with wolfSSL
+
+Build wolfSSL
+
+ % git clone https://github.com/wolfSSL/wolfssl.git
+ % cd wolfssl
+ % autoreconf -fi
+ % ./configure --prefix=<somewhere1> --enable-quic --enable-session-ticket --enable-earlydata --enable-psk --enable-harden --enable-altcertchains
+ % make
+ % make install
+
+Build nghttp3
+
+ % cd ..
+ % git clone -b v0.13.0 https://github.com/ngtcp2/nghttp3
+ % cd nghttp3
+ % autoreconf -fi
+ % ./configure --prefix=<somewhere2> --enable-lib-only
+ % make
+ % make install
+
+Build ngtcp2
+
+ % cd ..
+ % git clone -b v0.17.0 https://github.com/ngtcp2/ngtcp2
+ % cd ngtcp2
+ % autoreconf -fi
+ % ./configure PKG_CONFIG_PATH=<somewhere1>/lib/pkgconfig:<somewhere2>/lib/pkgconfig LDFLAGS="-Wl,-rpath,<somewhere1>/lib" --prefix=<somewhere3> --enable-lib-only --with-wolfssl
+ % make
+ % make install
+
+Build curl
+
+ % cd ..
+ % git clone https://github.com/curl/curl
+ % cd curl
+ % autoreconf -fi
+ % ./configure --with-wolfssl=<somewhere1> --with-nghttp3=<somewhere2> --with-ngtcp2=<somewhere3>
% make
% make install
# quiche version
+Since the quiche build manages its dependencies, curl can be built against the latest version. You are *probably* able to build against their main branch, but in case of problems, we recommend their latest release tag.
+
## build
Build quiche and BoringSSL:
@@ -140,7 +198,7 @@
Build msh3:
- % git clone --depth 1 --recursive https://github.com/nibanks/msh3
+ % git clone -b v0.6.0 --depth 1 --recursive https://github.com/nibanks/msh3
% cd msh3 && mkdir build && cd build
% cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
% cmake --build .
@@ -161,7 +219,7 @@
Build msh3:
- % git clone --depth 1 --recursive https://github.com/nibanks/msh3
+ % git clone -b v0.6.0 --depth 1 --recursive https://github.com/nibanks/msh3
% cd msh3 && mkdir build && cd build
% cmake -G 'Visual Studio 17 2022' -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
% cmake --build . --config Release
@@ -190,7 +248,11 @@
# `--http3`
-Use HTTP/3 directly:
+Use only HTTP/3:
+
+ curl --http3-only https://nghttp2.org:4433/
+
+Use HTTP/3 with fallback to HTTP/2 or HTTP/1.1 (see "HTTPS eyeballing" below):
curl --http3 https://nghttp2.org:4433/
@@ -200,6 +262,28 @@
See this [list of public HTTP/3 servers](https://bagder.github.io/HTTP3-test/)
+### HTTPS eyeballing
+
+With option `--http3` curl will attempt earlier HTTP versions as well should the connect
+attempt via HTTP/3 not succeed "fast enough". This strategy is similar to IPv4/6 happy
+eyeballing where the alternate address family is used in parallel after a short delay.
+
+The IPv4/6 eyeballing has a default of 200ms and you may override that via `--happy-eyeballs-timeout-ms value`.
+Since HTTP/3 is still relatively new, we decided to use this timeout also for the HTTP eyeballing - with a slight twist.
+
+The `happy-eyeballs-timeout-ms` value is the **hard** timeout, meaning after that time expired, a TLS connection is opened in addition to negotiate HTTP/2 or HTTP/1.1. At half of that value - currently - is the **soft** timeout. The soft timeout fires, when there has been **no data at all** seen from the server on the HTTP/3 connection.
+
+So, without you specifying anything, the hard timeout is 200ms and the soft is 100ms:
+
+ * Ideally, the whole QUIC handshake happens and curl has an HTTP/3 connection in less than 100ms.
+ * When QUIC is not supported (or UDP does not work for this network path), no reply is seen and the HTTP/2 TLS+TCP connection starts 100ms later.
+ * In the worst case, UDP replies start before 100ms, but drag on. This will start the TLS+TCP connection after 200ms.
+ * When the QUIC handshake fails, the TLS+TCP connection is attempted right away. For example, when the QUIC server presents the wrong certificate.
+
+The whole transfer only fails, when **both** QUIC and TLS+TCP fail to handshake or time out.
+
+Note that all this happens in addition to IP version happy eyeballing. If the name resolution for the server gives more than one IP address, curl will try all those until one succeeds - just as with all other protocols. And if those IP addresses contain both IPv6 and IPv4, those attempts will happen, delayed, in parallel (the actual eyeballing).
+
## Known Bugs
Check out the [list of known HTTP3 bugs](https://curl.se/docs/knownbugs.html#HTTP3).
@@ -212,12 +296,12 @@
## Prerequisite(s)
An existing local HTTP/1.1 server that hosts files. Preferably also a few huge
-ones. You can easily create huge local files like `truncate -s=8G 8GB` - they
+ones. You can easily create huge local files like `truncate -s=8G 8GB` - they
are huge but do not occupy that much space on disk since they are just big
holes.
-In my Debian setup I just installed **apache2**. It runs on port 80 and has a
-document root in `/var/www/html`. I can get the 8GB file from it with `curl
+In a Debian setup you can install **apache2**. It runs on port 80 and has a
+document root in `/var/www/html`. Download the 8GB file from apache with `curl
localhost/8GB -o dev/null`
In this description we setup and run an HTTP/3 reverse-proxy in front of the
@@ -250,26 +334,21 @@
### Caddy
-[Install caddy](https://caddyserver.com/docs/install), you can even put the
-single binary in a separate directory if you prefer.
+[Install Caddy](https://caddyserver.com/docs/install). For easiest use, the binary
+should be either in your PATH or your current directory.
-In the same directory you put caddy, create a `Caddyfile` with the following
-content to run an HTTP/3 reverse-proxy on port 7443:
+Create a `Caddyfile` with the following content:
~~~
-{
- auto_https disable_redirects
- servers :7443 {
- protocol {
- experimental_http3
- }
- }
-}
-
localhost:7443 {
- reverse_proxy localhost:80
+ respond "Hello, world! You're using {http.request.proto}"
}
~~~
-Then run caddy:
+Then run Caddy:
./caddy start
+
+Making requests to `https://localhost:7443` should tell you which protocol is being used.
+
+You can change the hard-coded response to something more useful by replacing `respond`
+with `reverse_proxy` or `file_server`, for example: `reverse_proxy localhost:80`
diff --git a/docs/HYPER.md b/docs/HYPER.md
index ad23a90..44a6785 100644
--- a/docs/HYPER.md
+++ b/docs/HYPER.md
@@ -9,7 +9,7 @@
needs to be explicitly enabled at build-time.
Further development and tweaking of the Hyper backend support in curl will
-happen in in the master branch using pull-requests, just like ordinary
+happen in the master branch using pull-requests, just like ordinary
changes.
## Hyper version
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index 03d7384..29863af 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -17,7 +17,9 @@
./vcpkg integrate install
vcpkg install curl[tool]
-The curl port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
+The curl port in vcpkg is kept up to date by Microsoft team members and
+community contributors. If the version is out of date, please [create an issue
+or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
## Building from git
@@ -72,8 +74,8 @@
./configure --with-openssl=/opt/OpenSSL
-If you insist on forcing a build without SSL support, even though you may
-have OpenSSL installed in your system, you can run configure like this:
+If you insist on forcing a build without SSL support, you can run configure
+like this:
./configure --without-ssl
@@ -90,17 +92,32 @@
LDFLAGS=-Wl,-R/usr/local/ssl/lib ./configure --with-openssl
-## More Options
+## Static builds
To force a static library compile, disable the shared library creation by
running configure like:
./configure --disable-shared
-To tell the configure script to skip searching for thread-safe functions, add
-an option like:
+The configure script is primarily done to work with shared/dynamic third party
+dependencies. When linking with shared libraries, the dependency "chain" is
+handled automatically by the library loader - on all modern systems.
- ./configure --disable-thread
+If you instead link with a static library, you need to provide all the
+dependency libraries already at the link command line.
+
+Figuring out all the dependency libraries for a given library is hard, as it
+might involve figuring out the dependencies of the dependencies and they vary
+between platforms and change between versions.
+
+When using static dependencies, the build scripts will mostly assume that you,
+the user, will provide all the necessary additional dependency libraries as
+additional arguments in the build. With configure, by setting `LIBS` or
+`LDFLAGS` on the command line.
+
+Building statically is not for the faint of heart.
+
+## Debug
If you are a curl developer and use gcc, you might want to enable more debug
options with the `--enable-debug` option.
@@ -118,12 +135,32 @@
- GnuTLS: `--with-gnutls`.
- mbedTLS: `--with-mbedtls`
- NSS: `--with-nss`
- - OpenSSL: `--with-openssl` (also for BoringSSL and libressl)
+ - OpenSSL: `--with-openssl` (also for BoringSSL, AWS-LC, libressl, and quictls)
- rustls: `--with-rustls`
- - schannel: `--with-schannel`
- - secure transport: `--with-secure-transport`
+ - Schannel: `--with-schannel`
+ - Secure Transport: `--with-secure-transport`
- wolfSSL: `--with-wolfssl`
+You can build curl with *multiple* TLS backends at your choice, but some TLS
+backends cannot be combined: if you build with an OpenSSL fork (or wolfSSL),
+you cannot add another OpenSSL fork (or wolfSSL) simply because they have
+conflicting identical symbol names.
+
+When you build with multiple TLS backends, you can select the active one at
+run-time when curl starts up.
+
+## configure finding libs in wrong directory
+
+When the configure script checks for third-party libraries, it adds those
+directories to the `LDFLAGS` variable and then tries linking to see if it
+works. When successful, the found directory is kept in the `LDFLAGS` variable
+when the script continues to execute and do more tests and possibly check for
+more libraries.
+
+This can make subsequent checks for libraries wrongly detect another
+installation in a directory that was previously added to `LDFLAGS` by another
+library check.
+
# Windows
## Building Windows DLLs and C runtime (CRT) linkage issues
@@ -140,14 +177,14 @@
- [Run-Time Library Compiler Options](https://docs.microsoft.com/cpp/build/reference/md-mt-ld-use-run-time-library)
- [Potential Errors Passing CRT Objects Across DLL Boundaries](https://docs.microsoft.com/cpp/c-runtime-library/potential-errors-passing-crt-objects-across-dll-boundaries)
-If your app is misbehaving in some strange way, or it is suffering from
-memory corruption, before asking for further help, please try first to
-rebuild every single library your app uses as well as your app using the
-debug multithreaded dynamic C runtime.
+If your app is misbehaving in some strange way, or it is suffering from memory
+corruption, before asking for further help, please try first to rebuild every
+single library your app uses as well as your app using the debug
+multi-threaded dynamic C runtime.
If you get linkage errors read section 5.7 of the FAQ document.
-## MingW32
+## MinGW32
Make sure that MinGW32's bin directory is in the search path, for example:
@@ -165,32 +202,35 @@
and SSPI support.
If you have any problems linking libraries or finding header files, be sure
-to verify that the provided `Makefile.m32` files use the proper paths, and
+to verify that the provided `Makefile.mk` files use the proper paths, and
adjust as necessary. It is also possible to override these paths with
environment variables, for example:
```cmd
-set ZLIB_PATH=c:\zlib-1.2.8
-set OPENSSL_PATH=c:\openssl-1.0.2c
-set LIBSSH2_PATH=c:\libssh2-1.6.0
+set ZLIB_PATH=c:\zlib-1.2.12
+set OPENSSL_PATH=c:\openssl-3.0.5
+set LIBSSH2_PATH=c:\libssh2-1.10.0
```
-It is also possible to build with other LDAP SDKs than MS LDAP; currently
-it is possible to build with native Win32 OpenLDAP, or with the Novell CLDAP
-SDK. If you want to use these you need to set these vars:
+It is also possible to build with other LDAP installations than MS LDAP;
+currently it is possible to build with native Win32 OpenLDAP, or with the
+*Novell CLDAP* SDK. If you want to use these you need to set these vars:
```cmd
-set LDAP_SDK=c:\openldap
-set USE_LDAP_OPENLDAP=1
+set CPPFLAGS=-Ic:/openldap/include -DCURL_HAS_OPENLDAP_LDAPSDK
+set LDFLAGS=-Lc:/openldap/lib
+set LIBS=-lldap -llber
```
or for using the Novell SDK:
```cmd
-set USE_LDAP_NOVELL=1
+set CPPFLAGS=-Ic:/openldapsdk/inc -DCURL_HAS_NOVELL_LDAPSDK
+set LDFLAGS=-Lc:/openldapsdk/lib/mscvc
+set LIBS=-lldapsdk -lldapssl -lldapx
```
-If you want to enable LDAPS support then set LDAPS=1.
+If you want to enable LDAPS support then append `-ldaps` to the make target.
## Cygwin
@@ -200,6 +240,30 @@
Run `make`
+## MS-DOS
+
+Requires DJGPP in the search path and pointing to the Watt-32 stack via
+`WATT_PATH=c:/djgpp/net/watt`.
+
+Run `make -f Makefile.dist djgpp` in the root curl dir.
+
+For build configuration options, please see the MinGW32 section.
+
+Notes:
+
+ - DJGPP 2.04 beta has a `sscanf()` bug so the URL parsing is not done
+ properly. Use DJGPP 2.03 until they fix it.
+
+ - Compile Watt-32 (and OpenSSL) with the same version of DJGPP. Otherwise
+ things go wrong because things like FS-extensions and `errno` values have
+ been changed between releases.
+
+## AmigaOS
+
+Run `make -f Makefile.dist amiga` in the root curl dir.
+
+For build configuration options, please see the MinGW32 section.
+
## Disabling Specific Protocols in Windows builds
The configure utility, unfortunately, is not available for the Windows
@@ -207,7 +271,7 @@
the configure utility on this platform.
You can use specific defines to disable specific protocols and features. See
-[CURL-DISABLE.md](CURL-DISABLE.md) for the full list.
+[CURL-DISABLE](CURL-DISABLE.md) for the full list.
If you want to set any of these defines you have the following options:
@@ -241,13 +305,11 @@
before including any libcurl header. Your program does not need the
`USE_LWIPSOCK` preprocessor definition which is for libcurl internals only.
-Compilation has been verified with [lwIP
-1.4.0](https://download.savannah.gnu.org/releases/lwip/lwip-1.4.0.zip) and
-[contrib-1.4.0](https://download.savannah.gnu.org/releases/lwip/contrib-1.4.0.zip).
+Compilation has been verified with lwIP 1.4.0.
This BSD-style lwIP TCP/IP stack support must be considered experimental given
that it has been verified that lwIP 1.4.0 still needs some polish, and libcurl
-might yet need some additional adjustment, caveat emptor.
+might yet need some additional adjustment.
## Important static libcurl usage note
@@ -267,8 +329,7 @@
On modern Apple operating systems, curl can be built to use Apple's SSL/TLS
implementation, Secure Transport, instead of OpenSSL. To build with Secure
-Transport for SSL/TLS, use the configure option `--with-secure-transport`. (It
-is not necessary to use the option `--without-openssl`.)
+Transport for SSL/TLS, use the configure option `--with-secure-transport`.
When Secure Transport is in use, the curl options `--cacert` and `--capath`
and their libcurl equivalents, will be ignored, because Secure Transport uses
@@ -326,7 +387,7 @@
# Android
-When building curl for Android it's recommended to use a Linux environment
+When building curl for Android it's recommended to use a Linux/macOS environment
since using curl's `configure` script is the easiest way to build curl
for Android. Before you can build curl for Android, you need to install the
Android NDK first. This can be done using the SDK Manager that is part of
@@ -336,16 +397,16 @@
for `aarch64` and API level 29:
```bash
-export NDK=~/Library/Android/sdk/ndk/20.1.5948944
-export HOST_TAG=darwin-x86_64
-export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_TAG
-export AR=$TOOLCHAIN/bin/aarch64-linux-android-ar
-export AS=$TOOLCHAIN/bin/aarch64-linux-android-as
-export CC=$TOOLCHAIN/bin/aarch64-linux-android29-clang
-export CXX=$TOOLCHAIN/bin/aarch64-linux-android29-clang++
-export LD=$TOOLCHAIN/bin/aarch64-linux-android-ld
-export RANLIB=$TOOLCHAIN/bin/aarch64-linux-android-ranlib
-export STRIP=$TOOLCHAIN/bin/aarch64-linux-android-strip
+export ANDROID_NDK_HOME=~/Library/Android/sdk/ndk/25.1.8937393 # Point into your NDK.
+export HOST_TAG=darwin-x86_64 # Same tag for Apple Silicon. Other OS values here: https://developer.android.com/ndk/guides/other_build_systems#overview
+export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/$HOST_TAG
+export AR=$TOOLCHAIN/bin/llvm-ar
+export AS=$TOOLCHAIN/bin/llvm-as
+export CC=$TOOLCHAIN/bin/aarch64-linux-android21-clang
+export CXX=$TOOLCHAIN/bin/aarch64-linux-android21-clang++
+export LD=$TOOLCHAIN/bin/ld
+export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
+export STRIP=$TOOLCHAIN/bin/llvm-strip
```
When building on Linux or targeting other API levels or architectures, you need
@@ -361,11 +422,10 @@
`$TOOLCHAIN/sysroot/usr/include`. Now you can build curl for Android using
OpenSSL like this:
- ./configure --host aarch64-linux-android --with-pic --disable-shared --with-openssl="$TOOLCHAIN/sysroot/usr"
-
-Note, however, that you must target at least Android M (API level 23) or `configure`
-will not be able to detect OpenSSL since `stderr` (and the like) were not defined
-before Android M.
+```bash
+LIBS="-lssl -lcrypto -lc++" # For OpenSSL/BoringSSL. In general, you will need to the SSL/TLS layer's transitive dependencies if you are linking statically.
+./configure --host aarch64-linux-android --with-pic --disable-shared --with-openssl="$TOOLCHAIN/sysroot/usr"
+```
# IBM i
@@ -383,12 +443,12 @@
There are some additional limitations and quirks with curl on this platform;
they affect both environments.
-## Multithreading notes
+## Multi-threading notes
By default, jobs in IBM i will not start with threading enabled. (Exceptions
include interactive PASE sessions started by `QP2TERM` or SSH.) If you use
-curl in an environment without threading when options like async DNS were
-enabled, you will get messages like:
+curl in an environment without threading when options like asynchronous DNS
+were enabled, you will get messages like:
```
getaddrinfo() thread failed to start
@@ -408,9 +468,9 @@
Set environment variables to point to the cross-compile toolchain and call
configure with any options you need. Be sure and specify the `--host` and
-`--build` parameters at configuration time. The following script is an
-example of cross-compiling for the IBM 405GP PowerPC processor using the
-toolchain from MonteVista for Hardhat Linux.
+`--build` parameters at configuration time. The following script is an example
+of cross-compiling for the IBM 405GP PowerPC processor using the toolchain on
+Linux.
```bash
#! /bin/sh
@@ -462,7 +522,7 @@
use, here are some other flags that can reduce the size of the library by
disabling support for some feature:
- - `--disable-alt-svc` (HTTP Alt-Srv)
+ - `--disable-alt-svc` (HTTP Alt-Svc)
- `--disable-ares` (the C-ARES DNS library)
- `--disable-cookies` (HTTP cookies)
- `--disable-crypto-auth` (cryptographic authentication)
@@ -479,8 +539,8 @@
- `--disable-ntlm-wb` (NTLM WinBind)
- `--disable-progress-meter` (graphical progress meter in library)
- `--disable-proxy` (HTTP and SOCKS proxies)
- - `--disable-pthreads` (multithreading)
- - `--disable-socketpair` (socketpair for async name resolving)
+ - `--disable-pthreads` (multi-threading)
+ - `--disable-socketpair` (socketpair for asynchronous name resolving)
- `--disable-threaded-resolver` (threaded name resolver)
- `--disable-tls-srp` (Secure Remote Password authentication for TLS)
- `--disable-unix-sockets` (UNIX sockets)
@@ -526,8 +586,8 @@
that are not automatically detected:
- `--disable-cookies` !cookies
- - `--disable-dateparse` !RETRY-AFTER !CURLOPT_TIMECONDITION !CURLINFO_FILETIME !If-Modified-Since !getdate !-z
- - `--disable-libcurl-option` !--libcurl
+ - `--disable-dateparse` !RETRY-AFTER !`CURLOPT_TIMECONDITION` !`CURLINFO_FILETIME` !`If-Modified-Since` !`curl_getdate` !`-z`
+ - `--disable-libcurl-option` !`--libcurl`
- `--disable-verbose` !verbose\ logs
# PORTS
@@ -536,21 +596,23 @@
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!
-## 85 Operating Systems
+## 92 Operating Systems
-AIX, AmigaOS, Android, Aros, BeOS, Blackberry 10, Blackberry Tablet OS, Cell
-OS, ChromeOS, Cisco IOS, Cygwin, Dragonfly BSD, eCOS, FreeBSD, FreeDOS,
-FreeRTOS, Fuchsia, Garmin OS, Genode, Haiku, HardenedBSD, HP-UX, Hurd,
-Illumos, Integrity, iOS, ipadOS, IRIX, LineageOS, Linux, Lua RTOS, Mac OS 9,
-macOS, Mbed, Micrium, MINIX, MorphOS, MPE/iX, MS-DOS, NCR MP-RAS, NetBSD,
-Netware, Nintendo Switch, NonStop OS, NuttX, OpenBSD, OpenStep, Orbis OS,
-OS/2, OS/400, OS21, Plan 9, PlayStation Portable, QNX, Qubes OS, ReactOS,
-Redox, RICS OS, Sailfish OS, SCO Unix, Serenity, SINIX-Z, Solaris, SunOS,
-Syllable OS, Symbian, Tizen, TPF, Tru64, tvOS, ucLinux, Ultrix, UNICOS,
-UnixWare, VMS, vxWorks, WebOS, Wii system software, Windows, Windows CE, Xbox
-System, z/OS, z/TPF, z/VM, z/VSE
+ AIX, AmigaOS, Android, Aros, BeOS, Blackberry 10, Blackberry Tablet OS,
+ Cell OS, Chrome OS, Cisco IOS, Cygwin, DG/UX, Dragonfly BSD, DR DOS, eCOS,
+ FreeBSD, FreeDOS, FreeRTOS, Fuchsia, Garmin OS, Genode, Haiku, HardenedBSD,
+ HP-UX, Hurd, Illumos, Integrity, iOS, ipadOS, IRIX, Linux, Lua RTOS,
+ Mac OS 9, macOS, Mbed, Micrium, MINIX, MorphOS, MPE/iX, MS-DOS, NCR MP-RAS,
+ NetBSD, Netware, Nintendo Switch, NonStop OS, NuttX, Omni OS, OpenBSD,
+ OpenStep, Orbis OS, OS/2, OS/400, OS21, Plan 9, PlayStation Portable, QNX,
+ Qubes OS, ReactOS, Redox, RICS OS, RTEMS, Sailfish OS, SCO Unix, Serenity,
+ SINIX-Z, Solaris, SunOS, Syllable OS, Symbian, Tizen, TPF, Tru64, tvOS,
+ ucLinux, Ultrix, UNICOS, UnixWare, VMS, vxWorks, watchOS, WebOS,
+ Wii system software, Windows, Windows CE, Xbox System, Xenix, Zephyr,
+ z/OS, z/TPF, z/VM, z/VSE
-## 22 CPU Architectures
+## 26 CPU Architectures
-Alpha, ARC, ARM, AVR32, Cell, HP-PA, Itanium, m68k, MicroBlaze, MIPS, Nios,
-OpenRISC, POWER, PowerPC, RISC-V, s390, SH4, SPARC, VAX, x86, x86-64, Xtensa
+ Alpha, ARC, ARM, AVR32, CompactRISC, Elbrus, ETRAX, HP-PA, Itanium,
+ LoongArch, m68k, m88k, MicroBlaze, MIPS, Nios, OpenRISC, POWER, PowerPC,
+ RISC-V, s390, SH4, SPARC, Tilera, VAX, x86, Xtensa
diff --git a/docs/INTERNALS.md b/docs/INTERNALS.md
index 7da0be5..cd8cc8f 100644
--- a/docs/INTERNALS.md
+++ b/docs/INTERNALS.md
@@ -2,11 +2,11 @@
The canonical libcurl internals documentation is now in the [everything
curl](https://everything.curl.dev/internals) book. This file lists supported
-versions of libs, tools and operating systems.
+versions of libs and build tools.
## Portability
- We write curl and libcurl to compile with C89 compilers. On 32-bit and up
+ We write curl and libcurl to compile with C89 compilers on 32-bit and up
machines. Most of libcurl assumes more or less POSIX compliance but that is
not a requirement.
@@ -25,26 +25,14 @@
- c-ares 1.16.0
- libidn2 2.0.0
- wolfSSL 2.0.0
- - openldap 2.0
+ - OpenLDAP 2.0
- MIT Kerberos 1.2.4
- GSKit V5R3M0
- NSS 3.14.x
- Heimdal ?
- - nghttp2 1.12.0
+ - nghttp2 1.15.0
- WinSock 2.2 (on Windows 95+ and Windows CE .NET 4.1+)
-## Operating Systems
-
- On systems where configure runs, we aim at working on them all - if they have
- a suitable C compiler. On systems that do not run configure, we strive to
- keep curl running correctly on:
-
- - Windows 98
- - AS/400 V5R3M0
- - Symbian 9.1
- - Windows CE ?
- - TPF ?
-
## Build tools
When writing code (mostly for generating stuff included in release tarballs)
@@ -52,19 +40,19 @@
these versions:
- GNU Libtool 1.4.2
- - GNU Autoconf 2.57
+ - GNU Autoconf 2.59
- GNU Automake 1.7
- GNU M4 1.4
- - perl 5.004
+ - perl 5.6
- roffit 0.5
- - groff ? (any version that supports `groff -Tps -man [in] [out]`)
+ - nroff any version that supports `-man [in] [out]`
+ - cmake 3.7
Library Symbols
===============
All symbols used internally in libcurl must use a `Curl_` prefix if they are
used in more than a single file. Single-file symbols must be made static.
- Public ("exported") symbols must use a `curl_` prefix. (There are exceptions,
- but they are to be changed to follow this pattern in future versions.) Public
- API functions are marked with `CURL_EXTERN` in the public header files so
- that all others can be hidden on platforms where this is possible.
+ Public ("exported") symbols must use a `curl_` prefix. Public API functions
+ are marked with `CURL_EXTERN` in the public header files so that all others
+ can be hidden on platforms where this is possible.
diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS
index 67197cf..38b888c 100644
--- a/docs/KNOWN_BUGS
+++ b/docs/KNOWN_BUGS
@@ -12,30 +12,18 @@
problems may have been fixed or changed somewhat since this was written.
1. HTTP
- 1.2 Multiple methods in a single WWW-Authenticate: header
- 1.3 STARTTRANSFER time is wrong for HTTP POSTs
- 1.4 multipart formposts file name encoding
+ 1.1 hyper memory-leaks
1.5 Expect-100 meets 417
- 1.6 Unnecessary close when 401 received waiting for 100
- 1.7 Deflate error after all content was received
- 1.8 DoH is not used for all name resolves when enabled
- 1.11 CURLOPT_SEEKFUNCTION not called with CURLFORM_STREAM
2. TLS
- 2.1 CURLINFO_SSL_VERIFYRESULT has limited support
- 2.2 DER in keychain
2.3 Unable to use PKCS12 certificate with Secure Transport
2.4 Secure Transport will not import PKCS#12 client certificates without a password
2.5 Client cert handling with Issuer DN differs between backends
- 2.6 CURL_GLOBAL_SSL
2.7 Client cert (MTLS) issues with Schannel
2.8 Schannel disable CURLOPT_SSL_VERIFYPEER and verify hostname
- 2.9 TLS session cache does not work with TFO
- 2.10 Store TLS context per transfer instead of per connection
2.11 Schannel TLS 1.2 handshake bug in old Windows versions
2.12 FTPS with Schannel times out file list operation
- 2.14 Secure Transport disabling hostname validation also disables SNI
- 2.15 Renegotiate from server may cause hang for OpenSSL backend
+ 2.13 CURLOPT_CERTINFO results in CURLE_OUT_OF_MEMORY with Schannel
3. Email protocols
3.1 IMAP SEARCH ALL truncated response
@@ -44,23 +32,17 @@
3.4 AUTH PLAIN for SMTP is not working on all servers
4. Command line
- 4.1 -J and -O with %-encoded file names
- 4.2 -J with -C - fails
- 4.3 --retry and transfer timeouts
5. Build and portability issues
5.1 OS400 port requires deprecated IBM library
5.2 curl-config --libs contains private details
- 5.3 curl compiled on OSX 10.13 failed to run on OSX 10.10
- 5.4 Build with statically built dependency
+ 5.3 building for old macOS fails with gcc
5.5 cannot handle Unicode arguments in non-Unicode builds on Windows
- 5.6 make distclean loops forever
- 5.7 Visual Studio project gaps
- 5.8 configure finding libs in wrong directory
5.9 Utilize Requires.private directives in libcurl.pc
- 5.10 curl hangs on SMB upload over stdin
5.11 configure --with-gssapi with Heimdal is ignored on macOS
- 5.12 flaky Windows CI builds
+ 5.12 flaky CI builds
+ 5.13 long paths are not fully supported on Windows
+ 5.14 Windows Unicode builds use homedir in current locale
6. Authentication
6.1 NTLM authentication and unicode
@@ -70,54 +52,31 @@
6.5 NTLM does not support password with § character
6.6 libcurl can fail to try alternatives with --proxy-any
6.7 Do not clear digest for single realm
- 6.8 RTSP authentication breaks without redirect support
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.12 cannot use Secure Transport with Crypto Token Kit
+ 6.13 Negotiate against Hadoop HDFS
7. FTP
- 7.1 FTP without or slow 220 response
- 7.2 FTP with CONNECT and slow server
7.3 FTP with NOBODY and FAILONERROR
7.4 FTP with ACCT
- 7.5 ASCII FTP
- 7.6 FTP with NULs in URL parts
- 7.7 FTP and empty path parts in the URL
- 7.8 Premature transfer end but healthy control channel
- 7.9 Passive transfer tries only one IP address
- 7.10 FTPS needs session reuse
7.11 FTPS upload data loss with TLS 1.3
-
- 8. TELNET
- 8.1 TELNET and time limitations do not work
- 8.2 Microsoft telnet server
+ 7.12 FTPS directory listing hangs on Windows with Schannel
9. SFTP and SCP
9.1 SFTP does not do CURLOPT_POSTQUOTE correct
9.2 wolfssh: publickey auth does not work
9.3 Remote recursive folder creation with SFTP
+ 9.4 libssh blocking and infinite loop problem
10. SOCKS
10.3 FTPS over SOCKS
- 10.4 active FTP over a SOCKS
11. Internals
- 11.1 Curl leaks .onion hostnames in DNS
11.2 error buffer not set if connection to multiple addresses fails
- 11.3 Disconnects do not do verbose
11.4 HTTP test server 'connection-monitor' problems
11.5 Connection information when using TCP Fast Open
- 11.7 signal-based resolver timeouts
- 11.8 DoH leaks memory after followlocation
- 11.9 DoH does not inherit all transfer options
- 11.10 Blocking socket operations in non-blocking API
- 11.11 A shared connection cache is not thread-safe
- 11.12 'no_proxy' string-matches IPv6 numerical addresses
- 11.13 wakeup socket disconnect causes havoc
- 11.14 Multi perform hangs waiting for threaded resolver
- 11.15 CURLOPT_OPENSOCKETPAIRFUNCTION is missing
- 11.16 libcurl uses renames instead of locking for atomic operations
12. LDAP
12.1 OpenLDAP hangs after returning results
@@ -126,70 +85,36 @@
12.4 LDAPS with NSS is slow
13. TCP/IP
- 13.1 --interface for ipv6 binds to unusable IP address
13.2 Trying local ports fails on Windows
- 14. DICT
- 14.1 DICT responses show the underlying protocol
-
15. CMake
- 15.1 use correct SONAME
15.2 support build with GnuTLS
15.3 unusable tool_hugehelp.c with MinGW
15.4 build docs/curl.1
- 15.5 build on Linux links libcurl to libdl
15.6 uses -lpthread instead of Threads::Threads
15.7 generated .pc file contains strange entries
15.8 libcurl.pc uses absolute library paths
- 15.9 cert paths autodetected when cross-compiling
- 15.10 libpsl is not supported
15.11 ExternalProject_Add does not set CURL_CA_PATH
- 15.12 cannot enable LDAPS on Windows
15.13 CMake build with MIT Kerberos does not work
16. Applications
17. HTTP/2
- 17.1 Excessive HTTP/2 packets with TCP_NODELAY
17.2 HTTP/2 frames while in the connection pool kill reuse
17.3 ENHANCE_YOUR_CALM causes infinite retries
- 17.4 Connection failures with parallel HTTP/2
- 17.5 HTTP/2 connections through HTTPS proxy frequently stall
18. HTTP/3
- 18.1 If the HTTP/3 server closes connection during upload curl hangs
- 18.2 Transfer closed with n bytes remaining to read
- 18.4 timeout when reusing a http3 connection
- 18.9 connection migration does not work
+ 18.1 connection migration does not work
==============================================================================
1. HTTP
-1.2 Multiple methods in a single WWW-Authenticate: header
+1.1 hyper memory-leaks
- The HTTP responses headers WWW-Authenticate: can provide information about
- multiple authentication methods as multiple headers or as several methods
- within a single header. The latter way, several methods in the same physical
- line, is not supported by libcurl's parser. (For no good reason.)
+ Building curl with the hyper backend causes mysterious memory-leaks
-1.3 STARTTRANSFER time is wrong for HTTP POSTs
-
- Wrong STARTTRANSFER timer accounting for POST requests Timer works fine with
- GET requests, but while using POST the time for CURLINFO_STARTTRANSFER_TIME
- is wrong. While using POST CURLINFO_STARTTRANSFER_TIME minus
- CURLINFO_PRETRANSFER_TIME is near to zero every time.
-
- https://github.com/curl/curl/issues/218
- https://curl.se/bug/view.cgi?id=1213
-
-1.4 multipart formposts file name encoding
-
- When creating multipart formposts. The file name part can be encoded with
- something beyond ascii but currently libcurl will only pass in the verbatim
- string the app provides. There are several browsers that already do this
- encoding. The key seems to be the updated draft to RFC2231:
- https://datatracker.ietf.org/doc/html/draft-reschke-rfc2231-in-http-02
+ https://github.com/curl/curl/issues/10803
1.5 Expect-100 meets 417
@@ -198,54 +123,8 @@
the client application to redo the transfer after disabling Expect:.
https://curl.se/mail/archive-2008-02/0043.html
-1.6 Unnecessary close when 401 received waiting for 100
-
- libcurl closes the connection if an HTTP 401 reply is received while it is
- waiting for the 100-continue response.
- https://curl.se/mail/lib-2008-08/0462.html
-
-1.7 Deflate error after all content was received
-
- There's a situation where we can get an error in an HTTP response that is
- compressed, when that error is detected after all the actual body contents
- have been received and delivered to the application. This is tricky, but is
- ultimately a broken server.
-
- See https://github.com/curl/curl/issues/2719
-
-1.8 DoH is not used for all name resolves when enabled
-
- Even if DoH is specified to be used, there are some name resolves that are
- done without it. This should be fixed. When the internal function
- `Curl_resolver_wait_resolv()` is called, it does not use DoH to complete the
- resolve as it otherwise should.
-
- See https://github.com/curl/curl/pull/3857 and
- https://github.com/curl/curl/pull/3850
-
-1.11 CURLOPT_SEEKFUNCTION not called with CURLFORM_STREAM
-
- When using libcurl to POST form data using a FILE* with the CURLFORM_STREAM
- option of curl_formadd(). I notice that if the connection drops at just the
- right time, the POST is reattempted without the data from the file. It seems
- like the file stream position is not getting reset to the beginning of the
- file. I found the CURLOPT_SEEKFUNCTION option and set that with a function
- that performs an fseek() on the FILE*. However, setting that did not seem to
- fix the issue or even get called. See https://github.com/curl/curl/issues/768
-
-
2. TLS
-2.1 CURLINFO_SSL_VERIFYRESULT has limited support
-
- CURLINFO_SSL_VERIFYRESULT is only implemented for the OpenSSL, NSS and
- GnuTLS backends, so relying on this information in a generic app is flaky.
-
-2.2 DER in keychain
-
- Curl does not recognize certificates in DER format in keychain, but it works
- with PEM. https://curl.se/bug/view.cgi?id=1065
-
2.3 Unable to use PKCS12 certificate with Secure Transport
See https://github.com/curl/curl/issues/5403
@@ -264,34 +143,6 @@
See https://github.com/curl/curl/issues/1411
-2.6 CURL_GLOBAL_SSL
-
- Since libcurl 7.57.0, the flag CURL_GLOBAL_SSL is a no-op. The change was
- merged in https://github.com/curl/curl/commit/d661b0afb571a
-
- It was removed since it was
-
- A) never clear for applications on how to deal with init in the light of
- different SSL backends (the option was added back in the days when life
- was simpler)
-
- B) multissl introduced dynamic switching between SSL backends which
- emphasized (A) even more
-
- C) libcurl uses some TLS backend functionality even for non-TLS functions (to
- get "good" random) so applications trying to avoid the init for
- performance reasons would do wrong anyway
-
- D) not documented carefully so all this mostly just happened to work
- for some users
-
- However, in spite of the problems with the feature, there were some users who
- apparently depended on this feature and who now claim libcurl is broken for
- them. The fix for this situation is not obvious as a downright revert of the
- patch is totally ruled out due to those reasons above.
-
- https://github.com/curl/curl/issues/2276
-
2.7 Client cert (MTLS) issues with Schannel
See https://github.com/curl/curl/issues/3145
@@ -302,20 +153,6 @@
https://github.com/curl/curl/issues/3284
-2.9 TLS session cache does not work with TFO
-
- See https://github.com/curl/curl/issues/4301
-
-2.10 Store TLS context per transfer instead of per connection
-
- The GnuTLS `backend->cred` and the OpenSSL `backend->ctx` data and their
- proxy versions (and possibly other TLS backends), could be better moved to be
- stored in the Curl_easy handle instead of in per connection so that a single
- transfer that makes multiple connections can reuse the context and reduce
- memory consumption.
-
- https://github.com/curl/curl/issues/5102
-
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
@@ -330,30 +167,9 @@
expires." - the same command line seems to work with other TLS backends and
other operating systems. See https://github.com/curl/curl/issues/5284.
-2.14 Secure Transport disabling hostname validation also disables SNI
+2.13 CURLOPT_CERTINFO results in CURLE_OUT_OF_MEMORY with Schannel
- SNI is the hostname that is sent by the TLS library to the server as part of
- the TLS handshake. Secure Transport does not send SNI when hostname validation
- is disabled. Servers that host multiple websites may not know which
- certificate to serve without SNI or which backend server to connect to. The
- server may serve the certificate of a default server or abort.
-
- If a server aborts a handshake then curl shows error "SSL peer handshake
- failed, the server most likely requires a client certificate to connect".
- In this case the error may also have been caused by lack of SNI.
-
- https://github.com/curl/curl/issues/6347
-
-2.15 Renegotiate from server may cause hang for OpenSSL backend
-
- A race condition has been observed when, immediately after the initial
- handshake, curl has sent an HTTP request to the server and at the same time
- the server has sent a TLS hello request (renegotiate) to curl. Both are
- waiting for the other to respond. OpenSSL is supposed to send a handshake
- response but does not.
-
- https://github.com/curl/curl/issues/6785
- https://github.com/openssl/openssl/issues/14722
+ https://github.com/curl/curl/issues/8741
3. Email protocols
@@ -384,40 +200,6 @@
4. Command line
-4.1 -J and -O with %-encoded file names
-
- -J/--remote-header-name does not decode %-encoded file names. RFC6266 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 will not add decoding to -O without the user asking for it with
- some other means as well, since -O has always been documented to use the name
- exactly as specified in the URL.
-
-4.2 -J with -C - fails
-
- 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 file name (and thus its
- pre-transfer size) has been figured out.
- https://curl.se/bug/view.cgi?id=1169
-
-4.3 --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 will truncate and restart 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
-
5. Build and portability issues
5.1 OS400 port requires deprecated IBM library
@@ -434,31 +216,12 @@
run that might be needed only for building libcurl. Further, curl-config
--cflags suffers from the same effects with CFLAGS/CPPFLAGS.
-5.3 curl compiled on OSX 10.13 failed to run on OSX 10.10
+5.3 building for old macOS fails with gcc
- See https://github.com/curl/curl/issues/2905
+ Building curl for certain old macOS versions fails when gcc is used. We
+ command using clang in those cases.
-5.4 Build with statically built dependency
-
- The build scripts in curl (autotools, cmake and others) are primarily done to
- work with shared/dynamic third party dependencies. When linking with shared
- libraries, the dependency "chain" is handled automatically by the library
- loader - on all modern systems.
-
- If you instead link with a static library, we need to provide all the
- dependency libraries already at the link command line.
-
- Figuring out all the dependency libraries for a given library is hard, as it
- might also involve figuring out the dependencies of the dependencies and they
- may vary between platforms and even change between versions.
-
- When using static dependencies, the build scripts will mostly assume that
- you, the user, will provide all the necessary additional dependency libraries
- as additional arguments in the build. With configure, by setting LIBS/LDFLAGS
- on the command line.
-
- We welcome help to improve curl's ability to link with static libraries, but
- it is likely a task that we can never fully support.
+ See https://github.com/curl/curl/issues/11441
5.5 cannot handle Unicode arguments in non-Unicode builds on Windows
@@ -473,59 +236,17 @@
https://curl.se/bug/?i=731
https://curl.se/bug/?i=3747
-5.6 make distclean loops forever
-
- Due to an issue (probably) in automake, "make distclean" can end up in a
- never-ending loop.
-
- See https://github.com/curl/curl/issues/7716
-
-5.7 Visual Studio project gaps
-
- The Visual Studio projects lack some features that the autoconf and nmake
- builds offer, such as the following:
-
- - support for zlib and nghttp2
- - use of static runtime libraries
- - add the test suite components
-
- In addition to this the following could be implemented:
-
- - support for other development IDEs
- - add PATH environment variables for third-party DLLs
-
-5.8 configure finding libs in wrong directory
-
- When the configure script checks for third-party libraries, it adds those
- directories to the LDFLAGS variable and then tries linking to see if it
- works. When successful, the found directory is kept in the LDFLAGS variable
- when the script continues to execute and do more tests and possibly check for
- more libraries.
-
- This can make subsequent checks for libraries wrongly detect another
- installation in a directory that was previously added to LDFLAGS by another
- library check.
-
- A possibly better way to do these checks would be to keep the pristine LDFLAGS
- even after successful checks and instead add those verified paths to a
- separate variable that only after all library checks have been performed gets
- appended to LDFLAGS.
-
5.9 Utilize Requires.private directives in libcurl.pc
https://github.com/curl/curl/issues/864
-5.10 curl hangs on SMB upload over stdin
-
- See https://github.com/curl/curl/issues/7896
-
5.11 configure --with-gssapi with Heimdal is ignored on macOS
... unless you also pass --with-gssapi-libs
https://github.com/curl/curl/issues/3841
-5.12 flaky Windows CI builds
+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
@@ -535,6 +256,25 @@
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.14 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
+
6. Authentication
6.1 NTLM authentication and unicode
@@ -591,15 +331,6 @@
https://github.com/curl/curl/issues/3267
-6.8 RTSP authentication breaks without redirect support
-
- RTSP authentication broke in 7.66.0. A work-around is to enable RTSP in
- CURLOPT_REDIR_PROTOCOLS. Authentication should however not be considered an
- actual redirect so a "proper" fix needs to be different and not require users
- to allow redirects to RTSP to work.
-
- See https://github.com/curl/curl/pull/4750
-
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
@@ -629,25 +360,12 @@
https://github.com/curl/curl/issues/7048
+6.13 Negotiate authentication against Hadoop HDFS
+
+ https://github.com/curl/curl/issues/8264
+
7. FTP
-7.1 FTP without or slow 220 response
-
- If a connection is made to an FTP server but the server then just never sends
- the 220 response or otherwise is dead slow, libcurl will not acknowledge the
- connection timeout during that phase but only the "real" timeout - which may
- surprise users as it is probably considered to be the connect phase to most
- people. Brought up (and is being misunderstood) in:
- https://curl.se/bug/view.cgi?id=856
-
-7.2 FTP with CONNECT and slow server
-
- When doing FTP over a socks proxy or CONNECT through HTTP proxy and the multi
- interface is used, libcurl will fail if the (passive) TCP connection for the
- data transfer is not more or less instant as the code does not properly wait
- for the connect to be confirmed. See test case 564 for a first shot at a test
- case.
-
7.3 FTP with NOBODY and FAILONERROR
It seems sensible to be able to use CURLOPT_NOBODY and CURLOPT_FAILONERROR
@@ -661,71 +379,6 @@
thus fails to issue the correct command:
https://curl.se/bug/view.cgi?id=635
-7.5 ASCII FTP
-
- FTP ASCII transfers do not follow RFC959. They do not convert the data
- accordingly (not for sending nor for receiving). RFC 959 section 3.1.1.1
- clearly describes how this should be done:
-
- The sender converts the data from an internal character representation to
- the standard 8-bit NVT-ASCII representation (see the Telnet
- specification). The receiver will convert the data from the standard
- form to his own internal form.
-
- Since 7.15.4 at least line endings are converted.
-
-7.6 FTP with NULs in URL parts
-
- FTP URLs passed to curl may contain NUL (0x00) in the RFC 1738 <user>,
- <password>, and <fpath> components, encoded as "%00". The problem is that
- curl_unescape does not detect this, but instead returns a shortened C string.
- From a strict FTP protocol standpoint, NUL is a valid character within RFC
- 959 <string>, so the way to handle this correctly in curl would be to use a
- data structure other than a plain C string, one that can handle embedded NUL
- characters. From a practical standpoint, most FTP servers would not
- meaningfully support NUL characters within RFC 959 <string>, anyway (e.g.,
- Unix pathnames may not contain NUL).
-
-7.7 FTP and empty path parts in the URL
-
- libcurl ignores empty path parts in FTP URLs, whereas RFC1738 states that
- such parts should be sent to the server as 'CWD ' (without an argument). The
- only exception to this rule, is that we knowingly break this if the empty
- part is first in the path, as then we use the double slashes to indicate that
- the user wants to reach the root dir (this exception SHALL remain even when
- this bug is fixed).
-
-7.8 Premature transfer end but healthy control channel
-
- When 'multi_done' is called before the transfer has been completed the normal
- way, it is considered a "premature" transfer end. In this situation, libcurl
- closes the connection assuming it does not know the state of the connection so
- it cannot be reused for subsequent requests.
-
- With FTP however, this is not necessarily true but there are a bunch of
- situations (listed in the ftp_done code) where it *could* keep the connection
- alive even in this situation - but the current code does not. Fixing this would
- allow libcurl to reuse FTP connections better.
-
-7.9 Passive transfer tries only one IP address
-
- 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 should 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
-
-7.10 FTPS needs session reuse
-
- When the control connection is reused for a subsequent transfer, some FTPS
- servers complain about "missing session reuse" for the data channel for the
- second transfer.
-
- https://github.com/curl/curl/issues/4654
-
7.11 FTPS upload data loss with TLS 1.3
During FTPS upload curl does not attempt to read TLS handshake messages sent
@@ -743,18 +396,9 @@
https://github.com/curl/curl/issues/6149
-8. TELNET
+7.12 FTPS directory listing hangs on Windows with Schannel
-8.1 TELNET and time limitations do not work
-
- When using telnet, the time limitation options do not work.
- https://curl.se/bug/view.cgi?id=846
-
-8.2 Microsoft telnet server
-
- There seems to be a problem when connecting to the Microsoft telnet server.
- https://curl.se/bug/view.cgi?id=649
-
+ https://github.com/curl/curl/issues/9161
9. SFTP and SCP
@@ -782,6 +426,14 @@
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 will be stuck, even if curl is configured with a timeout.
+
+ https://github.com/curl/curl/issues/8632
+
10. SOCKS
@@ -789,21 +441,9 @@
libcurl does not support FTPS over a SOCKS proxy.
-10.4 active FTP over a SOCKS
-
- libcurl does not support active FTP over a SOCKS proxy
-
11. Internals
-11.1 Curl leaks .onion hostnames in DNS
-
- Curl sends DNS requests for hostnames with a .onion TLD. This leaks
- information about what the user is attempting to access, and violates this
- requirement of RFC7686: https://datatracker.ietf.org/doc/html/rfc7686
-
- Issue: https://github.com/curl/curl/issues/543
-
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
@@ -811,24 +451,6 @@
CURLE_COULDNT_CONNECT. But the error buffer set by CURLOPT_ERRORBUFFER
remains empty. Issue: https://github.com/curl/curl/issues/544
-11.3 Disconnects do not do verbose
-
- Due to how libcurl keeps connections alive in the "connection pool" after use
- to potentially transcend the life-time of the initial easy handle that was
- used to drive the transfer over that connection, it uses a *separate* and
- internal easy handle when it shuts down the connection. That separate
- connection might not have the same settings as the original easy handle, and
- in particular it is often note-worthy that it does not have the same VERBOSE
- and debug callbacks setup so that an application will not get the protocol
- data for the disconnect phase of a transfer the same way it got all the other
- data.
-
- This is because the original easy handle might have already been freed at that
- point and the application might not at all be prepared that the callback
- would get called again long after the handle was freed.
-
- See for example https://github.com/curl/curl/issues/6995
-
11.4 HTTP test server 'connection-monitor' problems
The 'connection-monitor' feature of the sws HTTP test server does not work
@@ -844,102 +466,14 @@
See https://github.com/curl/curl/issues/1332 and
https://github.com/curl/curl/issues/4296
-11.7 signal-based resolver timeouts
-
- libcurl built without an asynchronous resolver library uses alarm() to time
- out DNS lookups. When a timeout occurs, this causes libcurl to jump from the
- signal handler back into the library with a sigsetjmp, which effectively
- causes libcurl to continue running within the signal handler. This is
- non-portable and could cause problems on some platforms. A discussion on the
- problem is available at https://curl.se/mail/lib-2008-09/0197.html
-
- Also, alarm() provides timeout resolution only to the nearest second. alarm
- ought to be replaced by setitimer on systems that support it.
-
-11.8 DoH leaks memory after followlocation
-
- https://github.com/curl/curl/issues/4592
-
-11.9 DoH does not inherit all transfer options
-
- 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
-
-11.10 Blocking socket operations in non-blocking API
-
- The list of blocking socket operations is in TODO section "More non-blocking".
-
-11.11 A shared connection cache is not thread-safe
-
- 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
-
-11.12 'no_proxy' string-matches IPv6 numerical addresses
-
- This has the downside that "::1" for example does not match "::0:1" even
- though they are in fact the same address.
-
- See https://github.com/curl/curl/issues/5745
-
-11.13 wakeup socket disconnect causes havoc
-
- waking an iPad breaks the wakeup socket pair, triggering a POLLIN event and
- resulting in SOCKERRNO being set to ENOTCONN.
-
- This condition, and other possible error conditions on the wakeup socket, are
- not handled, so the condition remains on the FD and curl_multi_poll will
- never block again.
-
- See https://github.com/curl/curl/issues/6132 and
- https://github.com/curl/curl/pull/6133
-
-11.14 Multi perform hangs waiting for threaded resolver
-
- If a threaded resolver takes a long time to complete, libcurl can be blocked
- waiting for it for a longer time than expected - and longer than the set
- timeouts.
-
- See https://github.com/curl/curl/issues/2975 and
- https://github.com/curl/curl/issues/4852
-
-11.15 CURLOPT_OPENSOCKETPAIRFUNCTION is missing
-
- When libcurl creates sockets with socketpair(), those are not "exposed" in
- CURLOPT_OPENSOCKETFUNCTION and therefore might surprise and be unknown to
- applications that expect and want all sockets known beforehand. One way to
- address this issue is to introduce a CURLOPT_OPENSOCKETPAIRFUNCTION callback.
-
- https://github.com/curl/curl/issues/5747
-
-11.16 libcurl uses renames instead of locking for atomic operations
-
- For saving cookies, alt-svc and hsts files. This is bad when for example the
- file is stored in a directory where the application has no write permission
- but it has permission for the file.
-
- https://github.com/curl/curl/issues/6882
- https://github.com/curl/curl/pull/6884
-
12. LDAP
12.1 OpenLDAP hangs after returning results
- By configuration defaults, openldap automatically chase referrals on
+ 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
+ descriptors are not monitored, causing OpenLDAP library to never receive
data from them.
As a temporary workaround, disable referrals chasing by configuration.
@@ -970,14 +504,6 @@
13. TCP/IP
-13.1 --interface for ipv6 binds to unusable IP address
-
- Since IPv6 provides a lot of addresses with different scope, binding to an
- IPv6 address needs to take the proper care so that it does not bind to a
- locally scoped address as that is bound to fail.
-
- https://github.com/curl/curl/issues/686
-
13.2 Trying local ports fails on Windows
This makes '--local-port [range]' to not work since curl can't properly
@@ -986,24 +512,8 @@
https://github.com/curl/curl/issues/8112
-14. DICT
-
-14.1 DICT responses show the underlying protocol
-
- When getting a DICT response, the protocol parts of DICT are not stripped off
- from the output.
-
- https://github.com/curl/curl/issues/1809
-
15. CMake
-15.1 use correct SONAME
-
- The autotools build sets the SONAME properly according to VERSIONINFO in
- lib/Makefile.am and so should cmake to make comparable build.
-
- See https://github.com/curl/curl/pull/5935
-
15.2 support build with GnuTLS
15.3 unusable tool_hugehelp.c with MinGW
@@ -1016,12 +526,6 @@
it being there already. This makes the --manual option not work and test
cases like 1139 cannot function.
-15.5 build on Linux links libcurl to libdl
-
- ... which it should not need to!
-
- See https://github.com/curl/curl/issues/6165
-
15.6 uses -lpthread instead of Threads::Threads
See https://github.com/curl/curl/issues/6166
@@ -1041,17 +545,6 @@
See https://github.com/curl/curl/issues/6169
-15.9 cert paths autodetected when cross-compiling
-
- The autotools build disables the ca_path/ca_bundle detection when
- cross-compiling. The cmake build keeps doing the detection.
-
- See https://github.com/curl/curl/issues/6178
-
-15.10 libpsl is not supported
-
- See https://github.com/curl/curl/issues/6214
-
15.11 ExternalProject_Add does not set CURL_CA_PATH
CURL_CA_BUNDLE and CURL_CA_PATH are not set properly when cmake's
@@ -1059,10 +552,6 @@
See https://github.com/curl/curl/issues/6313
-15.12 cannot enable LDAPS on Windows
-
- See https://github.com/curl/curl/issues/6284
-
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
@@ -1078,16 +567,6 @@
17. HTTP/2
-17.1 Excessive HTTP/2 packets with TCP_NODELAY
-
- Because of how curl sets TCP_NODELAY by default, HTTP/2 requests are issued
- using more separate TCP packets than it would otherwise need to use. This
- means spending more bytes than it has to. Just disabling TCP_NODELAY for
- HTTP/2 is also not the correct fix because that then makes the outgoing
- packets to get delayed.
-
- See https://github.com/curl/curl/issues/6363
-
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
@@ -1105,33 +584,8 @@
See https://github.com/curl/curl/issues/5119
-17.4 Connection failures with parallel HTTP/2
-
- See https://github.com/curl/curl/issues/5611
-
-17.5 HTTP/2 connections through HTTPS proxy frequently stall
-
- See https://github.com/curl/curl/issues/6936
-
18. HTTP/3
-18.1 If the HTTP/3 server closes connection during upload curl hangs
-
- See https://github.com/curl/curl/issues/6606
-
-18.2 Transfer closed with n bytes remaining to read
-
- HTTP/3 transfers with the Jetty HTTP/3 server seem to not work.
-
- https://github.com/curl/curl/issues/8523
-
-18.4 timeout when reusing a http3 connection
-
- HTTP/3 with quiche seems to not work and always timeout a subsequent transfer
- that reuses an already established connection
-
- https://github.com/curl/curl/issues/8764
-
-18.9 connection migration does not work
+18.1 connection migration does not work
https://github.com/curl/curl/issues/7695
diff --git a/docs/MAIL-ETIQUETTE b/docs/MAIL-ETIQUETTE
index 8d5f10a..ccd3e01 100644
--- a/docs/MAIL-ETIQUETTE
+++ b/docs/MAIL-ETIQUETTE
@@ -105,7 +105,7 @@
messages"
No matter what, we NEVER EVER respond to trolls or spammers on the list. If
- you believe the list admin should do something in particular, contact him/her
+ you believe the list admin should do something in particular, contact them
off-list. The subject will be taken care of as much as possible to prevent
repeated offenses, but responding on the list to such messages never leads to
anything good and only puts the light even more on the offender: which was
@@ -277,7 +277,7 @@
one of the hints was what solved your problems. The guys who write answers
feel good to know that they provided a good answer and that you fixed the
problem. Far too often, the person who asked the question is never heard from
- again, and we never get to know if he/she is gone because the problem was
+ again, and we never get to know if they are gone because the problem was
solved or perhaps because the problem was unsolvable.
Getting the solution posted also helps other users that experience the same
diff --git a/docs/MANUAL.md b/docs/MANUAL.md
index 6b8acd6..64f5b58 100644
--- a/docs/MANUAL.md
+++ b/docs/MANUAL.md
@@ -6,7 +6,7 @@
curl https://www.example.com/
-Get the README file the user's home directory at funet's ftp-server:
+Get a README file from an FTP server:
curl ftp://ftp.funet.fi/README
@@ -18,10 +18,14 @@
curl ftp://ftp.funet.fi
-Get the definition of curl from a dictionary:
+Get the all terms matching curl from a dictionary:
curl dict://dict.org/m:curl
+Get the definition of curl from a dictionary:
+
+ curl dict://dict.org/d:curl
+
Fetch two documents at once:
curl ftp://ftp.funet.fi/ http://www.weirdserver.com:8000/
@@ -77,11 +81,11 @@
### FTP
-To ftp files using name+passwd, include them in the URL like:
+To ftp files using name and password, include them in the URL like:
curl ftp://name:passwd@machine.domain:port/full/path/to/file
-or specify them with the -u flag like
+or specify them with the `-u` flag like
curl -u name:passwd ftp://machine.domain:port/full/path/to/file
@@ -90,9 +94,9 @@
It is just like for FTP, but you may also want to specify and use SSL-specific
options for certificates etc.
-Note that using `FTPS://` as prefix is the "implicit" way as described in the
-standards while the recommended "explicit" way is done by using FTP:// and the
-`--ftp-ssl` option.
+Note that using `FTPS://` as prefix is the *implicit* way as described in the
+standards while the recommended *explicit* way is done by using `FTP://` and
+the `--ssl-reqd` option.
### SFTP / SCP
@@ -177,11 +181,21 @@
See the manual for your FTP proxy to determine the form it expects to set up
transfers, and curl's `-v` option to see exactly what curl is sending.
+## Piping
+
+Get a key file and add it with `apt-key` (when on a system that uses `apt` for
+package management):
+
+ curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
+
+The '|' pipes the output to STDIN. `-` tells `apt-key` that the key file
+should be read from STDIN.
+
## Ranges
HTTP 1.1 introduced byte-ranges. Using this, a client can request to get only
-one or more subparts of a specified document. Curl supports this with the `-r`
-flag.
+one or more sub-parts of a specified document. Curl supports this with the
+`-r` flag.
Get the first 100 bytes of a document:
@@ -281,26 +295,30 @@
## POST (HTTP)
-It's easy to post data using curl. This is done using the `-d <data>` option.
+It is easy to post data using curl. This is done using the `-d <data>` option.
The post data must be urlencoded.
-Post a simple "name" and "phone" guestbook.
+Post a simple `name` and `phone` guestbook.
curl -d "name=Rafael%20Sagula&phone=3320780" http://www.where.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.where.com/guest.cgi
+
How to post a form with curl, lesson #1:
Dig out all the `<input>` tags in the form that you want to fill in.
-If there is a "normal" post, you use `-d` to post. `-d` takes a full "post
-string", which is in the format
+If there is a normal post, you use `-d` to post. `-d` takes a full post
+string, which is in the format
<variable1>=<data1>&<variable2>=<data2>&...
-The 'variable' names are the names set with `"name="` in the `<input>` tags,
-and the data is the contents you want to fill in for the inputs. The data
-*must* be properly URL encoded. That means you replace space with + and that
-you replace weird letters with %XX where XX is the hexadecimal representation
+The variable names are the names set with `"name="` in the `<input>` tags, and
+the data is the contents you want to fill in for the inputs. The data *must*
+be properly URL encoded. That means you replace space with + and that you
+replace weird letters with `%XX` where `XX` is the hexadecimal representation
of the letter's ASCII code.
Example:
@@ -316,7 +334,7 @@
</form>
```
-We want to enter user 'foobar' with password '12345'.
+We want to enter user `foobar` with password `12345`.
To post to this, you enter a curl command line like:
@@ -331,7 +349,7 @@
be read from a file, use `@filename` as contents. When specifying a file, you
can also specify the file content type by appending `;type=<mime type>` to the
file name. You can also post the contents of several files in one field. For
-example, the field name 'coolfiles' is used to send three files, with
+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"
@@ -340,15 +358,15 @@
If the content-type is not specified, curl will try to guess from the file
extension (it only knows a few), or use the previously specified type (from an
earlier file if several files are specified in a list) or else it will use the
-default type 'application/octet-stream'.
+default type `application/octet-stream`.
Emulate a fill-in form with `-F`. Let's say you fill in three fields in a
form. One field is a file name which to post, one field is your name and one
field is a file description. We want to post the file we have written named
-"cooltext.txt". To let curl do the posting of this data instead of your
-favourite browser, you have to read the HTML source of the form page and find
+`cooltext.txt`. To let curl do the posting of this data instead of your
+favorite browser, you have to read the HTML source of the form page and find
the names of the input fields. In our example, the input field names are
-'file', 'yourname' and 'filedescription'.
+`file`, `yourname` and `filedescription`.
curl -F "file=@cooltext.txt" -F "yourname=Daniel"
-F "filedescription=Cool text file with cool text inside"
@@ -356,7 +374,7 @@
To send two files in one post you can do it in two ways:
-Send multiple files in a single "field" with a single field name:
+Send multiple files in a single field with a single field name:
curl -F "pictures=@dog.gif,cat.gif" $URL
@@ -415,7 +433,7 @@
headers that looks like `Set-Cookie: <data>` where the data part then
typically contains a set of `NAME=VALUE` pairs (separated by semicolons `;`
like `NAME1=VALUE1; NAME2=VALUE2;`). The server can also specify for what path
-the "cookie" should be used for (by specifying `path=value`), when the cookie
+the cookie should be used for (by specifying `path=value`), when the cookie
should expire (`expire=DATE`), for what domain to use it (`domain=NAME`) and
if it should be used on secure connections only (`secure`).
@@ -426,7 +444,7 @@
```
it means the server wants that first pair passed on when we get anything in a
-path beginning with "/foo".
+path beginning with `/foo`.
Example, get a page that wants my name passed in a cookie:
@@ -439,9 +457,9 @@
curl --dump-header headers www.example.com
... you can then in a second connect to that (or another) site, use the
-cookies from the 'headers' file like:
+cookies from the `headers.txt` file like:
- curl -b headers www.example.com
+ curl -b headers.txt www.example.com
While saving headers to a file is a working way to store cookies, it is
however error-prone and not the preferred way to do this. Instead, make curl
@@ -450,9 +468,9 @@
curl -c cookies.txt www.example.com
-Note that by specifying `-b` you enable the "cookie awareness" and with `-L`
-you can make curl follow a location: (which often is used in combination with
-cookies). So that if a site sends cookies and a location, you can use a
+Note that by specifying `-b` you enable the cookie engine and with `-L` you
+can make curl follow a `location:` (which often is used in combination with
+cookies). If a site sends cookies and a location field, you can use a
non-existing file to trigger the cookie awareness like:
curl -L -b empty.txt www.example.com
@@ -460,9 +478,9 @@
The file to read cookies from must be formatted using plain HTTP headers OR as
Netscape's cookie file. Curl will determine what kind it is based on the file
contents. In the above command, curl will parse the header and store the
-cookies received from www.example.com. curl will send to the server the
-stored cookies which match the request as it follows the location. The file
-"empty.txt" may be a nonexistent file.
+cookies received from www.example.com. curl will send to the server the stored
+cookies which match the request as it follows the location. The file
+`empty.txt` may be a nonexistent file.
To read and write cookies from a Netscape cookie file, you can set both `-b`
and `-c` to use the same file:
@@ -480,18 +498,18 @@
From left-to-right:
- - % - percentage completed of the whole transfer
- - Total - total size of the whole expected transfer
- - % - percentage completed of the download
- - Received - currently downloaded amount of bytes
- - % - percentage completed of the upload
- - Xferd - currently uploaded amount of bytes
- - Average Speed Dload - the average transfer speed of the download
- - Average Speed Upload - the average transfer speed of the upload
- - Time Total - expected time to complete the operation
- - Time Current - time passed since the invoke
- - Time Left - expected time left to completion
- - Curr.Speed - the average transfer speed the last 5 seconds (the first
+ - `%` - percentage completed of the whole transfer
+ - `Total` - total size of the whole expected transfer
+ - `%` - percentage completed of the download
+ - `Received` - currently downloaded amount of bytes
+ - `%` - percentage completed of the upload
+ - `Xferd` - currently uploaded amount of bytes
+ - `Average Speed Dload` - the average transfer speed of the download
+ - `Average Speed Upload` - the average transfer speed of the upload
+ - `Time Total` - expected time to complete the operation
+ - `Time Current` - time passed since the invoke
+ - `Time Left` - expected time left to completion
+ - `Curr.Speed` - the average transfer speed the last 5 seconds (the first
5 seconds of a transfer is based on less time of course.)
The `-#` option will display a totally different progress bar that does not
@@ -517,7 +535,7 @@
Forcing curl not to transfer data faster than a given rate is also possible,
which might be useful if you are using a limited bandwidth connection and you
do not want your transfer to use all of it (sometimes referred to as
-"bandwidth throttle").
+*bandwidth throttle*).
Make curl transfer data no faster than 10 kilobytes per second:
@@ -649,7 +667,7 @@
curl -P - ftp.download.com
Download with `PORT` but use the IP address of our `le0` interface (this does
-not work on windows):
+not work on Windows):
curl -P le0 ftp.download.com
@@ -681,8 +699,8 @@
that require valid certificates. The only drawback is that the certificate
needs to be in PEM-format. PEM is a standard and open format to store
certificates with, but it is not used by the most commonly used browsers. If
-you want curl to use the certificates you use with your (favourite) browser,
-you may need to download/compile a converter that can convert your browser's
+you want curl to use the certificates you use with your favorite browser, you
+may need to download/compile a converter that can convert your browser's
formatted certificates to PEM formatted ones.
Example on how to automatically retrieve a document using a certificate with a
@@ -695,10 +713,9 @@
Many older HTTPS servers have problems with specific SSL or TLS versions,
which newer versions of OpenSSL etc use, therefore it is sometimes useful to
-specify what SSL-version curl should use. Use -3, -2 or -1 to specify that
-exact SSL version to use (for SSLv3, SSLv2 or TLSv1 respectively):
+specify what TLS version curl should use.:
- curl -2 https://secure.site.com/
+ curl --tlv1.0 https://secure.site.com/
Otherwise, curl will attempt to use a sensible TLS default version.
@@ -735,13 +752,13 @@
curl -z -local.html http://remote.server.com/remote.html
-You can specify a "free text" date as condition. Tell curl to only download
-the file if it was updated since January 12, 2012:
+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.server.com/remote.html
-Curl will then accept a wide range of date formats. You always make the date
-check the other way around by prepending it with a dash (`-`).
+curl accepts a wide range of date formats. You always make the date check the
+other way around by prepending it with a dash (`-`).
## DICT
@@ -751,8 +768,8 @@
curl dict://dict.org/d:heisenbug:jargon
curl dict://dict.org/d:daniel:gcide
-Aliases for 'm' are 'match' and 'find', and aliases for 'd' are 'define' and
-'lookup'. For example,
+Aliases for `m` are `match` and `find`, and aliases for `d` are `define` and
+`lookup`. For example,
curl dict://dict.org/find:curl
@@ -770,22 +787,19 @@
offer `ldap://` support. On Windows, curl will use WinLDAP from Platform SDK
by default.
-Default protocol version used by curl is LDAPv3. LDAPv2 will be used as a
-fallback mechanism in case LDAPv3 fails to connect.
+Default protocol version used by curl is LDAP version 3. Version 2 will be
+used as a fallback mechanism in case version 3 fails to connect.
-LDAP is a complex thing and writing an LDAP query is not an easy task. I do
-advise you to dig up the syntax description for that elsewhere. One such place
-might be: [RFC 2255, The LDAP URL
+LDAP is a complex thing and writing an LDAP query is not an easy
+task. Familiarize yourself with the exact syntax description elsewhere. One
+such place might be: [RFC 2255, The LDAP URL
Format](https://curl.se/rfc/rfc2255.txt)
-To show you an example, this is how I can get all people from my local LDAP
-server that has a certain sub-domain in their email address:
+To show you an example, this is how to get all people from an LDAP server that
+has a certain sub-domain in their email address:
curl -B "ldap://ldap.frontec.se/o=frontec??sub?mail=*sth.frontec.se"
-If I want the same info in HTML format, I can get it by not using the `-B`
-(enforce ASCII) flag.
-
You also can use authentication when accessing LDAP catalog:
curl -u user:passwd "ldap://ldap.frontec.se/o=frontec??sub?mail=*"
@@ -817,8 +831,8 @@
NO_PROXY
If the host name matches one of these strings, or the host is within the
-domain of one of these strings, transactions with that node will not be
-proxied. When a domain is used, it needs to start with a period. A user can
+domain of one of these strings, transactions with that node will not be done
+over proxy. When a domain is used, it needs to start with a period. A user can
specify that both www.example.com and foo.example.com should not use a proxy
by setting `NO_PROXY` to `.example.com`. By including the full name you can
exclude specific host names, so to make `www.example.com` not use a proxy but
@@ -831,7 +845,7 @@
Unix introduced the `.netrc` concept a long time ago. It is a way for a user
to specify name and password for commonly visited FTP sites in a file so that
you do not have to type them in each time you visit those sites. You realize
-this is a big security risk if someone else gets hold of your passwords, so
+this is a big security risk if someone else gets hold of your passwords,
therefore most Unix programs will not read this file unless it is only readable
by yourself (curl does not care though).
@@ -859,13 +873,13 @@
Curl supports kerberos4 and kerberos5/GSSAPI for FTP transfers. You need the
kerberos package installed and used at curl build time for it to be available.
-First, get the krb-ticket the normal way, like with the kinit/kauth tool.
+First, get the krb-ticket the normal way, like with the `kinit`/`kauth` tool.
Then use curl in way similar to:
curl --krb private ftp://krb4site.com -u username:fakepwd
There is no use for a password on the `-u` switch, but a blank one will make
-curl ask for one and you already entered the real password to kinit/kauth.
+curl ask for one and you already entered the real password to `kinit`/`kauth`.
## TELNET
@@ -908,7 +922,7 @@
better use of the network.
Note that curl cannot use persistent connections for transfers that are used
-in subsequence curl invokes. Try to stuff as many URLs as possible on the same
+in subsequent curl invokes. Try to stuff as many URLs as possible on the same
command line if they are using the same host, as that will make the transfers
faster. If you use an HTTP proxy for file transfers, practically all transfers
will be persistent.
@@ -963,28 +977,27 @@
Available lists include:
-### curl-users
+### `curl-users`
Users of the command line tool. How to use it, what does not work, new
features, related tools, questions, news, installations, compilations,
running, porting etc.
-### curl-library
+### `curl-library`
Developers using or developing libcurl. Bugs, extensions, improvements.
-### curl-announce
+### `curl-announce`
Low-traffic. Only receives announcements of new public versions. At worst,
that makes something like one or two mails per month, but usually only one
mail every second month.
-### curl-and-php
+### `curl-and-php`
Using the curl functions in PHP. Everything curl with a PHP angle. Or PHP with
a curl angle.
-### curl-and-python
+### `curl-and-python`
Python hackers using curl with or without the python binding pycurl.
-
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 0959ac5..4220f12 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -55,10 +55,12 @@
CODE_OF_CONDUCT.md \
CODE_REVIEW.md \
CODE_STYLE.md \
+ CONNECTION-FILTERS.md \
CONTRIBUTE.md \
CURL-DISABLE.md \
DEPRECATE.md \
DYNBUF.md \
+ EARLY-RELEASE.md \
EXPERIMENTAL.md \
FAQ \
FEATURES.md \
@@ -84,6 +86,7 @@
RELEASE-PROCEDURE.md \
RUSTLS.md \
ROADMAP.md \
+ SECURITY-ADVISORY.md \
SECURITY-PROCESS.md \
SSL-PROBLEMS.md \
SSLCERTS.md \
@@ -91,7 +94,8 @@
TODO \
TheArtOfHttpScripting.md \
URL-SYNTAX.md \
- VERSIONS.md
+ VERSIONS.md \
+ WEBSOCKET.md
MAN2HTML= roffit $< >$@
diff --git a/docs/NEW-PROTOCOL.md b/docs/NEW-PROTOCOL.md
index 9a14518..a8b227d 100644
--- a/docs/NEW-PROTOCOL.md
+++ b/docs/NEW-PROTOCOL.md
@@ -1,6 +1,6 @@
# Adding a new protocol?
-Every once in a while someone comes up with the idea of adding support for yet
+Every once in a while, someone comes up with the idea of adding support for yet
another protocol to curl. After all, curl already supports 25 something
protocols and it is the Internet transfer machine for the world.
@@ -98,7 +98,7 @@
little easier!
The protocol specification itself should be freely available without requiring
-any NDA or similar.
+a non-disclosure agreement or similar.
## Do not compare
diff --git a/docs/PARALLEL-TRANSFERS.md b/docs/PARALLEL-TRANSFERS.md
index 325e64f..337fab5 100644
--- a/docs/PARALLEL-TRANSFERS.md
+++ b/docs/PARALLEL-TRANSFERS.md
@@ -1,6 +1,6 @@
# Parallel transfers
-curl 7.66.0 introduces support for doing multiple transfers simultaneously; in
+curl 7.66.0 introduced support for doing multiple transfers simultaneously; in
parallel.
## -Z, --parallel
@@ -27,8 +27,8 @@
o total time all transfers are expected to take (if sizes are known)
o current time the transfers have spent so far
o estimated time left (if sizes are known)
- o current transfer speed (the faster of UL/DL speeds measured over the last
- few seconds)
+ o current transfer speed (the faster of upload/download speeds measured over
+ the last few seconds)
Example:
@@ -48,11 +48,3 @@
share API as well, as a context per origin + path (realm?) basically.
Visible in test 153, 1412 and more.
-
-## Feedback
-
-This is early days for parallel transfer support. Keep your eyes open for
-unintended side effects or downright bugs.
-
-Tell us what you think and how you think we could improve this feature!
-
diff --git a/docs/RELEASE-PROCEDURE.md b/docs/RELEASE-PROCEDURE.md
index 65c02f9..4ff8fcc 100644
--- a/docs/RELEASE-PROCEDURE.md
+++ b/docs/RELEASE-PROCEDURE.md
@@ -16,14 +16,14 @@
tag and we use underscores instead of dots in the version number. Make sure
the tag is GPG signed (using -s).
-- run "./maketgz 7.34.0" to build the release tarballs. It is important that
+- run `./maketgz 7.34.0` to build the release tarballs. It is important that
you run this on a machine with the correct set of autotools etc installed
as this is what then will be shipped and used by most users on \*nix like
systems.
- push the git commits and the new tag
-- gpg sign the 4 tarballs as maketgz suggests
+- GPG sign the 4 tarballs as `maketgz` suggests
- upload the 8 resulting files to the primary download directory
@@ -66,41 +66,52 @@
Release Cycle
-------------
-We do releases every 8 weeks on Wednesdays. If critical problems arise, we can
-insert releases outside of the schedule or we can move the release date - but
-this is rare.
+We normally do releases every 8 weeks on Wednesdays. If important problems
+arise, we can insert releases outside the schedule or we can move the release
+date.
-Each 8 week release cycle is split in two 4-week periods.
+Each 8 week (56 days) release cycle is divided into three distinct periods:
-- During the first 4 weeks after a release, we allow new features and changes
- to curl and libcurl. If we accept any such changes, we bump the minor number
- used for the next release.
+- During the first 10 calendar days after a release, we are in "cool down". We
+ do not merge features but only bug-fixes. If a regression is reported, we
+ might do a follow-up patch release.
-- During the second 4-week period we do not merge any features or changes, we
- then only focus on fixing bugs and polishing things to make a solid coming
- release.
+- During the following 3 weeks (21 days) there is a feature window: we allow
+ new features and changes to curl and libcurl. If we accept any such changes,
+ we bump the minor number used for the next release.
-- After a regular procedure-following release (made on Wednesdays), the
- feature window remains closed until the following Monday in case of special
- actions or patch releases etc.
+- During the next 25 days we are in feature freeze. We do not merge any
+ features or changes, and we only focus on fixing bugs and polishing things
+ to make the pending release a solid one.
If a future release date happens to end up on a "bad date", like in the middle
-of common public holidays or when the lead release manager is away traveling,
-the release date can be moved forwards or backwards a full week. This is then
+of common public holidays or when the lead release manager is unavailable, the
+release date can be moved forwards or backwards a full week. This is then
advertised well in advance.
+Critical problems
+-----------------
+
+We can break the release cycle and do a patch release at any point if a
+critical enough problem is reported. There is no exact definition of how to
+assess such criticality, but if an issue is highly disturbing or has a
+security impact on a large enough share of the user population it might
+qualify.
+
+If you think an issue qualifies, bring it to the curl-library mailing list and
+push for it.
+
Coming dates
------------
Based on the description above, here are some planned release dates (at the
time of this writing):
-- May 11, 2022 (7.83.1)
-- July 1, 2022
-- August 31, 2022
-- October 25, 2022
-- December 21, 2022
-- February 15, 2023 (last version 7 release, no feature window after)
-- March 20, 2023 (8.0.0 - curl 25 years)
-- April 17, 2023
-- July 12, 2023
+- July 19, 2023
+- September 13, 2023
+- November 8, 2023
+- January 3, 2024
+- February 28, 2024
+- April 24, 2024
+- June 19, 2024
+- August 14, 2024
diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md
index e48c21b..4642938 100644
--- a/docs/ROADMAP.md
+++ b/docs/ROADMAP.md
@@ -21,4 +21,4 @@
See Daniel's post on [Support of Encrypted
SNI](https://curl.se/mail/lib-2019-03/0000.html) on the mailing list.
- Initial work exists in https://github.com/curl/curl/pull/4011
+ Initial work exists in [PR 4011](https://github.com/curl/curl/pull/4011)
diff --git a/docs/RUSTLS.md b/docs/RUSTLS.md
index 4b49b5c..7a0d806 100644
--- a/docs/RUSTLS.md
+++ b/docs/RUSTLS.md
@@ -1,9 +1,9 @@
# Rustls
-[Rustls is a TLS backend written in Rust.](https://docs.rs/rustls/). Curl can
+[Rustls is a TLS backend written in Rust](https://docs.rs/rustls/). Curl can
be built to use it as an alternative to OpenSSL or other TLS backends. We use
the [rustls-ffi C bindings](https://github.com/rustls/rustls-ffi/). This
-version of curl depends on version v0.8.2 of rustls-ffi.
+version of curl depends on version v0.10.0 of rustls-ffi.
# Building with rustls
@@ -12,7 +12,7 @@
Next, check out, build, and install the appropriate version of rustls-ffi:
% cargo install cbindgen
- % git clone https://github.com/rustls/rustls-ffi -b v0.8.2
+ % git clone https://github.com/rustls/rustls-ffi -b v0.10.0
% cd rustls-ffi
% make
% make DESTDIR=${HOME}/rustls-ffi-built/ install
diff --git a/docs/SECURITY-ADVISORY.md b/docs/SECURITY-ADVISORY.md
new file mode 100644
index 0000000..c2d13c9
--- /dev/null
+++ b/docs/SECURITY-ADVISORY.md
@@ -0,0 +1,129 @@
+# Anatomy of a curl security advisory
+
+As described in the `SECURITY-PROCESS.md` document, when a security
+vulnerability has been reported to the project and confirmed, we author an
+advisory document for for the issue. It should ideally be written in
+cooperation with the reporter to make sure all the angles and details of the
+problem are gathered and described correctly and succinctly.
+
+## New document
+
+A security advisory for curl is created in the `docs/` folder in the
+[curl-www](https://github.com/curl/curl-www) repository. It should be named
+`$CVEID.md` where `$CVEID` is the full CVE Id that has been registered for the
+flaw. Like `CVE-2016-0755`. The `.md` extension of course means that the
+document is written using markdown.
+
+The standard way to go about this is to first write the `VULNERABILITY`
+section for the document, so that there is description of the flaw available,
+then paste this description into the CVE Id request.
+
+### `vuln.pm`
+
+The new issue should be entered at the top of the list in the file `vuln.pm`
+in the same directory. It holds a large array with all published curl
+vulnerabilities. All fields should be filled in accordingly, separated by a
+pipe character (`|`).
+
+The eleven fields for each CVE in `vuln.pm` are, in order:
+
+ HTML page name, first vulnerable version, last vulnerable version, name of
+ the issue, CVE Id, announce date (`YYYYMMDD`), report to the project date
+ (`YYYYMMDD`), CWE, awarded reward amount (USD), area (single word), C-issue
+ (`-` if not a C issue at all, `OVERFLOW` , `OVERREAD`, `DOUBLE_FREE`,
+ `USE_AFTER_FREE`, `NULL_MISTAKE`, `UNINIT`)
+
+### `Makefile`
+
+The new CVE web page file name needs to be added in the `Makefile`'s `CVELIST`
+macro.
+
+When the markdown is in place and the `Makefile` and `vuln.pm` are updated,
+all other files and metadata for all curl advisories and versions get
+generated automatically using those files.
+
+## Document format
+
+The easy way is to start with a recent previously published advisory and just
+blank out old texts and save it using a new name. Save the subtitles and
+general layout.
+
+Some details and metadata will be extracted from this document so it is
+important to stick to the existing format.
+
+The first list must be the title of the issue.
+
+### VULNERABILITY
+
+The first subtitle should be `VULNERABILITY`. That should then include a
+through and detailed description of the flaw. Including how it can be
+triggered and maybe something about what might happen if triggered or
+exploited.
+
+### INFO
+
+The next section is `INFO` which adds meta data information about the flaw. It
+specifically mentions the official CVE Id for the issue and it must list the
+CWE Id, starting on its own line. We write CWE identifiers in advisories with
+the full (official) explanation on the right side of a colon. Like this:
+
+`CWE-305: Authentication Bypass by Primary Weakness`
+
+### AFFECTED VERSIONS
+
+The third section first lists what versions that are affected, then adds
+clarity by stressing what versions that are *not* affected. A third line adds
+information about which specific git commit that introduced the vulnerability.
+
+The `Introduced-in` commit should be a full URL that displays the commit, but
+should work as a stand-alone commit hash if everything up to the last slash is
+cut out.
+
+An example using the correct syntax:
+
+~~~
+- Affected versions: curl 7.16.1 to and including 7.88.1
+- Not affected versions: curl < 7.16.1 and curl >= 8.0.0
+- Introduced-in: https://github.com/curl/curl/commit/2147284cad
+~~~
+
+### THE SOLUTION
+
+This section describes and discusses the fix. The only mandatory information
+here is the link to the git commit that fixes the problem.
+
+The `Fixed-in` value should be a full URL that displays the commit, but should
+work as a stand-alone commit hash if everything up to the last slash is cut
+out.
+
+Example:
+
+`- Fixed-in: https://github.com/curl/curl/commit/af369db4d3833272b8ed`
+
+### RECOMMENDATIONS
+
+This section lists the recommended actions for the users in a top to bottom
+priority order and should ideally contain three items but no less than two.
+
+The top two are almost always `upgrade curl to version XXX` and `apply the
+patch to your local version`.
+
+### TIMELINE
+
+Detail when this report was received in the project. When package distributors
+were notified (via the distros mailing list or similar)
+
+When the advisory and fixed version are released.
+
+### CREDITS
+
+Mention the reporter and patch author at least, then everyone else involved
+you think deserves a mention.
+
+If you want to mention more than one name, separate the names with comma
+(`,`).
+
+~~~
+- Reported-by: Full Name
+- Patched-by: Full Name
+~~~
diff --git a/docs/SECURITY-PROCESS.md b/docs/SECURITY-PROCESS.md
index a7e8661..e553507 100644
--- a/docs/SECURITY-PROCESS.md
+++ b/docs/SECURITY-PROCESS.md
@@ -19,13 +19,13 @@
formally announced at the end of this process. That means, for example, that a
bug tracker entry must NOT be created to track the issue since that will make
the issue public and it should not be discussed on any of the project's public
-mailing lists. Also messages associated with any commits should not make any
+mailing lists. Messages associated with any commits should not make any
reference to the security nature of the commit if done prior to the public
announcement.
- The person discovering the issue, the reporter, reports the vulnerability on
- [https://hackerone.com/curl](https://hackerone.com/curl). Issues filed there
- reach a handful of selected and trusted people.
+ [HackerOne](https://hackerone.com/curl). Issues filed there reach a handful
+ of selected and trusted people.
- Messages that do not relate to the reporting or managing of an undisclosed
security vulnerability in curl or libcurl are ignored and no further action
@@ -40,7 +40,7 @@
- If the report is rejected, the team writes to the reporter to explain why.
-- If the report is accepted, the team writes to the reporter to let him/her
+- If the report is accepted, the team writes to the reporter to let them
know it is accepted and that they are working on a fix.
- The security team discusses the problem, works out a fix, considers the
@@ -55,7 +55,8 @@
- Write a security advisory draft about the problem that explains what the
problem is, its impact, which versions it affects, solutions or workarounds,
when the release is out and make sure to credit all contributors properly.
- Figure out the CWE (Common Weakness Enumeration) number for the flaw.
+ Figure out the CWE (Common Weakness Enumeration) number for the flaw. See
+ [SECURITY-ADVISORY](SECURITY-ADVISORY.md) for help on creating the advisory.
- Request a CVE number from
[HackerOne](https://docs.hackerone.com/programs/cve-requests.html)
@@ -63,10 +64,14 @@
- Update the "security advisory" with the CVE number.
- The security team commits the fix in a private branch. The commit message
- should ideally contain the CVE number.
+ should ideally contain the CVE number. If the severity level of the issue is
+ set to Low or Medium, the fix is allowed to get merged into the master
+ repository via a normal PR - but without mentioning it being a security
+ vulnerability.
-- The security team also decides on and delivers a monetary reward to the
- reporter as per the bug-bounty policies.
+- The monetary reward part of the bug-bounty is managed by the Internet Bug
+ Bounty team and the reporter is asked to request the reward from them after
+ the issue has been completely handled and published by curl.
- No more than 10 days before release, inform
[distros@openwall](https://oss-security.openwall.org/wiki/mailing-lists/distros)
@@ -112,9 +117,9 @@
2. Name the advisory file after the allocated CVE id.
-3. Add a line on the top of the array in `curl-www/docs/vuln.pm'.
+3. Add a line on the top of the array in `curl-www/docs/vuln.pm`.
-4. Put the new advisory markdown file in the curl-www/docs/ directory. Add it
+4. Put the new advisory markdown file in the `curl-www/docs/` directory. Add it
to the git repository.
5. Run `make` in your local web checkout and verify that things look fine.
@@ -122,7 +127,7 @@
6. On security advisory release day, push the changes on the curl-www
repository's remote master branch.
-## Hackerone
+## HackerOne
Request the issue to be disclosed. If there are sensitive details present in
the report and discussion, those should be redacted from the disclosure. The
@@ -134,6 +139,49 @@
See [BUG-BOUNTY](https://curl.se/docs/bugbounty.html) for details on the
bug bounty program.
+# Severity levels
+
+The curl project's security team rates security problems using four severity
+levels depending how serious we consider the problem to be. We use **Low**,
+**Medium**, **High** and **Critical**. We refrain from using numerical scoring
+of vulnerabilities.
+
+When deciding severity level on a particular issue, we take all the factors
+into account: attack vector, attack complexity, required privileges, necessary
+build configuration, protocols involved, platform specifics and also what
+effects a possible exploit or trigger of the issue can lead do, including
+confidentiality, integrity or availability problems.
+
+## Low
+
+This is a security problem that is truly hard or unlikely to exploit or
+trigger. Due to timing, platform requirements or the fact that options or
+protocols involved are rare etc. [Past
+example](https://curl.se/docs/CVE-2022-43552.html)
+
+## Medium
+
+This is a security problem that is less hard than **Low** to exploit or
+trigger. Less strict timing, wider platforms availability or involving more
+widely used options or protocols. A problem that usually needs something else
+to also happen to become serious. [Past
+example](https://curl.se/docs/CVE-2022-32206.html)
+
+## High
+
+This issue in itself a serious problem with real world impact. Flaws that can
+easily compromise the confidentiality, integrity or availability of resources.
+Exploiting or triggering this problem is not hard. [Past
+example](https://curl.se/docs/CVE-2019-3822.html)
+
+## Critical
+
+Easily exploitable by a remote unauthenticated attacker and lead to system
+compromise (arbitrary code execution) without requiring user interaction, with
+a common configuration on a popular platform. This issue has few restrictions
+and requirements and can be exploited easily using most curl configurations.
+[Past example](https://curl.se/docs/CVE-2000-0973.html)
+
# Not security issues
This is an incomplete list of issues that are not considered vulnerabilities.
@@ -158,7 +206,7 @@
transfers already need to have counter-measures established.
If the problem avoids the regular counter-measures when it causes a never-
-ending transfer, it might very well be a security problem.
+ending transfer, it might be a security problem.
## Not practically possible
@@ -208,7 +256,15 @@
- not all systems allow the arguments to be blanked in the first place
- since curl blanks the argument itself they will be readable for a short
- moment in time no matter what
+ 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
+
+## Busy-loops
+
+Busy-loops that consume 100% CPU time but eventually end (perhaps due to a set
+timeout value or otherwise) are not considered security problems. Applications
+are supposed to already handle situations when the transfer loop legitimately
+consumes 100% CPU time, so while a prolonged such busy-loop is a nasty bug, we
+do not consider it a security problem.
diff --git a/docs/SSL-PROBLEMS.md b/docs/SSL-PROBLEMS.md
index 4afe300..afe4250 100644
--- a/docs/SSL-PROBLEMS.md
+++ b/docs/SSL-PROBLEMS.md
@@ -17,7 +17,7 @@
## CA certs
CA certs are used to digitally verify the server's certificate. You need a
- "ca bundle" for this. See lots of more details on this in the SSLCERTS
+ "ca bundle" for this. See lots of more details on this in the `SSLCERTS`
document.
## CA bundle missing intermediate certificates
@@ -59,18 +59,17 @@
ciphers from its default set (slightly depending on SSL backend in use).
You may have to explicitly provide an alternative list of ciphers for curl
- to use to allow the server to use a WEAK cipher for you.
+ to use to allow the server to use a weak cipher for you.
Note that these weak ciphers are identified as flawed. For example, this
includes symmetric ciphers with less than 128 bit keys and RC4.
Schannel in Windows XP is not able to connect to servers that no longer
support the legacy handshakes and algorithms used by those versions, so we
- advice against building curl to use Schannel on really old Windows versions.
+ advise against building curl to use Schannel on really old Windows versions.
- References:
-
- https://datatracker.ietf.org/doc/html/draft-popov-tls-prohibiting-rc4-01
+ Reference: [Prohibiting RC4 Cipher
+ Suites](https://datatracker.ietf.org/doc/html/draft-popov-tls-prohibiting-rc4-01)
## Allow BEAST
diff --git a/docs/SSLCERTS.md b/docs/SSLCERTS.md
index ec57f41..7f2f735 100644
--- a/docs/SSLCERTS.md
+++ b/docs/SSLCERTS.md
@@ -6,7 +6,6 @@
SSL is the old name. It is called TLS these days.
-
Native SSL
----------
@@ -21,15 +20,16 @@
-----------------
This system is about trust. In your local CA certificate store you have certs
-from *trusted* Certificate Authorities that you then can use to verify that the
-server certificates you see are valid. they are signed by one of the CAs you
-trust.
+from *trusted* Certificate Authorities that you then can use to verify that
+the server certificates you see are valid. They are signed by one of the
+certificate authorities you trust.
-Which CAs do you trust? You can decide to trust the same set of companies your
-operating system trusts, or the set one of the known browsers trust. That is
-basically trust via someone else you trust. You should just be aware that
-modern operating systems and browsers are setup to trust *hundreds* of
-companies and in recent years several such CAs have been found untrustworthy.
+Which certificate authorities do you trust? You can decide to trust the same
+set of companies your operating system trusts, or the set one of the known
+browsers trust. That is basically trust via someone else you trust. You should
+just be aware that modern operating systems and browsers are setup to trust
+*hundreds* of companies and in recent years several certificate authorities
+have been found untrustworthy.
Certificate Verification
------------------------
@@ -39,8 +39,8 @@
peer's server certificate is valid.
If you communicate with HTTPS, FTPS or other TLS-using servers using
-certificates that are signed by CAs present in the store, you can be sure
-that the remote server really is the one it claims to be.
+certificates in the CA store, you can be sure that the remote server really is
+the one it claims to be.
If the remote server uses a self-signed certificate, if you do not install a CA
cert store, if the server uses a certificate signed by a CA that is not
@@ -51,30 +51,31 @@
1. Tell libcurl to *not* verify the peer. With libcurl you disable this with
`curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);`
- With the curl command line tool, you disable this with -k/--insecure.
+ With the curl command line tool, you disable this with `-k`/`--insecure`.
2. Get a CA certificate that can verify the remote server and use the proper
option to point out this CA cert for verification when connecting. For
libcurl hackers: `curl_easy_setopt(curl, CURLOPT_CAINFO, cacert);`
- With the curl command line tool: --cacert [file]
+ With the curl command line tool: `--cacert [file]`
3. Add the CA cert for your server to the existing default CA certificate
store. The default CA certificate store can be changed at compile time with
the following configure options:
- --with-ca-bundle=FILE: use the specified file as the CA certificate store.
- CA certificates need to be concatenated in PEM format into this file.
+ `--with-ca-bundle=FILE`: use the specified file as the CA certificate
+ store. CA certificates need to be concatenated in PEM format into this
+ file.
- --with-ca-path=PATH: use the specified path as CA certificate store. CA
+ `--with-ca-path=PATH`: use the specified path as CA certificate store. CA
certificates need to be stored as individual PEM files in this directory.
You may need to run c_rehash after adding files there.
- If neither of the two options is specified, configure will try to auto-detect
- a setting. It's also possible to explicitly not hardcode any default store
- but rely on the built in default the crypto library may provide instead.
- You can achieve that by passing both --without-ca-bundle and
- --without-ca-path to the configure script.
+ If neither of the two options is specified, configure will try to
+ auto-detect a setting. It's also possible to explicitly not set any
+ default store but rely on the built in default the crypto library may
+ provide instead. You can achieve that by passing both
+ `--without-ca-bundle` and `--without-ca-path` to the configure script.
If you use Internet Explorer, this is one way to get extract the CA cert
for a particular server:
@@ -83,22 +84,21 @@
- Find out where the CA certificate is kept (Certificate>
Authority Information Access>URL)
- Get a copy of the crt file using curl
- - Convert it from crt to PEM using the openssl tool:
- openssl x509 -inform DES -in yourdownloaded.crt \
- -out outcert.pem -text
- - Add the 'outcert.pem' to the CA certificate store or use it stand-alone
+ - Convert it from crt to PEM using the OpenSSL tool:
+ `openssl x509 -inform DES -in yourdownloaded.crt -out outcert.pem -text`
+ - Add the `outcert.pem` to the CA certificate store or use it stand-alone
as described below.
- If you use the 'openssl' tool, this is one way to get extract the CA cert
+ If you use the `openssl` tool, this is one way to get extract the CA cert
for a particular server:
- `openssl s_client -showcerts -servername server -connect server:443 > cacert.pem`
- type "quit", followed by the "ENTER" key
- The certificate will have "BEGIN CERTIFICATE" and "END CERTIFICATE"
markers.
- - If you want to see the data in the certificate, you can do: "openssl
- x509 -inform PEM -in certfile -text -out certdata" where certfile is
- the cert you extracted from logfile. Look in certdata.
+ - If you want to see the data in the certificate, you can do: `openssl
+ x509 -inform PEM -in certfile -text -out certdata` where `certfile` is
+ the cert you extracted from logfile. Look in `certdata`.
- If you want to trust the certificate, you can add it to your CA
certificate store or use it stand-alone as described. Just remember that
the security is no better than the way you obtained the certificate.
@@ -132,18 +132,20 @@
If libcurl was built with NSS support, then depending on the OS distribution,
it is probably required to take some additional steps to use the system-wide
-CA cert db. RedHat ships with an additional module, libnsspem.so, which
+CA cert db. Red Hat ships with an additional module, libnsspem.so, which
enables NSS to read the OpenSSL PEM CA bundle. On openSUSE you can install
-p11-kit-nss-trust which makes NSS use the system wide CA certificate store. NSS
-also has a new [database format](https://wiki.mozilla.org/NSS_Shared_DB).
+p11-kit-nss-trust which makes NSS use the system wide CA certificate
+store. NSS also has a new [database
+format](https://wiki.mozilla.org/NSS_Shared_DB).
-Starting with version 7.19.7, libcurl automatically adds the 'sql:' prefix to
-the certdb directory (either the hardcoded default /etc/pki/nssdb or the
-directory configured with SSL_DIR environment variable). To check which certdb
-format your distribution provides, examine the default certdb location:
-/etc/pki/nssdb; the new certdb format can be identified by the filenames
-cert9.db, key4.db, pkcs11.txt; filenames of older versions are cert8.db,
-key3.db, secmod.db.
+Starting with version 7.19.7, libcurl automatically adds the `sql:` prefix to
+the certificate database directory (either the set default `/etc/pki/nssdb` or
+the directory configured with the `SSL_DIR` environment variable). To check
+which certificate database format your distribution provides, examine the
+default certificate database location: `/etc/pki/nssdb`; the new certificate
+database format can be identified by the filenames `cert9.db`, `key4.db`,
+`pkcs11.txt`; filenames of older versions are `cert8.db`, `key3.db`,
+`secmod.db`.
Certificate Verification with Schannel and Secure Transport
-----------------------------------------------------------
diff --git a/docs/THANKS b/docs/THANKS
index b9f6eee..cbdf11e 100644
--- a/docs/THANKS
+++ b/docs/THANKS
@@ -6,6 +6,7 @@
0xee on github
0xflotus on github
+12932 on github
1337vt on github
1ocalhost on github
3dyd on github
@@ -21,6 +22,8 @@
Abram Pousada
accountantM on github
AceCrow on Github
+ad0p on github
+Adam Averay
Adam Barclay
Adam Brown
Adam Coyne
@@ -39,7 +42,9 @@
Adrian Schuur
Adriano Meirelles
afrind on github
+Aftab Alam
ahodesuka on github
+ajak in #curl
Ajit Dhumale
Akhil Kedia
Aki Koskinen
@@ -100,11 +105,14 @@
Alexander Traud
Alexander V. Tikhonov
Alexander Zhuravlev
+Alexandre Bury
+Alexandre Ferrieux
Alexandre Pion
Alexey Borzov
Alexey Eremikhin
Alexey Melnichuk
Alexey Pesternikov
+Alexey Savchuk
Alexey Simak
Alexey Zakhlestin
Alexis Carvalho
@@ -112,7 +120,11 @@
Alexis Vachette
Alfonso Martone
Alfred Gebert
+Ali Khodkar
+Ali Utku Selen
+ALittleDruid on github
Allen Pulsifer
+Alois Klink
Alona Rossen
Amaury Denoyelle
amishmm on github
@@ -136,6 +148,7 @@
Andreas Falkenhahn
Andreas Farber
Andreas Fischer
+Andreas Huebner
Andreas Kostyrka
Andreas Malzahn
Andreas Ntaflos
@@ -144,6 +157,7 @@
Andreas Roth
Andreas Schneider
Andreas Schuldei
+Andreas Sommer
Andreas Streichardt
Andreas Wurf
Andrei Benea
@@ -179,14 +193,17 @@
Andrii Moiseiev
Andrius Merkys
Andrés García
+Andy Alt
Andy Cedilnik
Andy Fiddaman
Andy Serpa
+Andy Stamp
Andy Tsouladze
Angus Mackay
anio on github
anon00000000 on github
anshnd on github
+Anssi Kolehmainen
Antarpreet Singh
Anthon Pang
Anthony Avina
@@ -197,7 +214,9 @@
Anthony Shaw
Antoine Aubert
Antoine Calando
+Antoine du Hamel
Antoine Pietri
+Antoine Pitrou
Anton Bychkov
Anton Gerasimov
Anton Kalmykov
@@ -215,6 +234,7 @@
Arnaud Compan
Arnaud Ebalard
Arnaud Rebillout
+Arne Soete
Aron Bergman
Aron Rotteveel
Artak Galoyan
@@ -228,7 +248,9 @@
Ashwin Metpalli
Ask Bjørn Hansen
Askar Safin
+AtariDreams on github
Ates Goral
+atjg on github
Augustus Saunders
Austin Green
Avery Fay
@@ -236,10 +258,12 @@
Axel Chong
Axel Morawietz
Axel Tillequin
+Ayesh Karunaratne
Ayoub Boudhar
Ayushman Singh Chauhan
b9a1 on github
Bachue Zhou
+Baitinq on github
Balaji Parasuram
Balaji S Rao
Balaji Salunke
@@ -260,6 +284,7 @@
beckenc on github
Ben Boeckel
Ben Darnell
+Ben Fritz
Ben Greear
Ben Kohler
Ben Madsen
@@ -273,6 +298,7 @@
Benjamin Gilbert
Benjamin Johnson
Benjamin Kircher
+Benjamin Loison
Benjamin Riefenstahl
Benjamin Ritcey
Benjamin Sergeant
@@ -301,6 +327,7 @@
Billyzou0741326 on github
Bin Lan
Bin Meng
+Biswapriyo Nath
Bjarni Ingi Gislason
Bjoern Franke
Bjoern Sikora
@@ -317,10 +344,13 @@
bobmitchell1956 on github
Bodo Bergmann
Bogdan Nicula
+Boris Kuschel
+Boris Okunskiy
Boris Rasin
Boris Verkhovskiy
Brad Burdick
Brad Fitzpatrick
+Brad Forschinger
Brad Harder
Brad Hards
Brad King
@@ -330,6 +360,7 @@
Brandon Casey
Brandon Dong
Brandon Wang
+BratSinot on github
Brendan Jurd
Brent Beardsley
Brian Akins
@@ -340,8 +371,11 @@
Brian Chrisman
Brian Dessent
Brian E. Gallew
+Brian Green
Brian Inglis
Brian J. Murrell
+Brian Lund
+Brian Nixon
Brian Prodoehl
Brian R Duffy
Brian Ulm
@@ -353,10 +387,12 @@
Bruno Baguette
Bruno de Carvalho
Bruno Grasselli
+Bruno Henrique Batista Cruz da Silva
Bruno Thomsen
Bryan Henderson
Bryan Kemp
bsammon on github
+bsergean on github
Bubu on github
buzo-ffm on github
bxac on github
@@ -364,6 +400,7 @@
Byrial Jensen
Caleb Raitto
Calvin Buckley
+Cameron Blomquist
Cameron Cawley
Cameron Kaiser
Cameron MacMinn
@@ -381,11 +418,13 @@
Carlo Wood
Carlos ORyan
Carsten Lange
+Casey Bodley
Casey O'Donnell
Catalin Patulea
causal-agent on github
cbartl on github
cclauss on github
+Cering on github
Cesar Eduardo Barros
Chad Monroe
Chandrakant Bagul
@@ -397,6 +436,8 @@
Chester Liu
Chih-Chung Chang
Chih-Hsuan Yen
+Chilledheart on github
+Chloe Kudryavtsev
Chris "Bob Bob"
Chris Araman
Chris Carlmar
@@ -411,10 +452,12 @@
Chris Paulson-Ellis
Chris Roberts
Chris Smowton
+Chris Talbot
Chris Young
Christian Fillion
Christian Grothoff
Christian Heimes
+Christian Hesse
Christian Hägele
Christian Krause
Christian Kurz
@@ -425,6 +468,7 @@
Christian Weisgerber
Christoph Krey
Christoph M. Becker
+Christoph Reiter
Christophe Demory
Christophe Dervieux
Christophe Legry
@@ -434,6 +478,7 @@
Christopher Palow
Christopher R. Palmer
Christopher Reid
+Christopher Sauer
Christopher Stone
Chungtsun Li
Ciprian Badescu
@@ -446,6 +491,7 @@
Cliff Crosland
Clifford Wolf
Clint Clayton
+Cloudogu Siebels
Clément Notin
cmfrolick on github
codesniffer13 on github
@@ -455,13 +501,16 @@
coinhubs on github
Colby Ranger
Colin Blair
+Colin Cross
Colin Hogben
Colin Leroy
Colin O'Dell
Colin Watson
Colm Buckley
+Colman Mbuya
Constantine Sapuntzakis
coralw on github
+correctmost on github
Cory Benfield
Cory Nelson
Costya Shulyupin
@@ -499,7 +548,7 @@
Dan Cristian
Dan Donahue
Dan Fandrich
-Dan Jacobson
+Dan Frandrich
Dan Johnson
Dan Kenigsberg
Dan Locks
@@ -514,11 +563,14 @@
Daniel Carpenter
Daniel Cater
Daniel Egger
+Daniel Faust
Daniel Gustafsson
+Daniel Hallberg
Daniel Hwang
Daniel Jeliński
Daniel Johnson
Daniel Kahn Gillmor
+Daniel Katz
Daniel Krügler
Daniel Kurečka
Daniel Lee Hwang
@@ -557,6 +609,7 @@
David Blaikie
David Bohman
David Byron
+David Carlier
David Cohen
David Cook
David Demelier
@@ -579,6 +632,7 @@
David Lopes
David Lord
David McCreedy
+David McLaughlin
David Odin
David Phillips
David Rosenstrauch
@@ -597,6 +651,9 @@
davidedec on github
dbrowndan on github
dEajL3kA on github
+Deal(一线灵)
+dekerser on github
+dengjfzh on github
Dengminwen
Denis Baručić
Denis Chaplygin
@@ -607,6 +664,7 @@
Dennis Clarke
Dennis Felsing
Derek Higgins
+Derzsi Dániel
Desmond O. Chang
destman on github
Detlef Schmier
@@ -625,19 +683,24 @@
Dimitrios Siganos
Dimitris Sarris
Dinar
+Diogo Teles Sant'Anna
+Dion Williams
Dirk Eddelbuettel
Dirk Feytons
Dirk Manske
+Dirk Rosenkranz
Dirk Wetter
Dirkjan Bussink
Diven Qi
divinity76 on github
+Divy Le Ray
dkjjr89 on github
dkwolfe4 on github
Dmitri Shubin
Dmitri Tikhonov
Dmitriy Sergeyev
dmitrmax on github
+Dmitry Atamanov
Dmitry Bartsevich
Dmitry Eremin-Solenikov
Dmitry Falko
@@ -651,9 +714,12 @@
Dmitry Wagin
dnivras on github
Dolbneff A.V
+Domen Kožar
Domenico Andreoli
Dominick Meglio
Dominik Hölzl
+Dominik Klemba
+Dominik Thalhammer
Dominique Leuenberger
Don J Olmstead
Dongliang Mu
@@ -675,12 +741,15 @@
Duncan Mac-Vicar Prett
Duncan Wilcox
Dustin Boswell
+Dustin Howett
Dusty Mabe
Duy Phan Thanh
Dwarakanath Yadavalli
+Dylan Anthony
Dylan Ellicott
Dylan Salisbury
Dániel Bakai
+eaglegai on github
Early Ehlinger
Earnestly on github
Eason-Yu on github
@@ -692,6 +761,7 @@
Edgaras Janušauskas
Edin Kadribasic
Edmond Yu
+Edoardo Lolletti
Eduard Bloch
Edward Kimmel
Edward Rudd
@@ -711,6 +781,7 @@
Ellis Pritchard
Elmira A Semenova
Elms
+Eloy Degen
elsamuko on github
emanruse on github
Emanuele Bovisio
@@ -718,7 +789,10 @@
Emil Engler
Emil Lerner
Emil Romanus
+Emil Österlund
Emiliano Ida
+Emilio Cobos Álvarez
+Emilio López
Emmanuel Tychon
Enrico Scholz
Enrik Berkhan
@@ -741,6 +815,7 @@
Eric Sauvageau
Eric Thelin
Eric Vergnaud
+Eric Vigeant
Eric Wong
Eric Wu
Eric Young
@@ -755,6 +830,7 @@
Ernst Sjöstrand
Erwan Legrand
Erwin Authried
+Esdras de Morais da Silva
Estanislau Augé-Pujadas
Ethan Glasser Camp
Etienne Simard
@@ -763,11 +839,12 @@
Evangelos Foutras
Even Rouault
Evert Pot
-Evgeny Grin
+Evgeny Grin (Karlson2k)
Evgeny Turnaev
eXeC64 on github
Eygene Ryabinkin
Eylem Ugurel
+Fabian Fischer
Fabian Frank
Fabian Hiernaux
Fabian Keil
@@ -778,11 +855,14 @@
Fahim Chandurwala
Faizur Rahman
Farzin on github
+Fata Nugraha
Fawad Mirza
fds242 on github
Federico Bianchi
+Federico Pellegrin
Fedor Karpelevitch
Fedor Korotkov
+FeignClaims on github
Feist Josselin
Felipe Gasper
Felix Hädicke
@@ -793,6 +873,7 @@
Fernando Muñoz
Filip Lundgren
Filip Salomonsson
+finkjsc on github
Firefox OS
Flameborn on github
Flavio Medeiros
@@ -819,6 +900,7 @@
Frank Van Uffelen
František Kučera
François Charlier
+François Michel
François Rigault
Frazer Smith
Fred Machado
@@ -830,7 +912,9 @@
Frederik Wedel-Heinen
Fredrik Thulin
FuccDucc on github
+Fujii Hironori
fullincome on github
+fundawang on github
Gabriel Kuri
Gabriel Simmer
Gabriel Sjoberg
@@ -884,11 +968,13 @@
Glenn de boer
Glenn Sheridan
Glenn Strauss
+godmar on github
Godwin Stewart
Google Inc.
Gordon Marler
Gorilla Maguila
Gou Lingfeng
+Graham Campbell
Grant Erickson
Grant Pannell
Greg Hewgill
@@ -901,18 +987,22 @@
Gregory Jefferis
Gregory Muchka
Gregory Nicholls
+Gregory Panakkal
Gregory Szorc
Griffin Downs
Grigory Entin
+Grisha Levit
Guenole Bescon
Guido Berhoerster
Guillaume Arluison
guitared on github
+Gunamoi Software
Gunter Knauf
Gustaf Hui
Gustavo Grieco
Guy Poizat
GwanYeong Kim
+Gwen Shapira
Gwenole Beauchesne
Gökhan Şengün
Götz Babin-Ebell
@@ -926,6 +1016,7 @@
Han Qiao
Hang Kin Lau
Hang Su
+Hannah Schierling
Hannes Magnusson
Hanno Böck
Hanno Kranzhoff
@@ -949,6 +1040,7 @@
Helmut K. C. Tessarek
Helwing Lutz
Hendrik Visage
+Henning Schild
Henri Gomez
Henrik Gaßmann
Henrik Holst
@@ -957,8 +1049,13 @@
Henry Roeland
Herve Amblard
HexTheDragon
+Hide Ishikawa
Hidemoto Nakada
+highmtworks on github
Himanshu Gupta
+Hind Montassif
+Hiroki Kurosawa
+Hirotaka Tagawa
Ho-chi Chen
Hoi-Ho Chan
Hongli Lai
@@ -970,6 +1067,7 @@
Hubert Kario
Hugh Macdonald
Hugo van Kemenade
+humbleacolyte
Huzaifa Sidhpurwala
huzunhao on github
hydra3333 on github
@@ -990,6 +1088,7 @@
Igor Makarov
Igor Novoseltsev
Igor Polyakov
+Igor Todorovski
Ihor Karpenko
ihsinme on github
Iida Yosiaki
@@ -998,6 +1097,7 @@
Ilja van Sprundel
Illarion Taev
illusory-dream on github
+Ilmari Lauhakangas
Ilya Kosarev
imilli on github
Immanuel Gregoire
@@ -1017,6 +1117,7 @@
Ishan SinghLevett
Ithubg on github
Ivan Avdeev
+Ivan Tsybulin
IvanoG on github
Ivo Bellin Salarin
iz8mbw on github
@@ -1024,15 +1125,18 @@
Jack Boos Yu
Jack Zhang
Jackarain on github
+JackBoosY on github
Jacky Lam
Jacob Barthelmeh
Jacob Hoffman-Andrews
Jacob Meuser
Jacob Moshenko
+Jacob Tolar
Jactry Zeng
Jad Chamcham
Jaime Fullaondo
jakirkham on github
+Jakob Hirsch
Jakub Bochenski
Jakub Wilk
Jakub Zakrzewski
@@ -1047,8 +1151,10 @@
James Gallagher
James Griffiths
James Housley
+James Keast
James Knight
James Le Cuirot
+James Lucas
James MacMillan
James Slaughter
Jamie Lokier
@@ -1057,8 +1163,10 @@
Jan Alexander Steffens
Jan Chren
Jan Ehrhardt
+Jan Engelhardt
Jan Koen Annot
Jan Kunder
+Jan Macku
Jan Mazur
Jan Schaumann
Jan Schmidt
@@ -1067,6 +1175,7 @@
Jan Verbeek
Jan-Piet Mens
JanB on github
+Janne Blomqvist
Janne Johansson
Jared Jennings
Jared Lundell
@@ -1089,6 +1198,7 @@
Jay Dommaschk
Jayesh A Shah
Jaz Fresh
+jbgoog on github
Jean Fabrice
Jean Gressmann
Jean Jacques Drouin
@@ -1113,6 +1223,7 @@
Jeffrey Tolar
Jeffrey Walton
jeffrson on github
+Jelle van der Waa
Jenny Heino
Jens Finkhaeuser
Jens Rantil
@@ -1132,6 +1243,7 @@
Jerome Mao
Jerome Muffat-Meridol
Jerome Robert
+Jerome St-Louis
Jerome Vouillon
Jerry Krinock
Jerry Wu
@@ -1143,11 +1255,13 @@
jethrogb on github
jhoyla on github
Jie He
+Jilayne Lovejoy
Jim Beveridge
Jim Drash
Jim Freeman
Jim Fuller
Jim Hollinger
+Jim King
Jim Meyering
Jimmy Gaussen
Jiri Dvorak
@@ -1179,6 +1293,7 @@
Johannes Lesr
Johannes Schindelin
John A. Bristor
+John Bampton
John Bradshaw
John Butterfield
John Coffey
@@ -1191,6 +1306,7 @@
John Gardiner Myers
John H. Ayad
John Hascall
+John Haugabook
John Janssen
John Joseph Bachir
John Kelly
@@ -1202,7 +1318,9 @@
John Marshall
John McGowan
John P. McCaskey
+John Porter
John Schroeder
+John Sherrill
John Simpson
John Starks
John Suprock
@@ -1225,7 +1343,9 @@
Jon Travis
Jon Turner
Jon Wilkes
+Jonas Bülow
Jonas Forsman
+Jonas Haag
Jonas Minnberg
Jonas Schnelli
Jonas Vautherin
@@ -1247,10 +1367,13 @@
Josef Wolf
Joseph Chen
Josh Bialkowski
+Josh Brobst
Josh Kapell
+Josh McCullough
Josh Soref
joshhe on github
Joshua Kwan
+Joshua Root
Joshua Swink
Josie Huddleston
Josip Medved
@@ -1258,6 +1381,7 @@
José Joaquín Atria
Jozef Kralik
Juan Barreto
+Juan Cruz Viotti
Juan F. Codagnone
Juan Ignacio Hervás
Juan RP
@@ -1282,14 +1406,19 @@
Jurij Smakov
jurisuk on github
Juro Bystricky
+JustAnotherArchivist on github
+justchen1369 on github
Justin Clift
Justin Ehlert
Justin Fletcher
Justin Karneges
Justin Maggard
jveazey on github
+jvreelanda on github
+jvvprasad78 on github
jzinn on github
János Fekete
+Jérémy Rabasco
Jérémy Rocher
Jörg Mueller-Tolk
Jörn Hartroth
@@ -1299,6 +1428,7 @@
Kael1117 on github
Kai Engert
Kai Noda
+Kai Pastor
Kai Sommerfeld
Kai-Uwe Rommel
Kalle Vahlman
@@ -1310,26 +1440,32 @@
Kari Pahula
Karl Chen
Karl Moerder
-Karlson2k on github
Karol Pietrzak
+Karthikdasari0423
+Karthikdasari0423 on github
Kartik Mahajan
Kaspar Brand
Katie Wang
Katsuhiko YOSHIDA
Kazuho Oku
+kchow-FTNT on github
Kees Cook
Kees Dekker
+Keitagit-kun on github
Keith MacDonald
Keith McGuigan
Keith Mok
+Kelly Kaoudis
Ken Brown
Ken Hirsch
Ken Rastatter
Kenneth Davidson
+Kenneth Myhra
Kenny To
Kent Boortz
Kerem Kat
Keshav Krity
+Kev Jackson
Kevin Adler
Kevin Baughman
Kevin Burke
@@ -1339,6 +1475,7 @@
Kevin R. Bulgrien
Kevin Reed
Kevin Roth
+Kevin Ryan
Kevin Smith
Kevin Ushey
Kim Minjoong
@@ -1375,6 +1512,8 @@
Kunal Ekawde
Kurt Fankhauser
Kushal Das
+Kvarec Lezki
+kwind on github
Kwon-Young Choi
Kyle Abramowitz
Kyle Edwards
@@ -1440,8 +1579,10 @@
Linus Nordberg
Lior Kaplan
Lisa Xu
+Litter White
Liviu Chircu
Liza Alenchery
+lizhuang0630 on github
lllaffer on github
Lloyd Fournier
Lluís Batlle i Rossell
@@ -1449,9 +1590,11 @@
Loganaden Velvindron
Loic Dachary
Loren Kirkby
+Lorenzo Miniero
Luan Cestari
Luca Altea
Luca Boccassi
+Luca Niccoli
Lucas Adamski
Lucas Clemente Vella
Lucas Holt
@@ -1474,13 +1617,16 @@
Luong Dinh Dung
Luz Paz
Luật Nguyễn
+lwthiker on github
Lyman Epp
Lyndon Hill
M.R.T on github
+Maciej Domanski
Maciej Karpiuk
Maciej Puzio
Maciej W. Rozycki
madblobfish on github
+MaeIsBad on github
Mahmoud Samir Fayed
Maks Naumov
Maksim Kuzevanov
@@ -1513,6 +1659,7 @@
Marcin Konicki
Marco Deckel
Marco G. Salvagno
+Marco Kamner
Marco Maggi
Marcos Diazr
Marcus Hoffmann
@@ -1520,18 +1667,23 @@
Marcus Sundberg
Marcus T
Marcus Webster
+Margu
Marian Klymov
Mario Schroeder
Mark Brand
Mark Butler
Mark Davies
Mark Dodgson
+Mark Gaiser
Mark Hamilton
Mark Incley
+Mark Itzcovitz
Mark Karpeles
Mark Lentczner
Mark Nottingham
+Mark Roszko
Mark Salisbury
+Mark Seuffert
Mark Snelling
Mark Swaanenburg
Mark Tully
@@ -1546,10 +1698,12 @@
Markus Westerlind
Maros Priputen
Marquis de Muesli
+marski on github
Martijn Koster
Martin Ankerl
Martin Bašti
Martin C. Martin
+Martin D'Aloia
Martin Dorey
Martin Drasar
Martin Dreher
@@ -1567,8 +1721,11 @@
Martin Skinner
Martin Staael
Martin Storsjö
+Martin Strunz
Martin V
Martin Vejnár
+Martin Waleczek
+Martin Ågren
Marty Kuhrt
Maruko
Masaya Suzuki
@@ -1576,9 +1733,12 @@
Massimiliano Fantuzzi
Massimiliano Ziccardi
Massimo Callegari
+Master Inspire
+MasterInQuestion on github
Mateusz Loskot
Mathias Axelsson
Mathias Gumz
+Mathieu Carbonneaux
Mathieu Legare
Matias N. Goldberg
Mats Lidell
@@ -1586,6 +1746,7 @@
Matt Arsenault
Matt Ford
Matt Holt
+Matt Jolly
Matt Kraai
Matt McClure
Matt Veenstra
@@ -1599,6 +1760,7 @@
Matthew Clarke
Matthew Hall
Matthew Kerwin
+Matthew Thompson
Matthew Whitehead
Matthias Bolte
Matthias Gatto
@@ -1631,6 +1793,7 @@
Melroy van den Berg
Mert Yazıcıoğlu
Mettgut Jamalla
+Micah Snyder)
Michael Afanasiev
Michael Anti
Michael Baentsch
@@ -1641,10 +1804,12 @@
Michael Cronenworth
Michael Curtis
Michael Day
+Michael Drake
Michael Felt
Michael Forney
Michael Gmelin
Michael Goffioul
+Michael Heimpold
Michael Hordijk
Michael Jahn
Michael Jerris
@@ -1667,6 +1832,7 @@
Michael Stapelberg
Michael Steuer
Michael Stillwell
+Michael Trebilcock
Michael Vittiglio
Michael Wallner
Michal Bonino
@@ -1679,6 +1845,7 @@
Michał Górny
Michał Janiszewski
Michał Kowalczyk
+Michał Petryka
Michał Piechowski
Michel Promonet
Michele Bini
@@ -1693,6 +1860,7 @@
Mike Crowe
Mike Dobbs
Mike Dowell
+Mike Duglas
Mike Frysinger
Mike Gelfand
Mike Giancola
@@ -1705,6 +1873,7 @@
Mike Protts
Mike Revi
Mike Tzou
+Mikhail Kuznetsov
Miklos Nemeth
Miloš Ljumović
Mingliang Zhu
@@ -1723,6 +1892,7 @@
Mohun Biswas
momala454 on github
Momoka Yamamoto
+MonkeybreadSoftware on github
moohoorama on github
Morten Minde Neergaard
Mostyn Bramley-Moore
@@ -1730,15 +1900,20 @@
MrdUkk on github
MrSorcus on github
Muhammad Herdiansyah
+Muhammad Hussein Ammari
Muhammed Yavuz Nuzumlalı
Murugan Balraj
+musvaage on github
Muz Dima
Myk Taylor
+n0name321 on github
Nach M. S.
Nagai H
+Nao Yonashiro
naost3rn on github
Nate Prewitt
Nathan Coulter
+Nathan Moinvaziri
Nathan O'Sullivan
Nathanael Nerode
Nathaniel J. Smith
@@ -1771,6 +1946,7 @@
Nick Humfrey
Nick Miyake
Nick Zitzmann
+nick-telia on github
Nicklas Avén
Nico Baggus
nico-abram on github
@@ -1798,6 +1974,7 @@
Nis Jorgensen
nk
Noam Moshe
+nobedee on github
NobodyXu on github
Nobuhiro Ban
Nodak Sodak
@@ -1805,30 +1982,38 @@
Norbert Frese
Norbert Kett
Norbert Novotny
+norbertmm on github
nosajsnikta on github
NTMan on Github
Nuru on github
Octavio Schroeder
+odek86 on github
Ofer
Okhin Vasilij
Ola Mork
Olaf Flebbe
Olaf Hering
Olaf Stüben
+Oleg Jukovec
Oleg Pudeyev
Oleguer Llopart
Olen Andoni
olesteban on github
Oli Kingshott
+Oliver Chang
Oliver Gondža
Oliver Graute
Oliver Kuckertz
+Oliver Roberts
Oliver Schindler
Oliver Urbann
Olivier Berger
Olivier Brunel
Omar Ramadan
omau on github
+Ondřej Koláček
+opensignature on github
+opensslonzos-github on github
Orange Tsai
Oren Souroujon
Oren Tirosh
@@ -1836,13 +2021,17 @@
Ori Avtalion
orycho on github
osabc on github
+Osaila on github
+Osama Albahrani
Oscar Koeroo
Oscar Norlander
Oskar Liljeblad
+Oskar Sigvardsson
Oumph on github
ovidiu-benea on github
P R Schaffner
Palo Markovic
+pandada8 on github
Paolo Mossino
Paolo Piacentini
Paras Sethia
@@ -1884,11 +2073,15 @@
Paul Oliver
Paul Querna
Paul Saab
+Paul Seligman
Paul Vixie
+Paul Wise
Paulo Roberto Tomasi
Pavel Cenek
Pavel Gushchin
+Pavel Kalyugin
Pavel Löbl
+Pavel Mayorov
Pavel Orehov
Pavel Pavlov
Pavel Raiskup
@@ -1899,6 +2092,7 @@
Pawel Kierski
Paweł Kowalski
Paweł Wegner
+Pedro Henrique
Pedro Larroy
Pedro Monreal
Pedro Neves
@@ -1914,6 +2108,7 @@
Peter Forret
Peter Frühberger
Peter Gal
+Peter Goodman
Peter Heuchert
Peter Hjalmarsson
Peter Korsgaard
@@ -1940,17 +2135,21 @@
Petr Novak
Petr Pisar
Petr Voytsik
+Petr Štetiar
Phil Blundell
Phil Crump
Phil E. Taylor
Phil Karn
Phil Lisiecki
Phil Pellouchoud
+Philip Chan
Philip Craig
Philip Gladstone
-Philip H
+Philip Heiduck
Philip Langdale
Philip Prindeville
+Philip Sanetra
+Philipp Engel
Philipp Klaus Krause
Philipp Waehnert
Philippe Hameau
@@ -1968,6 +2167,7 @@
Piotr Dobrogost
Piotr Komborski
Po-Chuan Hsieh
+Pontakorn Prasertsuk
Pontus Lundkvist
Pooyan McSporran
Poul T Lomholt
@@ -1975,7 +2175,10 @@
Prash Dush
Praveen Pvs
Prithvi MK
+privetryan on github
Priyanka Shah
+ProceduralMan on github
+Pronyushkin Petr
Przemysław Tomaszewski
pszemus on github
puckipedia on github
@@ -1987,8 +2190,10 @@
Quinn Slack
r-a-sattarov on github
R. Dennis Steed
+Radek Brich
Radek Zajic
Radoslav Georgiev
+Radu Hociung
Radu Simionescu
Rafa Muyo
Rafael Antonio
@@ -2000,6 +2205,7 @@
Rainer Jung
Rainer Koenig
Rainer Müller
+Raito Bezarius
Rajesh Naganathan
Rajkumar Mandal
Ralf S. Engelschall
@@ -2009,6 +2215,7 @@
Ram Krushna Mishra
ramsay-jones on github
Ran Mozes
+RanBarLavie on github
Randall S. Becker
Randolf J
Randy Armstrong
@@ -2090,10 +2297,13 @@
Rob Cotrone
Rob Crittenden
Rob Davies
+Rob de Wit
Rob Jones
Rob Sanders
Rob Stanzel
Rob Ward
+RobBotic1 on github
+Robby Simpson
Robert A. Monat
Robert B. Harris
Robert Brose
@@ -2115,6 +2325,7 @@
Robin Douine
Robin Johnson
Robin Kay
+Robin Marx
Robson Braga Araujo
Rod Widdowson
Rodger Combs
@@ -2140,9 +2351,12 @@
Ron Eldor
Ron Parker
Ron Zapp
+Ronan Pigott
Ronnie Mose
+Rosen Penev
Rosimildo da Silva
Ross Burton
+roughtex on github
Roy Bellingan
Roy Li
Roy Shan
@@ -2154,6 +2368,7 @@
Rutger Hofman
Ruurd Beerstra
RuurdBeerstra on github
+rwmjones on github
Ryan Beck-Buysse
Ryan Braud
Ryan Chan
@@ -2165,11 +2380,13 @@
Ryan Winograd
ryancaicse on github
Ryuichi KAWAMATA
+rzrymiak on github
Rémy Léone
S. Moonesamy
Sai Ram Kunala
Salah-Eddin Shaban
Saleem Abdulrasool
+SaltyMilk
Salvador Dávila
Salvatore Sorrentino
Sam Deane
@@ -2185,6 +2402,7 @@
Samuel Surtees
Samuel Thibault
Samuel Tranchet
+SandakovMM on github
Sander Gates
Sandor Feldi
Sandro Jaeckel
@@ -2217,11 +2435,17 @@
Sebastian Pohlschmidt
Sebastian Rasmussen
Sebastian Sterk
+selmelc on hackerone
+SendSonS on github
Senthil Raja Velu
Sergei Kuzmin
Sergei Nikulov
+Sergey Alirzaev
+Sergey Bronnikov
+Sergey Fionov
Sergey Markelov
Sergey Ogryzkov
+Sergey Ryabinin
Sergey Tatarincev
Sergii Kavunenko
Sergii Pylypenko
@@ -2229,14 +2453,18 @@
Sergio Barresi
Sergio Borghese
Sergio Durigan Junior
+Sergio Mijatovic
+Sergio-IME on github
sergio-nsk on github
Serj Kalichev
+SerusDev on github
Seshubabu Pasam
Seth Mos
Sevan Janiyan
Sgharat on github
Sh Diao
Shachaf Ben-Kiki
+ShadowZzj on github
Shailesh Kapse
Shankar Jadhavar
Shao Shuchao
@@ -2244,14 +2472,17 @@
Shard
Sharon Brizinov
Shaun Jackman
+Shaun Mirani
Shawn Landden
Shawn Poulson
+Sheshadri.V
Shikha Sharma
Shine Fan
Shiraz Kanga
shithappens2016 on github
Shlomi Fish
Shmulik Regev
+Shohei Maeda
Siddhartha Prakash Jain
siddharthchhabrap on github
Sidney San Martín
@@ -2265,8 +2496,10 @@
Simon Legner
Simon Liu
Simon Warta
+simplerobot on github
Siva Sivaraman
SLDiggie on github
+Smackd0wn on github
smuellerDD on github
sn on hackerone
sofaboss on github
@@ -2278,6 +2511,7 @@
Spiridonoff A.V
Spoon Man
Spork Schivago
+ssdbest on github
sspiri on github
sstruchtrup on github
Stadler Stephan
@@ -2285,6 +2519,7 @@
Stan van de Burgt
Stanislav Ivochkin
Stanislav Zidek
+Stanley Wucw
Stathis Kapnidis
Stav Nir
steelman on github
@@ -2299,6 +2534,7 @@
Stefan Krause
Stefan Neis
Stefan Strogin
+Stefan Talpalaru
Stefan Teleman
Stefan Tomanek
Stefan Ulrich
@@ -2309,6 +2545,7 @@
Stepan Broz
Stepan Efremov
Stephan Bergmann
+Stephan Guilloux
Stephan Lagerholm
Stephan Mühlstrasser
Stephan Szabo
@@ -2324,6 +2561,7 @@
Steve Green
Steve H Truong
Steve Havelka
+Steve Herrell
Steve Holme
Steve Lhomme
Steve Little
@@ -2342,10 +2580,12 @@
Stoned Elipot
stootill on github
Stuart Henderson
+Sukanya Hanumanthu
SumatraPeter on github
Sune Ahlgren
Sunny Bean
Sunny Purushe
+SuperIlu on github
Sven Anders
Sven Blumenstein
Sven Neuhaus
@@ -2355,6 +2595,7 @@
sylgal on github
Sylvestre Ledru
Symeon Paraschoudis
+Sébastien Helleu
Sébastien Willemijns
T. Bharath
T. Yamada
@@ -2369,6 +2610,7 @@
Tatsuhiro Tsujikawa
tawmoto on github
tbugfinder on github
+Ted Lyngmo
Teemu Yli-Elsila
Temprimus
Terri Oda
@@ -2376,8 +2618,10 @@
thanhchungbtc on github
The Infinnovation team
TheAssassin on github
+TheKnarf on github
Theodore Dubois
therealhirudo on github
+Thiago Suchorski
tholin on github
Thomas Bouzerar
Thomas Braun
@@ -2393,9 +2637,12 @@
Thomas Petazzoni
Thomas Ruecker
Thomas Schwinge
+Thomas Taylor
Thomas Tonino
Thomas van Hesteren
Thomas Vegas
+Thomas Weißschuh
+Thomas1664 on github
Thorsten Schöning
Tiit Pikma
Till Maas
@@ -2415,6 +2662,7 @@
Tim Starling
Tim Tassonis
Tim Verhoeven
+Timmy Schierling
Timo Lange
Timo Sirainen
Timotej Lazar
@@ -2434,8 +2682,10 @@
Tobias Lindgren
Tobias Markus
Tobias Nießen
+Tobias Nygren
Tobias Nyholm
Tobias Rundström
+Tobias Schaefer
Tobias Stoeckmann
Toby Peterson
Todd A Ouska
@@ -2487,6 +2737,7 @@
Toshiyuki Maezawa
tpaukrt on github
Traian Nicolescu
+Trail of Bits
Travis Burtrum
Travis Obenhaus
Trivikram Kamat
@@ -2498,11 +2749,13 @@
Tupone Alfredo
Tyler Hall
Török Edwin
+u20221022 on github
Ulf Härnhammar
Ulf Samuelsson
Ulrich Doehner
Ulrich Telle
Ulrich Zadow
+UnicornZhang on Github
updatede on github
UrsusArctos on github
User Sg
@@ -2516,6 +2769,7 @@
vanillajonathan on github
Varnavas Papaioannou
Vasiliy Faronov
+Vasiliy Ulyanov
Vasily Lobaskin
Vasy Okhin
Venkat Akella
@@ -2524,6 +2778,7 @@
Victor Magierski
Victor Snezhko
Victor Vieux
+VictorVG on github
Vijay Panghal
Vikram Saxena
Viktor Szakats
@@ -2537,6 +2792,7 @@
Vincent Penquerc'h
Vincent Sanders
Vincent Torri
+violetlige on github
vitaha85 on github
Vitaly Varyvdin
vl409 on github
@@ -2548,6 +2804,8 @@
Vladimir Panteleev
Vladimir Varlamov
Vlastimil Ovčáčík
+vlkl-sap on github
+vlubart on github
Vojtech Janota
Vojtech Minarik
Vojtěch Král
@@ -2556,12 +2814,14 @@
vshmuk on hackerone
vvb2060 on github
Vyron Tsingaras
+Vítor Galvão
W. Mark Kubacki
Waldek Kozba
Walter J. Mack
Ward Willats
Warren Menzer
Wayne Haigh
+Wei Chong Tan
Wenchao Li
Wenxiang Qian
Werner Koch
@@ -2580,12 +2840,14 @@
William A. Rowe Jr
William Ahern
William Desportes
+William Tang
wmsch on github
wncboy on github
Wojciech Zwiefka
Wolf Vollprecht
Wouter Van Rooy
Wu Yongzheng
+Wu Zheng
Wyatt O'Day
Wyatt OʼDay
x2018 on github
@@ -2594,12 +2856,16 @@
XhstormR on github
Xiang Xiao
Xiangbin Li
+xianghongai on github
Xiaoke Wang
Xiaoyin Liu
XmiliaH on github
xnynx on github
+xtonik on github
xwxbug on github
+Xì Gà
Yaakov Selkowitz
+Yair Lenga
Yang Tse
Yaobin Wen
Yarram Sunil
@@ -2612,6 +2878,7 @@
Yi Huang
Yiming Jing
Yingwei Liu
+yiyuaner on github
Ymir1711 on github
Yonggang Luo
Yongkang Huang
@@ -2622,10 +2889,13 @@
Yukihiro Kawada
Yun SangHo
Yuri Slobodyanyuk
+Yurii Rashkovskii
+Yuriy Chernyshov
Yuriy Sosov
Yusuke Nakamura
Yves Arrouye
Yves Lejeune
+YX Hao
z2-2z on github
z2_ on hackerone
Zachary Seguin
@@ -2634,7 +2904,9 @@
zelinchen on github
Zenju on github
Zero King
+Zespre Schmidt
Zhang Xiuhua
+zhanghu on xiaomi
Zhao Yisha
Zhaoyang Wu
Zhibiao Wu
@@ -2646,6 +2918,7 @@
zzq1015 on github
Ádler Jonas Gross
Érico Nogueira
+Érico Nogueira Rolim
İsmail Dönmez
Łukasz Domeradzki
Štefan Kremeň
@@ -2655,4 +2928,6 @@
ウさん
不确定
加藤郁之
+左潇峰
梦终无痕
+積丹尼 Dan Jacobson
diff --git a/docs/THANKS-filter b/docs/THANKS-filter
index 2bb25e8..b56763e 100644
--- a/docs/THANKS-filter
+++ b/docs/THANKS-filter
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -29,7 +29,7 @@
# When removing dupes that aren't identical names from THANKS, add a line
# here!
#
-# Used-by: contributor.sh
+# Used-by: contributors.sh
s/Andres Garcia/Andrés García/
s/Chris Conroy/Christopher Conroy/
s/Francois Charlier/François Charlier/
@@ -130,3 +130,6 @@
s/Travis Burtrum on github//
s/i-ky on github/Gleb Ivanovsky/
s/ *via curl-library *//
+s/Evgeny Grin$/Evgeny Grin (Karlson2k)/
+s/Karlson2k on github/Evgeny Grin (Karlson2k)/
+s/GitHub$//
diff --git a/docs/TODO b/docs/TODO
index 97afcec..dfe6cc3 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -23,7 +23,6 @@
1.4 alt-svc sharing
1.5 get rid of PATH_MAX
1.6 native IDN support on macOS
- 1.7 Support HTTP/2 for HTTP(S) proxies
1.8 CURLOPT_RESOLVE for any port number
1.9 Cache negative name resolves
1.10 auto-detect proxy
@@ -45,6 +44,7 @@
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
@@ -68,9 +68,11 @@
4.5 ASCII support
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.2 Set custom client ip when using haproxy protocol
+ 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
@@ -120,6 +122,7 @@
13.9 TLS record padding
13.10 Support Authority Information Access certificate extension (AIA)
13.11 Support intermediate & root pinning for PINNEDPUBLICKEY
+ 13.12 Reduce CA certificate bundle reparsing
13.13 Make sure we forbid TLS 1.3 post-handshake authentication
13.14 Support the clienthello extension
@@ -167,6 +170,9 @@
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 file names
+ 18.28 -J with -C -
+ 18.29 --retry and transfer timeouts
19. Build
19.1 roffit
@@ -174,6 +180,7 @@
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
+ 19.6 build curl with Windows Unicode support
20. Test suite
20.1 SSL tunnel
@@ -181,7 +188,7 @@
20.3 more protocols supported
20.4 more platforms supported
20.5 Add support for concurrent connections
- 20.6 Use the RFC6265 test suite
+ 20.6 Use the RFC 6265 test suite
20.7 Support LD_PRELOAD on macOS
20.8 Run web-platform-tests URL tests
@@ -215,13 +222,22 @@
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
+1.4 Better and more 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 a 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:
@@ -241,12 +257,6 @@
See initial work in https://github.com/curl/curl/pull/5371
-1.7 Support HTTP/2 for HTTP(S) proxies
-
- Support for doing HTTP/2 to HTTP and HTTPS proxies is still missing.
-
- See https://github.com/curl/curl/issues/3570
-
1.8 CURLOPT_RESOLVE for any port number
This option allows applications to set a replacement IP address for a given
@@ -425,6 +435,21 @@
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
@@ -545,7 +570,7 @@
4.5 ASCII support
- FTP ASCII transfers do not follow RFC959. They do not convert the data
+ FTP ASCII transfers do not follow RFC 959. They do not convert the data
accordingly.
4.6 GSSAPI via Windows SSPI
@@ -562,14 +587,35 @@
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.2 Set custom client ip when using haproxy protocol
+5.1 Provide the error body from a CONNECT response
- This would allow testing servers with different client ip addresses (without
- using x-forward-for header).
+ When curl receives a body response from a CONNECT request to a proxy, it will
+ always just read and ignore 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?
- https://github.com/curl/curl/issues/5125
+ See https://github.com/curl/curl/issues/9513
+
+5.2 Obey Retry-After in redirects
+
+ The Retry-After is said to dicate "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
@@ -844,6 +890,15 @@
Adding this feature would make curls pinning 100% compatible to HPKP and
allow more flexible pinning.
+13.12 Reduce CA certificate bundle reparsing
+
+ When using the OpenSSL backend, curl will load and reparse the CA bundle at
+ the creation of the "SSL context" when it sets up a connection to do a TLS
+ handshake. A more effective way would be to somehow cache the CA bundle to
+ avoid it having to be repeatedly reloaded and reparsed.
+
+ See https://github.com/curl/curl/issues/9379
+
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
@@ -1183,6 +1238,43 @@
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 file names
+
+ -J/--remote-header-name does not decode %-encoded file names. 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 will not add decoding to -O without the user asking for it with
+ some other means as well, 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 file name (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 will truncate and restart 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.1 roffit
@@ -1223,6 +1315,13 @@
See https://github.com/curl/curl/issues/7753
+19.6 build curl with Windows Unicode support
+
+ The user wants an easier way to tell autotools to build curl with Windows
+ Unicode support, like ./configure --enable-windows-unicode
+
+ See https://github.com/curl/curl/issues/7229
+
20. Test suite
20.1 SSL tunnel
@@ -1260,7 +1359,7 @@
should not do in these tests) and thus the wait for connections loop is never
entered to receive the second connection.
-20.6 Use the RFC6265 test suite
+20.6 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
diff --git a/docs/TheArtOfHttpScripting.md b/docs/TheArtOfHttpScripting.md
index 78dbd7a..2973a36 100644
--- a/docs/TheArtOfHttpScripting.md
+++ b/docs/TheArtOfHttpScripting.md
@@ -11,8 +11,9 @@
Curl is a command line tool for doing all sorts of URL manipulations and
transfers, but this particular document will focus on how to use it when
- doing HTTP requests for fun and profit. I will assume that you know how to
- invoke `curl --help` or `curl --manual` to get basic information about it.
+ doing HTTP requests for fun and profit. This documents assumes that you know
+ how to invoke `curl --help` or `curl --manual` to get basic information about
+ it.
Curl is not written to do everything for you. It makes the requests, it gets
the data, it sends data and it retrieves the information. You probably need
@@ -63,10 +64,21 @@
curl --trace-ascii d.txt --trace-time http://example.com/
+## See which Transfer
+
+ When doing parallel transfers, it is relevant to see which transfer is
+ doing what. When response headers are received (and logged) you need to
+ know which transfer these are for.
+ [`--trace-ids`](https://curl.se/docs/manpage.html#--trace-ids) option
+ is what you need. It will prepend the transfer and connection identifier
+ to each trace output line:
+
+ curl --trace-ascii d.txt --trace-ids http://example.com/
+
## See the Response
By default curl sends the response to stdout. You need to redirect it
- somewhere to avoid that, most often that is done with ` -o` or `-O`.
+ somewhere to avoid that, most often that is done with `-o` or `-O`.
# URL
@@ -74,7 +86,7 @@
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://yourbank.com a million times. RFC 3986 is the
+ https://curl.se or https://example.com a million times. RFC 3986 is the
canonical spec. And yeah, the formal name is not URL, it is URI.
## Host
@@ -169,7 +181,7 @@
any. No limits. You will then get requests repeated over and over for all the
given URLs.
- Example, send two GETs:
+ Example, send two GET requests:
curl http://url1.example.com http://url2.example.com
@@ -292,7 +304,7 @@
Back in late 1995 they defined an additional way to post data over HTTP. It
is documented in the RFC 1867, why this method sometimes is referred to as
- RFC1867-posting.
+ RFC 1867-posting.
This method is mainly designed to better support file uploads. A form that
allows a user to upload a file could be written like this in HTML:
@@ -435,7 +447,7 @@
applications use this information to decide how to display pages. Silly web
programmers try to make different pages for users of different browsers to
make them look the best possible for their particular browsers. They usually
- also do different kinds of JavaScript, VBScript etc.
+ also do different kinds of JavaScript etc.
At times, you will see that getting a page with curl will not return the same
page that you see when getting the page with your browser. Then you know it
@@ -554,9 +566,8 @@
SSL. SSL encrypts all the data that is sent and received over the network and
thus makes it harder for attackers to spy on sensitive information.
- SSL (or TLS as the latest version of the standard is called) offers a
- truckload of advanced features to allow all those encryptions and key
- infrastructure mechanisms encrypted HTTP requires.
+ SSL (or TLS as the current version of the standard is called) offers a set of
+ advanced features to do secure transfers over HTTP.
Curl supports encrypted fetches when built to use a TLS library and it can be
built to use one out of a fairly large set of libraries - `curl -V` will show
@@ -584,7 +595,7 @@
verified.
More about server certificate verification and ca cert bundles can be read in
- the [SSLCERTS document](https://curl.se/docs/sslcerts.html).
+ the [`SSLCERTS` document](https://curl.se/docs/sslcerts.html).
At times you may end up with your own CA cert store and then you can tell
curl to use that to verify the server's certificate:
@@ -598,14 +609,15 @@
Doing fancy stuff, you may need to add or change elements of a single curl
request.
- For example, you can change the POST request to a PROPFIND and send the data
- as `Content-Type: text/xml` (instead of the default Content-Type) like this:
+ For example, you can change the POST method to `PROPFIND` and send the data
+ as `Content-Type: text/xml` (instead of the default `Content-Type`) like
+ this:
curl --data "<xml>" --header "Content-Type: text/xml" \
--request PROPFIND example.com
You can delete a default header by providing one without content. Like you
- can ruin the request by chopping off the Host: header:
+ can ruin the request by chopping off the `Host:` header:
curl --header "Host:" http://www.example.com
diff --git a/docs/URL-SYNTAX.md b/docs/URL-SYNTAX.md
index 0b452f8..384aa4a 100644
--- a/docs/URL-SYNTAX.md
+++ b/docs/URL-SYNTAX.md
@@ -52,7 +52,7 @@
3. Such a URL might use other schemes than you thought of or planned for.
-## "RFC3986 plus"
+## "RFC 3986 plus"
curl recognizes a URL syntax that we call "RFC 3986 plus". It is grounded on
the well established RFC 3986 to make sure previously written command lines and
@@ -259,7 +259,7 @@
imap://user:password@mail.example.com/INBOX
-Select the user's inbox and fetch message with uid = 1:
+Select the user's inbox and fetch message with `uid = 1`:
imap://user:password@mail.example.com/INBOX/;UID=1
@@ -289,26 +289,26 @@
imap://user:password@mail.example.com/INBOX?SUBJECT%20shadows
-Searching via the query part of the URL `?` is a search request for the results
-to be returned as message sequence numbers (MAILINDEX). It is possible to make
-a search request for results to be returned as unique ID numbers (UID) by using
-a custom curl request via `-X`. UID numbers are unique per session (and
-multiple sessions when UIDVALIDITY is the same). For example, if you are
-searching for `"foo bar"` in header+body (TEXT) and you want the matching
-MAILINDEX numbers returned then you could search via URL:
+Searching via the query part of the URL `?` is a search request for the
+results to be returned as message sequence numbers (`MAILINDEX`). It is
+possible to make a search request for results to be returned as unique ID
+numbers (`UID`) by using a custom curl request via `-X`. `UID` numbers are
+unique per session (and multiple sessions when `UIDVALIDITY` is the same). For
+example, if you are searching for `"foo bar"` in header+body (`TEXT`) and you
+want the matching `MAILINDEX` numbers returned then you could search via URL:
imap://user:password@mail.example.com/INBOX?TEXT%20%22foo%20bar%22
-.. but if you wanted matching UID numbers you would have to use a custom request:
+If you want matching `UID` numbers you have to use a custom request:
imap://user:password@mail.example.com/INBOX -X "UID SEARCH TEXT \"foo bar\""
For more information about IMAP commands please see RFC 9051. For more
information about the individual components of an IMAP URL please see RFC 5092.
-* Note old curl versions would FETCH by message sequence number when UID was
-specified in the URL. That was a bug fixed in 7.62.0, which added MAILINDEX to
-FETCH by mail sequence number.
+* Note old curl versions would `FETCH` by message sequence number when `UID`
+was specified in the URL. That was a bug fixed in 7.62.0, which added
+`MAILINDEX` to `FETCH` by mail sequence number.
## LDAP
@@ -317,15 +317,15 @@
separated by a question mark and when that field is not required an empty
string with the question mark separator should be included.
-Search for the DN as `My Organization`:
+Search for the `DN` as `My Organization`:
ldap://ldap.example.com/o=My%20Organization
-the same search but will only return postalAddress attributes:
+the same search but will only return `postalAddress` attributes:
ldap://ldap.example.com/o=My%20Organization?postalAddress
-Search for an empty DN and request information about the
+Search for an empty `DN` and request information about the
`rootDomainNamingContext` attribute for an Active Directory server:
ldap://ldap.example.com/?rootDomainNamingContext
@@ -360,6 +360,9 @@
If the user name is embedded in the URL then it must contain the domain name
and as such, the backslash must be URL encoded as %2f.
+When uploading to SMB, the size of the file needs to be known ahead of time,
+meaning that you can upload a file passed to curl over a pipe like stdin.
+
curl supports SMB version 1 (only)
## SMTP
diff --git a/docs/VERSIONS.md b/docs/VERSIONS.md
index de0b0d4..0ec9cd5 100644
--- a/docs/VERSIONS.md
+++ b/docs/VERSIONS.md
@@ -1,7 +1,7 @@
Version Numbers and Releases
============================
- Curl is not only curl. Curl is also libcurl. they are actually individually
+ Curl is not only curl. Curl is also libcurl. They are actually individually
versioned, but they usually follow each other closely.
The version numbering is always built up using the same system:
@@ -37,7 +37,7 @@
As a service to any application that might want to support new libcurl
features while still being able to build with older versions, all releases
- have the libcurl version stored in the curl/curlver.h file using a static
+ have the libcurl version stored in the `curl/curlver.h` file using a static
numbering scheme that can be used for comparison. The version number is
defined as:
@@ -45,10 +45,10 @@
#define LIBCURL_VERSION_NUM 0xXXYYZZ
```
- Where XX, YY and ZZ are the main version, release and patch numbers in
+ Where `XX`, `YY` and `ZZ` are the main version, release and patch numbers in
hexadecimal. All three number fields are always represented using two digits
(eight bits each). 1.2 would appear as "0x010200" while version 9.11.7
- appears as "0x090b07".
+ appears as `0x090b07`.
This 6-digit hexadecimal number is always a greater number in a more recent
release. It makes comparisons with greater than and less than work.
diff --git a/docs/WEBSOCKET.md b/docs/WEBSOCKET.md
new file mode 100644
index 0000000..ba84c22
--- /dev/null
+++ b/docs/WEBSOCKET.md
@@ -0,0 +1,136 @@
+<!--
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+
+SPDX-License-Identifier: curl
+-->
+
+# WebSocket in curl
+
+## URL
+
+WebSocket communication with libcurl is done by setting up a transfer to a URL
+using the `ws://` or `wss://` URL schemes. The latter one being the secure
+version done over HTTPS.
+
+When using `wss://` to do WebSocket over HTTPS, the standard TLS and HTTPS
+options will be acknowledged for the CA, verification of server certificate
+etc.
+
+WebSocket communication is done by upgrading a connection from either HTTP or
+HTTPS. When given a WebSocket URL to work with, libcurl considers it a
+transfer failure if the upgrade procedure fails. This means that a plain HTTP
+200 response code is considered an error for this work.
+
+## API
+
+The WebSocket API is described in the individual man pages for the new API.
+
+WebSocket with libcurl can be done two ways.
+
+1. Get the WebSocket frames from the server sent to the write callback. You
+ can then respond with `curl_ws_send()` from within the callback (or outside
+ of it).
+
+2. Set `CURLOPT_CONNECT_ONLY` to 2L (new for WebSocket), which makes libcurl
+ do an HTTP GET + `Upgrade:` request plus response in the
+ `curl_easy_perform()` call before it returns and then you can use
+ `curl_ws_recv()` and `curl_ws_send()` to receive and send WebSocket frames
+ from and to the server.
+
+The new options to `curl_easy_setopt()`:
+
+ `CURLOPT_WS_OPTIONS` - to control specific behavior. `CURLWS_RAW_MODE` makes
+ libcurl provide all WebSocket traffic raw in the callback.
+
+The new function calls:
+
+ `curl_ws_recv()` - receive a WebSocket frame
+
+ `curl_ws_send()` - send a WebSocket frame
+
+ `curl_ws_meta()` - return WebSocket metadata within a write callback
+
+## Max frame size
+
+The current implementation only supports frame sizes up to a max (64K right
+now). This is because the API delivers full frames and it then cannot manage
+the full 2^63 bytes size.
+
+If we decide we need to support (much) larger frames than 64K, we need to
+adjust the API accordingly to be able to deliver partial frames in both
+directions.
+
+## Errors
+
+If the given WebSocket URL (using `ws://` or `wss://`) fails to get upgraded
+via a 101 response code and instead gets another response code back from the
+HTTP server - the transfer will return `CURLE_HTTP_RETURNED_ERROR` for that
+transfer. Note then that even 2xx response codes are then considered error
+since it failed to provide a WebSocket transfer.
+
+## Test suite
+
+I looked for an existing small WebSocket server implementation with maximum
+flexibility to dissect and cram into the test suite but I ended up deciding
+that extending the existing test suite server sws to deal with WebSocket
+might be the better way.
+
+- This server is already integrated and working in the test suite
+
+- We want maximum control and ability to generate broken protocol and negative
+ tests as well. A dumber and simpler TCP server could then be easier to
+ massage into this than a "proper" WebSocket server.
+
+## Command line tool WebSocket
+
+The plan is to make curl do WebSocket similar to telnet/nc. That part of the
+work has not been started.
+
+Ideas:
+
+ - Read stdin and send off as messages. Consider newline as end of fragment.
+ (default to text? offer option to set binary)
+ - Respond to PINGs automatically
+ - Issue PINGs at some default interval (option to switch off/change interval?)
+ - Allow `-d` to specify (initial) data to send (should the format allow for
+ multiple separate frames?)
+ - Exit after N messages received, where N can be zero.
+
+## Future work
+
+- Verify the Sec-WebSocket-Accept response. It requires a sha-1 function.
+- Verify Sec-WebSocket-Extensions and Sec-WebSocket-Protocol in the response
+- Make WebSocket work with hyper
+- Consider a `curl_ws_poll()`
+- Make sure WebSocket code paths are fuzzed
+- Add client-side PING interval
+- Provide option to disable PING-PONG automation
+- Support compression (`CURLWS_COMPRESS`)
+
+## Why not libWebSocket
+
+[libWebSocket](https://libWebSockets.org/) is said to be a solid, fast and
+efficient WebSocket library with a vast amount of users. My plan was
+originally to build upon it to skip having to implement the low level parts of
+WebSocket myself.
+
+Here are the reasons why I have decided to move forward with WebSocket in
+curl **without using libWebSocket**:
+
+- doxygen generated docs only makes them hard to navigate. No tutorial, no
+ clearly written explanatory pages for specific functions.
+
+- seems (too) tightly integrated with a specific TLS library, while we want to
+ support WebSocket with whatever TLS library libcurl was already made to
+ work with.
+
+- seems (too) tightly integrated with event libraries
+
+- the references to threads and thread-pools in code and APIs indicate too
+ much logic for our purposes
+
+- "bloated" - it is a *huge* library that is actually more lines of code than
+ libcurl itself
+
+- WebSocket is a fairly simple protocol on the network/framing layer so
+ making a homegrown handling of it should be fine
diff --git a/docs/cmdline-opts/CMakeLists.txt b/docs/cmdline-opts/CMakeLists.txt
index fe7870f..3dd8be4 100644
--- a/docs/cmdline-opts/CMakeLists.txt
+++ b/docs/cmdline-opts/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/docs/cmdline-opts/MANPAGE.md b/docs/cmdline-opts/MANPAGE.md
index e35c826..541d780 100644
--- a/docs/cmdline-opts/MANPAGE.md
+++ b/docs/cmdline-opts/MANPAGE.md
@@ -1,5 +1,5 @@
<!--
- Copyright (C) 2000 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
@@ -23,20 +23,23 @@
### Meta-data
- Short: (single letter, without dash)
- Long: (long form name, without dashes)
- Arg: (the argument the option takes)
- Magic: (description of "magic" options)
- Tags: (space separated list)
- Protocols: (space separated list for which protocols this option works)
Added: (version number in which this was added)
- Mutexed: (space separated list of options this overrides, no dashes)
- Requires: (space separated list of features this requires, no dashes)
- See-also: (space separated list of related options, no dashes)
- Help: (short text for the --help output for this option)
- Example: (example command line, without "curl" and can use `$URL`)
+ Arg: (the argument the option takes)
c: (copyright line)
+ Example: (example command line, without "curl" and can use `$URL`)
+ Experimental: yes (if so)
+ Help: (short text for the --help output for this option)
+ Long: (long form name, without dashes)
+ Magic: (description of "magic" options)
+ Multi: single/append/boolean/mutex/custom (if used more than once)
+ Mutexed: (space separated list of options this overrides, no dashes)
+ Protocols: (space separated list for which protocols this option works)
+ Requires: (space separated list of features this requires, no dashes)
+ Scope: global (if the option is global)
+ See-also: (space separated list of related options, no dashes)
+ Short: (single letter, without dash)
SPDX-License-Identifier: curl
+ Tags: (space separated list)
--- (end of meta-data)
### Body
diff --git a/docs/cmdline-opts/Makefile.am b/docs/cmdline-opts/Makefile.am
index df38e19..5a8996b 100644
--- a/docs/cmdline-opts/Makefile.am
+++ b/docs/cmdline-opts/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -30,8 +30,12 @@
EXTRA_DIST = $(DPAGES) MANPAGE.md gen.pl $(OTHERPAGES) CMakeLists.txt
+GEN = $(GN_$(V))
+GN_0 = @echo " GENERATE" $@;
+GN_1 =
+GN_ = $(GN_0)
+
all: $(MANPAGE)
-$(MANPAGE): $(DPAGES) $(OTHERPAGES) Makefile.inc
- @echo "generate $(MANPAGE)"
- @(cd $(srcdir) && @PERL@ ./gen.pl mainpage $(DPAGES)) > $(MANPAGE)
+$(MANPAGE): $(DPAGES) $(OTHERPAGES) Makefile.inc gen.pl
+ $(GEN)(rm -f $(MANPAGE) && cd $(srcdir) && @PERL@ ./gen.pl mainpage $(DPAGES) > $(builddir)/manpage.tmp && mv $(builddir)/manpage.tmp $(MANPAGE))
diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc
index 350fa9f..d265e53 100644
--- a/docs/cmdline-opts/Makefile.inc
+++ b/docs/cmdline-opts/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -30,6 +30,7 @@
append.d \
aws-sigv4.d \
basic.d \
+ ca-native.d \
cacert.d \
capath.d \
cert-status.d \
@@ -95,6 +96,7 @@
globoff.d \
happy-eyeballs-timeout-ms.d \
haproxy-protocol.d \
+ haproxy-clientip.d \
head.d \
header.d \
help.d \
@@ -107,6 +109,7 @@
http2-prior-knowledge.d \
http2.d \
http3.d \
+ http3-only.d \
ignore-content-length.d \
include.d \
insecure.d \
@@ -169,6 +172,7 @@
proto.d \
proxy-anyauth.d \
proxy-basic.d \
+ proxy-ca-native.d \
proxy-cacert.d \
proxy-capath.d \
proxy-cert-type.d \
@@ -177,6 +181,7 @@
proxy-crlfile.d \
proxy-digest.d \
proxy-header.d \
+ proxy-http2.d \
proxy-insecure.d \
proxy-key-type.d \
proxy-key.d \
@@ -260,11 +265,13 @@
tlsv1.d \
tr-encoding.d \
trace-ascii.d \
+ trace-ids.d \
trace-time.d \
trace.d \
unix-socket.d \
upload-file.d \
url.d \
+ url-query.d \
use-ascii.d \
user-agent.d \
user.d \
diff --git a/docs/cmdline-opts/abstract-unix-socket.d b/docs/cmdline-opts/abstract-unix-socket.d
index 820dd16..5c2fd4a 100644
--- a/docs/cmdline-opts/abstract-unix-socket.d
+++ b/docs/cmdline-opts/abstract-unix-socket.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: abstract-unix-socket
Arg: <path>
@@ -8,6 +8,7 @@
Category: connection
See-also: unix-socket
Example: --abstract-unix-socket socketpath $URL
+Multi: single
---
Connect through an abstract Unix domain socket, instead of using the network.
Note: netstat shows the path of an abstract socket prefixed with '@', however
diff --git a/docs/cmdline-opts/alt-svc.d b/docs/cmdline-opts/alt-svc.d
index c1dcd2b..b505311 100644
--- a/docs/cmdline-opts/alt-svc.d
+++ b/docs/cmdline-opts/alt-svc.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: alt-svc
Arg: <file name>
@@ -8,6 +8,7 @@
Category: http
See-also: resolve connect-to
Example: --alt-svc svc.txt $URL
+Multi: append
---
This option enables the alt-svc parser in curl. If the file name points to an
existing alt-svc cache file, that will be used. After a completed transfer,
diff --git a/docs/cmdline-opts/anyauth.d b/docs/cmdline-opts/anyauth.d
index 8641904..1d0c395 100644
--- a/docs/cmdline-opts/anyauth.d
+++ b/docs/cmdline-opts/anyauth.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: anyauth
Help: Pick any authentication method
@@ -7,6 +7,7 @@
Category: http proxy auth
Example: --anyauth --user me:pwd $URL
Added: 7.10.6
+Multi: mutex
---
Tells curl to figure out authentication method by itself, and use the most
secure one the remote site claims to support. This is done by first doing a
diff --git a/docs/cmdline-opts/append.d b/docs/cmdline-opts/append.d
index e6e6ef2..d478aac 100644
--- a/docs/cmdline-opts/append.d
+++ b/docs/cmdline-opts/append.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: a
Long: append
@@ -8,6 +8,7 @@
See-also: range continue-at
Example: --upload-file local --append ftp://example.com/
Added: 4.8
+Multi: boolean
---
When used in an upload, this makes curl append to the target file instead of
overwriting it. If the remote file does not exist, it will be created. Note
diff --git a/docs/cmdline-opts/aws-sigv4.d b/docs/cmdline-opts/aws-sigv4.d
index 9859722..b771eee 100644
--- a/docs/cmdline-opts/aws-sigv4.d
+++ b/docs/cmdline-opts/aws-sigv4.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: aws-sigv4
Arg: <provider1[:provider2[:region[:service]]]>
@@ -6,7 +6,8 @@
Category: auth http
Added: 7.75.0
See-also: basic user
-Example: --aws-sigv4 "aws:amz:east-2:es" --user "key:secret" $URL
+Example: --aws-sigv4 "aws:amz:us-east-2:es" --user "key:secret" $URL
+Multi: single
---
Use AWS V4 signature authentication in the transfer.
diff --git a/docs/cmdline-opts/basic.d b/docs/cmdline-opts/basic.d
index 4def3cd..cb06426 100644
--- a/docs/cmdline-opts/basic.d
+++ b/docs/cmdline-opts/basic.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: basic
Help: Use HTTP Basic Authentication
@@ -7,6 +7,7 @@
Category: auth
Example: -u name:password --basic $URL
Added: 7.10.6
+Multi: mutex
---
Tells curl to use HTTP Basic authentication with the remote host. This is the
default and this option is usually pointless, unless you use it to override a
diff --git a/docs/cmdline-opts/ca-native.d b/docs/cmdline-opts/ca-native.d
new file mode 100644
index 0000000..30b068a
--- /dev/null
+++ b/docs/cmdline-opts/ca-native.d
@@ -0,0 +1,19 @@
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ca-native
+Help: Use CA certificates from the native OS
+Protocols: TLS
+Category: tls
+See-also: cacert capath insecure
+Example: --ca-native $URL
+Added: 8.2.0
+Multi: boolean
+---
+Tells curl to use the CA store from the native operating system to verify the
+peer. By default, curl will otherwise use a CA store provided in a single file
+or directory, but when using this option it will interface the operating
+system's own vault.
+
+This option only works for curl on Windows when built to use OpenSSL. When
+curl on Windows is built to use Schannel, this feature is implied and curl
+then only uses the native CA store.
diff --git a/docs/cmdline-opts/cacert.d b/docs/cmdline-opts/cacert.d
index f950b6c..97e051c 100644
--- a/docs/cmdline-opts/cacert.d
+++ b/docs/cmdline-opts/cacert.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: cacert
Arg: <file>
@@ -8,6 +8,7 @@
See-also: capath insecure
Example: --cacert CA-file.txt $URL
Added: 7.5
+Multi: single
---
Tells curl to use the specified certificate file to verify the peer. The file
may contain multiple CA certificates. The certificate(s) must be in PEM
@@ -35,5 +36,3 @@
with libcurl 7.60 or later. This option is supported for backward
compatibility with other SSL engines; instead it is recommended to use
Windows' store of root certificates (the default for Schannel).
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/capath.d b/docs/cmdline-opts/capath.d
index f3a2f47..a6753ad 100644
--- a/docs/cmdline-opts/capath.d
+++ b/docs/cmdline-opts/capath.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: capath
Arg: <dir>
@@ -8,14 +8,14 @@
See-also: cacert insecure
Example: --capath /local/directory $URL
Added: 7.9.8
+Multi: single
---
Tells curl to use the specified certificate directory to verify the
peer. Multiple paths can be provided by separating them with ":" (e.g.
-\&"path1:path2:path3"). The certificates must be in PEM format, and if curl is
+"path1:path2:path3"). The certificates must be in PEM format, and if curl is
built against OpenSSL, the directory must have been processed using the
c_rehash utility supplied with OpenSSL. Using --capath can allow
OpenSSL-powered curl to make SSL-connections much more efficiently than using
--cacert if the --cacert file contains many CA certificates.
-If this option is set, the default capath value will be ignored, and if it is
-used several times, the last one will be used.
+If this option is set, the default capath value will be ignored.
diff --git a/docs/cmdline-opts/cert-status.d b/docs/cmdline-opts/cert-status.d
index 73e8252..e8ac156 100644
--- a/docs/cmdline-opts/cert-status.d
+++ b/docs/cmdline-opts/cert-status.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: cert-status
Protocols: TLS
@@ -7,12 +7,13 @@
Category: tls
See-also: pinnedpubkey
Example: --cert-status $URL
+Multi: boolean
---
Tells curl to verify the status of the server certificate by using the
Certificate Status Request (aka. OCSP stapling) TLS extension.
If this option is enabled and the server sends an invalid (e.g. expired)
-response, if the response suggests that the server certificate has been revoked,
-or no response at all is received, the verification fails.
+response, if the response suggests that the server certificate has been
+revoked, or no response at all is received, the verification fails.
This is currently only implemented in the OpenSSL, GnuTLS and NSS backends.
diff --git a/docs/cmdline-opts/cert-type.d b/docs/cmdline-opts/cert-type.d
index 8dd767a..cf9f17b 100644
--- a/docs/cmdline-opts/cert-type.d
+++ b/docs/cmdline-opts/cert-type.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: cert-type
Protocols: TLS
@@ -8,6 +8,7 @@
Category: tls
Example: --cert-type PEM --cert file $URL
Added: 7.9.3
+Multi: single
---
Tells curl what type the provided client certificate is using. PEM, DER, ENG
and P12 are recognized types.
@@ -15,5 +16,3 @@
The default type depends on the TLS backend and is usually PEM, however for
Secure Transport and Schannel it is P12. If --cert is a pkcs11: URI then ENG is
the default type.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/cert.d b/docs/cmdline-opts/cert.d
index 0158023..aad749c 100644
--- a/docs/cmdline-opts/cert.d
+++ b/docs/cmdline-opts/cert.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: E
Long: cert
@@ -9,24 +9,29 @@
Category: tls
Example: --cert certfile --key keyfile $URL
Added: 5.0
+Multi: single
---
Tells curl to use the specified client certificate file when getting a file
with HTTPS, FTPS or another SSL-based protocol. The certificate must be in
PKCS#12 format if using Secure Transport, or PEM format if using any other
engine. If the optional password is not specified, it will be queried for on
-the terminal. Note that this option assumes a \&"certificate" file that is the
-private key and the client certificate concatenated! See --cert and --key to
+the terminal. Note that this option assumes a certificate file that is the
+private key and the client certificate concatenated. See --cert and --key to
specify them independently.
+In the <certificate> portion of the argument, you must escape the character ":"
+as "\\:" so that it is not recognized as the password delimiter. Similarly, you
+must escape the character "\\" as "\\\\" so that it is not recognized as an
+escape character.
+
If curl is built against the NSS SSL library then this option can tell
curl the nickname of the certificate to use within the NSS database defined
by the environment variable SSL_DIR (or by default /etc/pki/nssdb). If the
NSS PEM PKCS#11 module (libnsspem.so) is available then PEM files may be
-loaded. If you want to use a file from the current directory, please precede
-it with "./" prefix, in order to avoid confusion with a nickname. If the
-nickname contains ":", it needs to be preceded by "\\" so that it is not
-recognized as password delimiter. If the nickname contains "\\", it needs to
-be escaped as "\\\\" so that it is not recognized as an escape character.
+loaded.
+
+If you provide a path relative to the current directory, you must prefix the
+path with "./" in order to avoid confusion with an NSS database nickname.
If curl is built against OpenSSL library, and the engine pkcs11 is available,
then a PKCS#11 URI (RFC 7512) can be used to specify a certificate located in
@@ -51,5 +56,3 @@
store locations are supported: CurrentUser, LocalMachine, CurrentService,
Services, CurrentUserGroupPolicy, LocalMachineGroupPolicy,
LocalMachineEnterprise.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/ciphers.d b/docs/cmdline-opts/ciphers.d
index a5bc907..a30902b 100644
--- a/docs/cmdline-opts/ciphers.d
+++ b/docs/cmdline-opts/ciphers.d
@@ -1,17 +1,16 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ciphers
Arg: <list of ciphers>
Help: SSL ciphers to use
Protocols: TLS
Category: tls
-See-also: tlsv1.3
+See-also: tlsv1.3 tls13-ciphers proxy-ciphers
Example: --ciphers ECDHE-ECDSA-AES256-CCM8 $URL
Added: 7.9
+Multi: single
---
Specifies which ciphers to use in the connection. The list of ciphers must
specify valid ciphers. Read up on SSL cipher list details on this URL:
- https://curl.se/docs/ssl-ciphers.html
-
-If this option is used several times, the last one will be used.
+https://curl.se/docs/ssl-ciphers.html
diff --git a/docs/cmdline-opts/compressed-ssh.d b/docs/cmdline-opts/compressed-ssh.d
index 5aa2310..8973956 100644
--- a/docs/cmdline-opts/compressed-ssh.d
+++ b/docs/cmdline-opts/compressed-ssh.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: compressed-ssh
Help: Enable SSH compression
@@ -7,6 +7,7 @@
Category: scp ssh
See-also: compressed
Example: --compressed-ssh sftp://example.com/
+Multi: boolean
---
Enables built-in SSH compression.
This is a request, not an order; the server may or may not do it.
diff --git a/docs/cmdline-opts/compressed.d b/docs/cmdline-opts/compressed.d
index c7e2ff9..7dadf14 100644
--- a/docs/cmdline-opts/compressed.d
+++ b/docs/cmdline-opts/compressed.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: compressed
Help: Request compressed response
@@ -7,9 +7,14 @@
Example: --compressed $URL
See-also: compressed-ssh
Added: 7.10
+Multi: boolean
---
Request a compressed response using one of the algorithms curl supports, and
-automatically decompress the content. Headers are not modified.
+automatically decompress the content.
+
+Response headers are not modified when saved, so if they are "interpreted"
+separately again at a later point they might appear to be saying that the
+content is (still) compressed; while in fact it has already been decompressed.
If this option is used and the server sends an unsupported encoding, curl will
report an error. This is a request, not an order; the server may or may not
diff --git a/docs/cmdline-opts/config.d b/docs/cmdline-opts/config.d
index 5ca71a5..d57579c 100644
--- a/docs/cmdline-opts/config.d
+++ b/docs/cmdline-opts/config.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: config
Arg: <file>
@@ -8,6 +8,7 @@
Example: --config file.txt $URL
Added: 4.10
See-also: disable
+Multi: append
---
Specify a text file to read curl arguments from. The command line arguments
found in the text file will be used as if they were provided on the command
@@ -28,7 +29,8 @@
If the first column of a config line is a '#' character, the rest of the line
will be treated as a comment.
-Only write one option per physical line in the config file.
+Only write one option per physical line in the config file. A single line is
+required to be no more than 10 megabytes (since 8.2.0).
Specify the filename to --config as '-' to make curl read the file from stdin.
@@ -56,7 +58,7 @@
1) "$CURL_HOME/.curlrc"
-2) "$XDG_CONFIG_HOME/.curlrc" (Added in 7.73.0)
+2) "$XDG_CONFIG_HOME/curlrc" (Added in 7.73.0)
3) "$HOME/.curlrc"
@@ -73,5 +75,3 @@
On Windows two filenames are checked per location: .curlrc and _curlrc,
preferring the former. Older versions on Windows checked for _curlrc only.
-
-This option can be used multiple times to load multiple config files.
diff --git a/docs/cmdline-opts/connect-timeout.d b/docs/cmdline-opts/connect-timeout.d
index f33fc48..9636709 100644
--- a/docs/cmdline-opts/connect-timeout.d
+++ b/docs/cmdline-opts/connect-timeout.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: connect-timeout
Arg: <fractional seconds>
@@ -8,10 +8,15 @@
Example: --connect-timeout 20 $URL
Example: --connect-timeout 3.14 $URL
Added: 7.7
+Multi: single
---
Maximum time in seconds that you allow curl's connection to take. This only
limits the connection phase, so if curl connects within the given period it
will continue - if not it will exit. Since version 7.32.0, this option
accepts decimal values.
-If this option is used several times, the last one will be used.
+The "connection phase" is considered complete when the DNS lookup and
+requested TCP, TLS or QUIC handshakes are done.
+
+The decimal value needs to provided using a dot (.) as decimal separator - not
+the local version even if it might be using another separator.
diff --git a/docs/cmdline-opts/connect-to.d b/docs/cmdline-opts/connect-to.d
index eded7ed..95fab91 100644
--- a/docs/cmdline-opts/connect-to.d
+++ b/docs/cmdline-opts/connect-to.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: connect-to
Arg: <HOST1:PORT1:HOST2:PORT2>
@@ -7,6 +7,7 @@
See-also: resolve header
Category: connection
Example: --connect-to example.com:443:example.net:8443 $URL
+Multi: append
---
For a request to the given HOST1:PORT1 pair, connect to HOST2:PORT2 instead.
@@ -21,5 +22,3 @@
A "host" specified to this option is compared as a string, so it needs to
match the name used in request URL. It can be either numerical such as
"127.0.0.1" or the full host name such as "example.org".
-
-This option can be used many times to add many connect rules.
diff --git a/docs/cmdline-opts/continue-at.d b/docs/cmdline-opts/continue-at.d
index 3217f55..9f91c44 100644
--- a/docs/cmdline-opts/continue-at.d
+++ b/docs/cmdline-opts/continue-at.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: C
Long: continue-at
@@ -9,6 +9,7 @@
Example: -C - $URL
Example: -C 400 $URL
Added: 4.8
+Multi: single
---
Continue/Resume a previous file transfer at the given offset. The given offset
is the exact number of bytes that will be skipped, counting from the beginning
@@ -17,5 +18,3 @@
Use "-C -" to tell curl to automatically find out where/how to resume the
transfer. It then uses the given output/input files to figure that out.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/cookie-jar.d b/docs/cmdline-opts/cookie-jar.d
index 3c7759c..08f73fa 100644
--- a/docs/cmdline-opts/cookie-jar.d
+++ b/docs/cmdline-opts/cookie-jar.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: c
Long: cookie-jar
@@ -10,6 +10,7 @@
Example: -c store-here.txt -b read-these $URL
Added: 7.9
See-also: cookie
+Multi: single
---
Specify to which file you want curl to write all cookies after a completed
operation. Curl writes all cookies from its in-memory cookie storage to the
@@ -26,6 +27,3 @@
will not fail or even report an error clearly. Using --verbose will get a
warning displayed, but that is the only visible feedback you get about this
possibly lethal situation.
-
-If this option is used several times, the last specified file name will be
-used.
diff --git a/docs/cmdline-opts/cookie.d b/docs/cmdline-opts/cookie.d
index b05a0c7..1d24714 100644
--- a/docs/cmdline-opts/cookie.d
+++ b/docs/cmdline-opts/cookie.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: b
Long: cookie
@@ -10,6 +10,7 @@
Example: -b cookiefile -c cookiefile $URL
See-also: cookie-jar junk-session-cookies
Added: 4.9
+Multi: append
---
Pass the data to the HTTP server in the Cookie header. It is supposedly the
data previously received from the server in a "Set-Cookie:" line. The data
@@ -36,8 +37,6 @@
domain in Set-Cookie line (doing that will include sub-domains) or preferably:
use the Netscape format.
-This option can be used multiple times.
-
Users often want to both read cookies from a file and write updated cookies
back to a file, so using both --cookie and --cookie-jar in the same command
line is common.
diff --git a/docs/cmdline-opts/create-dirs.d b/docs/cmdline-opts/create-dirs.d
index 211d4bd..8f187b8 100644
--- a/docs/cmdline-opts/create-dirs.d
+++ b/docs/cmdline-opts/create-dirs.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: create-dirs
Help: Create necessary local directory hierarchy
@@ -6,6 +6,7 @@
Example: --create-dirs --output local/dir/file $URL
Added: 7.10.3
See-also: ftp-create-dirs output-dir
+Multi: boolean
---
When used in conjunction with the --output option, curl will create the
necessary local directory hierarchy as needed. This option creates the
diff --git a/docs/cmdline-opts/create-file-mode.d b/docs/cmdline-opts/create-file-mode.d
index c2bb496..c0ebc08 100644
--- a/docs/cmdline-opts/create-file-mode.d
+++ b/docs/cmdline-opts/create-file-mode.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: create-file-mode
Arg: <mode>
@@ -8,11 +8,10 @@
See-also: ftp-create-dirs
Added: 7.75.0
Example: --create-file-mode 0777 -T localfile sftp://example.com/new
+Multi: single
---
When curl is used to create files remotely using one of the supported
protocols, this option allows the user to set which 'mode' to set on the file
at creation time, instead of the default 0644.
This option takes an octal number as argument.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/crlf.d b/docs/cmdline-opts/crlf.d
index f440af6..ed9652c 100644
--- a/docs/cmdline-opts/crlf.d
+++ b/docs/cmdline-opts/crlf.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: crlf
Help: Convert LF to CRLF in upload
@@ -7,6 +7,7 @@
Example: --crlf -T file ftp://example.com/
Added: 5.7
See-also: use-ascii
+Multi: boolean
---
Convert LF to CRLF in upload. Useful for MVS (OS/390).
diff --git a/docs/cmdline-opts/crlfile.d b/docs/cmdline-opts/crlfile.d
index 9f8ee82..da0d239 100644
--- a/docs/cmdline-opts/crlfile.d
+++ b/docs/cmdline-opts/crlfile.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: crlfile
Arg: <file>
@@ -8,8 +8,7 @@
Category: tls
Example: --crlfile rejects.txt $URL
See-also: cacert capath
+Multi: single
---
Provide a file using PEM format with a Certificate Revocation List that may
specify peer certificates that are to be considered revoked.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/curves.d b/docs/cmdline-opts/curves.d
index 2a353be..3fa9c48 100644
--- a/docs/cmdline-opts/curves.d
+++ b/docs/cmdline-opts/curves.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: curves
Arg: <algorithm list>
@@ -8,6 +8,7 @@
Category: tls
Example: --curves X25519 $URL
See-also: ciphers
+Multi: single
---
Tells curl to request specific curves to use during SSL session establishment
according to RFC 8422, 5.1. Multiple algorithms can be provided by separating
diff --git a/docs/cmdline-opts/data-ascii.d b/docs/cmdline-opts/data-ascii.d
index 72887e7..5c7840b 100644
--- a/docs/cmdline-opts/data-ascii.d
+++ b/docs/cmdline-opts/data-ascii.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: data-ascii
Arg: <data>
@@ -8,5 +8,6 @@
Example: --data-ascii @file $URL
Added: 7.2
See-also: data-binary data-raw data-urlencode
+Multi: append
---
This is just an alias for --data.
diff --git a/docs/cmdline-opts/data-binary.d b/docs/cmdline-opts/data-binary.d
index 117a6d8..e966501 100644
--- a/docs/cmdline-opts/data-binary.d
+++ b/docs/cmdline-opts/data-binary.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: data-binary
Arg: <data>
@@ -8,6 +8,7 @@
Example: --data-binary @filename $URL
Added: 7.2
See-also: data-ascii
+Multi: append
---
This posts data exactly as specified with no extra processing whatsoever.
diff --git a/docs/cmdline-opts/data-raw.d b/docs/cmdline-opts/data-raw.d
index 462832b..e6a5a5b 100644
--- a/docs/cmdline-opts/data-raw.d
+++ b/docs/cmdline-opts/data-raw.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: data-raw
Arg: <data>
@@ -9,6 +9,7 @@
Category: http post upload
Example: --data-raw "hello" $URL
Example: --data-raw "@at@at@" $URL
+Multi: append
---
This posts data similarly to --data but without the special
interpretation of the @ character.
diff --git a/docs/cmdline-opts/data-urlencode.d b/docs/cmdline-opts/data-urlencode.d
index 93a2325..c1bc735 100644
--- a/docs/cmdline-opts/data-urlencode.d
+++ b/docs/cmdline-opts/data-urlencode.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: data-urlencode
Arg: <data>
@@ -11,6 +11,7 @@
Example: --data-urlencode =encodethis $URL
Example: --data-urlencode name@file $URL
Example: --data-urlencode @fileonly $URL
+Multi: append
---
This posts data, similar to the other --data options with the exception
that this performs URL-encoding.
@@ -38,3 +39,4 @@
sign appended, resulting in *name=urlencoded-file-content*. Note that the
name is expected to be URL-encoded already.
.RE
+.IP
diff --git a/docs/cmdline-opts/data.d b/docs/cmdline-opts/data.d
index 81db74c..ff8a3b0 100644
--- a/docs/cmdline-opts/data.d
+++ b/docs/cmdline-opts/data.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: data
Short: d
@@ -12,6 +12,7 @@
Example: -d "name=curl" -d "tool=cmdline" $URL
Example: -d @filename $URL
Added: 4.0
+Multi: append
---
Sends the specified data in a POST request to the HTTP server, in the same way
that a browser does when a user has filled in an HTML form and presses the
@@ -25,12 +26,16 @@
If any of these options is used more than once on the same command line, the
data pieces specified will be merged with a separating &-symbol. Thus, using
-\&'-d name=daniel -d skill=lousy' would generate a post chunk that looks like
-\&'name=daniel&skill=lousy'.
+'-d name=daniel -d skill=lousy' would generate a post chunk that looks like
+'name=daniel&skill=lousy'.
If you start the data with the letter @, the rest should be a file name to
read the data from, or - if you want curl to read the data from stdin. Posting
-data from a file named \&'foobar' would thus be done with --data @foobar. When
+data from a file named 'foobar' would thus be done with --data @foobar. When
--data is told to read from a file like that, carriage returns and newlines
will be stripped out. If you do not want the @ character to have a special
interpretation use --data-raw instead.
+
+The data for this option is passed on to the server exactly as provided on the
+command line. curl will not convert it, change it or improve it. It is up to
+the user to provide the data in the correct form.
diff --git a/docs/cmdline-opts/delegation.d b/docs/cmdline-opts/delegation.d
index aa37ceb..7941849 100644
--- a/docs/cmdline-opts/delegation.d
+++ b/docs/cmdline-opts/delegation.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: delegation
Arg: <LEVEL>
@@ -8,6 +8,7 @@
Example: --delegation "none" $URL
Added: 7.22.0
See-also: insecure ssl
+Multi: single
---
Set LEVEL to tell the server what it is allowed to delegate when it
comes to user credentials.
@@ -20,5 +21,4 @@
.IP "always"
Unconditionally allow the server to delegate.
.RE
-
-If this option is used several times, the last one will be used.
+.IP
diff --git a/docs/cmdline-opts/digest.d b/docs/cmdline-opts/digest.d
index ca60c06..f2ee551 100644
--- a/docs/cmdline-opts/digest.d
+++ b/docs/cmdline-opts/digest.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: digest
Help: Use HTTP Digest Authentication
@@ -8,9 +8,8 @@
Category: proxy auth http
Example: -u name:password --digest $URL
Added: 7.10.6
+Multi: boolean
---
Enables HTTP Digest authentication. This is an authentication scheme that
prevents the password from being sent over the wire in clear text. Use this in
combination with the normal --user option to set user name and password.
-
-If this option is used several times, only the first one is used.
diff --git a/docs/cmdline-opts/disable-eprt.d b/docs/cmdline-opts/disable-eprt.d
index 021d215..4863d9d 100644
--- a/docs/cmdline-opts/disable-eprt.d
+++ b/docs/cmdline-opts/disable-eprt.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: disable-eprt
Help: Inhibit using EPRT or LPRT
@@ -7,6 +7,7 @@
Example: --disable-eprt ftp://example.com/
Added: 7.10.5
See-also: disable-epsv ftp-port
+Multi: boolean
---
Tell curl to disable the use of the EPRT and LPRT commands when doing active
FTP transfers. Curl will normally always first attempt to use EPRT, then LPRT
diff --git a/docs/cmdline-opts/disable-epsv.d b/docs/cmdline-opts/disable-epsv.d
index 092b99e..bcc38db 100644
--- a/docs/cmdline-opts/disable-epsv.d
+++ b/docs/cmdline-opts/disable-epsv.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: disable-epsv
Help: Inhibit using EPSV
@@ -7,6 +7,7 @@
Example: --disable-epsv ftp://example.com/
Added: 7.9.2
See-also: disable-eprt ftp-port
+Multi: boolean
---
Tell curl to disable the use of the EPSV command when doing passive FTP
transfers. Curl will normally always first attempt to use EPSV before
diff --git a/docs/cmdline-opts/disable.d b/docs/cmdline-opts/disable.d
index 2577c0f..ea95925 100644
--- a/docs/cmdline-opts/disable.d
+++ b/docs/cmdline-opts/disable.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: disable
Short: q
@@ -7,6 +7,7 @@
Example: -q $URL
Added: 5.0
See-also: config
+Multi: boolean
---
If used as the first parameter on the command line, the *curlrc* config
file will not be read and used. See the --config for details on the default
diff --git a/docs/cmdline-opts/disallow-username-in-url.d b/docs/cmdline-opts/disallow-username-in-url.d
index 0cf6e75..d0537db 100644
--- a/docs/cmdline-opts/disallow-username-in-url.d
+++ b/docs/cmdline-opts/disallow-username-in-url.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: disallow-username-in-url
Help: Disallow username in URL
@@ -7,6 +7,7 @@
See-also: proto
Category: curl http
Example: --disallow-username-in-url $URL
+Multi: boolean
---
This tells curl to exit if passed a URL containing a username. This is probably
most useful when the URL is being provided at runtime or similar.
diff --git a/docs/cmdline-opts/dns-interface.d b/docs/cmdline-opts/dns-interface.d
index 0b07f85..fd924b8 100644
--- a/docs/cmdline-opts/dns-interface.d
+++ b/docs/cmdline-opts/dns-interface.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: dns-interface
Arg: <interface>
@@ -9,6 +9,7 @@
Requires: c-ares
Category: dns
Example: --dns-interface eth0 $URL
+Multi: single
---
Tell curl to send outgoing DNS requests through <interface>. This option is a
counterpart to --interface (which does not affect DNS). The supplied string
diff --git a/docs/cmdline-opts/dns-ipv4-addr.d b/docs/cmdline-opts/dns-ipv4-addr.d
index 31ec563..17caf46 100644
--- a/docs/cmdline-opts/dns-ipv4-addr.d
+++ b/docs/cmdline-opts/dns-ipv4-addr.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: dns-ipv4-addr
Arg: <address>
@@ -9,9 +9,8 @@
Requires: c-ares
Category: dns
Example: --dns-ipv4-addr 10.1.2.3 $URL
+Multi: single
---
Tell curl to bind to <ip-address> when making IPv4 DNS requests, so that
the DNS requests originate from this address. The argument should be a
single IPv4 address.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/dns-ipv6-addr.d b/docs/cmdline-opts/dns-ipv6-addr.d
index 719f4b2..717b347 100644
--- a/docs/cmdline-opts/dns-ipv6-addr.d
+++ b/docs/cmdline-opts/dns-ipv6-addr.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: dns-ipv6-addr
Arg: <address>
@@ -9,9 +9,8 @@
Requires: c-ares
Category: dns
Example: --dns-ipv6-addr 2a04:4e42::561 $URL
+Multi: single
---
Tell curl to bind to <ip-address> when making IPv6 DNS requests, so that
the DNS requests originate from this address. The argument should be a
single IPv6 address.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/dns-servers.d b/docs/cmdline-opts/dns-servers.d
index eea78a7..bec23a3 100644
--- a/docs/cmdline-opts/dns-servers.d
+++ b/docs/cmdline-opts/dns-servers.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: dns-servers
Arg: <addresses>
@@ -8,10 +8,9 @@
Category: dns
Example: --dns-servers 192.168.0.1,192.168.0.2 $URL
See-also: dns-interface dns-ipv4-addr
+Multi: single
---
Set the list of DNS servers to be used instead of the system default.
The list of IP addresses should be separated with commas. Port numbers
may also optionally be given as *:<port-number>* after each IP
address.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/doh-cert-status.d b/docs/cmdline-opts/doh-cert-status.d
index 4d62d68..37ae0f8 100644
--- a/docs/cmdline-opts/doh-cert-status.d
+++ b/docs/cmdline-opts/doh-cert-status.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: doh-cert-status
Help: Verify the status of the DoH server cert via OCSP-staple
@@ -6,5 +6,6 @@
Category: dns tls
Example: --doh-cert-status --doh-url https://doh.example $URL
See-also: doh-insecure
+Multi: boolean
---
Same as --cert-status but used for DoH (DNS-over-HTTPS).
diff --git a/docs/cmdline-opts/doh-insecure.d b/docs/cmdline-opts/doh-insecure.d
index 1b7a593..dcc65fb 100644
--- a/docs/cmdline-opts/doh-insecure.d
+++ b/docs/cmdline-opts/doh-insecure.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: doh-insecure
Help: Allow insecure DoH server connections
@@ -6,5 +6,6 @@
Category: dns tls
Example: --doh-insecure --doh-url https://doh.example $URL
See-also: doh-url
+Multi: boolean
---
Same as --insecure but used for DoH (DNS-over-HTTPS).
diff --git a/docs/cmdline-opts/doh-url.d b/docs/cmdline-opts/doh-url.d
index 94e1a0b..fef7d6a 100644
--- a/docs/cmdline-opts/doh-url.d
+++ b/docs/cmdline-opts/doh-url.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: doh-url
Arg: <URL>
@@ -7,6 +7,7 @@
Category: dns
Example: --doh-url https://doh.example $URL
See-also: doh-insecure
+Multi: single
---
Specifies which DNS-over-HTTPS (DoH) server to use to resolve hostnames,
instead of using the default name resolver mechanism. The URL must be HTTPS.
@@ -16,4 +17,5 @@
settings are not inherited and can be controlled separately via
--doh-insecure and --doh-cert-status.
-If this option is used several times, the last one will be used.
+This option is unset if an empty string "" is used as the URL. (Added in
+7.85.0)
diff --git a/docs/cmdline-opts/dump-header.d b/docs/cmdline-opts/dump-header.d
index 8fc1e2d..657abcd 100644
--- a/docs/cmdline-opts/dump-header.d
+++ b/docs/cmdline-opts/dump-header.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: dump-header
Short: D
@@ -9,6 +9,7 @@
Category: http ftp
Example: --dump-header store.txt $URL
Added: 5.7
+Multi: single
---
Write the received protocol headers to the specified file. If no headers are
received, the use of this option will create an empty file.
@@ -16,4 +17,5 @@
When used in FTP, the FTP server response lines are considered being "headers"
and thus are saved there.
-If this option is used several times, the last one will be used.
+Having multiple transfers in one set of operations (i.e. the URLs in one
+--next clause), will append them to the same file, separated by a blank line.
diff --git a/docs/cmdline-opts/egd-file.d b/docs/cmdline-opts/egd-file.d
index a46a638..8464acd 100644
--- a/docs/cmdline-opts/egd-file.d
+++ b/docs/cmdline-opts/egd-file.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: egd-file
Arg: <file>
@@ -8,6 +8,7 @@
Category: tls
Example: --egd-file /random/here $URL
Added: 7.7
+Multi: single
---
Deprecated option. This option is ignored by curl since 7.84.0. Prior to that
it only had an effect on curl if built to use old versions of OpenSSL.
diff --git a/docs/cmdline-opts/engine.d b/docs/cmdline-opts/engine.d
index 9e193d6..1ebc779 100644
--- a/docs/cmdline-opts/engine.d
+++ b/docs/cmdline-opts/engine.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: engine
Arg: <name>
@@ -8,6 +8,7 @@
Example: --engine flavor $URL
Added: 7.9.3
See-also: ciphers curves
+Multi: single
---
Select the OpenSSL crypto engine to use for cipher operations. Use --engine
list to print a list of build-time supported engines. Note that not all (and
diff --git a/docs/cmdline-opts/etag-compare.d b/docs/cmdline-opts/etag-compare.d
index 598a463..d3c48d1 100644
--- a/docs/cmdline-opts/etag-compare.d
+++ b/docs/cmdline-opts/etag-compare.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: etag-compare
Arg: <file>
@@ -8,6 +8,7 @@
Category: http
Example: --etag-compare etag.txt $URL
See-also: etag-save time-cond
+Multi: single
---
This option makes a conditional HTTP request for the specific ETag read
from the given file by sending a custom If-None-Match header using the
diff --git a/docs/cmdline-opts/etag-save.d b/docs/cmdline-opts/etag-save.d
index 221e90e..6295a9e 100644
--- a/docs/cmdline-opts/etag-save.d
+++ b/docs/cmdline-opts/etag-save.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: etag-save
Arg: <file>
@@ -8,6 +8,7 @@
Category: http
Example: --etag-save storetag.txt $URL
See-also: etag-compare
+Multi: single
---
This option saves an HTTP ETag to the specified file. An ETag is a
caching related header, usually returned in a response.
diff --git a/docs/cmdline-opts/expect100-timeout.d b/docs/cmdline-opts/expect100-timeout.d
index 523bc7a..f681658 100644
--- a/docs/cmdline-opts/expect100-timeout.d
+++ b/docs/cmdline-opts/expect100-timeout.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: expect100-timeout
Arg: <seconds>
@@ -8,8 +8,12 @@
See-also: connect-timeout
Category: http
Example: --expect100-timeout 2.5 -T file $URL
+Multi: single
---
Maximum time in seconds that you allow curl to wait for a 100-continue
response when curl emits an Expects: 100-continue header in its request. By
default curl will wait one second. This option accepts decimal values! When
curl stops waiting, it will continue as if the response has been received.
+
+The decimal value needs to provided using a dot (.) as decimal separator - not
+the local version even if it might be using another separator.
diff --git a/docs/cmdline-opts/fail-early.d b/docs/cmdline-opts/fail-early.d
index c8a78b9..975f346 100644
--- a/docs/cmdline-opts/fail-early.d
+++ b/docs/cmdline-opts/fail-early.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: fail-early
Help: Fail on first transfer error, do not continue
@@ -6,6 +6,8 @@
Category: curl
Example: --fail-early $URL https://two.example
See-also: fail fail-with-body
+Multi: boolean
+Scope: global
---
Fail and exit on the first detected transfer error.
@@ -19,8 +21,6 @@
that fails, independent of the amount of URLs that are given on the command
line. This way, no transfer failures go undetected by scripts and similar.
-This option is global and does not need to be specified for each use of --next.
-
This option does not imply --fail, which causes transfers to fail due to the
server's HTTP status code. You can combine the two options, however note --fail
is not global and is therefore contained by --next.
diff --git a/docs/cmdline-opts/fail-with-body.d b/docs/cmdline-opts/fail-with-body.d
index ff562b1..192b5e8 100644
--- a/docs/cmdline-opts/fail-with-body.d
+++ b/docs/cmdline-opts/fail-with-body.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: fail-with-body
Protocols: HTTP
@@ -6,7 +6,9 @@
Category: http output
Added: 7.76.0
See-also: fail
+Mutexed: fail
Example: --fail-with-body $URL
+Multi: boolean
---
Return an error on server errors where the HTTP response code is 400 or
greater). In normal cases when an HTTP server fails to deliver a document, it
diff --git a/docs/cmdline-opts/fail.d b/docs/cmdline-opts/fail.d
index b9ed63f..d16d110 100644
--- a/docs/cmdline-opts/fail.d
+++ b/docs/cmdline-opts/fail.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: fail
Short: f
@@ -7,7 +7,9 @@
See-also: fail-with-body
Category: important http
Example: --fail $URL
+Mutexed: fail-with-body
Added: 4.0
+Multi: boolean
---
Fail fast with no output at all on server errors. This is useful to enable
scripts and users to better deal with failed attempts. In normal cases when an
diff --git a/docs/cmdline-opts/false-start.d b/docs/cmdline-opts/false-start.d
index 72ff139..599b17a 100644
--- a/docs/cmdline-opts/false-start.d
+++ b/docs/cmdline-opts/false-start.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: false-start
Help: Enable TLS False Start
@@ -7,6 +7,7 @@
Category: tls
Example: --false-start $URL
See-also: tcp-fastopen
+Multi: boolean
---
Tells curl to use false start during the TLS handshake. False start is a mode
where a TLS client will start sending application data before verifying the
diff --git a/docs/cmdline-opts/form-escape.d b/docs/cmdline-opts/form-escape.d
index a3eecde..304bfe8 100644
--- a/docs/cmdline-opts/form-escape.d
+++ b/docs/cmdline-opts/form-escape.d
@@ -1,12 +1,13 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: form-escape
Help: Escape multipart form field/file names using backslash
Protocols: HTTP
See-also: form
Added: 7.81.0
-Category: http post
-Example: --form-escape --form 'field\\name=curl' 'file=@load"this' $URL
+Category: http upload
+Example: --form-escape -F 'field\\name=curl' -F 'file=@load"this' $URL
+Multi: single
---
Tells curl to pass on names of multipart form fields and files using
backslash-escaping instead of percent-encoding.
diff --git a/docs/cmdline-opts/form-string.d b/docs/cmdline-opts/form-string.d
index 0fc2500..32baab0 100644
--- a/docs/cmdline-opts/form-string.d
+++ b/docs/cmdline-opts/form-string.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: form-string
Help: Specify multipart MIME data
@@ -8,9 +8,10 @@
Category: http upload
Example: --form-string "data" $URL
Added: 7.13.2
+Multi: append
---
Similar to --form except that the value string for the named parameter is used
-literally. Leading \&'@' and \&'<' characters, and the \&';type=' string in
+literally. Leading '@' and '<' characters, and the ';type=' string in
the value have no special meaning. Use this in preference to --form if
there's any possibility that the string value may accidentally trigger the
-\&'@' or \&'<' features of --form.
+'@' or '<' features of --form.
diff --git a/docs/cmdline-opts/form.d b/docs/cmdline-opts/form.d
index f48c878..cf8366d 100644
--- a/docs/cmdline-opts/form.d
+++ b/docs/cmdline-opts/form.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: form
Short: F
@@ -10,6 +10,7 @@
Example: --form "name=curl" --form "file=@loadthis" $URL
Added: 5.0
See-also: data form-string form-escape
+Multi: append
---
For HTTP protocol family, this lets curl emulate a filled-in form in which a
user has pressed the submit button. This causes curl to POST data using the
@@ -34,7 +35,7 @@
before the transfer starts, such data is sent as chunks by HTTP and rejected
by IMAP.
-Example: send an image to an HTTP server, where \&'profile' is the name of the
+Example: send an image to an HTTP server, where 'profile' is the name of the
form-field to which the file portrait.jpg will be the input:
curl -F profile=@portrait.jpg https://example.com/upload.cgi
@@ -132,5 +133,3 @@
-F '=@localfile;encoder=base64' ... smtp://example.com
See further examples and details in the MANUAL.
-
-This option can be used multiple times.
diff --git a/docs/cmdline-opts/ftp-account.d b/docs/cmdline-opts/ftp-account.d
index 97be878..eb669c5 100644
--- a/docs/cmdline-opts/ftp-account.d
+++ b/docs/cmdline-opts/ftp-account.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ftp-account
Arg: <data>
@@ -8,8 +8,7 @@
Category: ftp auth
Example: --ftp-account "mr.robot" ftp://example.com/
See-also: user
+Multi: single
---
When an FTP server asks for "account data" after user name and password has
been provided, this data is sent off using the ACCT command.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/ftp-alternative-to-user.d b/docs/cmdline-opts/ftp-alternative-to-user.d
index 132ef07..06f29fc 100644
--- a/docs/cmdline-opts/ftp-alternative-to-user.d
+++ b/docs/cmdline-opts/ftp-alternative-to-user.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ftp-alternative-to-user
Arg: <command>
@@ -8,6 +8,7 @@
Category: ftp
Example: --ftp-alternative-to-user "U53r" ftp://example.com
See-also: ftp-account user
+Multi: single
---
If authenticating with the USER and PASS commands fails, send this command.
When connecting to Tumbleweed's Secure Transport server over FTPS using a
diff --git a/docs/cmdline-opts/ftp-create-dirs.d b/docs/cmdline-opts/ftp-create-dirs.d
index de61bbe..03f340c 100644
--- a/docs/cmdline-opts/ftp-create-dirs.d
+++ b/docs/cmdline-opts/ftp-create-dirs.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ftp-create-dirs
Protocols: FTP SFTP
@@ -7,6 +7,7 @@
Category: ftp sftp curl
Example: --ftp-create-dirs -T file ftp://example.com/remote/path/file
Added: 7.10.7
+Multi: boolean
---
When an FTP or SFTP URL/operation uses a path that does not currently exist on
the server, the standard behavior of curl is to fail. Using this option, curl
diff --git a/docs/cmdline-opts/ftp-method.d b/docs/cmdline-opts/ftp-method.d
index 117ab07..212e1ca 100644
--- a/docs/cmdline-opts/ftp-method.d
+++ b/docs/cmdline-opts/ftp-method.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ftp-method
Arg: <method>
@@ -10,6 +10,7 @@
Example: --ftp-method nocwd ftp://example.com/dir1/dir2/file
Example: --ftp-method singlecwd ftp://example.com/dir1/dir2/file
See-also: list-only
+Multi: single
---
Control what method curl should use to reach a file on an FTP(S)
server. The method argument should be one of the following alternatives:
@@ -23,6 +24,7 @@
path to the server for all these commands. This is the fastest behavior.
.IP singlecwd
curl does one CWD with the full target directory and then operates on the file
-\&"normally" (like in the multicwd case). This is somewhat more standards
+"normally" (like in the multicwd case). This is somewhat more standards
compliant than 'nocwd' but without the full penalty of 'multicwd'.
.RE
+.IP
diff --git a/docs/cmdline-opts/ftp-pasv.d b/docs/cmdline-opts/ftp-pasv.d
index a38fe0e..599493b 100644
--- a/docs/cmdline-opts/ftp-pasv.d
+++ b/docs/cmdline-opts/ftp-pasv.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ftp-pasv
Help: Use PASV/EPSV instead of PORT
@@ -7,14 +7,14 @@
See-also: disable-epsv
Category: ftp
Example: --ftp-pasv ftp://example.com/
+Multi: boolean
---
Use passive mode for the data connection. Passive is the internal default
behavior, but using this option can be used to override a previous --ftp-port
option.
-If this option is used several times, only the first one is used. Undoing an
-enforced passive really is not doable but you must then instead enforce the
-correct --ftp-port again.
+Reversing an enforced passive really is not doable but you must then instead
+enforce the correct --ftp-port again.
Passive mode means that curl will try the EPSV command first and then PASV,
unless --disable-epsv is used.
diff --git a/docs/cmdline-opts/ftp-port.d b/docs/cmdline-opts/ftp-port.d
index 1755538..e1f4a1d 100644
--- a/docs/cmdline-opts/ftp-port.d
+++ b/docs/cmdline-opts/ftp-port.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ftp-port
Arg: <address>
@@ -11,6 +11,7 @@
Example: -P eth0 ftp:/example.com
Example: -P 192.168.0.2 ftp:/example.com
Added: 4.0
+Multi: single
---
Reverses the default initiator/listener roles when connecting with FTP. This
option makes curl use active mode. curl then tells the server to connect back
@@ -28,12 +29,12 @@
make curl pick the same IP address that is already used for the control
connection
.RE
+.IP
-If this option is used several times, the last one will be used. Disable the
-use of PORT with --ftp-pasv. Disable the attempt to use the EPRT command
-instead of PORT by using --disable-eprt. EPRT is really PORT++.
+Disable the use of PORT with --ftp-pasv. Disable the attempt to use the EPRT
+command instead of PORT by using --disable-eprt. EPRT is really PORT++.
-You can also append \&":[start]-[end]\&" to the right of the address, to tell
+You can also append ":[start]-[end]\&" to the right of the address, to tell
curl what TCP port range to use. That means you specify a port range, from a
lower to a higher number. A single number works as well, but do note that it
increases the risk of failure since the port may not be available.
diff --git a/docs/cmdline-opts/ftp-pret.d b/docs/cmdline-opts/ftp-pret.d
index 16053f6..4bea99e 100644
--- a/docs/cmdline-opts/ftp-pret.d
+++ b/docs/cmdline-opts/ftp-pret.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ftp-pret
Help: Send PRET before PASV
@@ -7,6 +7,7 @@
Category: ftp
Example: --ftp-pret ftp://example.com/
See-also: ftp-port ftp-pasv
+Multi: boolean
---
Tell curl to send a PRET command before PASV (and EPSV). Certain FTP servers,
mainly drftpd, require this non-standard command for directory listings as
diff --git a/docs/cmdline-opts/ftp-skip-pasv-ip.d b/docs/cmdline-opts/ftp-skip-pasv-ip.d
index 89e7e57..4b38f9f 100644
--- a/docs/cmdline-opts/ftp-skip-pasv-ip.d
+++ b/docs/cmdline-opts/ftp-skip-pasv-ip.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ftp-skip-pasv-ip
Help: Skip the IP address for PASV
@@ -7,6 +7,7 @@
See-also: ftp-pasv
Category: ftp
Example: --ftp-skip-pasv-ip ftp://example.com/
+Multi: boolean
---
Tell curl to not use the IP address the server suggests in its response
to curl's PASV command when curl connects the data connection. Instead curl
diff --git a/docs/cmdline-opts/ftp-ssl-ccc-mode.d b/docs/cmdline-opts/ftp-ssl-ccc-mode.d
index 39f5ad5..6f446e6 100644
--- a/docs/cmdline-opts/ftp-ssl-ccc-mode.d
+++ b/docs/cmdline-opts/ftp-ssl-ccc-mode.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ftp-ssl-ccc-mode
Arg: <active/passive>
@@ -8,6 +8,7 @@
See-also: ftp-ssl-ccc
Category: ftp tls
Example: --ftp-ssl-ccc-mode active --ftp-ssl-ccc ftps://example.com/
+Multi: boolean
---
Sets the CCC mode. The passive mode will not initiate the shutdown, but
instead wait for the server to do it, and will not reply to the shutdown from
diff --git a/docs/cmdline-opts/ftp-ssl-ccc.d b/docs/cmdline-opts/ftp-ssl-ccc.d
index ab1d49b..6b7d61f 100644
--- a/docs/cmdline-opts/ftp-ssl-ccc.d
+++ b/docs/cmdline-opts/ftp-ssl-ccc.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ftp-ssl-ccc
Help: Send CCC after authenticating
@@ -7,6 +7,7 @@
Added: 7.16.1
Category: ftp tls
Example: --ftp-ssl-ccc ftps://example.com/
+Multi: boolean
---
Use CCC (Clear Command Channel) Shuts down the SSL/TLS layer after
authenticating. The rest of the control channel communication will be
diff --git a/docs/cmdline-opts/ftp-ssl-control.d b/docs/cmdline-opts/ftp-ssl-control.d
index b531d7a..b895779 100644
--- a/docs/cmdline-opts/ftp-ssl-control.d
+++ b/docs/cmdline-opts/ftp-ssl-control.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ftp-ssl-control
Help: Require SSL/TLS for FTP login, clear for transfer
@@ -7,6 +7,7 @@
Category: ftp tls
Example: --ftp-ssl-control ftp://example.com
See-also: ssl
+Multi: boolean
---
Require SSL/TLS for the FTP login, clear for transfer. Allows secure
authentication, but non-encrypted data transfers for efficiency. Fails the
diff --git a/docs/cmdline-opts/gen.pl b/docs/cmdline-opts/gen.pl
index e69dd99..db68d31 100755
--- a/docs/cmdline-opts/gen.pl
+++ b/docs/cmdline-opts/gen.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -51,6 +51,7 @@
my $date = strftime "%B %d %Y", localtime;
my $year = strftime "%Y", localtime;
my $version = "unknown";
+my $globals;
open(INC, "<../../include/curl/curlver.h");
while(<INC>) {
@@ -103,17 +104,25 @@
print ".fi\n"; # fill-in
}
# skip lines starting with space (examples)
- if($d =~ /^[^ ]/) {
- for my $k (keys %optlong) {
+ if($d =~ /^[^ ]/ && $d =~ /--/) {
+ # scan for options in longest-names first order
+ for my $k (sort {length($b) <=> length($a)} keys %optlong) {
+ # --tlsv1 is complicated since --tlsv1.2 etc are also
+ # acceptable options!
+ if(($k eq "tlsv1") && ($d =~ /--tlsv1\.[0-9]\\f/)) {
+ next;
+ }
my $l = manpageify($k);
- $d =~ s/--$k([^a-z0-9_-])(\W)/$l$1$2/;
+ $d =~ s/\-\-$k([^a-z0-9-])/$l$1/g;
}
}
# quote "bare" minuses in the output
$d =~ s/( |\\fI|^)--/$1\\-\\-/g;
$d =~ s/([ -]|\\fI|^)-/$1\\-/g;
# handle single quotes first on the line
- $d =~ s/(\s*)\'/$1\\(aq/;
+ $d =~ s/^(\s*)\'/$1\\(aq/;
+ # handle double quotes first on the line
+ $d =~ s/^(\s*)\"/$1\\(dq/;
print $d;
}
if($exam) {
@@ -202,6 +211,9 @@
my @examples; # there can be more than one
my $magic; # cmdline special option
my $line;
+ my $multi;
+ my $scope;
+ my $experimental;
while(<F>) {
$line++;
if(/^Short: *(.)/i) {
@@ -229,6 +241,10 @@
$protocols=$1;
}
elsif(/^See-also: *(.*)/i) {
+ if($seealso) {
+ print STDERR "ERROR: duplicated See-also in $f\n";
+ return 1;
+ }
$seealso=$1;
}
elsif(/^Requires: *(.*)/i) {
@@ -240,6 +256,15 @@
elsif(/^Example: *(.*)/i) {
push @examples, $1;
}
+ elsif(/^Multi: *(.*)/i) {
+ $multi=$1;
+ }
+ elsif(/^Scope: *(.*)/i) {
+ $scope=$1;
+ }
+ elsif(/^Experimental: yes/i) {
+ $experimental=1;
+ }
elsif(/^C: (.*)/i) {
$copyright=$1;
}
@@ -324,9 +349,57 @@
print ".SH DESCRIPTION\n";
}
+ if($experimental) {
+ print "**WARNING**: this option is experimental. Do not use in production.\n\n";
+ }
+
printdesc(@desc);
undef @desc;
+ if($scope) {
+ if($scope eq "global") {
+ print "\nThis option is global and does not need to be specified for each use of --next.\n";
+ }
+ else {
+ print STDERR "$f:$line:1:ERROR: unrecognized scope: '$scope'\n";
+ return 2;
+ }
+ }
+
+ my @extra;
+ if($multi eq "single") {
+ push @extra, "\nIf --$long is provided several times, the last set ".
+ "value will be used.\n";
+ }
+ elsif($multi eq "append") {
+ push @extra, "\n--$long can be used several times in a command line\n";
+ }
+ elsif($multi eq "boolean") {
+ my $rev = "no-$long";
+ # for options that start with "no-" the reverse is then without
+ # the no- prefix
+ if($long =~ /^no-/) {
+ $rev = $long;
+ $rev =~ s/^no-//;
+ }
+ push @extra,
+ "\nProviding --$long multiple times has no extra effect.\n".
+ "Disable it again with --$rev.\n";
+ }
+ elsif($multi eq "mutex") {
+ push @extra,
+ "\nProviding --$long multiple times has no extra effect.\n";
+ }
+ elsif($multi eq "custom") {
+ ; # left for the text to describe
+ }
+ else {
+ print STDERR "$f:$line:1:ERROR: unrecognized Multi: '$multi'\n";
+ return 2;
+ }
+
+ printdesc(@extra);
+
my @foot;
if($seealso) {
my @m=split(/ /, $seealso);
@@ -352,6 +425,7 @@
}
push @foot, seealso($standalone, $mstr);
}
+
if($requires) {
my $l = manpageify($long);
push @foot, "$l requires that the underlying libcurl".
@@ -451,6 +525,7 @@
while(<F>) {
s/%DATE/$date/g;
s/%VERSION/$version/g;
+ s/%GLOBALS/$globals/g;
push @d, $_;
}
close(F);
@@ -466,7 +541,7 @@
* | (__| |_| | _ <| |___
* \\___|\\___/|_| \\_\\_____|
*
- * Copyright (C) 1998 - $year, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel\@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -500,7 +575,7 @@
my $long = $f;
my $short = $optlong{$long};
my @categories = split ' ', $catlong{$long};
- my $bitmask;
+ my $bitmask = ' ';
my $opt;
if(defined($short) && $long) {
@@ -516,6 +591,7 @@
$bitmask .= ' | ';
}
}
+ $bitmask =~ s/(?=.{76}).{1,76}\|/$&\n /g;
my $arg = $arglong{$long};
if($arg) {
$opt .= " $arg";
@@ -523,7 +599,7 @@
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";
@@ -559,6 +635,36 @@
}
}
+sub listglobals {
+ my (@files) = @_;
+ my @globalopts;
+
+ # Find all global options and output them
+ foreach my $f (sort @files) {
+ open(F, "<:crlf", "$f") ||
+ next;
+ my $long;
+ while(<F>) {
+ if(/^Long: *(.*)/i) {
+ $long=$1;
+ }
+ elsif(/^Scope: global/i) {
+ push @globalopts, $long;
+ last;
+ }
+ elsif(/^---/) {
+ last;
+ }
+ }
+ close(F);
+ }
+ return $ret if($ret);
+ for my $e (0 .. $#globalopts) {
+ $globals .= sprintf "%s--%s", $e?($globalopts[$e+1] ? ", " : " and "):"",
+ $globalopts[$e],;
+ }
+}
+
sub mainpage {
my (@files) = @_;
my $ret;
@@ -570,7 +676,9 @@
$ret += single($f, 0);
}
- header("page-footer");
+ if(!$ret) {
+ header("page-footer");
+ }
exit $ret if($ret);
}
@@ -597,6 +705,7 @@
sub getargs {
my ($f, @s) = @_;
if($f eq "mainpage") {
+ listglobals(@s);
mainpage(@s);
return;
}
diff --git a/docs/cmdline-opts/get.d b/docs/cmdline-opts/get.d
index 3e3d680..8b34d10 100644
--- a/docs/cmdline-opts/get.d
+++ b/docs/cmdline-opts/get.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: get
Short: G
@@ -9,6 +9,7 @@
Example: --get -I -d "tool=curl" $URL
Added: 7.8.1
See-also: data request
+Multi: boolean
---
When used, this option will make all data specified with --data, --data-binary
or --data-urlencode to be used in an HTTP GET request instead of the POST
@@ -17,7 +18,3 @@
If used in combination with --head, the POST data will instead be appended to
the URL with a HEAD request.
-
-If this option is used several times, only the first one is used. This is
-because undoing a GET does not make sense, but you should then instead enforce
-the alternative method you prefer.
diff --git a/docs/cmdline-opts/globoff.d b/docs/cmdline-opts/globoff.d
index bf22f32..53bed6e 100644
--- a/docs/cmdline-opts/globoff.d
+++ b/docs/cmdline-opts/globoff.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: globoff
Short: g
@@ -7,6 +7,7 @@
Example: -g "https://example.com/{[]}}}}"
Added: 7.6
See-also: config disable
+Multi: boolean
---
This option switches off the "URL globbing parser". When you set this option,
you can specify URLs that contain the letters {}[] without having curl itself
diff --git a/docs/cmdline-opts/happy-eyeballs-timeout-ms.d b/docs/cmdline-opts/happy-eyeballs-timeout-ms.d
index d631cbe..29114e2 100644
--- a/docs/cmdline-opts/happy-eyeballs-timeout-ms.d
+++ b/docs/cmdline-opts/happy-eyeballs-timeout-ms.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: happy-eyeballs-timeout-ms
Arg: <milliseconds>
@@ -7,6 +7,7 @@
Category: connection
Example: --happy-eyeballs-timeout-ms 500 $URL
See-also: max-time connect-timeout
+Multi: single
---
Happy Eyeballs is an algorithm that attempts to connect to both IPv4 and IPv6
addresses for dual-stack hosts, giving IPv6 a head-start of the specified
@@ -18,5 +19,3 @@
"It is RECOMMENDED that connection attempts be paced 150-250 ms apart to
balance human factors against network load." libcurl currently defaults to
200 ms. Firefox and Chrome currently default to 300 ms.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/haproxy-clientip.d b/docs/cmdline-opts/haproxy-clientip.d
new file mode 100644
index 0000000..22eda07
--- /dev/null
+++ b/docs/cmdline-opts/haproxy-clientip.d
@@ -0,0 +1,29 @@
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: haproxy-clientip
+Help: Sets client IP in HAProxy PROXY protocol v1 header
+Protocols: HTTP
+Added: 8.2.0
+Category: http proxy
+Example: --haproxy-clientip $IP
+See-also: proxy
+Multi: single
+---
+Sets a client IP in HAProxy PROXY protocol v1 header at the beginning of the
+connection.
+
+For valid requests, IPv4 addresses must be indicated as a series of exactly
+4 integers in the range [0..255] inclusive written in decimal representation
+separated by exactly one dot between each other. Heading zeroes are not
+permitted in front of numbers in order to avoid any possible confusion
+with octal numbers. IPv6 addresses must be indicated as series of 4 hexadecimal
+digits (upper or lower case) delimited by colons between each other, with the
+acceptance of one double colon sequence to replace the largest acceptable range
+of consecutive zeroes. The total number of decoded bits must exactly be 128.
+
+Otherwise, any string can be accepted for the client IP and will be sent.
+
+It replaces `--haproxy-protocol` if used, it is not necessary to specify both flags.
+
+This option is primarily useful when sending test requests to
+verify a service is working as intended.
diff --git a/docs/cmdline-opts/haproxy-protocol.d b/docs/cmdline-opts/haproxy-protocol.d
index ed8b49f..3411906 100644
--- a/docs/cmdline-opts/haproxy-protocol.d
+++ b/docs/cmdline-opts/haproxy-protocol.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: haproxy-protocol
Help: Send HAProxy PROXY protocol v1 header
@@ -7,6 +7,7 @@
Category: http proxy
Example: --haproxy-protocol $URL
See-also: proxy
+Multi: boolean
---
Send a HAProxy PROXY protocol v1 header at the beginning of the
connection. This is used by some load balancers and reverse proxies to
diff --git a/docs/cmdline-opts/head.d b/docs/cmdline-opts/head.d
index 56fbf7b..bb748b7 100644
--- a/docs/cmdline-opts/head.d
+++ b/docs/cmdline-opts/head.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: head
Short: I
@@ -8,6 +8,7 @@
Example: -I $URL
Added: 4.0
See-also: get verbose trace-ascii
+Multi: boolean
---
Fetch the headers only! HTTP-servers feature the command HEAD which this uses
to get nothing but the header of a document. When used on an FTP or FILE file,
diff --git a/docs/cmdline-opts/header.d b/docs/cmdline-opts/header.d
index a427145..2a95c52 100644
--- a/docs/cmdline-opts/header.d
+++ b/docs/cmdline-opts/header.d
@@ -1,27 +1,35 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: header
Short: H
Arg: <header/@file>
Help: Pass custom header(s) to server
-Protocols: HTTP
-Category: http
+Protocols: HTTP IMAP SMTP
+Category: http imap smtp
See-also: user-agent referer
Example: -H "X-First-Name: Joe" $URL
Example: -H "User-Agent: yes-please/2000" $URL
Example: -H "Host:" $URL
+Example: -H @headers.txt $URL
Added: 5.0
+Multi: append
---
-Extra header to include in the request when sending HTTP to a server. You may
-specify any number of extra headers. Note that if you should add a custom
-header that has the same name as one of the internal ones curl would use, your
-externally set header will be used instead of the internal one. This allows
-you to make even trickier stuff than curl would normally do. You should not
-replace internally set headers without knowing perfectly well what you are
-doing. Remove an internal header by giving a replacement without content on
-the right side of the colon, as in: -H \&"Host:". If you send the custom
-header with no-value then its header must be terminated with a semicolon, such
-as \-H \&"X-Custom-Header;" to send "X-Custom-Header:".
+Extra header to include in information sent. When used within an HTTP request,
+it is added to the regular request headers.
+
+For an IMAP or SMTP MIME uploaded mail built with --form options, it is
+prepended to the resulting MIME document, effectively including it at the mail
+global level. It does not affect raw uploaded mails (Added in 7.56.0).
+
+You may specify any number of extra headers. Note that if you should add a
+custom header that has the same name as one of the internal ones curl would
+use, your externally set header will be used instead of the internal one.
+This allows you to make even trickier stuff than curl would normally do. You
+should not replace internally set headers without knowing perfectly well what
+you are doing. Remove an internal header by giving a replacement without
+content on the right side of the colon, as in: -H "Host:". If you send the
+custom header with no-value then its header must be terminated with a
+semicolon, such as \-H "X-Custom-Header;" to send "X-Custom-Header:".
curl will make sure that each header you add/replace is sent with the proper
end-of-line marker, you should thus **not** add that as a part of the header
@@ -32,15 +40,18 @@
for each line in the input file. Using @- will make curl read the header file
from stdin. Added in 7.55.0.
+Please note that most anti-spam utilities check the presence and value of
+several MIME mail headers: these are "From:", "To:", "Date:" and "Subject:"
+among others and should be added with this option.
+
You need --proxy-header to send custom headers intended for an HTTP
proxy. Added in 7.37.0.
Passing on a "Transfer-Encoding: chunked" header when doing an HTTP request
with a request body, will make curl send the data using chunked encoding.
-**WARNING**: headers set with this option will be set in all requests - even
-after redirects are followed, like when told with --location. This can lead to
-the header being sent to other hosts than the original host, so sensitive
-headers should be used with caution combined with following redirects.
-
-This option can be used multiple times to add/replace/remove multiple headers.
+**WARNING**: headers set with this option will be set in all HTTP requests
+- even after redirects are followed, like when told with --location. This can
+lead to the header being sent to other hosts than the original host, so
+sensitive headers should be used with caution combined with following
+redirects.
diff --git a/docs/cmdline-opts/help.d b/docs/cmdline-opts/help.d
index d1a794d..6c69dd4 100644
--- a/docs/cmdline-opts/help.d
+++ b/docs/cmdline-opts/help.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: help
Arg: <category>
@@ -8,6 +8,7 @@
Example: --help all
Added: 4.0
See-also: verbose
+Multi: custom
---
Usage help. This lists all commands of the <category>.
If no arg was provided, curl will display the most important
diff --git a/docs/cmdline-opts/hostpubmd5.d b/docs/cmdline-opts/hostpubmd5.d
index f0fd994..391b896 100644
--- a/docs/cmdline-opts/hostpubmd5.d
+++ b/docs/cmdline-opts/hostpubmd5.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: hostpubmd5
Arg: <md5>
@@ -8,6 +8,7 @@
Category: sftp scp
Example: --hostpubmd5 e5c1c49020640a5ab0f2034854c321a8 sftp://example.com/
See-also: hostpubsha256
+Multi: single
---
Pass a string containing 32 hexadecimal digits. The string should
be the 128 bit MD5 checksum of the remote host's public key, curl will refuse
diff --git a/docs/cmdline-opts/hostpubsha256.d b/docs/cmdline-opts/hostpubsha256.d
index 6742ba5..ba33318 100644
--- a/docs/cmdline-opts/hostpubsha256.d
+++ b/docs/cmdline-opts/hostpubsha256.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: hostpubsha256
Arg: <sha256>
@@ -8,7 +8,11 @@
Category: sftp scp
Example: --hostpubsha256 NDVkMTQxMGQ1ODdmMjQ3MjczYjAyOTY5MmRkMjVmNDQ= sftp://example.com/
See-also: hostpubmd5
+Multi: single
---
Pass a string containing a Base64-encoded SHA256 hash of the remote
host's public key. Curl will refuse the connection with the host
unless the hashes match.
+
+This feature requires libcurl to be built with libssh2 and does not work with
+other SSH backends.
diff --git a/docs/cmdline-opts/hsts.d b/docs/cmdline-opts/hsts.d
index 1b3fced..173ed0a 100644
--- a/docs/cmdline-opts/hsts.d
+++ b/docs/cmdline-opts/hsts.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: hsts
Arg: <file name>
@@ -8,11 +8,17 @@
Category: http
Example: --hsts cache.txt $URL
See-also: proto
+Multi: append
---
This option enables HSTS for the transfer. If the file name points to an
existing HSTS cache file, that will be used. After a completed transfer, the
cache will be saved to the file name again if it has been modified.
+If curl is told to use HTTP:// for a transfer involving a host name that
+exists in the HSTS cache, it upgrades the transfer to use HTTPS. Each HSTS
+cache entry has an individual life time after which the upgrade is no longer
+performed.
+
Specify a "" file name (zero length) to avoid loading/saving and make curl
just handle HSTS in memory.
diff --git a/docs/cmdline-opts/http0.9.d b/docs/cmdline-opts/http0.9.d
index 028a43f..a0b4e9f 100644
--- a/docs/cmdline-opts/http0.9.d
+++ b/docs/cmdline-opts/http0.9.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: http0.9
Tags: Versions
@@ -8,6 +8,7 @@
Example: --http0.9 $URL
Added: 7.64.0
See-also: http1.1 http2 http3
+Multi: boolean
---
Tells curl to be fine with HTTP version 0.9 response.
diff --git a/docs/cmdline-opts/http1.0.d b/docs/cmdline-opts/http1.0.d
index 1a8c96a..c5f4de8 100644
--- a/docs/cmdline-opts/http1.0.d
+++ b/docs/cmdline-opts/http1.0.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: 0
Long: http1.0
@@ -10,6 +10,7 @@
Category: http
Example: --http1.0 $URL
See-also: http0.9 http1.1
+Multi: mutex
---
Tells curl to use HTTP version 1.0 instead of using its internally preferred
HTTP version.
diff --git a/docs/cmdline-opts/http1.1.d b/docs/cmdline-opts/http1.1.d
index a4f0468..3057aed 100644
--- a/docs/cmdline-opts/http1.1.d
+++ b/docs/cmdline-opts/http1.1.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: http1.1
Tags: Versions
@@ -9,5 +9,6 @@
Category: http
Example: --http1.1 $URL
See-also: http1.0 http0.9
+Multi: mutex
---
Tells curl to use HTTP version 1.1.
diff --git a/docs/cmdline-opts/http2-prior-knowledge.d b/docs/cmdline-opts/http2-prior-knowledge.d
index 77d2d5d..8224e80 100644
--- a/docs/cmdline-opts/http2-prior-knowledge.d
+++ b/docs/cmdline-opts/http2-prior-knowledge.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: http2-prior-knowledge
Tags: Versions
@@ -10,6 +10,7 @@
Category: http
Example: --http2-prior-knowledge $URL
See-also: http2 http3
+Multi: boolean
---
Tells curl to issue its non-TLS HTTP requests using HTTP/2 without HTTP/1.1
Upgrade. It requires prior knowledge that the server supports HTTP/2 straight
diff --git a/docs/cmdline-opts/http2.d b/docs/cmdline-opts/http2.d
index 988cba5..17264b0 100644
--- a/docs/cmdline-opts/http2.d
+++ b/docs/cmdline-opts/http2.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: http2
Tags: Versions
@@ -6,11 +6,11 @@
Added: 7.33.0
Mutexed: http1.1 http1.0 http2-prior-knowledge http3
Requires: HTTP/2
-See-also: no-alpn
-Help: Use HTTP 2
-See-also: http1.1 http3
+Help: Use HTTP/2
+See-also: http1.1 http3 no-alpn
Category: http
Example: --http2 $URL
+Multi: mutex
---
Tells curl to use HTTP version 2.
diff --git a/docs/cmdline-opts/http3-only.d b/docs/cmdline-opts/http3-only.d
new file mode 100644
index 0000000..a1d7db9
--- /dev/null
+++ b/docs/cmdline-opts/http3-only.d
@@ -0,0 +1,25 @@
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: http3-only
+Tags: Versions
+Protocols: HTTP
+Added: 7.88.0
+Mutexed: http1.1 http1.0 http2 http2-prior-knowledge http3
+Requires: HTTP/3
+Help: Use HTTP v3 only
+See-also: http1.1 http2 http3
+Category: http
+Example: --http3-only $URL
+Multi: mutex
+Experimental: yes
+---
+Instructs curl to use HTTP/3 to the host in the URL, with no fallback to
+earlier HTTP versions. HTTP/3 can only be used for HTTPS and not for HTTP
+URLs. For HTTP, this option will trigger an error.
+
+This option allows a user to avoid using the Alt-Svc method of upgrading to
+HTTP/3 when you know that the target speaks HTTP/3 on the given host and port.
+
+This option will make curl fail if a QUIC connection cannot be established, it
+will not attempt any other HTTP version on its own. Use --http3 for similar
+functionality *with* a fallback.
diff --git a/docs/cmdline-opts/http3.d b/docs/cmdline-opts/http3.d
index 6df001c..1f6326f 100644
--- a/docs/cmdline-opts/http3.d
+++ b/docs/cmdline-opts/http3.d
@@ -1,22 +1,27 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: http3
Tags: Versions
Protocols: HTTP
Added: 7.66.0
-Mutexed: http1.1 http1.0 http2 http2-prior-knowledge
+Mutexed: http1.1 http1.0 http2 http2-prior-knowledge http3-only
Requires: HTTP/3
Help: Use HTTP v3
See-also: http1.1 http2
Category: http
Example: --http3 $URL
+Multi: mutex
+Experimental: yes
---
-**WARNING**: this option is experimental. Do not use in production.
+Tells curl to try HTTP/3 to the host in the URL, but fallback to earlier
+HTTP versions if the HTTP/3 connection establishment fails. HTTP/3 is only
+available for HTTPS and not for HTTP URLs.
-Tells curl to use HTTP version 3 directly to the host and port number used in
-the URL. A normal HTTP/3 transaction will be done to a host and then get
-redirected via Alt-Svc, but this option allows a user to circumvent that when
-you know that the target speaks HTTP/3 on the given host and port.
+This option allows a user to avoid using the Alt-Svc method of upgrading to
+HTTP/3 when you know that the target speaks HTTP/3 on the given host and port.
-This option will make curl fail if a QUIC connection cannot be established, it
-cannot fall back to a lower HTTP version on its own.
+When asked to use HTTP/3, curl will issue a separate attempt to use older HTTP
+versions with a slight delay, so if the HTTP/3 transfer fails or is very slow,
+curl will still try to proceed with an older HTTP version.
+
+Use --http3-only for similar functionality *without* a fallback.
diff --git a/docs/cmdline-opts/ignore-content-length.d b/docs/cmdline-opts/ignore-content-length.d
index 5013121..8d4e328 100644
--- a/docs/cmdline-opts/ignore-content-length.d
+++ b/docs/cmdline-opts/ignore-content-length.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ignore-content-length
Help: Ignore the size of the remote resource
@@ -7,6 +7,7 @@
Example: --ignore-content-length $URL
Added: 7.14.1
See-also: ftp-skip-pasv-ip
+Multi: boolean
---
For HTTP, Ignore the Content-Length header. This is particularly useful for
servers running Apache 1.x, which will report incorrect Content-Length for
diff --git a/docs/cmdline-opts/include.d b/docs/cmdline-opts/include.d
index a788805..5491ca1 100644
--- a/docs/cmdline-opts/include.d
+++ b/docs/cmdline-opts/include.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: include
Short: i
@@ -7,6 +7,7 @@
Category: important verbose
Example: -i $URL
Added: 4.8
+Multi: boolean
---
Include the HTTP response headers in the output. The HTTP response headers can
include things like server name, cookies, date of the document, HTTP version
diff --git a/docs/cmdline-opts/insecure.d b/docs/cmdline-opts/insecure.d
index f033f9a..e48d500 100644
--- a/docs/cmdline-opts/insecure.d
+++ b/docs/cmdline-opts/insecure.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: insecure
Short: k
@@ -8,6 +8,7 @@
Category: tls sftp scp
Example: --insecure $URL
Added: 7.10
+Multi: boolean
---
By default, every secure connection curl makes is verified to be secure before
the transfer takes place. This option makes curl skip the verification step
@@ -22,6 +23,11 @@
For SFTP and SCP, this option makes curl skip the *known_hosts* verification.
*known_hosts* is a file normally stored in the user's home directory in the
-\&.ssh subdirectory, which contains host names and their public keys.
+".ssh" subdirectory, which contains host names and their public keys.
**WARNING**: using this option makes the transfer insecure.
+
+When curl uses secure protocols it trusts responses and allows for example
+HSTS and Alt-Svc information to be stored and used subsequently. Using
+--insecure can make curl trust and use such information from malicious
+servers.
diff --git a/docs/cmdline-opts/interface.d b/docs/cmdline-opts/interface.d
index 0273a70..8c67688 100644
--- a/docs/cmdline-opts/interface.d
+++ b/docs/cmdline-opts/interface.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: interface
Arg: <name>
@@ -7,14 +7,13 @@
Category: connection
Example: --interface eth0 $URL
Added: 7.3
+Multi: single
---
Perform an operation using a specified interface. You can enter interface
name, IP address or host name. An example could look like:
curl --interface eth0:1 https://www.example.com/
-If this option is used several times, the last one will be used.
-
On Linux it can be used to specify a VRF, but the binary needs to either
have CAP_NET_RAW or to be run as root. More information about Linux VRF:
https://www.kernel.org/doc/Documentation/networking/vrf.txt
diff --git a/docs/cmdline-opts/ipv4.d b/docs/cmdline-opts/ipv4.d
index 133493d..60690be 100644
--- a/docs/cmdline-opts/ipv4.d
+++ b/docs/cmdline-opts/ipv4.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: 4
Long: ipv4
@@ -11,6 +11,7 @@
Help: Resolve names to IPv4 addresses
Category: connection dns
Example: --ipv4 $URL
+Multi: mutex
---
-This option tells curl to use IPv4 addresses only, and not for example try
-IPv6.
+This option tells curl to use IPv4 addresses only when resolving host names,
+and not for example try IPv6.
diff --git a/docs/cmdline-opts/ipv6.d b/docs/cmdline-opts/ipv6.d
index 55c1ad1..24ce201 100644
--- a/docs/cmdline-opts/ipv6.d
+++ b/docs/cmdline-opts/ipv6.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: 6
Long: ipv6
@@ -11,6 +11,7 @@
Help: Resolve names to IPv6 addresses
Category: connection dns
Example: --ipv6 $URL
+Multi: mutex
---
-This option tells curl to use IPv6 addresses only, and not for example try
-IPv4.
+This option tells curl to use IPv6 addresses only when resolving host names,
+and not for example try IPv4.
diff --git a/docs/cmdline-opts/json.d b/docs/cmdline-opts/json.d
index abec514..4414ac5 100644
--- a/docs/cmdline-opts/json.d
+++ b/docs/cmdline-opts/json.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: json
Arg: <data>
@@ -12,6 +12,7 @@
Example: --json @prepared $URL
Example: --json @- $URL < json.txt
Added: 7.82.0
+Multi: append
---
Sends the specified JSON data in a POST request to the HTTP server. --json
works as a shortcut for passing on these three options:
@@ -25,7 +26,7 @@
If you start the data with the letter @, the rest should be a file name to
read the data from, or a single dash (-) if you want curl to read the data
-from stdin. Posting data from a file named \&'foobar' would thus be done with
+from stdin. Posting data from a file named 'foobar' would thus be done with
--json @foobar and to instead read the data from stdin, use --json @-.
If this option is used more than once on the same command line, the additional
diff --git a/docs/cmdline-opts/junk-session-cookies.d b/docs/cmdline-opts/junk-session-cookies.d
index 937f844..c337819 100644
--- a/docs/cmdline-opts/junk-session-cookies.d
+++ b/docs/cmdline-opts/junk-session-cookies.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: junk-session-cookies
Short: j
@@ -8,6 +8,7 @@
Category: http
Example: --junk-session-cookies -b cookies.txt $URL
Added: 7.9.7
+Multi: boolean
---
When curl is told to read cookies from a given file, this option will make it
discard all "session cookies". This will basically have the same effect as if
diff --git a/docs/cmdline-opts/keepalive-time.d b/docs/cmdline-opts/keepalive-time.d
index b135e74..5e28477 100644
--- a/docs/cmdline-opts/keepalive-time.d
+++ b/docs/cmdline-opts/keepalive-time.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: keepalive-time
Arg: <seconds>
@@ -7,6 +7,7 @@
Category: connection
Example: --keepalive-time 20 $URL
See-also: no-keepalive max-time
+Multi: single
---
This option sets the time a connection needs to remain idle before sending
keepalive probes and the time between individual keepalive probes. It is
@@ -17,5 +18,4 @@
connection down is OS dependent and is commonly 9 or 10. This option has no
effect if --no-keepalive is used.
-If this option is used several times, the last one will be used. If
-unspecified, the option defaults to 60 seconds.
+If unspecified, the option defaults to 60 seconds.
diff --git a/docs/cmdline-opts/key-type.d b/docs/cmdline-opts/key-type.d
index d3ef4e0..22339b4 100644
--- a/docs/cmdline-opts/key-type.d
+++ b/docs/cmdline-opts/key-type.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: key-type
Arg: <type>
@@ -8,8 +8,7 @@
Example: --key-type DER --key here $URL
Added: 7.9.3
See-also: key
+Multi: single
---
Private key file type. Specify which type your --key provided private key
is. DER, PEM, and ENG are supported. If not specified, PEM is assumed.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/key.d b/docs/cmdline-opts/key.d
index f5cd044..3b90100 100644
--- a/docs/cmdline-opts/key.d
+++ b/docs/cmdline-opts/key.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: key
Arg: <key>
@@ -8,10 +8,11 @@
Example: --cert certificate --key here $URL
Added: 7.9.3
See-also: key-type cert
+Multi: single
---
Private key file name. Allows you to provide your private key in this separate
file. For SSH, if not specified, curl tries the following candidates in order:
-\&'~/.ssh/id_rsa', '~/.ssh/id_dsa', './id_rsa', './id_dsa'.
+'~/.ssh/id_rsa', '~/.ssh/id_dsa', './id_rsa', './id_dsa'.
If curl is built against OpenSSL library, and the engine pkcs11 is available,
then a PKCS#11 URI (RFC 7512) can be used to specify a private key located in a
@@ -24,5 +25,3 @@
ignored for TLS protocols (HTTPS, etc). Those backends expect the private key
to be already present in the keychain or PKCS#12 file containing the
certificate.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/krb.d b/docs/cmdline-opts/krb.d
index 0ba97a7..b4b96e4 100644
--- a/docs/cmdline-opts/krb.d
+++ b/docs/cmdline-opts/krb.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: krb
Arg: <level>
@@ -9,9 +9,8 @@
Example: --krb clear ftp://example.com/
Added: 7.3
See-also: delegation ssl
+Multi: single
---
Enable Kerberos authentication and use. The level must be entered and should
be one of 'clear', 'safe', 'confidential', or 'private'. Should you use a
level that is not one of these, 'private' will instead be used.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/libcurl.d b/docs/cmdline-opts/libcurl.d
index 24a1b10..0f5d582 100644
--- a/docs/cmdline-opts/libcurl.d
+++ b/docs/cmdline-opts/libcurl.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: libcurl
Arg: <file>
@@ -7,13 +7,9 @@
Category: curl
Example: --libcurl client.c $URL
See-also: verbose
+Multi: single
+Scope: global
---
Append this option to any ordinary curl command line, and you will get
libcurl-using C source code written to the file that does the equivalent
of what your command-line operation does!
-
-This option is global and does not need to be specified for each use of
---next.
-
-If this option is used several times, the last given file name will be
-used.
diff --git a/docs/cmdline-opts/limit-rate.d b/docs/cmdline-opts/limit-rate.d
index e25f4ac..2a43c4a 100644
--- a/docs/cmdline-opts/limit-rate.d
+++ b/docs/cmdline-opts/limit-rate.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: limit-rate
Arg: <speed>
@@ -8,7 +8,8 @@
Example: --limit-rate 1000 $URL
Example: --limit-rate 10M $URL
Added: 7.10
-See-also: speed-limit speed-time
+See-also: rate speed-limit speed-time
+Multi: single
---
Specify the maximum transfer rate you want curl to use - for both downloads
and uploads. This feature is useful if you have a limited pipe and you would like
@@ -26,5 +27,3 @@
If you also use the --speed-limit option, that option will take precedence and
might cripple the rate-limiting slightly, to help keeping the speed-limit
logic working.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/list-only.d b/docs/cmdline-opts/list-only.d
index 74c88e4..6b6021c 100644
--- a/docs/cmdline-opts/list-only.d
+++ b/docs/cmdline-opts/list-only.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: list-only
Short: l
@@ -8,6 +8,7 @@
Category: ftp pop3
Example: --list-only ftp://example.com/dir/
See-also: quote request
+Multi: boolean
---
(FTP)
When listing an FTP directory, this switch forces a name-only view. This is
diff --git a/docs/cmdline-opts/local-port.d b/docs/cmdline-opts/local-port.d
index 55961f8..71af9be 100644
--- a/docs/cmdline-opts/local-port.d
+++ b/docs/cmdline-opts/local-port.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: local-port
Arg: <num/range>
@@ -7,6 +7,7 @@
Category: connection
Example: --local-port 1000-3000 $URL
See-also: globoff
+Multi: single
---
Set a preferred single number or range (FROM-TO) of local port numbers to use
for the connection(s). Note that port numbers by nature are a scarce resource
diff --git a/docs/cmdline-opts/location-trusted.d b/docs/cmdline-opts/location-trusted.d
index cd920f4..d801cb6 100644
--- a/docs/cmdline-opts/location-trusted.d
+++ b/docs/cmdline-opts/location-trusted.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: location-trusted
Help: Like --location, and send auth to other hosts
@@ -7,6 +7,7 @@
Category: http auth
Example: --location-trusted -u user:password $URL
Added: 7.10.4
+Multi: boolean
---
Like --location, but will allow sending the name + password to all hosts that
the site may redirect to. This may or may not introduce a security breach if
diff --git a/docs/cmdline-opts/location.d b/docs/cmdline-opts/location.d
index 7b532ef..fcd2867 100644
--- a/docs/cmdline-opts/location.d
+++ b/docs/cmdline-opts/location.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: location
Short: L
@@ -8,6 +8,7 @@
Example: -L $URL
Added: 4.9
See-also: resolve alt-svc
+Multi: boolean
---
If the server reports that the requested page has moved to a different
location (indicated with a Location: header and a 3XX response code), this
diff --git a/docs/cmdline-opts/login-options.d b/docs/cmdline-opts/login-options.d
index 2c244e4..b1bad37 100644
--- a/docs/cmdline-opts/login-options.d
+++ b/docs/cmdline-opts/login-options.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: login-options
Arg: <options>
@@ -8,6 +8,7 @@
Category: imap pop3 smtp auth
Example: --login-options 'AUTH=*' imap://example.com
See-also: user
+Multi: single
---
Specify the login options to use during server authentication.
@@ -16,4 +17,8 @@
login options. For more information about login options please see RFC
2384, RFC 5092 and IETF draft draft-earhart-url-smtp-00.txt
-If this option is used several times, the last one will be used.
+Since 8.2.0, IMAP supports the login option "AUTH=+LOGIN". With this option,
+curl uses the plain (not SASL) LOGIN IMAP command even if the server advertises
+SASL authentication. Care should be taken in using this option, as it will send
+out your password in plain text. This will not work if the IMAP server disables
+the plain LOGIN (e.g. to prevent password snooping).
diff --git a/docs/cmdline-opts/mail-auth.d b/docs/cmdline-opts/mail-auth.d
index d077a5e..5e3f3f2 100644
--- a/docs/cmdline-opts/mail-auth.d
+++ b/docs/cmdline-opts/mail-auth.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: mail-auth
Arg: <address>
@@ -8,6 +8,7 @@
See-also: mail-rcpt mail-from
Category: smtp
Example: --mail-auth user@example.come -T mail smtp://example.com/
+Multi: single
---
Specify a single address. This will be used to specify the authentication
address (identity) of a submitted message that is being relayed to another
diff --git a/docs/cmdline-opts/mail-from.d b/docs/cmdline-opts/mail-from.d
index 2663600..0729e84 100644
--- a/docs/cmdline-opts/mail-from.d
+++ b/docs/cmdline-opts/mail-from.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: mail-from
Arg: <address>
@@ -8,5 +8,6 @@
See-also: mail-rcpt mail-auth
Category: smtp
Example: --mail-from user@example.com -T mail smtp://example.com/
+Multi: single
---
Specify a single address that the given mail should get sent from.
diff --git a/docs/cmdline-opts/mail-rcpt-allowfails.d b/docs/cmdline-opts/mail-rcpt-allowfails.d
index 6e1f6f8..2837ed0 100644
--- a/docs/cmdline-opts/mail-rcpt-allowfails.d
+++ b/docs/cmdline-opts/mail-rcpt-allowfails.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: mail-rcpt-allowfails
Help: Allow RCPT TO command to fail for some recipients
@@ -7,6 +7,7 @@
Category: smtp
Example: --mail-rcpt-allowfails --mail-rcpt dest@example.com smtp://example.com
See-also: mail-rcpt
+Multi: boolean
---
When sending data to multiple recipients, by default curl will abort SMTP
conversation if at least one of the recipients causes RCPT TO command to
diff --git a/docs/cmdline-opts/mail-rcpt.d b/docs/cmdline-opts/mail-rcpt.d
index 1890f90..ea43397 100644
--- a/docs/cmdline-opts/mail-rcpt.d
+++ b/docs/cmdline-opts/mail-rcpt.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: mail-rcpt
Arg: <address>
@@ -8,13 +8,14 @@
Category: smtp
Example: --mail-rcpt user@example.net smtp://example.com
See-also: mail-rcpt-allowfails
+Multi: append
---
Specify a single email address, user name or mailing list name. Repeat this
option several times to send to multiple recipients.
When performing an address verification (VRFY command), the recipient should be
specified as the user name or user name and domain (as per Section 3.5 of
-RFC5321). (Added in 7.34.0)
+RFC 5321). (Added in 7.34.0)
When performing a mailing list expand (EXPN command), the recipient should be
specified using the mailing list name, such as "Friends" or "London-Office".
diff --git a/docs/cmdline-opts/manual.d b/docs/cmdline-opts/manual.d
index 7becf1c..9ee4d07 100644
--- a/docs/cmdline-opts/manual.d
+++ b/docs/cmdline-opts/manual.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: manual
Short: M
@@ -7,5 +7,6 @@
Example: --manual
Added: 5.2
See-also: verbose libcurl trace
+Multi: custom
---
Manual. Display the huge help text.
diff --git a/docs/cmdline-opts/max-filesize.d b/docs/cmdline-opts/max-filesize.d
index 8ed66e9..1900b9d 100644
--- a/docs/cmdline-opts/max-filesize.d
+++ b/docs/cmdline-opts/max-filesize.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: max-filesize
Arg: <bytes>
@@ -8,6 +8,7 @@
Category: connection
Example: --max-filesize 100K $URL
Added: 7.10.8
+Multi: single
---
Specify the maximum size (in bytes) of a file to download. If the file
requested is larger than this value, the transfer will not start and curl will
diff --git a/docs/cmdline-opts/max-redirs.d b/docs/cmdline-opts/max-redirs.d
index fc5d5c8..31ce98e 100644
--- a/docs/cmdline-opts/max-redirs.d
+++ b/docs/cmdline-opts/max-redirs.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: max-redirs
Arg: <num>
@@ -8,9 +8,8 @@
Example: --max-redirs 3 --location $URL
Added: 7.5
See-also: location
+Multi: single
---
Set maximum number of redirections to follow. When --location is used, to
prevent curl from following too many redirects, by default, the limit is
set to 50 redirects. Set this option to -1 to make it unlimited.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/max-time.d b/docs/cmdline-opts/max-time.d
index c5362fc..4f5675d 100644
--- a/docs/cmdline-opts/max-time.d
+++ b/docs/cmdline-opts/max-time.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: max-time
Short: m
@@ -9,6 +9,7 @@
Example: --max-time 10 $URL
Example: --max-time 2.92 $URL
Added: 4.0
+Multi: single
---
Maximum time in seconds that you allow each transfer to take. This is
useful for preventing your batch jobs from hanging for hours due to slow
@@ -20,4 +21,5 @@
reset each time the transfer is retried. You can use --retry-max-time to limit
the retry time.
-If this option is used several times, the last one will be used.
+The decimal value needs to provided using a dot (.) as decimal separator - not
+the local version even if it might be using another separator.
diff --git a/docs/cmdline-opts/metalink.d b/docs/cmdline-opts/metalink.d
index c2677f0..25816a7 100644
--- a/docs/cmdline-opts/metalink.d
+++ b/docs/cmdline-opts/metalink.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: metalink
Help: Process given URLs as metalink XML file
@@ -6,6 +6,7 @@
Category: misc
Example: --metalink file $URL
See-also: parallel
+Multi: single
---
This option was previously used to specify a metalink resource. Metalink
support has been disabled in curl since 7.78.0 for security reasons.
diff --git a/docs/cmdline-opts/negotiate.d b/docs/cmdline-opts/negotiate.d
index c2d5f8a..c2adafa 100644
--- a/docs/cmdline-opts/negotiate.d
+++ b/docs/cmdline-opts/negotiate.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: negotiate
Help: Use HTTP Negotiate (SPNEGO) authentication
@@ -7,6 +7,7 @@
Category: auth http
Example: --negotiate -u : $URL
Added: 7.10.6
+Multi: mutex
---
Enables Negotiate (SPNEGO) authentication.
diff --git a/docs/cmdline-opts/netrc-file.d b/docs/cmdline-opts/netrc-file.d
index 2c98655..7e85721 100644
--- a/docs/cmdline-opts/netrc-file.d
+++ b/docs/cmdline-opts/netrc-file.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: netrc-file
Help: Specify FILE for netrc
@@ -8,10 +8,10 @@
Category: curl
Example: --netrc-file netrc $URL
See-also: netrc user config
+Multi: single
---
This option is similar to --netrc, except that you provide the path (absolute
or relative) to the netrc file that curl should use. You can only specify one
-netrc file per invocation. If several --netrc-file options are provided,
-the last one will be used.
+netrc file per invocation.
It will abide by --netrc-optional if specified.
diff --git a/docs/cmdline-opts/netrc-optional.d b/docs/cmdline-opts/netrc-optional.d
index 4c83295..a775964 100644
--- a/docs/cmdline-opts/netrc-optional.d
+++ b/docs/cmdline-opts/netrc-optional.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: netrc-optional
Help: Use either .netrc or URL
@@ -7,6 +7,7 @@
Category: curl
Example: --netrc-optional $URL
Added: 7.9.8
+Multi: boolean
---
Similar to --netrc, but this option makes the .netrc usage **optional**
and not mandatory as the --netrc option does.
diff --git a/docs/cmdline-opts/netrc.d b/docs/cmdline-opts/netrc.d
index 9490676..dd9af01 100644
--- a/docs/cmdline-opts/netrc.d
+++ b/docs/cmdline-opts/netrc.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: netrc
Short: n
@@ -7,6 +7,8 @@
Example: --netrc $URL
Added: 4.6
See-also: netrc-file config user
+Mutexed: netrc-file netrc-optional
+Multi: boolean
---
Makes curl scan the *.netrc* (*_netrc* on Windows) file in the user's home
directory for login name and password. This is typically used for FTP on
@@ -17,9 +19,9 @@
to find the home directory.
A quick and simple example of how to setup a *.netrc* to allow curl to FTP to
-the machine host.domain.com with user name \&'myself' and password \&'secret'
+the machine host.domain.com with user name 'myself' and password 'secret'
could look similar to:
machine host.domain.com
login myself
- password secret"
+ password secret
diff --git a/docs/cmdline-opts/next.d b/docs/cmdline-opts/next.d
index b4b2a41..778b3f3 100644
--- a/docs/cmdline-opts/next.d
+++ b/docs/cmdline-opts/next.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: :
Long: next
@@ -11,6 +11,7 @@
Example: $URL --next -d postthis www2.example.com
Example: -I $URL --next https://example.net/
See-also: parallel config
+Multi: append
---
Tells curl to use a separate operation for the following URL and associated
options. This allows you to send several URL requests, each with their own
diff --git a/docs/cmdline-opts/no-alpn.d b/docs/cmdline-opts/no-alpn.d
index 004ecec..7b86f12 100644
--- a/docs/cmdline-opts/no-alpn.d
+++ b/docs/cmdline-opts/no-alpn.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: no-alpn
Tags: HTTP/2
@@ -9,6 +9,7 @@
Help: Disable the ALPN TLS extension
Category: tls http
Example: --no-alpn $URL
+Multi: boolean
---
Disable the ALPN TLS extension. ALPN is enabled by default if libcurl was built
with an SSL library that supports ALPN. ALPN is used by a libcurl that supports
diff --git a/docs/cmdline-opts/no-buffer.d b/docs/cmdline-opts/no-buffer.d
index ef9d29c..274a5a0 100644
--- a/docs/cmdline-opts/no-buffer.d
+++ b/docs/cmdline-opts/no-buffer.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: no-buffer
Short: N
@@ -7,11 +7,9 @@
Example: --no-buffer $URL
Added: 6.5
See-also: progress-bar
+Multi: boolean
---
Disables the buffering of the output stream. In normal work situations, curl
will use a standard buffered output stream that will have the effect that it
will output the data in chunks, not necessarily exactly when the data arrives.
Using this option will disable that buffering.
-
-Note that this is the negated option name documented. You can thus use
---buffer to enforce the buffering.
diff --git a/docs/cmdline-opts/no-clobber.d b/docs/cmdline-opts/no-clobber.d
index 9cd4036..15f4ed3 100644
--- a/docs/cmdline-opts/no-clobber.d
+++ b/docs/cmdline-opts/no-clobber.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: no-clobber
Help: Do not overwrite files that already exist
@@ -6,6 +6,7 @@
Added: 7.83.0
See-also: output remote-name
Example: --no-clobber --output local/dir/file $URL
+Multi: boolean
---
When used in conjunction with the --output, --remote-header-name,
--remote-name, or --remote-name-all options, curl avoids overwriting files
@@ -14,5 +15,5 @@
create any file.
Note that this is the negated option name documented. You can thus use
---clobber to enforce the clobbering, even if --remote-header-name or -J is
+--clobber to enforce the clobbering, even if --remote-header-name is
specified.
diff --git a/docs/cmdline-opts/no-keepalive.d b/docs/cmdline-opts/no-keepalive.d
index a549333..0aeaef8 100644
--- a/docs/cmdline-opts/no-keepalive.d
+++ b/docs/cmdline-opts/no-keepalive.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: no-keepalive
Help: Disable TCP keepalive on the connection
@@ -6,6 +6,7 @@
Example: --no-keepalive $URL
Added: 7.18.0
See-also: keepalive-time
+Multi: boolean
---
Disables the use of keepalive messages on the TCP connection. curl otherwise
enables them by default.
diff --git a/docs/cmdline-opts/no-npn.d b/docs/cmdline-opts/no-npn.d
index f685502..80a0ec9 100644
--- a/docs/cmdline-opts/no-npn.d
+++ b/docs/cmdline-opts/no-npn.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: no-npn
Tags: Versions HTTP/2
@@ -10,7 +10,10 @@
Help: Disable the NPN TLS extension
Category: tls http
Example: --no-npn $URL
+Multi: boolean
---
+In curl 7.86.0 and later, curl never uses NPN.
+
Disable the NPN TLS extension. NPN is enabled by default if libcurl was built
with an SSL library that supports NPN. NPN is used by a libcurl that supports
HTTP/2 to negotiate HTTP/2 support with the server during https sessions.
diff --git a/docs/cmdline-opts/no-progress-meter.d b/docs/cmdline-opts/no-progress-meter.d
index fd57b13..820557d 100644
--- a/docs/cmdline-opts/no-progress-meter.d
+++ b/docs/cmdline-opts/no-progress-meter.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: no-progress-meter
Help: Do not show the progress meter
@@ -6,6 +6,7 @@
Added: 7.67.0
Category: verbose
Example: --no-progress-meter -o store $URL
+Multi: boolean
---
Option to switch off the progress meter output without muting or otherwise
affecting warning and informational messages like --silent does.
diff --git a/docs/cmdline-opts/no-sessionid.d b/docs/cmdline-opts/no-sessionid.d
index 5b86a95..9699f46 100644
--- a/docs/cmdline-opts/no-sessionid.d
+++ b/docs/cmdline-opts/no-sessionid.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: no-sessionid
Help: Disable SSL session-ID reusing
@@ -7,6 +7,7 @@
Category: tls
Example: --no-sessionid $URL
See-also: insecure
+Multi: boolean
---
Disable curl's use of SSL session-ID caching. By default all transfers are
done using the cache. Note that while nothing should ever get hurt by
diff --git a/docs/cmdline-opts/noproxy.d b/docs/cmdline-opts/noproxy.d
index f4d94ef..2bd42ad 100644
--- a/docs/cmdline-opts/noproxy.d
+++ b/docs/cmdline-opts/noproxy.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: noproxy
Arg: <no-proxy-list>
@@ -7,6 +7,7 @@
Category: proxy
Example: --noproxy "www.example" $URL
See-also: proxy
+Multi: single
---
Comma-separated list of hosts for which not to use a proxy, if one is
specified. The only wildcard is a single * character, which matches all hosts,
@@ -17,4 +18,9 @@
Since 7.53.0, This option overrides the environment variables that disable the
proxy ('no_proxy' and 'NO_PROXY'). If there's an environment variable
-disabling a proxy, you can set the noproxy list to \&"" to override it.
+disabling a proxy, you can set the noproxy list to "" to override it.
+
+Since 7.86.0, IP addresses specified to this option can be provided using CIDR
+notation: an appended slash and number specifies the number of "network bits"
+out of the address to use in the comparison. For example "192.168.0.0/16"
+would match all addresses starting with "192.168".
diff --git a/docs/cmdline-opts/ntlm-wb.d b/docs/cmdline-opts/ntlm-wb.d
index 039bd9c..4a32252 100644
--- a/docs/cmdline-opts/ntlm-wb.d
+++ b/docs/cmdline-opts/ntlm-wb.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ntlm-wb
Help: Use HTTP NTLM authentication with winbind
@@ -7,6 +7,7 @@
Category: auth http
Example: --ntlm-wb -u user:password $URL
Added: 7.22.0
+Multi: mutex
---
Enables NTLM much in the style --ntlm does, but hand over the authentication
to the separate binary ntlmauth application that is executed when needed.
diff --git a/docs/cmdline-opts/ntlm.d b/docs/cmdline-opts/ntlm.d
index 66b513e..416374d 100644
--- a/docs/cmdline-opts/ntlm.d
+++ b/docs/cmdline-opts/ntlm.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ntlm
Help: Use HTTP NTLM authentication
@@ -9,6 +9,7 @@
Category: auth http
Example: --ntlm -u user:password $URL
Added: 7.10.6
+Multi: mutex
---
Enables NTLM authentication. The NTLM authentication method was designed by
Microsoft and is used by IIS web servers. It is a proprietary protocol,
diff --git a/docs/cmdline-opts/oauth2-bearer.d b/docs/cmdline-opts/oauth2-bearer.d
index e5857b6..6f35147 100644
--- a/docs/cmdline-opts/oauth2-bearer.d
+++ b/docs/cmdline-opts/oauth2-bearer.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: oauth2-bearer
Help: OAuth 2 Bearer Token
@@ -8,11 +8,10 @@
Example: --oauth2-bearer "mF_9.B5f-4.1JqM" $URL
Added: 7.33.0
See-also: basic ntlm digest
+Multi: single
---
Specify the Bearer Token for OAUTH 2.0 server authentication. The Bearer Token
is used in conjunction with the user name which can be specified as part of
the --url or --user options.
The Bearer Token and user name are formatted according to RFC 6750.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/output-dir.d b/docs/cmdline-opts/output-dir.d
index 20adf9f..eb6274f 100644
--- a/docs/cmdline-opts/output-dir.d
+++ b/docs/cmdline-opts/output-dir.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: output-dir
Arg: <dir>
@@ -7,8 +7,8 @@
See-also: remote-name remote-header-name
Category: curl
Example: --output-dir "tmp" -O $URL
+Multi: single
---
-
This option specifies the directory in which files should be stored, when
--remote-name or --output are used.
@@ -17,6 +17,3 @@
If the specified target directory does not exist, the operation will fail
unless --create-dirs is also used.
-
-If this option is used multiple times, the last specified directory will be
-used.
diff --git a/docs/cmdline-opts/output.d b/docs/cmdline-opts/output.d
index 543d3e3..9cfb899 100644
--- a/docs/cmdline-opts/output.d
+++ b/docs/cmdline-opts/output.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: output
Arg: <file>
@@ -11,6 +11,7 @@
Example: "http://{site,host}.host[1-5].com" -o "#1_#2"
Example: -o file $URL -o file2 https://example.net
Added: 4.0
+Multi: append
---
Write output to <file> instead of stdout. If you are using {} or [] to fetch
multiple documents, you should quote the URL and you can use '#' followed by a
diff --git a/docs/cmdline-opts/page-footer b/docs/cmdline-opts/page-footer
index 613a3e8..6e7f9f3 100644
--- a/docs/cmdline-opts/page-footer
+++ b/docs/cmdline-opts/page-footer
@@ -22,7 +22,7 @@
Sets the proxy server to use if no protocol-specific proxy is set.
.IP "NO_PROXY <comma-separated list of hosts/domains>"
list of host names that should not go through any proxy. If set to an asterisk
-\&'*' only, it matches all hosts. Each name in this list is matched as either
+'*' only, it matches all hosts. Each name in this list is matched as either
a domain name which contains the hostname, or the hostname itself.
This environment variable disables use of the proxy even when specified with
@@ -37,9 +37,10 @@
The list of host names can also be include numerical IP addresses, and IPv6
versions should then be given without enclosing brackets.
-IPv6 numerical addresses are compared as strings, so they will only match if
-the representations are the same: "::1" is the same as "::0:1" but they do not
-match.
+Since 7.86.0, IP addresses can be specified using CIDR notation: an appended
+slash and number specifies the number of "network bits" out of the address to
+use in the comparison. For example "192.168.0.0/16" would match all addresses
+starting with "192.168".
.IP "APPDATA <dir>"
On Windows, this variable is used when trying to find the home directory. If
the primary home variable are all unset.
@@ -48,10 +49,10 @@
when the alternative progress-bar is shown. If not set, curl will try to
figure it out using other ways.
.IP "CURL_CA_BUNDLE <file>"
-If set, will be used as the \fI--cacert\fP value.
+If set, will be used as the --cacert value.
.IP "CURL_HOME <dir>"
If set, is the first variable curl checks when trying to find its home
-directory. If not set, it continues to check \fBXDG_CONFIG_HOME\fP.
+directory. If not set, it continues to check *XDG_CONFIG_HOME*
.IP "CURL_SSL_BACKEND <TLS backend>"
If curl was built with support for "MultiSSL", meaning that it has built-in
support for more than one TLS backend, this environment variable can be set to
@@ -63,7 +64,7 @@
nss, openssl, rustls, schannel, secure-transport, wolfssl
.IP "HOME <dir>"
If set, this is used to find the home directory when that is needed. Like when
-looking for the default .curlrc. \fBCURL_HOME\fP and \fBXDG_CONFIG_HOME\fP
+looking for the default .curlrc. *CURL_HOME* and *XDG_CONFIG_HOME*
have preference.
.IP "QLOGDIR <directory name>"
If curl was built with HTTP/3 support, setting this environment variable to a
@@ -73,9 +74,9 @@
.IP SHELL
Used on VMS when trying to detect if using a DCL or a "unix" shell.
.IP "SSL_CERT_DIR <dir>"
-If set, will be used as the \fI--capath\fP value.
+If set, will be used as the --capath value.
.IP "SSL_CERT_FILE <path>"
-If set, will be used as the \fI--cacert\fP value.
+If set, will be used as the --cacert value.
.IP "SSLKEYLOGFILE <file name>"
If you set this environment variable to a file name, curl will store TLS
secrets from its connections in that file when invoked to enable you to
@@ -87,7 +88,7 @@
the other, primary, variable are all unset. If set, curl will use the path
"$USERPROFILE\\Application Data".
.IP "XDG_CONFIG_HOME <dir>"
-If \fBCURL_HOME\fP is not set, this variable is checked when looking for a
+If *CURL_HOME* is not set, this variable is checked when looking for a
default .curlrc file.
.SH "PROXY PROTOCOL PREFIXES"
The proxy string may be specified with a protocol:// prefix to specify
@@ -217,8 +218,6 @@
manual!
.IP 49
Malformed telnet option.
-.IP 51
-The peer's SSL certificate or SSH MD5 fingerprint was not OK.
.IP 52
The server did not reply anything, which here is considered an error.
.IP 53
@@ -237,8 +236,6 @@
Peer certificate cannot be authenticated with known CA certificates.
.IP 61
Unrecognized transfer encoding.
-.IP 62
-Invalid LDAP URL.
.IP 63
Maximum file size exceeded.
.IP 64
@@ -263,10 +260,6 @@
File already exists (TFTP).
.IP 74
No such user (TFTP).
-.IP 75
-Character conversion failed.
-.IP 76
-Character conversion functions required.
.IP 77
Problem reading the SSL CA cert (path? access rights?).
.IP 78
@@ -307,6 +300,12 @@
.IP 96
QUIC connection error. This error may be caused by an SSL library error. QUIC
is the protocol used for HTTP/3 transfers.
+.IP 97
+Proxy handshake error.
+.IP 98
+A client-side certificate is required to complete the TLS handshake.
+.IP 99
+Poll or select returned fatal error.
.IP XX
More error codes will appear here in future releases. The existing ones
are meant to never change.
diff --git a/docs/cmdline-opts/page-header b/docs/cmdline-opts/page-header
index 84bd39d..566fe77 100644
--- a/docs/cmdline-opts/page-header
+++ b/docs/cmdline-opts/page-header
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -33,7 +33,7 @@
**curl** is a tool for transferring data from or to a server. 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 or TFTP. The command is designed to work without user
+SMTPS, TELNET, TFTP, WS and WSS. The command is designed to work without user
interaction.
curl offers a busload of useful tricks like proxy support, user
@@ -66,8 +66,9 @@
"http://example.com/archive[1996-1999]/vol[1-4]/part{a,b,c}.html"
You can specify any amount of URLs on the command line. They will be fetched
-in a sequential manner in the specified order. You can specify command line
-options and URLs mixed and in any order on the command line.
+in a sequential manner in the specified order unless you use --parallel. You
+can specify command line options and URLs mixed and in any order on the
+command line.
You can specify a step counter for the ranges to get every Nth number or
letter:
@@ -86,20 +87,16 @@
"http://[fe80::3%25eth0]/"
-If you specify URL without protocol:// prefix, curl will attempt to guess what
-protocol you might want. It will then default to HTTP but try other protocols
-based on often-used host name prefixes. For example, for host names starting
-with "ftp." curl will assume you want to speak FTP.
+If you specify a URL without a protocol:// scheme, curl guesses what protocol
+you want. It then defaults to HTTP but assumes others based on often-used host
+name prefixes. For example, for host names starting with "ftp." curl assumes
+you want FTP.
-curl will do its best to use what you pass to it as a URL. It is not trying to
-validate it as a syntactically correct URL by any means but is fairly liberal
-with what it accepts.
-
-curl will attempt to re-use connections for multiple file transfers, so that
-getting many files from the same server will not do multiple connects /
-handshakes. This improves speed. Of course this is only done on files
-specified on a single command line and cannot be used between separate curl
-invocations.
+curl attempts to re-use connections when doing multiple file transfers, so
+that getting many files from the same server do not use multiple connects /
+handshakes. This improves speed. Connection re-use can only be done for URLs
+specified for a single command line invocation and cannot be performed between
+separate curl runs.
.SH OUTPUT
If not told otherwise, curl writes the received data to stdout. It can be
instructed to instead save that data into a local file, using the --output or
@@ -161,9 +158,9 @@
.SH "PROGRESS METER"
curl normally displays a progress meter during operations, indicating the
amount of transferred data, transfer speeds and estimated time left, etc. The
-progress meter displays number of bytes and the speeds are in bytes per
-second. The suffixes (k, M, G, T, P) are 1024 based. For example 1k is 1024
-bytes. 1M is 1048576 bytes.
+progress meter displays the transfer rate in bytes per second. The suffixes
+(k, M, G, T, P) are 1024 based. For example 1k is 1024 bytes. 1M is 1048576
+bytes.
curl displays this data to the terminal by default, so if you invoke curl to
do an operation and it is about to write data to the terminal, it
@@ -180,6 +177,16 @@
If you prefer a progress "bar" instead of the regular meter, --progress-bar is
your friend. You can also disable the progress meter completely with the
--silent option.
+.SH VERSION
+This man page describes curl %VERSION. If you use a later version, chances are
+this man page does not fully document it. If you use an earlier version, this
+document tries to include version information about which specific version
+that introduced changes.
+
+You can always learn which the latest curl version is by running
+.nf
+curl https://curl.se/info
+.fi
.SH OPTIONS
Options start with one or two dashes. Many of the options require an
additional value next to them.
@@ -197,3 +204,10 @@
disabled with --**no-**option. That is, you use the same option name but
prefix it with "no-". However, in this list we mostly only list and show the
--option version of them.
+
+When --next is used, it resets the parser state and you start again with a
+clean option state, except for the options that are "global". Global options
+will retain their values and meaning even after --next.
+
+The following options are global:
+%GLOBALS.
diff --git a/docs/cmdline-opts/parallel-immediate.d b/docs/cmdline-opts/parallel-immediate.d
index 40a8c51..da15d62 100644
--- a/docs/cmdline-opts/parallel-immediate.d
+++ b/docs/cmdline-opts/parallel-immediate.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: parallel-immediate
Help: Do not wait for multiplexing (with --parallel)
@@ -6,11 +6,10 @@
See-also: parallel parallel-max
Category: connection curl
Example: --parallel-immediate -Z $URL -o file1 $URL -o file2
+Multi: boolean
+Scope: global
---
When doing parallel transfers, this option will instruct curl that it should
rather prefer opening up more connections in parallel at once rather than
waiting to see if new transfers can be added as multiplexed streams on another
connection.
-
-This option is global and does not need to be specified for each use of
---next.
diff --git a/docs/cmdline-opts/parallel-max.d b/docs/cmdline-opts/parallel-max.d
index 5e3ad42..cc6d32d 100644
--- a/docs/cmdline-opts/parallel-max.d
+++ b/docs/cmdline-opts/parallel-max.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: parallel-max
Arg: <num>
@@ -7,6 +7,7 @@
See-also: parallel
Category: connection curl
Example: --parallel-max 100 -Z $URL ftp://example.com/
+Multi: single
---
When asked to do parallel transfers, using --parallel, this option controls
the maximum amount of transfers to do simultaneously.
diff --git a/docs/cmdline-opts/parallel.d b/docs/cmdline-opts/parallel.d
index d0e9b32..4f698f8 100644
--- a/docs/cmdline-opts/parallel.d
+++ b/docs/cmdline-opts/parallel.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: Z
Long: parallel
@@ -7,9 +7,8 @@
Category: connection curl
Example: --parallel $URL -o file1 $URL -o file2
See-also: next verbose
+Multi: boolean
+Scope: global
---
Makes curl perform its transfers in parallel as compared to the regular serial
manner.
-
-This option is global and does not need to be specified for each use of
---next.
diff --git a/docs/cmdline-opts/pass.d b/docs/cmdline-opts/pass.d
index 127786e..2c0a2be 100644
--- a/docs/cmdline-opts/pass.d
+++ b/docs/cmdline-opts/pass.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: pass
Arg: <phrase>
@@ -8,7 +8,6 @@
Example: --pass secret --key file $URL
Added: 7.9.3
See-also: key user
+Multi: single
---
Passphrase for the private key.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/path-as-is.d b/docs/cmdline-opts/path-as-is.d
index e9dc2e8..c079c59 100644
--- a/docs/cmdline-opts/path-as-is.d
+++ b/docs/cmdline-opts/path-as-is.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: path-as-is
Help: Do not squash .. sequences in URL path
@@ -6,6 +6,7 @@
Category: curl
Example: --path-as-is https://example.com/../../etc/passwd
See-also: request-target
+Multi: boolean
---
Tell curl to not handle sequences of /../ or /./ in the given URL
path. Normally curl will squash or merge them according to standards but with
diff --git a/docs/cmdline-opts/pinnedpubkey.d b/docs/cmdline-opts/pinnedpubkey.d
index 89df109..f5a36a2 100644
--- a/docs/cmdline-opts/pinnedpubkey.d
+++ b/docs/cmdline-opts/pinnedpubkey.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: pinnedpubkey
Arg: <hashes>
@@ -9,6 +9,7 @@
Example: --pinnedpubkey 'sha256//ce118b51897f4452dc' $URL
Added: 7.39.0
See-also: hostpubsha256
+Multi: single
---
Tells curl to use the specified public key file (or hashes) to verify the
peer. This can be a path to a file which contains a single public key in PEM
@@ -35,5 +36,3 @@
7.47.0: mbedtls
Other SSL backends not supported.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/post301.d b/docs/cmdline-opts/post301.d
index 2c7a136..d067fc8 100644
--- a/docs/cmdline-opts/post301.d
+++ b/docs/cmdline-opts/post301.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: post301
Help: Do not switch to GET after following a 301
@@ -7,6 +7,7 @@
Added: 7.17.1
Category: http post
Example: --post301 --location -d "data" $URL
+Multi: boolean
---
Tells curl to respect RFC 7231/6.4.2 and not convert POST requests into GET
requests when following a 301 redirection. The non-RFC behavior is ubiquitous
diff --git a/docs/cmdline-opts/post302.d b/docs/cmdline-opts/post302.d
index 31c13bd..b7190ce 100644
--- a/docs/cmdline-opts/post302.d
+++ b/docs/cmdline-opts/post302.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: post302
Help: Do not switch to GET after following a 302
@@ -7,6 +7,7 @@
Added: 7.19.1
Category: http post
Example: --post302 --location -d "data" $URL
+Multi: boolean
---
Tells curl to respect RFC 7231/6.4.3 and not convert POST requests into GET
requests when following a 302 redirection. The non-RFC behavior is ubiquitous
diff --git a/docs/cmdline-opts/post303.d b/docs/cmdline-opts/post303.d
index 8d856ea..52d440c 100644
--- a/docs/cmdline-opts/post303.d
+++ b/docs/cmdline-opts/post303.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: post303
Help: Do not switch to GET after following a 303
@@ -7,6 +7,7 @@
Added: 7.26.0
Category: http post
Example: --post303 --location -d "data" $URL
+Multi: boolean
---
Tells curl to violate RFC 7231/6.4.4 and not convert POST requests into GET
requests when following 303 redirections. A server may require a POST to
diff --git a/docs/cmdline-opts/preproxy.d b/docs/cmdline-opts/preproxy.d
index 3f10a68..643179e 100644
--- a/docs/cmdline-opts/preproxy.d
+++ b/docs/cmdline-opts/preproxy.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: preproxy
Arg: [protocol://]host[:port]
@@ -7,6 +7,7 @@
Category: proxy
Example: --preproxy socks5://proxy.example -x http://http.example $URL
See-also: proxy socks5
+Multi: single
---
Use the specified SOCKS proxy before connecting to an HTTP or HTTPS --proxy. In
such a case curl first connects to the SOCKS proxy and then connects (through
@@ -23,5 +24,3 @@
User and password that might be provided in the proxy string are URL decoded
by curl. This allows you to pass in special characters such as @ by using %40
or pass in a colon with %3a.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/progress-bar.d b/docs/cmdline-opts/progress-bar.d
index 3a78530..a6cc8f5 100644
--- a/docs/cmdline-opts/progress-bar.d
+++ b/docs/cmdline-opts/progress-bar.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: #
Long: progress-bar
@@ -7,6 +7,8 @@
Example: -# -O $URL
Added: 5.10
See-also: styled-output
+Multi: boolean
+Scope: global
---
Make curl display transfer progress as a simple progress bar instead of the
standard, more informational, meter.
@@ -16,6 +18,3 @@
known size, there will be space ship (-=o=-) that moves back and forth but
only while data is being transferred, with a set of flying hash sign symbols on
top.
-
-This option is global and does not need to be specified for each use of
---next.
diff --git a/docs/cmdline-opts/proto-default.d b/docs/cmdline-opts/proto-default.d
index f9d4f6d..d5b4bcd 100644
--- a/docs/cmdline-opts/proto-default.d
+++ b/docs/cmdline-opts/proto-default.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proto-default
Help: Use PROTOCOL for any URL missing a scheme
@@ -7,6 +7,7 @@
Category: connection curl
Example: --proto-default https ftp.example.com
See-also: proto proto-redir
+Multi: single
---
Tells curl to use *protocol* for any URL missing a scheme name.
diff --git a/docs/cmdline-opts/proto-redir.d b/docs/cmdline-opts/proto-redir.d
index ea8c752..183b375 100644
--- a/docs/cmdline-opts/proto-redir.d
+++ b/docs/cmdline-opts/proto-redir.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proto-redir
Arg: <protocols>
@@ -7,6 +7,7 @@
Category: connection curl
Example: --proto-redir =http,https $URL
See-also: proto
+Multi: single
---
Tells curl to limit what protocols it may use on redirect. Protocols denied by
--proto are not overridden by this option. See --proto for how protocols are
diff --git a/docs/cmdline-opts/proto.d b/docs/cmdline-opts/proto.d
index 94d7243..ac024bf 100644
--- a/docs/cmdline-opts/proto.d
+++ b/docs/cmdline-opts/proto.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proto
Arg: <protocols>
@@ -7,10 +7,11 @@
Added: 7.20.2
Category: connection curl
Example: --proto =http,https,sftp $URL
+Multi: single
---
Tells curl to limit what protocols it may use for transfers. Protocols are
evaluated left to right, are comma separated, and are each a protocol name or
-\&'all', optionally prefixed by zero or more modifiers. Available modifiers are:
+'all', optionally prefixed by zero or more modifiers. Available modifiers are:
.RS
.TP 3
.B +
@@ -39,9 +40,9 @@
also only enables http and https
.RE
.IP
-Unknown protocols produce a warning. This allows scripts to safely rely on
-being able to disable potentially dangerous protocols, without relying upon
-support for that protocol being built into curl to avoid an error.
+Unknown and disabled protocols produce a warning. This allows scripts to
+safely rely on being able to disable potentially dangerous protocols, without
+relying upon support for that protocol being built into curl to avoid an error.
This option can be used multiple times, in which case the effect is the same
as concatenating the protocols into one instance of the option.
diff --git a/docs/cmdline-opts/proxy-anyauth.d b/docs/cmdline-opts/proxy-anyauth.d
index c7cdd04..fa46087 100644
--- a/docs/cmdline-opts/proxy-anyauth.d
+++ b/docs/cmdline-opts/proxy-anyauth.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-anyauth
Help: Pick any proxy authentication method
@@ -6,6 +6,7 @@
See-also: proxy proxy-basic proxy-digest
Category: proxy auth
Example: --proxy-anyauth --proxy-user user:passwd -x proxy $URL
+Multi: mutex
---
Tells curl to pick a suitable authentication method when communicating with
the given HTTP proxy. This might cause an extra request/response round-trip.
diff --git a/docs/cmdline-opts/proxy-basic.d b/docs/cmdline-opts/proxy-basic.d
index 608c9fa..ff56631 100644
--- a/docs/cmdline-opts/proxy-basic.d
+++ b/docs/cmdline-opts/proxy-basic.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-basic
Help: Use Basic authentication on the proxy
@@ -6,6 +6,7 @@
Category: proxy auth
Example: --proxy-basic --proxy-user user:passwd -x proxy $URL
Added: 7.12.0
+Multi: mutex
---
Tells curl to use HTTP Basic authentication when communicating with the given
proxy. Use --basic for enabling HTTP Basic with a remote host. Basic is the
diff --git a/docs/cmdline-opts/proxy-ca-native.d b/docs/cmdline-opts/proxy-ca-native.d
new file mode 100644
index 0000000..1498947
--- /dev/null
+++ b/docs/cmdline-opts/proxy-ca-native.d
@@ -0,0 +1,19 @@
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-ca-native
+Help: Use CA certificates from the native OS for proxy
+Protocols: TLS
+Category: tls
+See-also: cacert capath insecure
+Example: --ca-native $URL
+Added: 8.2.0
+Multi: boolean
+---
+Tells curl to use the CA store from the native operating system to verify the
+HTTPS proxy. By default, curl will otherwise use a CA store provided in a
+single file or directory, but when using this option it will interface the
+operating system's own vault.
+
+This option only works for curl on Windows when built to use OpenSSL. When
+curl on Windows is built to use Schannel, this feature is implied and curl
+then only uses the native CA store.
diff --git a/docs/cmdline-opts/proxy-cacert.d b/docs/cmdline-opts/proxy-cacert.d
index c05a03c..45dc3f3 100644
--- a/docs/cmdline-opts/proxy-cacert.d
+++ b/docs/cmdline-opts/proxy-cacert.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-cacert
Help: CA certificate to verify peer against for proxy
@@ -7,5 +7,6 @@
See-also: proxy-capath cacert capath proxy
Category: proxy tls
Example: --proxy-cacert CA-file.txt -x https://proxy $URL
+Multi: single
---
Same as --cacert but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-capath.d b/docs/cmdline-opts/proxy-capath.d
index 600e06e..309f940 100644
--- a/docs/cmdline-opts/proxy-capath.d
+++ b/docs/cmdline-opts/proxy-capath.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-capath
Help: CA directory to verify peer against for proxy
@@ -7,5 +7,6 @@
See-also: proxy-cacert proxy capath
Category: proxy tls
Example: --proxy-capath /local/directory -x https://proxy $URL
+Multi: single
---
Same as --capath but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-cert-type.d b/docs/cmdline-opts/proxy-cert-type.d
index 520a2b4..4ab38f5 100644
--- a/docs/cmdline-opts/proxy-cert-type.d
+++ b/docs/cmdline-opts/proxy-cert-type.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-cert-type
Arg: <type>
@@ -7,5 +7,6 @@
Category: proxy tls
Example: --proxy-cert-type PEM --proxy-cert file -x https://proxy $URL
See-also: proxy-cert
+Multi: single
---
Same as --cert-type but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-cert.d b/docs/cmdline-opts/proxy-cert.d
index 684b52c..2a869de 100644
--- a/docs/cmdline-opts/proxy-cert.d
+++ b/docs/cmdline-opts/proxy-cert.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-cert
Arg: <cert[:passwd]>
@@ -7,5 +7,6 @@
Category: proxy tls
Example: --proxy-cert file -x https://proxy $URL
See-also: proxy-cert-type
+Multi: single
---
Same as --cert but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-ciphers.d b/docs/cmdline-opts/proxy-ciphers.d
index 2b5c936..5879f39 100644
--- a/docs/cmdline-opts/proxy-ciphers.d
+++ b/docs/cmdline-opts/proxy-ciphers.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-ciphers
Arg: <list>
@@ -7,5 +7,12 @@
Category: proxy tls
Example: --proxy-ciphers ECDHE-ECDSA-AES256-CCM8 -x https://proxy $URL
See-also: ciphers curves proxy
+Multi: single
---
Same as --ciphers but used in HTTPS proxy context.
+
+Specifies which ciphers to use in the connection to the HTTPS proxy. The list
+of ciphers must specify valid ciphers. Read up on SSL cipher list details on
+this URL:
+
+https://curl.se/docs/ssl-ciphers.html
diff --git a/docs/cmdline-opts/proxy-crlfile.d b/docs/cmdline-opts/proxy-crlfile.d
index 9ece361..1a8fdf2 100644
--- a/docs/cmdline-opts/proxy-crlfile.d
+++ b/docs/cmdline-opts/proxy-crlfile.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-crlfile
Arg: <file>
@@ -7,5 +7,6 @@
Category: proxy tls
Example: --proxy-crlfile rejects.txt -x https://proxy $URL
See-also: crlfile proxy
+Multi: single
---
Same as --crlfile but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-digest.d b/docs/cmdline-opts/proxy-digest.d
index 0bcc9f3..c5cb19c 100644
--- a/docs/cmdline-opts/proxy-digest.d
+++ b/docs/cmdline-opts/proxy-digest.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-digest
Help: Use Digest authentication on the proxy
@@ -6,6 +6,7 @@
Category: proxy tls
Example: --proxy-digest --proxy-user user:passwd -x proxy $URL
Added: 7.12.0
+Multi: mutex
---
Tells curl to use HTTP Digest authentication when communicating with the given
proxy. Use --digest for enabling HTTP Digest with a remote host.
diff --git a/docs/cmdline-opts/proxy-header.d b/docs/cmdline-opts/proxy-header.d
index 64980ed..13efc11 100644
--- a/docs/cmdline-opts/proxy-header.d
+++ b/docs/cmdline-opts/proxy-header.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-header
Arg: <header/@file>
@@ -10,6 +10,7 @@
Example: --proxy-header "User-Agent: surprise" -x http://proxy $URL
Example: --proxy-header "Host:" -x http://proxy $URL
See-also: proxy
+Multi: append
---
Extra header to include in the request when sending HTTP to a proxy. You may
specify any number of extra headers. This is the equivalent option to --header
diff --git a/docs/cmdline-opts/proxy-http2.d b/docs/cmdline-opts/proxy-http2.d
new file mode 100644
index 0000000..0865300
--- /dev/null
+++ b/docs/cmdline-opts/proxy-http2.d
@@ -0,0 +1,18 @@
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-http2
+Tags: Versions HTTP/2
+Protocols: HTTP
+Added: 8.1.0
+Mutexed:
+Requires: HTTP/2
+See-also: proxy
+Help: Use HTTP/2 with HTTPS proxy
+Category: http proxy
+Example: --proxy-http2 -x proxy $URL
+Multi: boolean
+---
+Tells curl to try negotiate HTTP version 2 with an HTTPS proxy. The proxy might
+still only offer HTTP/1 and then curl will stick to using that version.
+
+This has no effect for any other kinds of proxies.
diff --git a/docs/cmdline-opts/proxy-insecure.d b/docs/cmdline-opts/proxy-insecure.d
index 4579246..beb8c25 100644
--- a/docs/cmdline-opts/proxy-insecure.d
+++ b/docs/cmdline-opts/proxy-insecure.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-insecure
Help: Do HTTPS proxy connections without verifying the proxy
@@ -6,5 +6,6 @@
Category: proxy tls
Example: --proxy-insecure -x https://proxy $URL
See-also: proxy insecure
+Multi: boolean
---
Same as --insecure but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-key-type.d b/docs/cmdline-opts/proxy-key-type.d
index c7b226d..3fd11f3 100644
--- a/docs/cmdline-opts/proxy-key-type.d
+++ b/docs/cmdline-opts/proxy-key-type.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-key-type
Arg: <type>
@@ -7,5 +7,6 @@
Category: proxy tls
Example: --proxy-key-type DER --proxy-key here -x https://proxy $URL
See-also: proxy-key proxy
+Multi: single
---
Same as --key-type but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-key.d b/docs/cmdline-opts/proxy-key.d
index 044f72e..4bf2748 100644
--- a/docs/cmdline-opts/proxy-key.d
+++ b/docs/cmdline-opts/proxy-key.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-key
Help: Private key for HTTPS proxy
@@ -7,5 +7,6 @@
Example: --proxy-key here -x https://proxy $URL
Added: 7.52.0
See-also: proxy-key-type proxy
+Multi: single
---
Same as --key but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-negotiate.d b/docs/cmdline-opts/proxy-negotiate.d
index 340873a..89b5c1b 100644
--- a/docs/cmdline-opts/proxy-negotiate.d
+++ b/docs/cmdline-opts/proxy-negotiate.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-negotiate
Help: Use HTTP Negotiate (SPNEGO) authentication on the proxy
@@ -6,6 +6,7 @@
See-also: proxy-anyauth proxy-basic
Category: proxy auth
Example: --proxy-negotiate --proxy-user user:passwd -x proxy $URL
+Multi: mutex
---
Tells curl to use HTTP Negotiate (SPNEGO) authentication when communicating
with the given proxy. Use --negotiate for enabling HTTP Negotiate (SPNEGO)
diff --git a/docs/cmdline-opts/proxy-ntlm.d b/docs/cmdline-opts/proxy-ntlm.d
index 424dc9c..f8481e5 100644
--- a/docs/cmdline-opts/proxy-ntlm.d
+++ b/docs/cmdline-opts/proxy-ntlm.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-ntlm
Help: Use NTLM authentication on the proxy
@@ -6,6 +6,7 @@
Category: proxy auth
Example: --proxy-ntlm --proxy-user user:passwd -x http://proxy $URL
Added: 7.10.7
+Multi: mutex
---
Tells curl to use HTTP NTLM authentication when communicating with the given
proxy. Use --ntlm for enabling NTLM with a remote host.
diff --git a/docs/cmdline-opts/proxy-pass.d b/docs/cmdline-opts/proxy-pass.d
index dbd9779..3071399 100644
--- a/docs/cmdline-opts/proxy-pass.d
+++ b/docs/cmdline-opts/proxy-pass.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-pass
Arg: <phrase>
@@ -7,5 +7,6 @@
Category: proxy tls auth
Example: --proxy-pass secret --proxy-key here -x https://proxy $URL
See-also: proxy proxy-key
+Multi: single
---
Same as --pass but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-pinnedpubkey.d b/docs/cmdline-opts/proxy-pinnedpubkey.d
index b6c644b..72f0cd1 100644
--- a/docs/cmdline-opts/proxy-pinnedpubkey.d
+++ b/docs/cmdline-opts/proxy-pinnedpubkey.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-pinnedpubkey
Arg: <hashes>
@@ -9,6 +9,7 @@
Example: --proxy-pinnedpubkey 'sha256//ce118b51897f4452dc' $URL
Added: 7.59.0
See-also: pinnedpubkey proxy
+Multi: single
---
Tells curl to use the specified public key file (or hashes) to verify the
proxy. This can be a path to a file which contains a single public key in PEM
@@ -19,5 +20,3 @@
indicating its identity. A public key is extracted from this certificate and
if it does not exactly match the public key provided to this option, curl will
abort the connection before sending or receiving any data.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/proxy-service-name.d b/docs/cmdline-opts/proxy-service-name.d
index 7ab263f..200973f 100644
--- a/docs/cmdline-opts/proxy-service-name.d
+++ b/docs/cmdline-opts/proxy-service-name.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-service-name
Arg: <name>
@@ -7,5 +7,6 @@
Category: proxy tls
Example: --proxy-service-name "shrubbery" -x proxy $URL
See-also: service-name proxy
+Multi: single
---
This option allows you to change the service name for proxy negotiation.
diff --git a/docs/cmdline-opts/proxy-ssl-allow-beast.d b/docs/cmdline-opts/proxy-ssl-allow-beast.d
index 787b50f..55ff62b 100644
--- a/docs/cmdline-opts/proxy-ssl-allow-beast.d
+++ b/docs/cmdline-opts/proxy-ssl-allow-beast.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-ssl-allow-beast
Help: Allow security flaw for interop for HTTPS proxy
@@ -6,5 +6,6 @@
Category: proxy tls
Example: --proxy-ssl-allow-beast -x https://proxy $URL
See-also: ssl-allow-beast proxy
+Multi: boolean
---
Same as --ssl-allow-beast but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-ssl-auto-client-cert.d b/docs/cmdline-opts/proxy-ssl-auto-client-cert.d
index ab1d898..ea0f0c0 100644
--- a/docs/cmdline-opts/proxy-ssl-auto-client-cert.d
+++ b/docs/cmdline-opts/proxy-ssl-auto-client-cert.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-ssl-auto-client-cert
Help: Use auto client certificate for proxy (Schannel)
@@ -6,5 +6,6 @@
Category: proxy tls
Example: --proxy-ssl-auto-client-cert -x https://proxy $URL
See-also: ssl-auto-client-cert proxy
+Multi: boolean
---
Same as --ssl-auto-client-cert but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-tls13-ciphers.d b/docs/cmdline-opts/proxy-tls13-ciphers.d
index 285e0cb..f18c3d5 100644
--- a/docs/cmdline-opts/proxy-tls13-ciphers.d
+++ b/docs/cmdline-opts/proxy-tls13-ciphers.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-tls13-ciphers
Arg: <ciphersuite list>
@@ -7,16 +7,15 @@
Category: proxy tls
Example: --proxy-tls13-ciphers TLS_AES_128_GCM_SHA256 -x proxy $URL
Added: 7.61.0
-See-also: tls13-ciphers curves
+See-also: tls13-ciphers curves proxy-ciphers
+Multi: single
---
Specifies which cipher suites to use in the connection to your HTTPS proxy
when it negotiates TLS 1.3. The list of ciphers suites must specify valid
ciphers. Read up on TLS 1.3 cipher suite details on this URL:
- https://curl.se/docs/ssl-ciphers.html
+https://curl.se/docs/ssl-ciphers.html
This option is currently used only when curl is built to use OpenSSL 1.1.1 or
later. If you are using a different SSL backend you can try setting TLS 1.3
cipher suites by using the --proxy-ciphers option.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/proxy-tlsauthtype.d b/docs/cmdline-opts/proxy-tlsauthtype.d
index fbee25f..f83153e 100644
--- a/docs/cmdline-opts/proxy-tlsauthtype.d
+++ b/docs/cmdline-opts/proxy-tlsauthtype.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-tlsauthtype
Arg: <type>
@@ -7,5 +7,6 @@
Category: proxy tls auth
Example: --proxy-tlsauthtype SRP -x https://proxy $URL
See-also: proxy proxy-tlsuser
+Multi: single
---
Same as --tlsauthtype but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-tlspassword.d b/docs/cmdline-opts/proxy-tlspassword.d
index c74400d..7ec0140 100644
--- a/docs/cmdline-opts/proxy-tlspassword.d
+++ b/docs/cmdline-opts/proxy-tlspassword.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-tlspassword
Arg: <string>
@@ -7,5 +7,6 @@
Category: proxy tls auth
Example: --proxy-tlspassword passwd -x https://proxy $URL
See-also: proxy proxy-tlsuser
+Multi: single
---
Same as --tlspassword but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-tlsuser.d b/docs/cmdline-opts/proxy-tlsuser.d
index 8e60cb5..17be7f7 100644
--- a/docs/cmdline-opts/proxy-tlsuser.d
+++ b/docs/cmdline-opts/proxy-tlsuser.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-tlsuser
Arg: <name>
@@ -7,5 +7,6 @@
Category: proxy tls auth
Example: --proxy-tlsuser smith -x https://proxy $URL
See-also: proxy proxy-tlspassword
+Multi: single
---
Same as --tlsuser but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-tlsv1.d b/docs/cmdline-opts/proxy-tlsv1.d
index 65ab3ee..c434502 100644
--- a/docs/cmdline-opts/proxy-tlsv1.d
+++ b/docs/cmdline-opts/proxy-tlsv1.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-tlsv1
Help: Use TLSv1 for HTTPS proxy
@@ -6,5 +6,6 @@
Category: proxy tls auth
Example: --proxy-tlsv1 -x https://proxy $URL
See-also: proxy
+Multi: mutex
---
Same as --tlsv1 but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-user.d b/docs/cmdline-opts/proxy-user.d
index 13e127a..5001ebb 100644
--- a/docs/cmdline-opts/proxy-user.d
+++ b/docs/cmdline-opts/proxy-user.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy-user
Short: U
@@ -8,6 +8,7 @@
Example: --proxy-user name:pwd -x proxy $URL
Added: 4.0
See-also: proxy-pass
+Multi: single
---
Specify the user name and password to use for proxy authentication.
@@ -20,5 +21,3 @@
getting seen by other users on the same system as they will still be visible
for a moment before cleared. Such sensitive data should be retrieved from a
file instead or similar and never used in clear text in a command line.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/proxy.d b/docs/cmdline-opts/proxy.d
index 7d2a4f0..8c85d39 100644
--- a/docs/cmdline-opts/proxy.d
+++ b/docs/cmdline-opts/proxy.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy
Short: x
@@ -8,6 +8,7 @@
Example: --proxy http://proxy.example $URL
Added: 4.0
See-also: socks5 proxy-basic
+Multi: single
---
Use the specified proxy.
@@ -20,7 +21,8 @@
part. e.g. socks5h://localhost/path/to/socket.sock
HTTPS proxy support via https:// protocol prefix was added in 7.52.0 for
-OpenSSL, GnuTLS and NSS.
+OpenSSL, GnuTLS and NSS. Since 7.87.0, it also works for BearSSL, mbedTLS,
+rustls, Schannel, Secure Transport and wolfSSL.
Unrecognized and unsupported proxy protocols cause an error since 7.52.0.
Prior versions may ignore the protocol and use http:// instead.
@@ -30,7 +32,7 @@
This option overrides existing environment variables that set the proxy to
use. If there's an environment variable setting a proxy, you can set proxy to
-\&"" to override it.
+"" to override it.
All operations that are performed over an HTTP proxy will transparently be
converted to HTTP. It means that certain protocol specific operations might
@@ -45,4 +47,5 @@
variables, including the protocol prefix (http://) and the embedded user +
password.
-If this option is used several times, the last one will be used.
+When a proxy is used, the active FTP mode as set with --ftp-port, cannot be
+used.
diff --git a/docs/cmdline-opts/proxy1.0.d b/docs/cmdline-opts/proxy1.0.d
index 07b7782..53a8dec 100644
--- a/docs/cmdline-opts/proxy1.0.d
+++ b/docs/cmdline-opts/proxy1.0.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxy1.0
Arg: <host[:port]>
@@ -7,6 +7,7 @@
Example: --proxy1.0 -x http://proxy $URL
Added: 7.19.4
See-also: proxy socks5 preproxy
+Multi: mutex
---
Use the specified HTTP 1.0 proxy. If the port number is not specified, it is
assumed at port 1080.
diff --git a/docs/cmdline-opts/proxytunnel.d b/docs/cmdline-opts/proxytunnel.d
index ec44fd7..f389406 100644
--- a/docs/cmdline-opts/proxytunnel.d
+++ b/docs/cmdline-opts/proxytunnel.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: proxytunnel
Short: p
@@ -7,6 +7,7 @@
Category: proxy
Example: --proxytunnel -x http://proxy $URL
Added: 7.3
+Multi: boolean
---
When an HTTP proxy is used --proxy, this option will make curl tunnel through
the proxy. The tunnel approach is made with the HTTP proxy CONNECT request and
diff --git a/docs/cmdline-opts/pubkey.d b/docs/cmdline-opts/pubkey.d
index c1dc99a..ef4a25f 100644
--- a/docs/cmdline-opts/pubkey.d
+++ b/docs/cmdline-opts/pubkey.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: pubkey
Arg: <key>
@@ -8,12 +8,11 @@
Example: --pubkey file.pub sftp://example.com/
Added: 7.16.2
See-also: pass
+Multi: single
---
Public key file name. Allows you to provide your public key in this separate
file.
-If this option is used several times, the last one will be used.
-
(As of 7.39.0, curl attempts to automatically extract the public key from the
private key file, so passing this option is generally not required. Note that
this public key extraction requires libcurl to be linked against a copy of
diff --git a/docs/cmdline-opts/quote.d b/docs/cmdline-opts/quote.d
index e410574..60893b3 100644
--- a/docs/cmdline-opts/quote.d
+++ b/docs/cmdline-opts/quote.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: quote
Arg: <command>
@@ -9,6 +9,7 @@
Example: --quote "DELE file" ftp://example.com/foo
Added: 5.3
See-also: request
+Multi: append
---
Send an arbitrary command to the remote FTP or SFTP server. Quote commands are
sent BEFORE the transfer takes place (just after the initial PWD command in an
@@ -29,47 +30,58 @@
You must send syntactically correct FTP commands as RFC 959 defines to FTP
servers, or one of the commands listed below to SFTP servers.
-This option can be used multiple times.
-
SFTP is a binary protocol. Unlike for FTP, curl interprets SFTP quote commands
itself before sending them to the server. File names may be quoted
shell-style to embed spaces or special characters. Following is the list of
all supported SFTP quote commands:
.RS
-.IP "atime date file"
+.TP
+.B "atime date file"
The atime command sets the last access time of the file named by the file
operand. The <date expression> can be all sorts of date strings, see the
*curl_getdate(3)* man page for date expression details. (Added in 7.73.0)
-.IP "chgrp group file"
+.TP
+.B "chgrp group file"
The chgrp command sets the group ID of the file named by the file operand to
the group ID specified by the group operand. The group operand is a decimal
integer group ID.
-.IP "chmod mode file"
+.TP
+.B "chmod mode file"
The chmod command modifies the file mode bits of the specified file. The
mode operand is an octal integer mode number.
-.IP "chown user file"
+.TP
+.B "chown user file"
The chown command sets the owner of the file named by the file operand to the
user ID specified by the user operand. The user operand is a decimal
integer user ID.
-.IP "ln source_file target_file"
+.TP
+.B "ln source_file target_file"
The ln and symlink commands create a symbolic link at the target_file location
pointing to the source_file location.
-.IP "mkdir directory_name"
+.TP
+.B "mkdir directory_name"
The mkdir command creates the directory named by the directory_name operand.
-.IP "mtime date file"
+.TP
+.B "mtime date file"
The mtime command sets the last modification time of the file named by the
file operand. The <date expression> can be all sorts of date strings, see the
*curl_getdate(3)* man page for date expression details. (Added in 7.73.0)
-.IP "pwd"
+.TP
+.B "pwd"
The pwd command returns the absolute pathname of the current working directory.
-.IP "rename source target"
+.TP
+.B "rename source target"
The rename command renames the file or directory named by the source
operand to the destination path named by the target operand.
-.IP "rm file"
+.TP
+.B "rm file"
The rm command removes the file specified by the file operand.
-.IP "rmdir directory"
+.TP
+.B "rmdir directory"
The rmdir command removes the directory entry specified by the directory
operand, provided it is empty.
-.IP "symlink source_file target_file"
+.TP
+.B "symlink source_file target_file"
See ln.
.RE
+.IP
diff --git a/docs/cmdline-opts/random-file.d b/docs/cmdline-opts/random-file.d
index dea2ec7..467d83a 100644
--- a/docs/cmdline-opts/random-file.d
+++ b/docs/cmdline-opts/random-file.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: random-file
Arg: <file>
@@ -7,6 +7,7 @@
Example: --random-file rubbish $URL
Added: 7.7
See-also: egd-file
+Multi: single
---
Deprecated option. This option is ignored by curl since 7.84.0. Prior to that
it only had an effect on curl if built to use old versions of OpenSSL.
diff --git a/docs/cmdline-opts/range.d b/docs/cmdline-opts/range.d
index 5d552b2..7fe19ca 100644
--- a/docs/cmdline-opts/range.d
+++ b/docs/cmdline-opts/range.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: range
Short: r
@@ -9,6 +9,7 @@
Example: --range 22-44 $URL
Added: 4.0
See-also: continue-at append
+Multi: single
---
Retrieve a byte range (i.e. a partial document) from an HTTP/1.1, FTP or SFTP
server or a local FILE. Ranges can be specified in a number of ways.
@@ -38,7 +39,7 @@
transforming this response is the responsibility of the caller.
Only digit characters (0-9) are valid in the 'start' and 'stop' fields of the
-\&'start-stop' range syntax. If a non-digit character is given in the range,
+'start-stop' range syntax. If a non-digit character is given in the range,
the server's response will be unspecified, depending on the server's
configuration.
@@ -49,5 +50,3 @@
FTP and SFTP range downloads only support the simple 'start-stop' syntax
(optionally with one of the numbers omitted). FTP use depends on the extended
FTP command SIZE.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/rate.d b/docs/cmdline-opts/rate.d
index 148c88f..232106a 100644
--- a/docs/cmdline-opts/rate.d
+++ b/docs/cmdline-opts/rate.d
@@ -1,14 +1,16 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: rate
Arg: <max request rate>
Help: Request rate for serial transfers
Category: connection
-Example: --rate 2/s $URL
-Example: --rate 3/h $URL
-Example: --rate 14/m $URL
+Example: --rate 2/s $URL ...
+Example: --rate 3/h $URL ...
+Example: --rate 14/m $URL ...
Added: 7.84.0
See-also: limit-rate retry-delay
+Multi: single
+Scope: global
---
Specify the maximum transfer frequency you allow curl to use - in number of
transfer starts per time unit (sometimes called request rate). Without this
@@ -31,5 +33,3 @@
When retrying transfers, enabled with --retry, the separate retry delay logic
is used and not this setting.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/raw.d b/docs/cmdline-opts/raw.d
index f87e926..0523d62 100644
--- a/docs/cmdline-opts/raw.d
+++ b/docs/cmdline-opts/raw.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: raw
Help: Do HTTP "raw"; no transfer decoding
@@ -7,6 +7,7 @@
Category: http
Example: --raw $URL
See-also: tr-encoding
+Multi: boolean
---
When used, it disables all internal HTTP decoding of content or transfer
encodings and instead makes them passed on unaltered, raw.
diff --git a/docs/cmdline-opts/referer.d b/docs/cmdline-opts/referer.d
index fbc2381..0609e8c 100644
--- a/docs/cmdline-opts/referer.d
+++ b/docs/cmdline-opts/referer.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: referer
Short: e
@@ -11,11 +11,10 @@
Example: --referer "https://fake.example;auto" -L $URL
Example: --referer ";auto" -L $URL
Added: 4.0
+Multi: single
---
Sends the "Referrer Page" information to the HTTP server. This can also be set
with the --header flag of course. When used with --location you can append
";auto" to the --referer URL to make curl automatically set the previous URL
-when it follows a Location: header. The \&";auto" string can be used alone,
+when it follows a Location: header. The ";auto" string can be used alone,
even if you do not set an initial --referer.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/remote-header-name.d b/docs/cmdline-opts/remote-header-name.d
index 0f22b84..8705b3b 100644
--- a/docs/cmdline-opts/remote-header-name.d
+++ b/docs/cmdline-opts/remote-header-name.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: remote-header-name
Short: J
@@ -8,6 +8,7 @@
Example: -OJ https://example.com/file
Added: 7.20.0
See-also: remote-name
+Multi: boolean
---
This option tells the --remote-name option to use the server-specified
Content-Disposition filename instead of extracting a filename from the URL. If
@@ -19,12 +20,15 @@
If the server specifies a file name and a file with that name already exists
in the destination directory, it will not be overwritten and an error will
-occur. If the server does not specify a file name then this option has no
-effect.
+occur - unless you allow it by using the --clobber option. If the server does
+not specify a file name then this option has no effect.
There's no attempt to decode %-sequences (yet) in the provided file name, so
this option may provide you with rather unexpected file names.
+This feature uses the name from the "filename" field, it does not yet support
+the "filename*" field (filenames with explicit character sets).
+
**WARNING**: Exercise judicious use of this option, especially on Windows. A
rogue server could send you the name of a DLL or other file that could be
loaded automatically by Windows or some third party software.
diff --git a/docs/cmdline-opts/remote-name-all.d b/docs/cmdline-opts/remote-name-all.d
index 8b2db66..249c4e2 100644
--- a/docs/cmdline-opts/remote-name-all.d
+++ b/docs/cmdline-opts/remote-name-all.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: remote-name-all
Help: Use the remote file name for all URLs
@@ -6,6 +6,7 @@
Category: output
Example: --remote-name-all ftp://example.com/file1 ftp://example.com/file2
See-also: remote-name
+Multi: boolean
---
This option changes the default action for all given URLs to be dealt with as
if --remote-name were used for each one. So if you want to disable that for a
diff --git a/docs/cmdline-opts/remote-name.d b/docs/cmdline-opts/remote-name.d
index 49a7aa3..8a4a9bc 100644
--- a/docs/cmdline-opts/remote-name.d
+++ b/docs/cmdline-opts/remote-name.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: remote-name
Short: O
@@ -7,6 +7,7 @@
Example: -O https://example.com/filename
Added: 4.0
See-also: remote-name-all output-dir remote-header-name
+Multi: append
---
Write output to a local file named like the remote file we get. (Only the file
part of the remote file is used, the path is cut off.)
diff --git a/docs/cmdline-opts/remote-time.d b/docs/cmdline-opts/remote-time.d
index 4b384c9..a8161c5 100644
--- a/docs/cmdline-opts/remote-time.d
+++ b/docs/cmdline-opts/remote-time.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: remote-time
Short: R
@@ -7,6 +7,7 @@
Example: --remote-time -o foo $URL
Added: 7.9
See-also: remote-name time-cond
+Multi: boolean
---
When used, this will make curl attempt to figure out the timestamp of the
remote file, and if that is available make the local file get that same
diff --git a/docs/cmdline-opts/remove-on-error.d b/docs/cmdline-opts/remove-on-error.d
index ebde0eb..50b7b1b 100644
--- a/docs/cmdline-opts/remove-on-error.d
+++ b/docs/cmdline-opts/remove-on-error.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: remove-on-error
Help: Remove output file on errors
@@ -6,6 +6,7 @@
Category: curl
Example: --remove-on-error -o output $URL
Added: 7.83.0
+Multi: boolean
---
When curl returns an error when told to save output in a local file, this
option removes that saved file before exiting. This prevents curl from
diff --git a/docs/cmdline-opts/request-target.d b/docs/cmdline-opts/request-target.d
index 18a386d..61ead5f 100644
--- a/docs/cmdline-opts/request-target.d
+++ b/docs/cmdline-opts/request-target.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: request-target
Arg: <path>
@@ -8,6 +8,7 @@
Category: http
Example: --request-target "*" -X OPTIONS $URL
See-also: request
+Multi: single
---
Tells curl to use an alternative "target" (path) instead of using the path as
provided in the URL. Particularly useful when wanting to issue HTTP requests
diff --git a/docs/cmdline-opts/request.d b/docs/cmdline-opts/request.d
index 6d80404..8fff3aa 100644
--- a/docs/cmdline-opts/request.d
+++ b/docs/cmdline-opts/request.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: request
Short: X
@@ -9,6 +9,7 @@
Example: -X NLST ftp://example.com/
Added: 6.0
See-also: request-target
+Multi: single
---
(HTTP) Specifies a custom request method to use when communicating with the
HTTP server. The specified request method will be used instead of the method
@@ -42,5 +43,3 @@
(SMTP)
Specifies a custom SMTP command to use instead of HELP or VRFY. (Added in 7.34.0)
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/resolve.d b/docs/cmdline-opts/resolve.d
index 3507b7e..bfecb14 100644
--- a/docs/cmdline-opts/resolve.d
+++ b/docs/cmdline-opts/resolve.d
@@ -1,12 +1,13 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: resolve
Arg: <[+]host:port:addr[,addr]...>
Help: Resolve the host+port to this address
Added: 7.21.3
-Category: connection
+Category: connection dns
Example: --resolve example.com:443:127.0.0.1 $URL
See-also: connect-to alt-svc
+Multi: append
---
Provide a custom address for a specific host and port pair. Using this, you
can make the curl requests(s) use a specified address and prevent the
diff --git a/docs/cmdline-opts/retry-all-errors.d b/docs/cmdline-opts/retry-all-errors.d
index da86a42..4e33612 100644
--- a/docs/cmdline-opts/retry-all-errors.d
+++ b/docs/cmdline-opts/retry-all-errors.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: retry-all-errors
Help: Retry all errors (use with --retry)
@@ -6,6 +6,7 @@
Category: curl
Example: --retry 5 --retry-all-errors $URL
See-also: retry
+Multi: boolean
---
Retry on any error. This option is used together with --retry.
diff --git a/docs/cmdline-opts/retry-connrefused.d b/docs/cmdline-opts/retry-connrefused.d
index 7517bf7..a7b9643 100644
--- a/docs/cmdline-opts/retry-connrefused.d
+++ b/docs/cmdline-opts/retry-connrefused.d
@@ -1,11 +1,12 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: retry-connrefused
Help: Retry on connection refused (use with --retry)
Added: 7.52.0
Category: curl
-Example: --retry-connrefused --retry $URL
+Example: --retry-connrefused --retry 7 $URL
See-also: retry retry-all-errors
+Multi: boolean
---
In addition to the other conditions, consider ECONNREFUSED as a transient
error too for --retry. This option is used together with --retry.
diff --git a/docs/cmdline-opts/retry-delay.d b/docs/cmdline-opts/retry-delay.d
index 45b0ed9..5f54897 100644
--- a/docs/cmdline-opts/retry-delay.d
+++ b/docs/cmdline-opts/retry-delay.d
@@ -1,16 +1,15 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: retry-delay
Arg: <seconds>
Help: Wait time between retries
Added: 7.12.3
Category: curl
-Example: --retry-delay 5 --retry $URL
+Example: --retry-delay 5 --retry 7 $URL
See-also: retry
+Multi: single
---
Make curl sleep this amount of time before each retry when a transfer has
failed with a transient error (it changes the default backoff time algorithm
between retries). This option is only interesting if --retry is also
used. Setting this delay to zero will make curl use the default backoff time.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/retry-max-time.d b/docs/cmdline-opts/retry-max-time.d
index 40d2421..a919dca 100644
--- a/docs/cmdline-opts/retry-max-time.d
+++ b/docs/cmdline-opts/retry-max-time.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: retry-max-time
Arg: <seconds>
@@ -7,6 +7,7 @@
Category: curl
Example: --retry-max-time 30 --retry 10 $URL
See-also: retry
+Multi: single
---
The retry timer is reset before the first transfer attempt. Retries will be
done as usual (see --retry) as long as the timer has not reached this given
@@ -14,5 +15,3 @@
made and while performing, it may take longer than this given time period. To
limit a single request's maximum time, use --max-time. Set this option to
zero to not timeout retries.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/retry.d b/docs/cmdline-opts/retry.d
index 1d4e01c..eddea1d 100644
--- a/docs/cmdline-opts/retry.d
+++ b/docs/cmdline-opts/retry.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: retry
Arg: <num>
@@ -7,6 +7,7 @@
Category: curl
Example: --retry 7 $URL
See-also: retry-max-time
+Multi: single
---
If a transient error is returned when curl tries to perform a transfer, it
will retry this number of times before giving up. Setting the number to 0
@@ -22,5 +23,3 @@
Since curl 7.66.0, curl will comply with the Retry-After: response header if
one was present to know when to issue the next retry.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/sasl-authzid.d b/docs/cmdline-opts/sasl-authzid.d
index a1f035e..904b3c8 100644
--- a/docs/cmdline-opts/sasl-authzid.d
+++ b/docs/cmdline-opts/sasl-authzid.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: sasl-authzid
Arg: <identity>
@@ -7,6 +7,7 @@
Category: auth
Example: --sasl-authzid zid imap://example.com/
See-also: login-options
+Multi: single
---
Use this authorization identity (authzid), during SASL PLAIN authentication,
in addition to the authentication identity (authcid) as specified by --user.
diff --git a/docs/cmdline-opts/sasl-ir.d b/docs/cmdline-opts/sasl-ir.d
index fb8fb8c..56f1ae8 100644
--- a/docs/cmdline-opts/sasl-ir.d
+++ b/docs/cmdline-opts/sasl-ir.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: sasl-ir
Help: Enable initial response in SASL authentication
@@ -6,5 +6,6 @@
Category: auth
Example: --sasl-ir imap://example.com/
See-also: sasl-authzid
+Multi: boolean
---
Enable initial response in SASL authentication.
diff --git a/docs/cmdline-opts/service-name.d b/docs/cmdline-opts/service-name.d
index 887a09e..0b4109e 100644
--- a/docs/cmdline-opts/service-name.d
+++ b/docs/cmdline-opts/service-name.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: service-name
Help: SPNEGO service name
@@ -7,6 +7,7 @@
Category: misc
Example: --service-name sockd/server $URL
See-also: negotiate proxy-service-name
+Multi: single
---
This option allows you to change the service name for SPNEGO.
diff --git a/docs/cmdline-opts/show-error.d b/docs/cmdline-opts/show-error.d
index 9a5d29e..f150287 100644
--- a/docs/cmdline-opts/show-error.d
+++ b/docs/cmdline-opts/show-error.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: show-error
Short: S
@@ -7,8 +7,7 @@
Category: curl
Example: --show-error --silent $URL
Added: 5.9
+Multi: boolean
+Scope: global
---
When used with --silent, it makes curl show an error message if it fails.
-
-This option is global and does not need to be specified for each use of
---next.
diff --git a/docs/cmdline-opts/silent.d b/docs/cmdline-opts/silent.d
index f0a788a..8742061 100644
--- a/docs/cmdline-opts/silent.d
+++ b/docs/cmdline-opts/silent.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: silent
Short: s
@@ -7,6 +7,7 @@
Category: important verbose
Example: -s $URL
Added: 4.0
+Multi: boolean
---
Silent or quiet mode. Do not show progress meter or error messages. Makes Curl
mute. It will still output the data you ask for, potentially even to the
diff --git a/docs/cmdline-opts/socks4.d b/docs/cmdline-opts/socks4.d
index 5c4f4b1..803032d 100644
--- a/docs/cmdline-opts/socks4.d
+++ b/docs/cmdline-opts/socks4.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: socks4
Arg: <host[:port]>
@@ -7,6 +7,7 @@
Category: proxy
Example: --socks4 hostname:4096 $URL
See-also: socks4a socks5 socks5-hostname
+Multi: single
---
Use the specified SOCKS4 proxy. If the port number is not specified, it is
assumed at port 1080. Using this socket type make curl resolve the host name
@@ -24,5 +25,3 @@
Since 7.52.0, --preproxy can be used to specify a SOCKS proxy at the same time
--proxy is used with an HTTP/HTTPS proxy. In such a case curl first connects to
the SOCKS proxy and then connects (through SOCKS) to the HTTP or HTTPS proxy.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/socks4a.d b/docs/cmdline-opts/socks4a.d
index 4b8c5f7..0d80600 100644
--- a/docs/cmdline-opts/socks4a.d
+++ b/docs/cmdline-opts/socks4a.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: socks4a
Arg: <host[:port]>
@@ -7,6 +7,7 @@
Category: proxy
Example: --socks4a hostname:4096 $URL
See-also: socks4 socks5 socks5-hostname
+Multi: single
---
Use the specified SOCKS4a proxy. If the port number is not specified, it is
assumed at port 1080. This asks the proxy to resolve the host name.
@@ -23,5 +24,3 @@
Since 7.52.0, --preproxy can be used to specify a SOCKS proxy at the same time
--proxy is used with an HTTP/HTTPS proxy. In such a case curl first connects to
the SOCKS proxy and then connects (through SOCKS) to the HTTP or HTTPS proxy.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/socks5-basic.d b/docs/cmdline-opts/socks5-basic.d
index d5c1b8a..a16831b 100644
--- a/docs/cmdline-opts/socks5-basic.d
+++ b/docs/cmdline-opts/socks5-basic.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: socks5-basic
Help: Enable username/password auth for SOCKS5 proxies
@@ -6,6 +6,7 @@
Category: proxy auth
Example: --socks5-basic --socks5 hostname:4096 $URL
See-also: socks5
+Multi: mutex
---
Tells curl to use username/password authentication when connecting to a SOCKS5
proxy. The username/password authentication is enabled by default. Use
diff --git a/docs/cmdline-opts/socks5-gssapi-nec.d b/docs/cmdline-opts/socks5-gssapi-nec.d
index 3f85b9a..957655a 100644
--- a/docs/cmdline-opts/socks5-gssapi-nec.d
+++ b/docs/cmdline-opts/socks5-gssapi-nec.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: socks5-gssapi-nec
Help: Compatibility with NEC SOCKS5 server
@@ -6,6 +6,7 @@
Category: proxy auth
Example: --socks5-gssapi-nec --socks5 hostname:4096 $URL
See-also: socks5
+Multi: boolean
---
As part of the GSS-API negotiation a protection mode is negotiated. RFC 1961
says in section 4.3/4.4 it should be protected, but the NEC reference
diff --git a/docs/cmdline-opts/socks5-gssapi-service.d b/docs/cmdline-opts/socks5-gssapi-service.d
index f092f7d..ac5b686 100644
--- a/docs/cmdline-opts/socks5-gssapi-service.d
+++ b/docs/cmdline-opts/socks5-gssapi-service.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: socks5-gssapi-service
Arg: <name>
@@ -7,6 +7,7 @@
Category: proxy auth
Example: --socks5-gssapi-service sockd --socks5 hostname:4096 $URL
See-also: socks5
+Multi: single
---
The default service name for a socks server is rcmd/server-fqdn. This option
allows you to change it.
diff --git a/docs/cmdline-opts/socks5-gssapi.d b/docs/cmdline-opts/socks5-gssapi.d
index ea2ffe5..cec684f 100644
--- a/docs/cmdline-opts/socks5-gssapi.d
+++ b/docs/cmdline-opts/socks5-gssapi.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: socks5-gssapi
Help: Enable GSS-API auth for SOCKS5 proxies
@@ -6,6 +6,7 @@
Category: proxy auth
Example: --socks5-gssapi --socks5 hostname:4096 $URL
See-also: socks5
+Multi: boolean
---
Tells curl to use GSS-API authentication when connecting to a SOCKS5 proxy.
The GSS-API authentication is enabled by default (if curl is compiled with
diff --git a/docs/cmdline-opts/socks5-hostname.d b/docs/cmdline-opts/socks5-hostname.d
index 04d8dbf..8845e19 100644
--- a/docs/cmdline-opts/socks5-hostname.d
+++ b/docs/cmdline-opts/socks5-hostname.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: socks5-hostname
Arg: <host[:port]>
@@ -7,6 +7,7 @@
Category: proxy
Example: --socks5-hostname proxy.example:7000 $URL
See-also: socks5 socks4a
+Multi: single
---
Use the specified SOCKS5 proxy (and let the proxy resolve the host name). If
the port number is not specified, it is assumed at port 1080.
@@ -23,5 +24,3 @@
Since 7.52.0, --preproxy can be used to specify a SOCKS proxy at the same time
--proxy is used with an HTTP/HTTPS proxy. In such a case curl first connects to
the SOCKS proxy and then connects (through SOCKS) to the HTTP or HTTPS proxy.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/socks5.d b/docs/cmdline-opts/socks5.d
index 0959ebd..c93c3f6 100644
--- a/docs/cmdline-opts/socks5.d
+++ b/docs/cmdline-opts/socks5.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: socks5
Arg: <host[:port]>
@@ -7,6 +7,7 @@
Category: proxy
Example: --socks5 proxy.example:7000 $URL
See-also: socks5-hostname socks4a
+Multi: single
---
Use the specified SOCKS5 proxy - but resolve the host name locally. If the
port number is not specified, it is assumed at port 1080.
@@ -24,6 +25,4 @@
--proxy is used with an HTTP/HTTPS proxy. In such a case curl first connects to
the SOCKS proxy and then connects (through SOCKS) to the HTTP or HTTPS proxy.
-If this option is used several times, the last one will be used.
-
This option (as well as --socks4) does not work with IPV6, FTPS or LDAP.
diff --git a/docs/cmdline-opts/speed-limit.d b/docs/cmdline-opts/speed-limit.d
index 4135743..dc9778d 100644
--- a/docs/cmdline-opts/speed-limit.d
+++ b/docs/cmdline-opts/speed-limit.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: speed-limit
Short: Y
@@ -8,9 +8,8 @@
Example: --speed-limit 300 --speed-time 10 $URL
Added: 4.7
See-also: speed-time limit-rate max-time
+Multi: single
---
If a transfer is slower than this given speed (in bytes per second) for
speed-time seconds it gets aborted. speed-time is set with --speed-time and is
30 if not set.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/speed-time.d b/docs/cmdline-opts/speed-time.d
index 0df1503..fe92b97 100644
--- a/docs/cmdline-opts/speed-time.d
+++ b/docs/cmdline-opts/speed-time.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: speed-time
Short: y
@@ -8,6 +8,7 @@
Example: --speed-limit 300 --speed-time 10 $URL
Added: 4.7
See-also: speed-limit limit-rate
+Multi: single
---
If a transfer runs slower than speed-limit bytes per second during a speed-time
period, the transfer is aborted. If speed-time is used, the default
@@ -15,5 +16,3 @@
This option controls transfers (in both directions) but will not affect slow
connects etc. If this is a concern for you, try the --connect-timeout option.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/ssl-allow-beast.d b/docs/cmdline-opts/ssl-allow-beast.d
index 361fd24..2547675 100644
--- a/docs/cmdline-opts/ssl-allow-beast.d
+++ b/docs/cmdline-opts/ssl-allow-beast.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ssl-allow-beast
Help: Allow security flaw to improve interop
@@ -6,6 +6,7 @@
Category: tls
Example: --ssl-allow-beast $URL
See-also: proxy-ssl-allow-beast insecure
+Multi: boolean
---
This option tells curl to not work around a security flaw in the SSL3 and
TLS1.0 protocols known as BEAST. If this option is not used, the SSL layer
diff --git a/docs/cmdline-opts/ssl-auto-client-cert.d b/docs/cmdline-opts/ssl-auto-client-cert.d
index 8c460c0..4eab1ab 100644
--- a/docs/cmdline-opts/ssl-auto-client-cert.d
+++ b/docs/cmdline-opts/ssl-auto-client-cert.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ssl-auto-client-cert
Help: Use auto client certificate (Schannel)
@@ -6,6 +6,7 @@
See-also: proxy-ssl-auto-client-cert
Category: tls
Example: --ssl-auto-client-cert $URL
+Multi: boolean
---
Tell libcurl to automatically locate and use a client certificate for
authentication, when requested by the server. This option is only supported
diff --git a/docs/cmdline-opts/ssl-no-revoke.d b/docs/cmdline-opts/ssl-no-revoke.d
index 84b0092..37e91d9 100644
--- a/docs/cmdline-opts/ssl-no-revoke.d
+++ b/docs/cmdline-opts/ssl-no-revoke.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ssl-no-revoke
Help: Disable cert revocation checks (Schannel)
@@ -6,6 +6,7 @@
Category: tls
Example: --ssl-no-revoke $URL
See-also: crlfile
+Multi: boolean
---
(Schannel) This option tells curl to disable certificate revocation checks.
WARNING: this option loosens the SSL security, and by using this flag you ask
diff --git a/docs/cmdline-opts/ssl-reqd.d b/docs/cmdline-opts/ssl-reqd.d
index 0c07184..acb7d34 100644
--- a/docs/cmdline-opts/ssl-reqd.d
+++ b/docs/cmdline-opts/ssl-reqd.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ssl-reqd
Help: Require SSL/TLS
@@ -7,12 +7,17 @@
Category: tls
Example: --ssl-reqd ftp://example.com
See-also: ssl insecure
+Multi: boolean
---
-Require SSL/TLS for the connection. Terminates the connection if the server
-does not support SSL/TLS.
+Require SSL/TLS for the connection. Terminates the connection if the transfer
+cannot be upgraded to use SSL/TLS.
This option is handled in LDAP since version 7.81.0. It is fully supported
-by the openldap backend and rejected by the generic ldap backend if explicit
+by the OpenLDAP backend and rejected by the generic ldap backend if explicit
TLS is required.
+This option is unnecessary if you use a URL scheme that in itself implies
+immediate and implicit use of TLS, like for FTPS, IMAPS, POP3S, SMTPS and
+LDAPS. Such transfers will always fail if the TLS handshake does not work.
+
This option was formerly known as --ftp-ssl-reqd.
diff --git a/docs/cmdline-opts/ssl-revoke-best-effort.d b/docs/cmdline-opts/ssl-revoke-best-effort.d
index 7594783..b2d94d5 100644
--- a/docs/cmdline-opts/ssl-revoke-best-effort.d
+++ b/docs/cmdline-opts/ssl-revoke-best-effort.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ssl-revoke-best-effort
Help: Ignore missing/offline cert CRL dist points
@@ -6,6 +6,7 @@
Category: tls
Example: --ssl-revoke-best-effort $URL
See-also: crlfile insecure
+Multi: boolean
---
(Schannel) This option tells curl to ignore certificate revocation checks when
they failed due to missing/offline distribution points for the revocation check
diff --git a/docs/cmdline-opts/ssl.d b/docs/cmdline-opts/ssl.d
index e9f23a3..b5d0e25 100644
--- a/docs/cmdline-opts/ssl.d
+++ b/docs/cmdline-opts/ssl.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: ssl
Help: Try SSL/TLS
@@ -6,14 +6,18 @@
Added: 7.20.0
Category: tls
Example: --ssl pop3://example.com/
-See-also: insecure ciphers
+See-also: ssl-reqd insecure ciphers
+Multi: boolean
---
+Warning: this is considered an insecure option. Consider using --ssl-reqd
+instead to be sure curl upgrades to a secure connection.
+
Try to use SSL/TLS for the connection. Reverts to a non-secure connection if
the server does not support SSL/TLS. See also --ftp-ssl-control and --ssl-reqd
for different levels of encryption required.
This option is handled in LDAP since version 7.81.0. It is fully supported
-by the openldap backend and ignored by the generic ldap backend.
+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.
diff --git a/docs/cmdline-opts/sslv2.d b/docs/cmdline-opts/sslv2.d
index 0a541d0..cef94ec 100644
--- a/docs/cmdline-opts/sslv2.d
+++ b/docs/cmdline-opts/sslv2.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: 2
Long: sslv2
@@ -11,6 +11,7 @@
Help: Use SSLv2
Category: tls
Example: --sslv2 $URL
+Multi: mutex
---
This option previously asked curl to use SSLv2, but starting in curl 7.77.0
this instruction is ignored. SSLv2 is widely considered insecure (see RFC
diff --git a/docs/cmdline-opts/sslv3.d b/docs/cmdline-opts/sslv3.d
index ba52910..e78a69a 100644
--- a/docs/cmdline-opts/sslv3.d
+++ b/docs/cmdline-opts/sslv3.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: 3
Long: sslv3
@@ -11,6 +11,7 @@
Help: Use SSLv3
Category: tls
Example: --sslv3 $URL
+Multi: mutex
---
This option previously asked curl to use SSLv3, but starting in curl 7.77.0
this instruction is ignored. SSLv3 is widely considered insecure (see RFC
diff --git a/docs/cmdline-opts/stderr.d b/docs/cmdline-opts/stderr.d
index 274c742..a80bf43 100644
--- a/docs/cmdline-opts/stderr.d
+++ b/docs/cmdline-opts/stderr.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: stderr
Arg: <file>
@@ -7,11 +7,8 @@
Category: verbose
Example: --stderr output.txt $URL
Added: 6.2
+Multi: single
+Scope: global
---
Redirect all writes to stderr to the specified file instead. If the file name
is a plain '-', it is instead written to stdout.
-
-This option is global and does not need to be specified for each use of
---next.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/styled-output.d b/docs/cmdline-opts/styled-output.d
index 2cc11e9..70e9da4 100644
--- a/docs/cmdline-opts/styled-output.d
+++ b/docs/cmdline-opts/styled-output.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: styled-output
Help: Enable styled output for HTTP headers
@@ -6,9 +6,11 @@
Category: verbose
Example: --styled-output -I $URL
See-also: head verbose
+Multi: boolean
+Scope: global
---
Enables the automatic use of bold font styles when writing HTTP headers to the
terminal. Use --no-styled-output to switch them off.
-This option is global and does not need to be specified for each use of
---next.
+Styled output requires a terminal that supports bold fonts. This feature is
+not present on curl for Windows due to lack of this capability.
diff --git a/docs/cmdline-opts/suppress-connect-headers.d b/docs/cmdline-opts/suppress-connect-headers.d
index 62e8820..ed38f36 100644
--- a/docs/cmdline-opts/suppress-connect-headers.d
+++ b/docs/cmdline-opts/suppress-connect-headers.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: suppress-connect-headers
Help: Suppress proxy CONNECT response headers
@@ -6,6 +6,7 @@
Category: proxy
Example: --suppress-connect-headers --include -x proxy $URL
Added: 7.54.0
+Multi: boolean
---
When --proxytunnel is used and a CONNECT request is made do not output proxy
CONNECT response headers. This option is meant to be used with --dump-header or
diff --git a/docs/cmdline-opts/tcp-fastopen.d b/docs/cmdline-opts/tcp-fastopen.d
index 36a5e28..bcf1edb 100644
--- a/docs/cmdline-opts/tcp-fastopen.d
+++ b/docs/cmdline-opts/tcp-fastopen.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tcp-fastopen
Added: 7.49.0
@@ -6,5 +6,9 @@
Category: connection
Example: --tcp-fastopen $URL
See-also: false-start
+Multi: boolean
---
-Enable use of TCP Fast Open (RFC7413).
+
+Enable use of TCP Fast Open (RFC 7413). TCP Fast Open is a TCP extension that
+allows data to get sent earlier over the connection (before the final
+handshake ACK) if the client and server have been connected previously.
diff --git a/docs/cmdline-opts/tcp-nodelay.d b/docs/cmdline-opts/tcp-nodelay.d
index a62d7f2..86b92fe 100644
--- a/docs/cmdline-opts/tcp-nodelay.d
+++ b/docs/cmdline-opts/tcp-nodelay.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tcp-nodelay
Help: Use the TCP_NODELAY option
@@ -6,6 +6,7 @@
Category: connection
Example: --tcp-nodelay $URL
See-also: no-buffer
+Multi: boolean
---
Turn on the TCP_NODELAY option. See the *curl_easy_setopt(3)* man page for
details about this option.
diff --git a/docs/cmdline-opts/telnet-option.d b/docs/cmdline-opts/telnet-option.d
index 4eed7ac..dc9ba6d 100644
--- a/docs/cmdline-opts/telnet-option.d
+++ b/docs/cmdline-opts/telnet-option.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: telnet-option
Short: t
@@ -8,6 +8,7 @@
Example: -t TTYPE=vt100 telnet://example.com/
Added: 7.7
See-also: config
+Multi: append
---
Pass options to the telnet protocol. Supported options are:
diff --git a/docs/cmdline-opts/tftp-blksize.d b/docs/cmdline-opts/tftp-blksize.d
index 823f69c..cd90242 100644
--- a/docs/cmdline-opts/tftp-blksize.d
+++ b/docs/cmdline-opts/tftp-blksize.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tftp-blksize
Arg: <value>
@@ -8,9 +8,8 @@
Category: tftp
Example: --tftp-blksize 1024 tftp://example.com/file
See-also: tftp-no-options
+Multi: single
---
Set TFTP BLKSIZE option (must be >512). This is the block size that curl will
try to use when transferring data to or from a TFTP server. By default 512
bytes will be used.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/tftp-no-options.d b/docs/cmdline-opts/tftp-no-options.d
index cdff872..43b1c00 100644
--- a/docs/cmdline-opts/tftp-no-options.d
+++ b/docs/cmdline-opts/tftp-no-options.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tftp-no-options
Help: Do not send any TFTP options
@@ -7,6 +7,7 @@
Category: tftp
Example: --tftp-no-options tftp://192.168.0.1/
See-also: tftp-blksize
+Multi: boolean
---
Tells curl not to send TFTP options requests.
diff --git a/docs/cmdline-opts/time-cond.d b/docs/cmdline-opts/time-cond.d
index 5fde251..aea4b3b 100644
--- a/docs/cmdline-opts/time-cond.d
+++ b/docs/cmdline-opts/time-cond.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: time-cond
Short: z
@@ -11,6 +11,7 @@
Example: -z file $URL
Added: 5.8
See-also: etag-compare remote-time
+Multi: single
---
Request a file that has been modified later than the given time and date, or
one that has been modified before that time. The <date expression> can be all
@@ -21,5 +22,3 @@
Start the date expression with a dash (-) to make it request for a document
that is older than the given date/time, default is a document that is newer
than the specified date/time.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/tls-max.d b/docs/cmdline-opts/tls-max.d
index a195734..2d52c10 100644
--- a/docs/cmdline-opts/tls-max.d
+++ b/docs/cmdline-opts/tls-max.d
@@ -1,9 +1,9 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tls-max
Arg: <VERSION>
Tags: Versions
-Protocols: SSL
+Protocols: TLS
Added: 7.54.0
Requires: TLS
See-also: tlsv1.0 tlsv1.1 tlsv1.2 tlsv1.3
@@ -11,6 +11,7 @@
Category: tls
Example: --tls-max 1.2 $URL
Example: --tls-max 1.3 --tlsv1.2 $URL
+Multi: single
---
VERSION defines maximum supported TLS version. The minimum acceptable version
is set by tlsv1.0, tlsv1.1, tlsv1.2 or tlsv1.3.
@@ -30,3 +31,4 @@
.IP "1.3"
Use up to TLSv1.3.
.RE
+.IP
diff --git a/docs/cmdline-opts/tls13-ciphers.d b/docs/cmdline-opts/tls13-ciphers.d
index 01d8de5..e319341 100644
--- a/docs/cmdline-opts/tls13-ciphers.d
+++ b/docs/cmdline-opts/tls13-ciphers.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tls13-ciphers
Arg: <ciphersuite list>
@@ -7,16 +7,15 @@
Category: tls
Example: --tls13-ciphers TLS_AES_128_GCM_SHA256 $URL
Added: 7.61.0
-See-also: ciphers curves
+See-also: ciphers curves proxy-tls13-ciphers
+Multi: single
---
Specifies which cipher suites to use in the connection if it negotiates TLS
1.3. The list of ciphers suites must specify valid ciphers. Read up on TLS 1.3
cipher suite details on this URL:
- https://curl.se/docs/ssl-ciphers.html
+https://curl.se/docs/ssl-ciphers.html
This option is currently used only when curl is built to use OpenSSL 1.1.1 or
-later. If you are using a different SSL backend you can try setting TLS 1.3
-cipher suites by using the --ciphers option.
-
-If this option is used several times, the last one will be used.
+later or Schannel. If you are using a different SSL backend you can try
+setting TLS 1.3 cipher suites by using the --ciphers option.
diff --git a/docs/cmdline-opts/tlsauthtype.d b/docs/cmdline-opts/tlsauthtype.d
index 239fdbe..7d3f7e5 100644
--- a/docs/cmdline-opts/tlsauthtype.d
+++ b/docs/cmdline-opts/tlsauthtype.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tlsauthtype
Arg: <type>
@@ -7,6 +7,7 @@
Category: tls auth
Example: --tlsauthtype SRP $URL
See-also: tlsuser
+Multi: single
---
Set TLS authentication type. Currently, the only supported option is "SRP",
for TLS-SRP (RFC 5054). If --tlsuser and --tlspassword are specified but
diff --git a/docs/cmdline-opts/tlspassword.d b/docs/cmdline-opts/tlspassword.d
index bc6e9d4..0513191 100644
--- a/docs/cmdline-opts/tlspassword.d
+++ b/docs/cmdline-opts/tlspassword.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tlspassword
Arg: <string>
@@ -7,6 +7,7 @@
Category: tls auth
Example: --tlspassword pwd --tlsuser user $URL
See-also: tlsuser
+Multi: single
---
Set password for use with the TLS authentication method specified with
--tlsauthtype. Requires that --tlsuser also be set.
diff --git a/docs/cmdline-opts/tlsuser.d b/docs/cmdline-opts/tlsuser.d
index 2a4f43e..f87532a 100644
--- a/docs/cmdline-opts/tlsuser.d
+++ b/docs/cmdline-opts/tlsuser.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tlsuser
Arg: <name>
@@ -7,6 +7,7 @@
Category: tls auth
Example: --tlspassword pwd --tlsuser user $URL
See-also: tlspassword
+Multi: single
---
Set username for use with the TLS authentication method specified with
--tlsauthtype. Requires that --tlspassword also is set.
diff --git a/docs/cmdline-opts/tlsv1.0.d b/docs/cmdline-opts/tlsv1.0.d
index f7c7059..493c0c6 100644
--- a/docs/cmdline-opts/tlsv1.0.d
+++ b/docs/cmdline-opts/tlsv1.0.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tlsv1.0
Help: Use TLSv1.0 or greater
@@ -7,6 +7,7 @@
Category: tls
Example: --tlsv1.0 $URL
See-also: tlsv1.3
+Multi: mutex
---
Forces curl to use TLS version 1.0 or later when connecting to a remote TLS server.
diff --git a/docs/cmdline-opts/tlsv1.1.d b/docs/cmdline-opts/tlsv1.1.d
index ae62dbe..f8ecdf6 100644
--- a/docs/cmdline-opts/tlsv1.1.d
+++ b/docs/cmdline-opts/tlsv1.1.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tlsv1.1
Help: Use TLSv1.1 or greater
@@ -7,6 +7,7 @@
Category: tls
Example: --tlsv1.1 $URL
See-also: tlsv1.3 tls-max
+Multi: mutex
---
Forces curl to use TLS version 1.1 or later when connecting to a remote TLS server.
diff --git a/docs/cmdline-opts/tlsv1.2.d b/docs/cmdline-opts/tlsv1.2.d
index 91b1729..a995360 100644
--- a/docs/cmdline-opts/tlsv1.2.d
+++ b/docs/cmdline-opts/tlsv1.2.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tlsv1.2
Help: Use TLSv1.2 or greater
@@ -7,6 +7,7 @@
Category: tls
Example: --tlsv1.2 $URL
See-also: tlsv1.3 tls-max
+Multi: mutex
---
Forces curl to use TLS version 1.2 or later when connecting to a remote TLS server.
diff --git a/docs/cmdline-opts/tlsv1.3.d b/docs/cmdline-opts/tlsv1.3.d
index 008ca78..5690aa1 100644
--- a/docs/cmdline-opts/tlsv1.3.d
+++ b/docs/cmdline-opts/tlsv1.3.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tlsv1.3
Help: Use TLSv1.3 or greater
@@ -7,6 +7,7 @@
Category: tls
Example: --tlsv1.3 $URL
See-also: tlsv1.2 tls-max
+Multi: mutex
---
Forces curl to use TLS version 1.3 or later when connecting to a remote TLS
server.
diff --git a/docs/cmdline-opts/tlsv1.d b/docs/cmdline-opts/tlsv1.d
index 6a7afbe..16aee71 100644
--- a/docs/cmdline-opts/tlsv1.d
+++ b/docs/cmdline-opts/tlsv1.d
@@ -1,9 +1,9 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: 1
Long: tlsv1
Tags: Versions
-Protocols: SSL
+Protocols: TLS
Added: 7.9.2
Mutexed: tlsv1.1 tlsv1.2 tlsv1.3
Requires: TLS
@@ -11,6 +11,7 @@
Help: Use TLSv1.0 or greater
Category: tls
Example: --tlsv1 $URL
+Multi: mutex
---
Tells curl to use at least TLS version 1.x when negotiating with a remote TLS
server. That means TLS version 1.0 or higher
diff --git a/docs/cmdline-opts/tr-encoding.d b/docs/cmdline-opts/tr-encoding.d
index 09f2988..053e18c 100644
--- a/docs/cmdline-opts/tr-encoding.d
+++ b/docs/cmdline-opts/tr-encoding.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: tr-encoding
Added: 7.21.6
@@ -7,6 +7,7 @@
Category: http
Example: --tr-encoding $URL
See-also: compressed
+Multi: boolean
---
Request a compressed Transfer-Encoding response using one of the algorithms
curl supports, and uncompress the data while receiving it.
diff --git a/docs/cmdline-opts/trace-ascii.d b/docs/cmdline-opts/trace-ascii.d
index 861730d..3d74b29 100644
--- a/docs/cmdline-opts/trace-ascii.d
+++ b/docs/cmdline-opts/trace-ascii.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: trace-ascii
Arg: <file>
@@ -8,6 +8,8 @@
Example: --trace-ascii log.txt $URL
Added: 7.9.7
See-also: verbose trace
+Multi: single
+Scope: global
---
Enables a full trace dump of all incoming and outgoing data, including
descriptive information, to the given output file. Use "-" as filename to have
@@ -16,8 +18,3 @@
This is similar to --trace, but leaves out the hex part and only shows the
ASCII part of the dump. It makes smaller output that might be easier to read
for untrained humans.
-
-This option is global and does not need to be specified for each use of
---next.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/trace-ids.d b/docs/cmdline-opts/trace-ids.d
new file mode 100644
index 0000000..7b8ce6f
--- /dev/null
+++ b/docs/cmdline-opts/trace-ids.d
@@ -0,0 +1,12 @@
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: trace-ids
+Help: Add transfer and connection identifiers to trace/verbose output
+Added: 8.2.0
+Category: verbose
+Example: --trace-ids --trace-ascii output $URL
+See-also: trace verbose
+Multi: boolean
+Scope: global
+---
+Prepends the transfer and connection identifiers to each trace or verbose line that curl displays.
diff --git a/docs/cmdline-opts/trace-time.d b/docs/cmdline-opts/trace-time.d
index 7e4cf85..f40ee02 100644
--- a/docs/cmdline-opts/trace-time.d
+++ b/docs/cmdline-opts/trace-time.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: trace-time
Help: Add time stamps to trace/verbose output
@@ -6,8 +6,7 @@
Category: verbose
Example: --trace-time --trace-ascii output $URL
See-also: trace verbose
+Multi: boolean
+Scope: global
---
Prepends a time stamp to each trace or verbose line that curl displays.
-
-This option is global and does not need to be specified for each use of
---next.
diff --git a/docs/cmdline-opts/trace.d b/docs/cmdline-opts/trace.d
index c1e4759..cc3087a 100644
--- a/docs/cmdline-opts/trace.d
+++ b/docs/cmdline-opts/trace.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: trace
Arg: <file>
@@ -7,14 +7,11 @@
Category: verbose
Example: --trace log.txt $URL
Added: 7.9.7
-See-also: trace-ascii trace-time
+See-also: trace-ascii trace-ids trace-time
+Multi: single
+Scope: global
---
Enables a full trace dump of all incoming and outgoing data, including
descriptive information, to the given output file. Use "-" as filename to have
the output sent to stdout. Use "%" as filename to have the output sent to
stderr.
-
-This option is global and does not need to be specified for each use of
---next.
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/unix-socket.d b/docs/cmdline-opts/unix-socket.d
index 73c87b4..5ea56eb 100644
--- a/docs/cmdline-opts/unix-socket.d
+++ b/docs/cmdline-opts/unix-socket.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: unix-socket
Arg: <path>
@@ -8,5 +8,6 @@
Category: connection
See-also: abstract-unix-socket
Example: --unix-socket socket-path $URL
+Multi: single
---
Connect through this Unix domain socket, instead of using the network.
diff --git a/docs/cmdline-opts/upload-file.d b/docs/cmdline-opts/upload-file.d
index 239952a..b6cbef1 100644
--- a/docs/cmdline-opts/upload-file.d
+++ b/docs/cmdline-opts/upload-file.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: upload-file
Short: T
@@ -10,6 +10,7 @@
Example: --upload-file "{file1,file2}" $URL
Added: 4.0
See-also: get head
+Multi: append
---
This transfers the specified local file to the remote URL. If there is no file
part in the specified URL, curl will append the local file name. NOTE that you
diff --git a/docs/cmdline-opts/url-query.d b/docs/cmdline-opts/url-query.d
new file mode 100644
index 0000000..29b31e3
--- /dev/null
+++ b/docs/cmdline-opts/url-query.d
@@ -0,0 +1,25 @@
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: url-query
+Arg: <data>
+Help: Add a URL query part
+Protocols: all
+See-also: data-urlencode get
+Added: 7.87.0
+Category: http post upload
+Example: --url-query name=val $URL
+Example: --url-query =encodethis http://example.net/foo
+Example: --url-query name@file $URL
+Example: --url-query @fileonly $URL
+Example: --url-query "+name=%20foo" $URL
+Multi: append
+---
+This option adds a piece of data, usually a name + value pair, to the end of
+the URL query part. The syntax is identical to that used for --data-urlencode
+with one extension:
+
+If the argument starts with a '+' (plus), the rest of the string is provided
+as-is unencoded.
+
+The query part of a URL is the one following the question mark on the right
+end.
diff --git a/docs/cmdline-opts/url.d b/docs/cmdline-opts/url.d
index 7f84a0d..df399cc 100644
--- a/docs/cmdline-opts/url.d
+++ b/docs/cmdline-opts/url.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: url
Arg: <url>
@@ -7,6 +7,7 @@
Example: --url $URL
Added: 7.5
See-also: next config
+Multi: append
---
Specify a URL to fetch. This option is mostly handy when you want to specify
URL(s) in a config file.
@@ -17,8 +18,8 @@
used, otherwise HTTP will be used. Since 7.45.0 guessing can be disabled by
setting a default protocol, see --proto-default for details.
-This option may be used any number of times. To control where this URL is
-written, use the --output or the --remote-name options.
+To control where this URL is written, use the --output or the --remote-name
+options.
**WARNING**: On Windows, particular file:// accesses can be converted to
network accesses by the operating system. Beware!
diff --git a/docs/cmdline-opts/use-ascii.d b/docs/cmdline-opts/use-ascii.d
index d27f653..772992c 100644
--- a/docs/cmdline-opts/use-ascii.d
+++ b/docs/cmdline-opts/use-ascii.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: B
Long: use-ascii
@@ -8,6 +8,7 @@
Example: -B ftp://example.com/README
Added: 5.0
See-also: crlf data-ascii
+Multi: boolean
---
Enable ASCII transfer. For FTP, this can also be enforced by using a URL that
ends with ";type=A". This option causes data sent to stdout to be in text mode
diff --git a/docs/cmdline-opts/user-agent.d b/docs/cmdline-opts/user-agent.d
index a5854bc..33cbe21 100644
--- a/docs/cmdline-opts/user-agent.d
+++ b/docs/cmdline-opts/user-agent.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: A
Long: user-agent
@@ -9,6 +9,7 @@
Example: -A "Agent 007" $URL
Added: 4.5.1
See-also: header proxy-header
+Multi: single
---
Specify the User-Agent string to send to the HTTP server. To encode blanks in
the string, surround the string with single quote marks. This header can also
@@ -17,5 +18,3 @@
If you give an empty argument to --user-agent (""), it will remove the header
completely from the request. If you prefer a blank header, you can set it to a
single space (" ").
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/user.d b/docs/cmdline-opts/user.d
index 197f39f..63ca4c5 100644
--- a/docs/cmdline-opts/user.d
+++ b/docs/cmdline-opts/user.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: user
Short: u
@@ -8,6 +8,7 @@
Example: -u user:secret $URL
Added: 4.0
See-also: netrc config
+Multi: single
---
Specify the user name and password to use for server authentication. Overrides
--netrc and --netrc-optional.
@@ -41,5 +42,3 @@
Negotiate, NTLM or Digest authentication then you can tell curl to select
the user name and password from your environment by specifying a single colon
with this option: "-u :".
-
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/verbose.d b/docs/cmdline-opts/verbose.d
index c4f5130..4036aad 100644
--- a/docs/cmdline-opts/verbose.d
+++ b/docs/cmdline-opts/verbose.d
@@ -1,13 +1,15 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Short: v
Long: verbose
Mutexed: trace trace-ascii
Help: Make the operation more talkative
-See-also: include
+See-also: include silent trace trace-ascii
Category: important verbose
Example: --verbose $URL
Added: 4.0
+Multi: boolean
+Scope: global
---
Makes curl verbose during the operation. Useful for debugging and seeing
what's going on "under the hood". A line starting with '>' means "header data"
@@ -15,13 +17,8 @@
normal cases, and a line starting with '*' means additional info provided by
curl.
-If you only want HTTP headers in the output, --include might be the option
-you are looking for.
+If you only want HTTP headers in the output, --include or --dump-header might
+be more suitable options.
If you think this option still does not give you enough details, consider using
--trace or --trace-ascii instead.
-
-This option is global and does not need to be specified for each use of
---next.
-
-Use --silent to make curl really quiet.
diff --git a/docs/cmdline-opts/version.d b/docs/cmdline-opts/version.d
index 459e85e..2cfabdc 100644
--- a/docs/cmdline-opts/version.d
+++ b/docs/cmdline-opts/version.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: version
Short: V
@@ -7,6 +7,7 @@
Example: --version
Added: 4.0
See-also: help manual
+Multi: custom
---
Displays information about curl and the libcurl version it uses.
@@ -82,3 +83,4 @@
.IP "zstd"
Automatic decompression (via zstd) of compressed files over HTTP is supported.
.RE
+.IP
diff --git a/docs/cmdline-opts/write-out.d b/docs/cmdline-opts/write-out.d
index 5a436b9..e2fc2db 100644
--- a/docs/cmdline-opts/write-out.d
+++ b/docs/cmdline-opts/write-out.d
@@ -1,13 +1,14 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: write-out
Short: w
Arg: <format>
Help: Use output FORMAT after completion
Category: verbose
-Example: -w '%{http_code}\\n' $URL
+Example: -w '%{response_code}\\n' $URL
Added: 6.5
See-also: verbose head
+Multi: single
---
Make curl display information on stdout after a completed transfer. The format
is a string that may contain plain text mixed with any number of
@@ -30,12 +31,18 @@
with leading and trailing whitespace trimmed. Added in curl 7.84.0.
.B NOTE:
-The %-symbol is a special symbol in the win32-environment, where all
-occurrences of % must be doubled when using this option.
+In Windows the %-symbol is a special symbol used to expand environment
+variables. In batch files all occurrences of % must be doubled when using this
+option to properly escape. If this option is used at the command prompt then
+the % cannot be escaped and unintended expansion is possible.
The variables available are:
.RS
.TP 15
+.B certs
+Output the certificate chain with details. Supported only by the OpenSSL,
+GnuTLS, Schannel, NSS, GSKit and Secure Transport backends. (Added in 7.88.0)
+.TP
.B content_type
The Content-Type of the requested document, if there was any.
.TP
@@ -58,7 +65,7 @@
.B header_json
A JSON object with all HTTP response headers from the recent transfer. Values
are provided as arrays, since in the case of multiple headers there can be
-multiple values.
+multiple values. (Added in 7.83.0)
The header names provided in lowercase, listed in order of appearance over the
wire. Except for duplicated headers. They are grouped on the first occurrence
@@ -88,6 +95,11 @@
.B method
The http method used in the most recent HTTP request. (Added in 7.72.0)
.TP
+.B num_certs
+Number of server certificates received in the TLS handshake. Supported only by
+the OpenSSL, GnuTLS, Schannel, NSS, GSKit and Secure Transport backends. (Added
+in 7.88.0)
+.TP
.B num_connects
Number of new connects made in the recent transfer. (Added in 7.12.3)
.TP
@@ -99,7 +111,7 @@
Number of redirects that were followed in the request. (Added in 7.12.3)
.TP
.B onerror
-The rest of the output is only shown if the transfer returned a non-zero error
+The rest of the output is only shown if the transfer returned a non-zero error.
(Added in 7.75.0)
.TP
.B proxy_ssl_verify_result
@@ -197,6 +209,70 @@
.B url
The URL that was fetched. (Added in 7.75.0)
.TP
+.B url.scheme
+The scheme part of the URL that was fetched. (Added in 8.1.0)
+.TP
+.B url.user
+The user part of the URL that was fetched. (Added in 8.1.0)
+.TP
+.B url.password
+The password part of the URL that was fetched. (Added in 8.1.0)
+.TP
+.B url.options
+The options part of the URL that was fetched. (Added in 8.1.0)
+.TP
+.B url.host
+The host part of the URL that was fetched. (Added in 8.1.0)
+.TP
+.B url.port
+The port number of the URL that was fetched. If no port number was specified,
+but the URL scheme is known, that scheme's default port number is
+shown. (Added in 8.1.0)
+.TP
+.B url.path
+The path part of the URL that was fetched. (Added in 8.1.0)
+.TP
+.B url.query
+The query part of the URL that was fetched. (Added in 8.1.0)
+.TP
+.B url.fragment
+The fragment part of the URL that was fetched. (Added in 8.1.0)
+.TP
+.B url.zoneid
+The zoneid part of the URL that was fetched. (Added in 8.1.0)
+.TP
+.B urle.scheme
+The scheme part of the effective (last) URL that was fetched. (Added in 8.1.0)
+.TP
+.B urle.user
+The user part of the effective (last) URL that was fetched. (Added in 8.1.0)
+.TP
+.B urle.password
+The password part of the effective (last) URL that was fetched. (Added in 8.1.0)
+.TP
+.B urle.options
+The options part of the effective (last) URL that was fetched. (Added in 8.1.0)
+.TP
+.B urle.host
+The host part of the effective (last) URL that was fetched. (Added in 8.1.0)
+.TP
+.B urle.port
+The port number of the effective (last) URL that was fetched. If no port
+number was specified, but the URL scheme is known, that scheme's default port
+number is shown. (Added in 8.1.0)
+.TP
+.B urle.path
+The path part of the effective (last) URL that was fetched. (Added in 8.1.0)
+.TP
+.B urle.query
+The query part of the effective (last) URL that was fetched. (Added in 8.1.0)
+.TP
+.B urle.fragment
+The fragment part of the effective (last) URL that was fetched. (Added in 8.1.0)
+.TP
+.B urle.zoneid
+The zoneid part of the effective (last) URL that was fetched. (Added in 8.1.0)
+.TP
.B urlnum
The URL index number of this transfer, 0-indexed. De-globbed URLs share the
same index number as the origin globbed URL. (Added in 7.75.0)
@@ -206,4 +282,3 @@
to follow location: headers.
.RE
.IP
-If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/xattr.d b/docs/cmdline-opts/xattr.d
index f8b6e49..31bdb2d 100644
--- a/docs/cmdline-opts/xattr.d
+++ b/docs/cmdline-opts/xattr.d
@@ -1,4 +1,4 @@
-c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: xattr
Help: Store metadata in extended file attributes
@@ -6,6 +6,7 @@
Example: --xattr -o storage $URL
Added: 7.21.3
See-also: remote-time write-out verbose
+Multi: boolean
---
When saving output to a file, this option tells curl to store certain file
metadata in extended file attributes. Currently, the URL is stored in the
diff --git a/docs/curl-config.1 b/docs/curl-config.1
index 8151b26..65cd2c9 100644
--- a/docs/curl-config.1
+++ b/docs/curl-config.1
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH curl-config 1 "25 Oct 2007" "Curl 7.17.1" "curl-config manual"
+.TH curl-config 1 "25 Oct 2007" curl-config curl-config
.SH NAME
curl-config \- Get information about a libcurl installation
.SH SYNOPSIS
@@ -62,9 +62,9 @@
.IP "--protocols"
Lists what particular protocols the installed libcurl was built to support. At
the time of writing, this list may include HTTP, HTTPS, FTP, FTPS, FILE,
-TELNET, LDAP, DICT. Do not assume any particular order. The protocols will
-be listed using uppercase and are separated by newlines. There may be none,
-one, or several protocols in the list. (Added in 7.13.0)
+TELNET, LDAP, DICT and many more. Do not assume any particular order. The
+protocols will be listed using uppercase and are separated by newlines. There
+may be none, one, or several protocols in the list. (Added in 7.13.0)
.IP "--ssl-backends"
Lists the SSL backends that were enabled when libcurl was built. It might be
no, one or several names. If more than one name, they will appear
@@ -82,23 +82,24 @@
omitted. (This option was broken in the 7.15.0 release.)
.SH "EXAMPLES"
What linker options do I need when I link with libcurl?
-
+.nf
$ curl-config --libs
-
+.fi
What compiler options do I need when I compile using libcurl functions?
-
+.nf
$ curl-config --cflags
-
+.fi
How do I know if libcurl was built with SSL support?
-
+.nf
$ curl-config --feature | grep SSL
-
+.fi
What's the installed libcurl version?
-
+.nf
$ curl-config --version
-
+.fi
How do I build a single file with a one-line command?
-
+.nf
$ `curl-config --cc --cflags` -o example example.c `curl-config --libs`
+.fi
.SH "SEE ALSO"
.BR curl (1)
diff --git a/docs/examples/.gitignore b/docs/examples/.gitignore
index 3443a8f..f9a2c77 100644
--- a/docs/examples/.gitignore
+++ b/docs/examples/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/docs/examples/10-at-a-time.c b/docs/examples/10-at-a-time.c
index 1739a9e..b54a441 100644
--- a/docs/examples/10-at-a-time.c
+++ b/docs/examples/10-at-a-time.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -95,13 +95,14 @@
return n*l;
}
-static void add_transfer(CURLM *cm, int i)
+static void add_transfer(CURLM *cm, 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);
+ (*left)++;
}
int main(void)
@@ -110,7 +111,7 @@
CURLMsg *msg;
unsigned int transfers = 0;
int msgs_left = -1;
- int still_alive = 1;
+ int left = 0;
curl_global_init(CURL_GLOBAL_ALL);
cm = curl_multi_init();
@@ -118,10 +119,12 @@
/* Limit the amount of simultaneous connections curl should allow: */
curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, (long)MAX_PARALLEL);
- for(transfers = 0; transfers < MAX_PARALLEL; transfers++)
- add_transfer(cm, transfers);
+ for(transfers = 0; transfers < MAX_PARALLEL && transfers < NUM_URLS;
+ transfers++)
+ add_transfer(cm, transfers, &left);
do {
+ int still_alive = 1;
curl_multi_perform(cm, &still_alive);
while((msg = curl_multi_info_read(cm, &msgs_left))) {
@@ -133,17 +136,18 @@
msg->data.result, curl_easy_strerror(msg->data.result), url);
curl_multi_remove_handle(cm, e);
curl_easy_cleanup(e);
+ left--;
}
else {
fprintf(stderr, "E: CURLMsg (%d)\n", msg->msg);
}
if(transfers < NUM_URLS)
- add_transfer(cm, transfers++);
+ add_transfer(cm, transfers++, &left);
}
- if(still_alive)
+ if(left)
curl_multi_wait(cm, NULL, 0, 1000, NULL);
- } while(still_alive || (transfers < NUM_URLS));
+ } while(left);
curl_multi_cleanup(cm);
curl_global_cleanup();
diff --git a/docs/examples/Makefile.am b/docs/examples/Makefile.am
index 6759d97..80ccc59 100644
--- a/docs/examples/Makefile.am
+++ b/docs/examples/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -24,8 +24,8 @@
AUTOMAKE_OPTIONS = foreign nostdinc
-EXTRA_DIST = README.md Makefile.example Makefile.inc Makefile.m32 \
- makefile.dj $(COMPLICATED_EXAMPLES) .checksrc
+EXTRA_DIST = README.md Makefile.example Makefile.inc Makefile.mk \
+ $(COMPLICATED_EXAMPLES) .checksrc
# Specify our include paths here, and do it relative to $(top_srcdir) and
# $(top_builddir), to ensure that these paths which belong to the library
@@ -34,7 +34,8 @@
#
# $(top_srcdir)/include is for libcurl's external include files
-AM_CPPFLAGS = -I$(top_srcdir)/include
+AM_CPPFLAGS = -I$(top_srcdir)/include \
+ -DCURL_DISABLE_DEPRECATION
LIBDIR = $(top_builddir)/lib
diff --git a/docs/examples/Makefile.example b/docs/examples/Makefile.example
index b05ca8e..cde0046 100644
--- a/docs/examples/Makefile.example
+++ b/docs/examples/Makefile.example
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/docs/examples/Makefile.inc b/docs/examples/Makefile.inc
index c25c6d8..6831365 100644
--- a/docs/examples/Makefile.inc
+++ b/docs/examples/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -29,8 +29,10 @@
anyauthput \
certinfo \
chkspeed \
+ connect-to \
cookie_interface \
debug \
+ default-scheme \
externalsocket \
fileupload \
ftp-wildcard \
@@ -46,6 +48,8 @@
getredirect \
getreferrer \
headerapi \
+ hsts-preload \
+ http-options \
http-post \
http2-download \
http2-pushinmemory \
@@ -72,6 +76,8 @@
imap-ssl \
imap-store \
imap-tls \
+ ipv6 \
+ maxconnects \
multi-app \
multi-debugcallback \
multi-double \
@@ -97,6 +103,7 @@
postit2 \
postit2-formadd \
progressfunc \
+ protofeats \
resolve \
sendrecv \
sepheaders \
@@ -115,16 +122,17 @@
smtp-tls \
smtp-vrfy \
sslbackend \
+ unixsocket \
url2file \
- urlapi
+ urlapi \
+ websocket \
+ websocket-cb
# These examples require external dependencies that may not be commonly
# available on POSIX systems, so don't bother attempting to compile them here.
COMPLICATED_EXAMPLES = \
cacertinmem.c \
crawler.c \
- curlgtk.c \
- curlx.c \
ephiperfifo.c \
evhiperfifo.c \
ghiper.c \
@@ -135,7 +143,6 @@
multi-event.c \
multi-uv.c \
multithread.c \
- opensslthreadlock.c \
sessioninfo.c \
smooth-gtk-thread.c \
synctime.c \
diff --git a/docs/examples/Makefile.m32 b/docs/examples/Makefile.m32
deleted file mode 100644
index 15eaf82..0000000
--- a/docs/examples/Makefile.m32
+++ /dev/null
@@ -1,403 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-#***************************************************************************
-
-###########################################################################
-#
-## Makefile for building curl examples with MingW (GCC-3.2 or later)
-## and optionally OpenSSL (1.0.2a), libssh2 (1.5), zlib (1.2.8), librtmp (2.4),
-## brotli (1.0.1), zstd (1.4.5)
-##
-## Usage: mingw32-make -f Makefile.m32 CFG=-feature1[-feature2][-feature3][...]
-## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-sspi-winidn
-##
-## Hint: you can also set environment vars to control the build, f.e.:
-## set ZLIB_PATH=c:/zlib-1.2.8
-## set ZLIB=1
-#
-###########################################################################
-
-# Edit the path below to point to the base of your Zlib sources.
-ifndef ZLIB_PATH
-ZLIB_PATH = ../../../zlib-1.2.8
-endif
-# Edit the path below to point to the base of your Zstandard sources.
-ifndef ZSTD_PATH
-ZSTD_PATH = ../../../zstd-1.4.5
-endif
-# Edit the path below to point to the base of your Brotli sources.
-ifndef BROTLI_PATH
-BROTLI_PATH = ../../../brotli-1.0.1
-endif
-# Edit the path below to point to the base of your OpenSSL package.
-ifndef OPENSSL_PATH
-OPENSSL_PATH = ../../../openssl-1.0.2a
-endif
-# Edit the path below to point to the base of your LibSSH2 package.
-ifndef LIBSSH2_PATH
-LIBSSH2_PATH = ../../../libssh2-1.5.0
-endif
-# Edit the path below to point to the base of your librtmp package.
-ifndef LIBRTMP_PATH
-LIBRTMP_PATH = ../../../librtmp-2.4
-endif
-# Edit the path below to point to the base of your libexpat package.
-ifndef LIBEXPAT_PATH
-LIBEXPAT_PATH = ../../../expat-2.1.0
-endif
-# Edit the path below to point to the base of your libxml2 package.
-ifndef LIBXML2_PATH
-LIBXML2_PATH = ../../../libxml2-2.9.2
-endif
-# Edit the path below to point to the base of your libgsasl package.
-ifndef LIBGSASL_PATH
-LIBGSASL_PATH = ../../../libgsasl-1.10.0
-endif
-# Edit the path below to point to the base of your libidn2 package.
-ifndef LIBIDN2_PATH
-LIBIDN2_PATH = ../../../libidn2-2.0.3
-endif
-# Edit the path below to point to the base of your MS IDN package.
-# Microsoft Internationalized Domain Names (IDN) Mitigation APIs 1.1
-# https://www.microsoft.com/en-us/download/details.aspx?id=734
-ifndef WINIDN_PATH
-WINIDN_PATH = ../../../Microsoft IDN Mitigation APIs
-endif
-# Edit the path below to point to the base of your Novell LDAP NDK.
-ifndef LDAP_SDK
-LDAP_SDK = c:/novell/ndk/cldapsdk/win32
-endif
-# Edit the path below to point to the base of your nghttp2 package.
-ifndef NGHTTP2_PATH
-NGHTTP2_PATH = ../../../nghttp2-1.0.0
-endif
-# Edit the path below to point to the base of your nghttp3 package.
-ifndef NGHTTP3_PATH
-NGHTTP3_PATH = ../../../nghttp3-1.0.0
-endif
-# Edit the path below to point to the base of your ngtcp2 package.
-ifndef NGTCP2_PATH
-NGTCP2_PATH = ../../../ngtcp2-1.0.0
-endif
-
-PROOT = ../..
-
-# Edit the path below to point to the base of your c-ares package.
-ifndef LIBCARES_PATH
-LIBCARES_PATH = $(PROOT)/ares
-endif
-
-ifeq ($(CURL_CC),)
-CURL_CC := $(CROSSPREFIX)gcc
-endif
-ifeq ($(CURL_AR),)
-CURL_AR := $(CROSSPREFIX)ar
-endif
-
-CC = $(CURL_CC)
-CFLAGS = -O3 $(CURL_CFLAG_EXTRAS) -W -Wall
-LDFLAGS = $(CURL_LDFLAG_EXTRAS) $(CURL_LDFLAG_EXTRAS_EXE)
-RC = $(CROSSPREFIX)windres
-RCFLAGS = --include-dir=$(PROOT)/include -O coff
-
-# Set environment var ARCH to your architecture to override autodetection.
-ifndef ARCH
-ifeq ($(findstring x86_64,$(shell $(CC) -dumpmachine)),x86_64)
-ARCH = w64
-else
-ARCH = w32
-endif
-endif
-
-ifeq ($(ARCH),w64)
-CFLAGS += -m64
-LDFLAGS += -m64
-RCFLAGS += -F pe-x86-64
-else
-CFLAGS += -m32
-LDFLAGS += -m32
-RCFLAGS += -F pe-i386
-endif
-
-# Platform-dependent helper tool macros
-ifeq ($(findstring /sh,$(SHELL)),/sh)
-DEL = rm -f $1
-RMDIR = rm -fr $1
-MKDIR = mkdir -p $1
-COPY = -cp -afv $1 $2
-#COPYR = -cp -afr $1/* $2
-COPYR = -rsync -aC $1/* $2
-TOUCH = touch $1
-CAT = cat
-ECHONL = echo ""
-DL = '
-else
-ifeq "$(OS)" "Windows_NT"
-DEL = -del 2>NUL /q /f $(subst /,\,$1)
-RMDIR = -rd 2>NUL /q /s $(subst /,\,$1)
-else
-DEL = -del 2>NUL $(subst /,\,$1)
-RMDIR = -deltree 2>NUL /y $(subst /,\,$1)
-endif
-MKDIR = -md 2>NUL $(subst /,\,$1)
-COPY = -copy 2>NUL /y $(subst /,\,$1) $(subst /,\,$2)
-COPYR = -xcopy 2>NUL /q /y /e $(subst /,\,$1) $(subst /,\,$2)
-TOUCH = copy 2>&1>NUL /b $(subst /,\,$1) +,,
-CAT = type
-ECHONL = $(ComSpec) /c echo.
-endif
-
-########################################################
-## Nothing more to do below this line!
-
-ifneq ($(findstring -dyn,$(CFG)),)
-DYN = 1
-endif
-ifneq ($(findstring -ares,$(CFG)),)
-ARES = 1
-endif
-ifneq ($(findstring -rtmp,$(CFG)),)
-RTMP = 1
-ZLIB = 1
-endif
-ifneq ($(findstring -ssh2,$(CFG)),)
-SSH2 = 1
-ZLIB = 1
-endif
-ifneq ($(findstring -ssl,$(CFG)),)
-SSL = 1
-endif
-ifneq ($(findstring -zlib,$(CFG)),)
-ZLIB = 1
-endif
-ifneq ($(findstring -zstd,$(CFG)),)
-ZSTD = 1
-endif
-ifneq ($(findstring -brotli,$(CFG)),)
-BROTLI = 1
-endif
-ifneq ($(findstring -gsasl,$(CFG)),)
-GSASL = 1
-endif
-ifneq ($(findstring -idn2,$(CFG)),)
-IDN2 = 1
-endif
-ifneq ($(findstring -winidn,$(CFG)),)
-WINIDN = 1
-endif
-ifneq ($(findstring -sspi,$(CFG)),)
-SSPI = 1
-endif
-ifneq ($(findstring -ldaps,$(CFG)),)
-LDAPS = 1
-endif
-ifneq ($(findstring -ipv6,$(CFG)),)
-IPV6 = 1
-endif
-ifneq ($(findstring -schannel,$(CFG))$(findstring -winssl,$(CFG)),)
-SCHANNEL = 1
-SSPI = 1
-endif
-ifneq ($(findstring -nghttp2,$(CFG)),)
-NGHTTP2 = 1
-endif
-ifneq ($(findstring -nghttp3,$(CFG)),)
-NGHTTP3 = 1
-endif
-ifneq ($(findstring -ngtcp2,$(CFG)),)
-NGTCP2 = 1
-endif
-
-# SSH2 and RTMP require an SSL library; assume OpenSSL if none specified
-ifneq ($(SSH2)$(RTMP),)
- ifeq ($(SSL)$(SCHANNEL),)
- SSL = 1
- endif
-endif
-
-INCLUDES = -I. -I$(PROOT) -I$(PROOT)/include -I$(PROOT)/lib
-
-ifdef DYN
- curl_DEPENDENCIES = $(PROOT)/lib/libcurldll.a $(PROOT)/lib/libcurl.dll
- curl_LDADD = -L$(PROOT)/lib -lcurldll
-else
- curl_DEPENDENCIES = $(PROOT)/lib/libcurl.a
- curl_LDADD = -L$(PROOT)/lib -lcurl
- CFLAGS += -DCURL_STATICLIB
- LDFLAGS += -static
-endif
-ifdef ARES
- ifndef DYN
- curl_DEPENDENCIES += $(LIBCARES_PATH)/libcares.a
- endif
- CFLAGS += -DUSE_ARES
- curl_LDADD += -L"$(LIBCARES_PATH)" -lcares
-endif
-ifdef RTMP
- CFLAGS += -DUSE_LIBRTMP
- curl_LDADD += -L"$(LIBRTMP_PATH)/librtmp" -lrtmp -lwinmm
-endif
-ifdef NGHTTP2
- CFLAGS += -DUSE_NGHTTP2
- curl_LDADD += -L"$(NGHTTP2_PATH)/lib" -lnghttp2
-endif
-ifdef SSH2
- CFLAGS += -DUSE_LIBSSH2 -DHAVE_LIBSSH2_H
- curl_LDADD += -L"$(LIBSSH2_PATH)/win32" -lssh2
- ifdef SCHANNEL
- ifndef DYN
- curl_LDADD += -lbcrypt -lcrypt32
- endif
- endif
-endif
-ifdef SSL
- ifdef NGHTTP3
- CFLAGS += -DUSE_NGHTTP3
- curl_LDADD += -L"$(NGHTTP3_PATH)/lib" -lnghttp3
- ifdef NGTCP2
- CFLAGS += -DUSE_NGTCP2
- curl_LDADD += -L"$(NGTCP2_PATH)/lib" -lngtcp2 -lngtcp2_crypto_openssl
- endif
- endif
-
- ifndef OPENSSL_INCLUDE
- ifeq "$(wildcard $(OPENSSL_PATH)/outinc)" "$(OPENSSL_PATH)/outinc"
- OPENSSL_INCLUDE = $(OPENSSL_PATH)/outinc
- endif
- ifeq "$(wildcard $(OPENSSL_PATH)/include)" "$(OPENSSL_PATH)/include"
- OPENSSL_INCLUDE = $(OPENSSL_PATH)/include
- endif
- endif
- ifneq "$(wildcard $(OPENSSL_INCLUDE)/openssl/opensslv.h)" "$(OPENSSL_INCLUDE)/openssl/opensslv.h"
- $(error Invalid path to OpenSSL package: $(OPENSSL_PATH))
- endif
- ifndef OPENSSL_LIBPATH
- OPENSSL_LIBS = -lssl -lcrypto
- ifeq "$(wildcard $(OPENSSL_PATH)/out)" "$(OPENSSL_PATH)/out"
- OPENSSL_LIBPATH = $(OPENSSL_PATH)/out
- ifdef DYN
- OPENSSL_LIBS = -lssl32 -leay32
- endif
- endif
- ifeq "$(wildcard $(OPENSSL_PATH)/lib)" "$(OPENSSL_PATH)/lib"
- OPENSSL_LIBPATH = $(OPENSSL_PATH)/lib
- endif
- endif
- ifndef DYN
- OPENSSL_LIBS += -lgdi32 -lcrypt32
- endif
- INCLUDES += -I"$(OPENSSL_INCLUDE)"
- CFLAGS += -DUSE_OPENSSL
- curl_LDADD += -L"$(OPENSSL_LIBPATH)" $(OPENSSL_LIBS)
-endif
-ifdef SCHANNEL
- CFLAGS += -DUSE_SCHANNEL
- curl_LDADD += -lcrypt32
-endif
-ifdef ZLIB
- INCLUDES += -I"$(ZLIB_PATH)"
- CFLAGS += -DHAVE_LIBZ -DHAVE_ZLIB_H
- curl_LDADD += -L"$(ZLIB_PATH)" -lz
-endif
-ifdef ZSTD
- INCLUDES += -I"$(ZSTD_PATH)/include"
- CFLAGS += -DHAVE_ZSTD
- curl_LDADD += -L"$(ZSTD_PATH)/lib"
- ifdef ZSTD_LIBS
- curl_LDADD += $(ZSTD_LIBS)
- else
- curl_LDADD += -lzstd
- endif
-endif
-ifdef BROTLI
- INCLUDES += -I"$(BROTLI_PATH)/include"
- CFLAGS += -DHAVE_BROTLI
- curl_LDADD += -L"$(BROTLI_PATH)/lib"
- ifdef BROTLI_LIBS
- curl_LDADD += $(BROTLI_LIBS)
- else
- curl_LDADD += -lbrotlidec
- endif
-endif
-ifdef GSASL
- CFLAGS += -DUSE_GSASL
- curl_LDADD += -L"$(LIBGSASL_PATH)/lib" -lgsasl
-endif
-ifdef IDN2
- CFLAGS += -DUSE_LIBIDN2
- curl_LDADD += -L"$(LIBIDN2_PATH)/lib" -lidn2
-else
-ifdef WINIDN
- CFLAGS += -DUSE_WIN32_IDN
- curl_LDADD += -L"$(WINIDN_PATH)" -lnormaliz
-endif
-endif
-ifdef SSPI
- CFLAGS += -DUSE_WINDOWS_SSPI
-endif
-ifdef IPV6
- CFLAGS += -DENABLE_IPV6
-endif
-ifdef LDAPS
- CFLAGS += -DHAVE_LDAP_SSL
-endif
-ifdef USE_LDAP_NOVELL
- CFLAGS += -DCURL_HAS_NOVELL_LDAPSDK
- curl_LDADD += -L"$(LDAP_SDK)/lib/mscvc" -lldapsdk -lldapssl -lldapx
-endif
-ifdef USE_LDAP_OPENLDAP
- CFLAGS += -DCURL_HAS_OPENLDAP_LDAPSDK
- curl_LDADD += -L"$(LDAP_SDK)/lib" -lldap -llber
-endif
-ifndef USE_LDAP_NOVELL
-ifndef USE_LDAP_OPENLDAP
- curl_LDADD += -lwldap32
-endif
-endif
-curl_LDADD += -lws2_32
-
-# Makefile.inc provides the check_PROGRAMS and COMPLICATED_EXAMPLES defines
-include Makefile.inc
-
-check_PROGRAMS := $(patsubst %,%.exe,$(strip $(check_PROGRAMS)))
-check_PROGRAMS += ftpuploadresume.exe synctime.exe
-
-.PRECIOUS: %.o
-
-
-all: $(check_PROGRAMS)
-
-%.exe: %.o $(curl_DEPENDENCIES)
- $(CC) $(LDFLAGS) -o $@ $< $(curl_LDADD)
-
-%.o: %.c
- $(CC) $(INCLUDES) $(CFLAGS) -c $<
-
-%.res: %.rc
- $(RC) $(RCFLAGS) -i $< -o $@
-
-clean:
- @$(call DEL, $(check_PROGRAMS:.exe=.o))
-
-distclean vclean: clean
- @$(call DEL, $(check_PROGRAMS))
diff --git a/docs/examples/Makefile.mk b/docs/examples/Makefile.mk
new file mode 100644
index 0000000..599acee
--- /dev/null
+++ b/docs/examples/Makefile.mk
@@ -0,0 +1,74 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+#***************************************************************************
+
+# Build libcurl via lib/Makefile.mk first.
+
+PROOT := ../..
+
+ifeq ($(findstring -static,$(CFG)),)
+ DYN := 1
+endif
+
+### Common
+
+include $(PROOT)/lib/Makefile.mk
+
+### Local
+
+CPPFLAGS += -DCURL_NO_OLDIES
+LDFLAGS += -L$(PROOT)/lib
+LIBS := -lcurl $(LIBS)
+
+ifdef DYN
+ curl_DEPENDENCIES += $(PROOT)/lib/libcurl.dll.a
+else
+ curl_DEPENDENCIES := $(PROOT)/lib/libcurl.a
+ ifdef WIN32
+ CPPFLAGS += -DCURL_STATICLIB
+ LDFLAGS += -static
+ endif
+endif
+
+ifdef WIN32
+ LIBS += -lws2_32
+endif
+
+### Sources and targets
+
+# Provides check_PROGRAMS
+include Makefile.inc
+
+ifdef WIN32
+check_PROGRAMS += synctime
+endif
+
+TARGETS := $(patsubst %,%$(BIN_EXT),$(strip $(check_PROGRAMS)))
+TOCLEAN := $(TARGETS)
+
+### Rules
+
+%$(BIN_EXT): %.c $(curl_DEPENDENCIES)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(CURL_LDFLAGS_BIN) $< -o $@ $(LIBS)
+
+all: $(TARGETS)
diff --git a/docs/examples/README.md b/docs/examples/README.md
index 1ad9f22..3f95f03 100644
--- a/docs/examples/README.md
+++ b/docs/examples/README.md
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 1998 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
@@ -15,8 +15,9 @@
## Building
-The Makefile.example is an example makefile that could be used to build these
-examples. Just edit the file according to your system and requirements first.
+The `Makefile.example` is an example Makefile that could be used to build
+these examples. Just edit the file according to your system and requirements
+first.
Most examples should build fine using a command line like this:
@@ -27,10 +28,10 @@
`curl-config --cc` -o example example.c `curl-config --cflags --libs`
-**Please** do not use the `curl.se` site as a test target for your
-libcurl applications/experiments. Even if some of the examples use that site
-as a URL at some places, it does not mean that the URLs work or that we expect
-you to actually torture our website with your tests! Thanks.
+**Please** do not use the `curl.se` site as a test target for your libcurl
+applications/experiments. Even if some of the examples use that site as a URL
+at some places, it does not mean that the URLs work or that we expect you to
+actually torture our website with your tests. Thanks.
## Examples
diff --git a/docs/examples/adddocsref.pl b/docs/examples/adddocsref.pl
index 811319f..01be96a 100755
--- a/docs/examples/adddocsref.pl
+++ b/docs/examples/adddocsref.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2004 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/docs/examples/altsvc.c b/docs/examples/altsvc.c
index 7fa47c2..28e9794 100644
--- a/docs/examples/altsvc.c
+++ b/docs/examples/altsvc.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/anyauthput.c b/docs/examples/anyauthput.c
index 33862fc..ff09d83 100644
--- a/docs/examples/anyauthput.c
+++ b/docs/examples/anyauthput.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,11 +34,9 @@
#include <curl/curl.h>
#ifdef WIN32
-# include <io.h>
-# define READ_3RD_ARG unsigned int
+# define FILENO(fp) _fileno(fp)
#else
-# include <unistd.h>
-# define READ_3RD_ARG size_t
+# define FILENO(fp) fileno(fp)
#endif
#if LIBCURL_VERSION_NUM < 0x070c03
@@ -46,37 +44,26 @@
#endif
/*
- * This example shows a HTTP PUT operation with authentication using "any"
+ * This example shows an HTTP PUT operation with authentication using "any"
* type. It PUTs a file given as a command line argument to the URL also given
* on the command line.
*
- * Since libcurl 7.12.3, using "any" auth and POST/PUT requires a set ioctl
+ * Since libcurl 7.12.3, using "any" auth and POST/PUT requires a set seek
* function.
*
* This example also uses its own read callback.
*/
-/* ioctl callback function */
-static curlioerr my_ioctl(CURL *handle, curliocmd cmd, void *userp)
+/* seek callback function */
+static int my_seek(void *userp, curl_off_t offset, int origin)
{
- int *fdp = (int *)userp;
- int fd = *fdp;
+ FILE *fp = (FILE *) userp;
- (void)handle; /* not used in here */
+ if(-1 == fseek(fp, (long) offset, origin))
+ /* couldn't seek */
+ return CURL_SEEKFUNC_CANTSEEK;
- switch(cmd) {
- case CURLIOCMD_RESTARTREAD:
- /* mr libcurl kindly asks as to rewind the read data stream to start */
- if(-1 == lseek(fd, 0, SEEK_SET))
- /* couldn't rewind */
- return CURLIOE_FAILRESTART;
-
- break;
-
- default: /* ignore unknown commands */
- return CURLIOE_UNKNOWNCMD;
- }
- return CURLIOE_OK; /* success! */
+ return CURL_SEEKFUNC_OK; /* success! */
}
/* read callback function, fread() look alike */
@@ -85,10 +72,7 @@
ssize_t retcode;
unsigned long nread;
- int *fdp = (int *)stream;
- int fd = *fdp;
-
- retcode = read(fd, ptr, (READ_3RD_ARG)(size * nmemb));
+ retcode = fread(ptr, size, nmemb, stream);
if(retcode > 0) {
nread = (unsigned long)retcode;
@@ -102,7 +86,7 @@
{
CURL *curl;
CURLcode res;
- int hd;
+ FILE *fp;
struct stat file_info;
char *file;
@@ -115,8 +99,8 @@
url = argv[2];
/* get the file size of the local file */
- hd = open(file, O_RDONLY);
- fstat(hd, &file_info);
+ fp = fopen(file, "rb");
+ fstat(FILENO(fp), &file_info);
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
@@ -128,13 +112,13 @@
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
/* which file to upload */
- curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&hd);
+ curl_easy_setopt(curl, CURLOPT_READDATA, (void *) fp);
- /* set the ioctl function */
- curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, my_ioctl);
+ /* set the seek function */
+ curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, my_seek);
- /* pass the file descriptor to the ioctl callback as well */
- curl_easy_setopt(curl, CURLOPT_IOCTLDATA, (void *)&hd);
+ /* pass the file descriptor to the seek callback as well */
+ curl_easy_setopt(curl, CURLOPT_SEEKDATA, (void *) fp);
/* enable "uploading" (which means PUT when doing HTTP) */
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
@@ -166,7 +150,7 @@
/* always cleanup */
curl_easy_cleanup(curl);
}
- close(hd); /* close the local file */
+ fclose(fp); /* close the local file */
curl_global_cleanup();
return 0;
diff --git a/docs/examples/cacertinmem.c b/docs/examples/cacertinmem.c
index a16d319..647b495 100644
--- a/docs/examples/cacertinmem.c
+++ b/docs/examples/cacertinmem.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
*
***************************************************************************/
/* <DESC>
- * CA cert in memory with OpenSSL to get a HTTPS page.
+ * CA cert in memory with OpenSSL to get an HTTPS page.
* </DESC>
*/
diff --git a/docs/examples/certinfo.c b/docs/examples/certinfo.c
index 381ee51..795be6c 100644
--- a/docs/examples/certinfo.c
+++ b/docs/examples/certinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/chkspeed.c b/docs/examples/chkspeed.c
index 07854ea..45765b9 100644
--- a/docs/examples/chkspeed.c
+++ b/docs/examples/chkspeed.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,7 +37,6 @@
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <time.h>
#include <curl/curl.h>
@@ -73,58 +72,66 @@
if(argc > 1) {
/* parse input parameters */
for(argc--, argv++; *argv; argc--, argv++) {
- if(strncasecmp(*argv, "-", 1) == 0) {
- if(strncasecmp(*argv, "-H", 2) == 0) {
+ if(argv[0][0] == '-') {
+ switch(argv[0][1]) {
+ case 'h':
+ case 'H':
fprintf(stderr,
"\rUsage: %s [-m=1|2|5|10|20|50|100] [-t] [-x] [url]\n",
appname);
exit(1);
- }
- else if(strncasecmp(*argv, "-V", 2) == 0) {
+ case 'v':
+ case 'V':
fprintf(stderr, "\r%s %s - %s\n",
appname, CHKSPEED_VERSION, curl_version());
exit(1);
- }
- else if(strncasecmp(*argv, "-A", 2) == 0) {
+ case 'a':
+ case 'A':
prtall = 1;
- }
- else if(strncasecmp(*argv, "-X", 2) == 0) {
+ break;
+ case 'x':
+ case 'X':
prtsep = 1;
- }
- else if(strncasecmp(*argv, "-T", 2) == 0) {
+ break;
+ case 't':
+ case 'T':
prttime = 1;
- }
- else if(strncasecmp(*argv, "-M=", 3) == 0) {
- long m = strtol((*argv) + 3, NULL, 10);
- switch(m) {
- case 1:
- url = URL_1M;
+ break;
+ case 'm':
+ case 'M':
+ if(argv[0][2] == '=') {
+ long m = strtol((*argv) + 3, NULL, 10);
+ switch(m) {
+ case 1:
+ url = URL_1M;
+ break;
+ case 2:
+ url = URL_2M;
+ break;
+ case 5:
+ url = URL_5M;
+ break;
+ case 10:
+ url = URL_10M;
+ break;
+ case 20:
+ url = URL_20M;
+ break;
+ case 50:
+ url = URL_50M;
+ break;
+ case 100:
+ url = URL_100M;
+ break;
+ default:
+ fprintf(stderr, "\r%s: invalid parameter %s\n",
+ appname, *argv + 3);
+ exit(1);
+ }
break;
- case 2:
- url = URL_2M;
- break;
- case 5:
- url = URL_5M;
- break;
- case 10:
- url = URL_10M;
- break;
- case 20:
- url = URL_20M;
- break;
- case 50:
- url = URL_50M;
- break;
- case 100:
- url = URL_100M;
- break;
- default:
- fprintf(stderr, "\r%s: invalid parameter %s\n",
- appname, *argv + 3);
- exit(1);
}
- }
- else {
+ /* FALLTHROUGH */
+ default:
fprintf(stderr, "\r%s: invalid or unknown option %s\n",
appname, *argv);
exit(1);
diff --git a/docs/examples/connect-to.c b/docs/examples/connect-to.c
new file mode 100644
index 0000000..21f59b2
--- /dev/null
+++ b/docs/examples/connect-to.c
@@ -0,0 +1,70 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Use CURLOPT_CONNECT_TO to connect to "wrong" host name
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+
+ /*
+ Each single string should be written using the format
+ HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT where HOST is the host of the
+ request, PORT is the port of the request, CONNECT-TO-HOST is the host name
+ to connect to, and CONNECT-TO-PORT is the port to connect to.
+ */
+ /* instead of curl.se:443, it will resolve and use example.com:443 but in
+ other aspects work as if it still is curl.se */
+ struct curl_slist *host = curl_slist_append(NULL,
+ "curl.se:443:example.com:443");
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_CONNECT_TO, host);
+ 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
+ server certificate will fail, 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 certficate be okay, the transfer
+ goes through but will (most likely) cause a 404 or similar because it
+ sends an unknown name in the Host: header field */
+ res = curl_easy_perform(curl);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+
+ curl_slist_free_all(host);
+
+ return (int)res;
+}
diff --git a/docs/examples/cookie_interface.c b/docs/examples/cookie_interface.c
index 62e9dd7..131ef65 100644
--- a/docs/examples/cookie_interface.c
+++ b/docs/examples/cookie_interface.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/crawler.c b/docs/examples/crawler.c
index 1859c27..2ff4ae7 100644
--- a/docs/examples/crawler.c
+++ b/docs/examples/crawler.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2022 Jeroen Ooms <jeroenooms@gmail.com>
+ * Copyright (C) Jeroen Ooms <jeroenooms@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -95,8 +95,17 @@
curl_easy_setopt(handle, CURLOPT_ACCEPT_ENCODING, "");
curl_easy_setopt(handle, CURLOPT_TIMEOUT, 5L);
curl_easy_setopt(handle, 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(handle, CURLOPT_CONNECTTIMEOUT, 2L);
+ /* each transfer needs to be done within 20 seconds! */
+ curl_easy_setopt(handle, CURLOPT_TIMEOUT_MS, 20000L);
+ /* connect fast or fail */
+ curl_easy_setopt(handle, 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");
diff --git a/docs/examples/curlgtk.c b/docs/examples/curlgtk.c
deleted file mode 100644
index 7568941..0000000
--- a/docs/examples/curlgtk.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (c) 2000 - 2022 David Odin (aka DindinX) for MandrakeSoft
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-/* <DESC>
- * use the libcurl in a gtk-threaded application
- * </DESC>
- */
-
-#include <stdio.h>
-#include <gtk/gtk.h>
-
-#include <curl/curl.h>
-
-GtkWidget *Bar;
-
-static size_t my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
-{
- return fwrite(ptr, size, nmemb, stream);
-}
-
-static size_t my_read_func(char *ptr, size_t size, size_t nmemb, FILE *stream)
-{
- return fread(ptr, size, nmemb, stream);
-}
-
-static int my_progress_func(GtkWidget *bar,
- double t, /* dltotal */
- double d, /* dlnow */
- double ultotal,
- double ulnow)
-{
-/* printf("%d / %d (%g %%)\n", d, t, d*100.0/t);*/
- gdk_threads_enter();
- gtk_progress_set_value(GTK_PROGRESS(bar), d*100.0/t);
- gdk_threads_leave();
- return 0;
-}
-
-static void *my_thread(void *ptr)
-{
- CURL *curl;
-
- curl = curl_easy_init();
- if(curl) {
- gchar *url = ptr;
- const char *filename = "test.curl";
- FILE *outfile = fopen(filename, "wb");
-
- curl_easy_setopt(curl, CURLOPT_URL, url);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func);
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, my_read_func);
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
- curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);
- curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, Bar);
-
- curl_easy_perform(curl);
-
- fclose(outfile);
- /* always cleanup */
- curl_easy_cleanup(curl);
- }
-
- return NULL;
-}
-
-int main(int argc, char **argv)
-{
- GtkWidget *Window, *Frame, *Frame2;
- GtkAdjustment *adj;
-
- /* Must initialize libcurl before any threads are started */
- curl_global_init(CURL_GLOBAL_ALL);
-
- /* Init thread */
- g_thread_init(NULL);
-
- gtk_init(&argc, &argv);
- Window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- Frame = gtk_frame_new(NULL);
- gtk_frame_set_shadow_type(GTK_FRAME(Frame), GTK_SHADOW_OUT);
- gtk_container_add(GTK_CONTAINER(Window), Frame);
- Frame2 = gtk_frame_new(NULL);
- gtk_frame_set_shadow_type(GTK_FRAME(Frame2), GTK_SHADOW_IN);
- gtk_container_add(GTK_CONTAINER(Frame), Frame2);
- gtk_container_set_border_width(GTK_CONTAINER(Frame2), 5);
- adj = (GtkAdjustment*)gtk_adjustment_new(0, 0, 100, 0, 0, 0);
- Bar = gtk_progress_bar_new_with_adjustment(adj);
- gtk_container_add(GTK_CONTAINER(Frame2), Bar);
- gtk_widget_show_all(Window);
-
- if(!g_thread_create(&my_thread, argv[1], FALSE, NULL) != 0)
- g_warning("cannot create the thread");
-
- gdk_threads_enter();
- gtk_main();
- gdk_threads_leave();
- return 0;
-}
diff --git a/docs/examples/curlx.c b/docs/examples/curlx.c
deleted file mode 100644
index 2c24d23..0000000
--- a/docs/examples/curlx.c
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- curlx.c Authors: Peter Sylvester, Jean-Paul Merlin
-
- This is a little program to demonstrate the usage of
-
- - an SSL initialization callback setting a user key and trustbases
- coming from a pkcs12 file
- - using an ssl application callback to find a URI in the
- certificate presented during ssl session establishment.
-
-*/
-/* <DESC>
- * demonstrates use of SSL context callback, requires OpenSSL
- * </DESC>
- */
-
-/*
- * Copyright (c) 2003 - 2022 The OpenEvidence Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions, the following disclaimer,
- * and the original OpenSSL and SSLeay Licences below.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions, the following disclaimer
- * and the original OpenSSL and SSLeay Licences below in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgments:
- * "This product includes software developed by the Openevidence Project
- * for use in the OpenEvidence Toolkit. (http://www.openevidence.org/)"
- * This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (https://www.openssl.org/)"
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com)."
- *
- * 4. The names "OpenEvidence Toolkit" and "OpenEvidence Project" must not be
- * used to endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * openevidence-core@openevidence.org.
- *
- * 5. Products derived from this software may not be called "OpenEvidence"
- * nor may "OpenEvidence" appear in their names without prior written
- * permission of the OpenEvidence Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgments:
- * "This product includes software developed by the OpenEvidence Project
- * for use in the OpenEvidence Toolkit (http://www.openevidence.org/)
- * This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (https://www.openssl.org/)"
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com)."
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenEvidence PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenEvidence PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (https://www.openssl.org/)
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- * SPDX-License-Identifier: LicenseRef-OpenEvidence
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <curl/curl.h>
-#include <openssl/x509v3.h>
-#include <openssl/x509_vfy.h>
-#include <openssl/crypto.h>
-#include <openssl/lhash.h>
-#include <openssl/objects.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include <openssl/pkcs12.h>
-#include <openssl/bio.h>
-#include <openssl/ssl.h>
-
-static const char *curlx_usage[]={
- "usage: curlx args\n",
- " -p12 arg - tia file ",
- " -envpass arg - environment variable which content the tia private"
- " key password",
- " -out arg - output file (response)- default stdout",
- " -in arg - input file (request)- default stdin",
- " -connect arg - URL of the server for the connection ex:"
- " www.openevidence.org",
- " -mimetype arg - MIME type for data in ex : application/timestamp-query"
- " or application/dvcs -default application/timestamp-query",
- " -acceptmime arg - MIME type acceptable for the response ex : "
- "application/timestamp-response or application/dvcs -default none",
- " -accesstype arg - an Object identifier in an AIA/SIA method, e.g."
- " AD_DVCS or ad_timestamping",
- NULL
-};
-
-/*
-
-./curlx -p12 psy.p12 -envpass XX -in request -verbose -accesstype AD_DVCS
--mimetype application/dvcs -acceptmime application/dvcs -out response
-
-*/
-
-/*
- * We use this ZERO_NULL to avoid picky compiler warnings,
- * when assigning a NULL pointer to a function pointer var.
- */
-
-#define ZERO_NULL 0
-
-/* This is a context that we pass to all callbacks */
-
-typedef struct sslctxparm_st {
- unsigned char *p12file;
- const char *pst;
- PKCS12 *p12;
- EVP_PKEY *pkey;
- X509 *usercert;
- STACK_OF(X509) * ca;
- CURL *curl;
- BIO *errorbio;
- int accesstype;
- int verbose;
-
-} sslctxparm;
-
-/* some helper function. */
-
-static char *ia5string(ASN1_IA5STRING *ia5)
-{
- char *tmp;
- if(!ia5 || !ia5->length)
- return NULL;
- tmp = OPENSSL_malloc(ia5->length + 1);
- memcpy(tmp, ia5->data, ia5->length);
- tmp[ia5->length] = 0;
- return tmp;
-}
-
-/* A convenience routine to get an access URI. */
-static unsigned char *my_get_ext(X509 *cert, const int type,
- int extensiontype)
-{
- int i;
- STACK_OF(ACCESS_DESCRIPTION) * accessinfo;
- accessinfo = X509_get_ext_d2i(cert, extensiontype, NULL, NULL);
-
- if(!sk_ACCESS_DESCRIPTION_num(accessinfo))
- return NULL;
- for(i = 0; i < sk_ACCESS_DESCRIPTION_num(accessinfo); i++) {
- ACCESS_DESCRIPTION * ad = sk_ACCESS_DESCRIPTION_value(accessinfo, i);
- if(OBJ_obj2nid(ad->method) == type) {
- if(ad->location->type == GEN_URI) {
- return ia5string(ad->location->d.ia5);
- }
- return NULL;
- }
- }
- return NULL;
-}
-
-/* This is an application verification call back, it does not
- perform any addition verification but tries to find a URL
- in the presented certificate. If found, this will become
- the URL to be used in the POST.
-*/
-
-static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg)
-{
- sslctxparm * p = (sslctxparm *) arg;
- int ok;
-#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
- X509 *cert = X509_STORE_CTX_get0_cert(ctx);
-#else
- X509 *cert = ctx->cert;
-#endif
-
- if(p->verbose > 2)
- BIO_printf(p->errorbio, "entering ssl_app_verify_callback\n");
-
- ok = X509_verify_cert(ctx);
- if(ok && cert) {
- unsigned char *accessinfo;
- if(p->verbose > 1)
- X509_print_ex(p->errorbio, cert, 0, 0);
-
- accessinfo = my_get_ext(cert, p->accesstype, NID_sinfo_access);
- if(accessinfo) {
- if(p->verbose)
- BIO_printf(p->errorbio, "Setting URL from SIA to: %s\n", accessinfo);
-
- curl_easy_setopt(p->curl, CURLOPT_URL, accessinfo);
- }
- else if(accessinfo = my_get_ext(cert, p->accesstype,
- NID_info_access)) {
- if(p->verbose)
- BIO_printf(p->errorbio, "Setting URL from AIA to: %s\n", accessinfo);
-
- curl_easy_setopt(p->curl, CURLOPT_URL, accessinfo);
- }
- }
- if(p->verbose > 2)
- BIO_printf(p->errorbio, "leaving ssl_app_verify_callback with %d\n", ok);
-
- return ok;
-}
-
-
-/* The SSL initialization callback. The callback sets:
- - a private key and certificate
- - a trusted ca certificate
- - a preferred cipherlist
- - an application verification callback (the function above)
-*/
-
-static CURLcode sslctxfun(CURL *curl, void *sslctx, void *parm)
-{
- sslctxparm *p = (sslctxparm *) parm;
- SSL_CTX *ctx = (SSL_CTX *) sslctx;
-
- if(!SSL_CTX_use_certificate(ctx, p->usercert)) {
- BIO_printf(p->errorbio, "SSL_CTX_use_certificate problem\n");
- goto err;
- }
- if(!SSL_CTX_use_PrivateKey(ctx, p->pkey)) {
- BIO_printf(p->errorbio, "SSL_CTX_use_PrivateKey\n");
- goto err;
- }
-
- if(!SSL_CTX_check_private_key(ctx)) {
- BIO_printf(p->errorbio, "SSL_CTX_check_private_key\n");
- goto err;
- }
-
- SSL_CTX_set_quiet_shutdown(ctx, 1);
- SSL_CTX_set_cipher_list(ctx, "RC4-MD5");
- SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
-
- X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx),
- sk_X509_value(p->ca, sk_X509_num(p->ca)-1));
-
- SSL_CTX_set_verify_depth(ctx, 2);
- SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, ZERO_NULL);
- SSL_CTX_set_cert_verify_callback(ctx, ssl_app_verify_callback, parm);
-
- return CURLE_OK;
- err:
- ERR_print_errors(p->errorbio);
- return CURLE_SSL_CERTPROBLEM;
-
-}
-
-int main(int argc, char **argv)
-{
- BIO* in = NULL;
- BIO* out = NULL;
-
- char *outfile = NULL;
- char *infile = NULL;
-
- int tabLength = 100;
- char *binaryptr;
- char *mimetype = NULL;
- char *mimetypeaccept = NULL;
- char *contenttype;
- const char **pp;
- unsigned char *hostporturl = NULL;
- BIO *p12bio;
- char **args = argv + 1;
- unsigned char *serverurl;
- sslctxparm p;
- char *response;
-
- CURLcode res;
- struct curl_slist *headers = NULL;
- int badarg = 0;
-
- binaryptr = malloc(tabLength);
-
- memset(&p, '\0', sizeof(p));
- p.errorbio = BIO_new_fp(stderr, BIO_NOCLOSE);
-
- curl_global_init(CURL_GLOBAL_DEFAULT);
-
- /* we need some more for the P12 decoding */
-
- OpenSSL_add_all_ciphers();
- OpenSSL_add_all_digests();
- ERR_load_crypto_strings();
-
- while(*args && *args[0] == '-') {
- if(!strcmp (*args, "-in")) {
- if(args[1]) {
- infile = *(++args);
- }
- else
- badarg = 1;
- }
- else if(!strcmp (*args, "-out")) {
- if(args[1]) {
- outfile = *(++args);
- }
- else
- badarg = 1;
- }
- else if(!strcmp (*args, "-p12")) {
- if(args[1]) {
- p.p12file = *(++args);
- }
- else
- badarg = 1;
- }
- else if(strcmp(*args, "-envpass") == 0) {
- if(args[1]) {
- p.pst = getenv(*(++args));
- }
- else
- badarg = 1;
- }
- else if(strcmp(*args, "-connect") == 0) {
- if(args[1]) {
- hostporturl = *(++args);
- }
- else
- badarg = 1;
- }
- else if(strcmp(*args, "-mimetype") == 0) {
- if(args[1]) {
- mimetype = *(++args);
- }
- else
- badarg = 1;
- }
- else if(strcmp(*args, "-acceptmime") == 0) {
- if(args[1]) {
- mimetypeaccept = *(++args);
- }
- else
- badarg = 1;
- }
- else if(strcmp(*args, "-accesstype") == 0) {
- if(args[1]) {
- p.accesstype = OBJ_obj2nid(OBJ_txt2obj(*++args, 0));
- if(p.accesstype == 0)
- badarg = 1;
- }
- else
- badarg = 1;
- }
- else if(strcmp(*args, "-verbose") == 0) {
- p.verbose++;
- }
- else
- badarg = 1;
- args++;
- }
-
- if(!mimetype || !mimetypeaccept || !p.p12file)
- badarg = 1;
-
- if(badarg) {
- for(pp = curlx_usage; (*pp != NULL); pp++)
- BIO_printf(p.errorbio, "%s\n", *pp);
- BIO_printf(p.errorbio, "\n");
- goto err;
- }
-
- /* set input */
-
- in = BIO_new(BIO_s_file());
- if(!in) {
- BIO_printf(p.errorbio, "Error setting input bio\n");
- goto err;
- }
- else if(!infile)
- BIO_set_fp(in, stdin, BIO_NOCLOSE|BIO_FP_TEXT);
- else if(BIO_read_filename(in, infile) <= 0) {
- BIO_printf(p.errorbio, "Error opening input file %s\n", infile);
- BIO_free(in);
- goto err;
- }
-
- /* set output */
-
- out = BIO_new(BIO_s_file());
- if(!out) {
- BIO_printf(p.errorbio, "Error setting output bio.\n");
- goto err;
- }
- else if(!outfile)
- BIO_set_fp(out, stdout, BIO_NOCLOSE|BIO_FP_TEXT);
- else if(BIO_write_filename(out, outfile) <= 0) {
- BIO_printf(p.errorbio, "Error opening output file %s\n", outfile);
- BIO_free(out);
- goto err;
- }
-
-
- p.errorbio = BIO_new_fp(stderr, BIO_NOCLOSE);
-
- p.curl = curl_easy_init();
- if(!p.curl) {
- BIO_printf(p.errorbio, "Cannot init curl lib\n");
- goto err;
- }
-
- p12bio = BIO_new_file(p.p12file, "rb");
- if(!p12bio) {
- BIO_printf(p.errorbio, "Error opening P12 file %s\n", p.p12file);
- goto err;
- }
- p.p12 = d2i_PKCS12_bio(p12bio, NULL);
- if(!p.p12) {
- BIO_printf(p.errorbio, "Cannot decode P12 structure %s\n", p.p12file);
- goto err;
- }
-
- p.ca = NULL;
- if(!(PKCS12_parse (p.p12, p.pst, &(p.pkey), &(p.usercert), &(p.ca) ) )) {
- BIO_printf(p.errorbio, "Invalid P12 structure in %s\n", p.p12file);
- goto err;
- }
-
- if(sk_X509_num(p.ca) <= 0) {
- BIO_printf(p.errorbio, "No trustworthy CA given.%s\n", p.p12file);
- goto err;
- }
-
- if(p.verbose > 1)
- X509_print_ex(p.errorbio, p.usercert, 0, 0);
-
- /* determine URL to go */
-
- if(hostporturl) {
- size_t len = strlen(hostporturl) + 9;
- serverurl = malloc(len);
- snprintf(serverurl, len, "https://%s", hostporturl);
- }
- else if(p.accesstype) { /* see whether we can find an AIA or SIA for a
- given access type */
- serverurl = my_get_ext(p.usercert, p.accesstype, NID_info_access);
- if(!serverurl) {
- int j = 0;
- BIO_printf(p.errorbio, "no service URL in user cert "
- "searching in others certificates\n");
- for(j = 0; j<sk_X509_num(p.ca); j++) {
- serverurl = my_get_ext(sk_X509_value(p.ca, j), p.accesstype,
- NID_info_access);
- if(serverurl)
- break;
- serverurl = my_get_ext(sk_X509_value(p.ca, j), p.accesstype,
- NID_sinfo_access);
- if(serverurl)
- break;
- }
- }
- }
-
- if(!serverurl) {
- BIO_printf(p.errorbio, "no service URL in certificates,"
- " check '-accesstype (AD_DVCS | ad_timestamping)'"
- " or use '-connect'\n");
- goto err;
- }
-
- if(p.verbose)
- BIO_printf(p.errorbio, "Service URL: <%s>\n", serverurl);
-
- curl_easy_setopt(p.curl, CURLOPT_URL, serverurl);
-
- /* Now specify the POST binary data */
-
- curl_easy_setopt(p.curl, CURLOPT_POSTFIELDS, binaryptr);
- curl_easy_setopt(p.curl, CURLOPT_POSTFIELDSIZE, (long)tabLength);
-
- /* pass our list of custom made headers */
-
- contenttype = malloc(15 + strlen(mimetype));
- snprintf(contenttype, 15 + strlen(mimetype), "Content-type: %s", mimetype);
- headers = curl_slist_append(headers, contenttype);
- curl_easy_setopt(p.curl, CURLOPT_HTTPHEADER, headers);
-
- if(p.verbose)
- BIO_printf(p.errorbio, "Service URL: <%s>\n", serverurl);
-
- {
- FILE *outfp;
- BIO_get_fp(out, &outfp);
- curl_easy_setopt(p.curl, CURLOPT_WRITEDATA, outfp);
- }
-
- res = curl_easy_setopt(p.curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun);
-
- if(res != CURLE_OK)
- BIO_printf(p.errorbio, "%d %s=%d %d\n", __LINE__,
- "CURLOPT_SSL_CTX_FUNCTION", CURLOPT_SSL_CTX_FUNCTION, res);
-
- curl_easy_setopt(p.curl, CURLOPT_SSL_CTX_DATA, &p);
-
- {
- char *ptr;
- int lu; int i = 0;
- while((lu = BIO_read(in, &binaryptr[i], tabLength-i)) >0) {
- i += lu;
- if(i == tabLength) {
- tabLength += 100;
- ptr = realloc(binaryptr, tabLength); /* should be more careful */
- if(!ptr) {
- /* out of memory */
- BIO_printf(p.errorbio, "out of memory (realloc returned NULL)\n");
- goto fail;
- }
- binaryptr = ptr;
- ptr = NULL;
- }
- }
- tabLength = i;
- }
- /* Now specify the POST binary data */
-
- curl_easy_setopt(p.curl, CURLOPT_POSTFIELDS, binaryptr);
- curl_easy_setopt(p.curl, CURLOPT_POSTFIELDSIZE, (long)tabLength);
-
-
- /* Perform the request, res will get the return code */
-
- BIO_printf(p.errorbio, "%d %s %d\n", __LINE__, "curl_easy_perform",
- res = curl_easy_perform(p.curl));
- {
- curl_easy_getinfo(p.curl, CURLINFO_CONTENT_TYPE, &response);
- if(mimetypeaccept && p.verbose) {
- if(!strcmp(mimetypeaccept, response))
- BIO_printf(p.errorbio, "the response has a correct mimetype : %s\n",
- response);
- else
- BIO_printf(p.errorbio, "the response doesn\'t have an acceptable "
- "mime type, it is %s instead of %s\n",
- response, mimetypeaccept);
- }
- }
-
- /*** code d'erreur si accept mime ***, egalement code return HTTP != 200 ***/
-
-/* free the header list*/
-fail:
- curl_slist_free_all(headers);
-
- /* always cleanup */
- curl_easy_cleanup(p.curl);
-
- BIO_free(in);
- BIO_free(out);
- return (EXIT_SUCCESS);
-
- err: BIO_printf(p.errorbio, "error");
- exit(1);
-}
diff --git a/docs/examples/debug.c b/docs/examples/debug.c
index aeef829..684a183 100644
--- a/docs/examples/debug.c
+++ b/docs/examples/debug.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/default-scheme.c b/docs/examples/default-scheme.c
new file mode 100644
index 0000000..525dcc3
--- /dev/null
+++ b/docs/examples/default-scheme.c
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Change default scheme when none is provided in the URL
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "example.com");
+
+ /* Change the default protocol (scheme) for schemeless URLs from plain
+ "http" to use a secure one instead. */
+ curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
+
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ return 0;
+}
diff --git a/docs/examples/ephiperfifo.c b/docs/examples/ephiperfifo.c
index 7079846..f0ee0a1 100644
--- a/docs/examples/ephiperfifo.c
+++ b/docs/examples/ephiperfifo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -166,7 +166,7 @@
memset(&its, 0, sizeof(struct itimerspec));
}
- timerfd_settime(g->tfd, /*flags=*/0, &its, NULL);
+ timerfd_settime(g->tfd, /* flags= */0, &its, NULL);
return 0;
}
@@ -197,7 +197,7 @@
}
}
-/* Called by libevent when we get action on a multi socket filedescriptor*/
+/* Called by libevent when we get action on a multi socket filedescriptor */
static void event_cb(GlobalInfo *g, int fd, int revents)
{
CURLMcode rc;
diff --git a/docs/examples/evhiperfifo.c b/docs/examples/evhiperfifo.c
index 3c9ca57..2a361b9 100644
--- a/docs/examples/evhiperfifo.c
+++ b/docs/examples/evhiperfifo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/externalsocket.c b/docs/examples/externalsocket.c
index dfdd1c2..1c78c3d 100644
--- a/docs/examples/externalsocket.c
+++ b/docs/examples/externalsocket.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,8 +22,7 @@
*
***************************************************************************/
/* <DESC>
- * An example demonstrating how an application can pass in a custom
- * socket to libcurl to use. This example also handles the connect itself.
+ * Pass in a custom socket for libcurl to use.
* </DESC>
*/
#include <stdio.h>
diff --git a/docs/examples/fileupload.c b/docs/examples/fileupload.c
index 8d3e6cd..9e3bd84 100644
--- a/docs/examples/fileupload.c
+++ b/docs/examples/fileupload.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/ftp-wildcard.c b/docs/examples/ftp-wildcard.c
index 63e1809..f805432 100644
--- a/docs/examples/ftp-wildcard.c
+++ b/docs/examples/ftp-wildcard.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -79,7 +79,7 @@
/* curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L); */
- /* set an URL containing wildcard pattern (only in the last part) */
+ /* set a URL containing wildcard pattern (only in the last part) */
if(argc == 2)
curl_easy_setopt(handle, CURLOPT_URL, argv[1]);
else
diff --git a/docs/examples/ftpget.c b/docs/examples/ftpget.c
index 3229dbf..b25e668 100644
--- a/docs/examples/ftpget.c
+++ b/docs/examples/ftpget.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/ftpgetinfo.c b/docs/examples/ftpgetinfo.c
index b298c28..be24fa7 100644
--- a/docs/examples/ftpgetinfo.c
+++ b/docs/examples/ftpgetinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -46,7 +46,7 @@
CURL *curl;
CURLcode res;
long filetime = -1;
- double filesize = 0.0;
+ curl_off_t filesize = 0;
const char *filename = strrchr(ftpurl, '/') + 1;
curl_global_init(CURL_GLOBAL_DEFAULT);
@@ -72,10 +72,11 @@
time_t file_time = (time_t)filetime;
printf("filetime %s: %s", filename, ctime(&file_time));
}
- res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
+ res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,
&filesize);
- if((CURLE_OK == res) && (filesize>0.0))
- printf("filesize %s: %0.0f bytes\n", filename, filesize);
+ if((CURLE_OK == res) && (filesize>0))
+ printf("filesize %s: %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ filename, filesize);
}
else {
/* we failed */
diff --git a/docs/examples/ftpgetresp.c b/docs/examples/ftpgetresp.c
index 1bee903..238885d 100644
--- a/docs/examples/ftpgetresp.c
+++ b/docs/examples/ftpgetresp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/ftpsget.c b/docs/examples/ftpsget.c
index 521ad5c..88ba002 100644
--- a/docs/examples/ftpsget.c
+++ b/docs/examples/ftpsget.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/ftpupload.c b/docs/examples/ftpupload.c
index 046166a..00de126 100644
--- a/docs/examples/ftpupload.c
+++ b/docs/examples/ftpupload.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/ftpuploadfrommem.c b/docs/examples/ftpuploadfrommem.c
index b32020e..9613cca 100644
--- a/docs/examples/ftpuploadfrommem.c
+++ b/docs/examples/ftpuploadfrommem.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/ftpuploadresume.c b/docs/examples/ftpuploadresume.c
index 7b4c8bd..42d31a2 100644
--- a/docs/examples/ftpuploadresume.c
+++ b/docs/examples/ftpuploadresume.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
*
***************************************************************************/
/* <DESC>
- * Upload to FTP, resuming failed transfers.
+ * Upload to FTP, resuming failed transfers. Active mode.
* </DESC>
*/
@@ -86,7 +86,7 @@
curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath);
if(timeout)
- curl_easy_setopt(curlhandle, CURLOPT_FTP_RESPONSE_TIMEOUT, timeout);
+ curl_easy_setopt(curlhandle, CURLOPT_SERVER_RESPONSE_TIMEOUT, timeout);
curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getcontentlengthfunc);
curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &uploaded_len);
@@ -96,8 +96,12 @@
curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc);
curl_easy_setopt(curlhandle, CURLOPT_READDATA, f);
- /* disable passive mode */
+ /* enable active mode */
curl_easy_setopt(curlhandle, CURLOPT_FTPPORT, "-");
+
+ /* allow the server no more than 7 seconds to connect back */
+ curl_easy_setopt(curlhandle, CURLOPT_ACCEPTTIMEOUT_MS, 7000L);
+
curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L);
curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);
diff --git a/docs/examples/getinfo.c b/docs/examples/getinfo.c
index d63b030..9c178c2 100644
--- a/docs/examples/getinfo.c
+++ b/docs/examples/getinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/getinmemory.c b/docs/examples/getinmemory.c
index 085ece7..8ec8414 100644
--- a/docs/examples/getinmemory.c
+++ b/docs/examples/getinmemory.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/getredirect.c b/docs/examples/getredirect.c
index 85ea382..9163c9b 100644
--- a/docs/examples/getredirect.c
+++ b/docs/examples/getredirect.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/getreferrer.c b/docs/examples/getreferrer.c
index d320c10..6073f9f 100644
--- a/docs/examples/getreferrer.c
+++ b/docs/examples/getreferrer.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/ghiper.c b/docs/examples/ghiper.c
index e18ca6e..b30afd1 100644
--- a/docs/examples/ghiper.c
+++ b/docs/examples/ghiper.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/headerapi.c b/docs/examples/headerapi.c
index 58c8586..4df6cbd 100644
--- a/docs/examples/headerapi.c
+++ b/docs/examples/headerapi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/hiperfifo.c b/docs/examples/hiperfifo.c
index ea0cdb1..06cb138 100644
--- a/docs/examples/hiperfifo.c
+++ b/docs/examples/hiperfifo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/href_extractor.c b/docs/examples/href_extractor.c
index b73157b..5c92b0c 100644
--- a/docs/examples/href_extractor.c
+++ b/docs/examples/href_extractor.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/hsts-preload.c b/docs/examples/hsts-preload.c
new file mode 100644
index 0000000..ee42535
--- /dev/null
+++ b/docs/examples/hsts-preload.c
@@ -0,0 +1,118 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Preload domains to HSTS
+ * </DESC>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <curl/curl.h>
+
+struct entry {
+ const char *name;
+ const char *exp;
+};
+
+static const struct entry preload_hosts[] = {
+ { "example.com", "20370320 01:02:03" },
+ { "curl.se", "20370320 03:02:01" },
+ { NULL, NULL } /* end of list marker */
+};
+
+struct state {
+ int index;
+};
+
+/* "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)
+{
+ const char *host;
+ const char *expire;
+ struct state *s = (struct state *)userp;
+ (void)easy;
+ host = preload_hosts[s->index].name;
+ expire = preload_hosts[s->index++].exp;
+
+ if(host && (strlen(host) < e->namelen)) {
+ strcpy(e->name, host);
+ e->includeSubDomains = 0;
+ strcpy(e->expire, expire);
+ fprintf(stderr, "HSTS preload '%s' until '%s'\n", host, expire);
+ }
+ else
+ return CURLSTS_DONE;
+ return CURLSTS_OK;
+}
+
+static CURLSTScode hstswrite(CURL *easy, struct curl_hstsentry *e,
+ struct curl_index *i, void *userp)
+{
+ (void)easy;
+ (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);
+ return CURLSTS_OK;
+}
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl = curl_easy_init();
+ if(curl) {
+ struct state st = {0};
+
+ /* enable HSTS for this handle */
+ curl_easy_setopt(curl, CURLOPT_HSTS_CTRL, (long)CURLHSTS_ENABLE);
+
+ /* function to call at first to populate the cache before the transfer */
+ curl_easy_setopt(curl, CURLOPT_HSTSREADFUNCTION, hstsread);
+ curl_easy_setopt(curl, CURLOPT_HSTSREADDATA, &st);
+
+ /* function to call after transfer to store the new state of the HSTS
+ cache */
+ curl_easy_setopt(curl, CURLOPT_HSTSWRITEFUNCTION, hstswrite);
+ curl_easy_setopt(curl, CURLOPT_HSTSWRITEDATA, NULL);
+
+ /* use the domain with HTTP but due to the preload, it should do the
+ transfer using HTTPS */
+ curl_easy_setopt(curl, CURLOPT_URL, "http://curl.se");
+
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ return 0;
+}
diff --git a/docs/examples/htmltidy.c b/docs/examples/htmltidy.c
index 97e3eac..cc6f63e 100644
--- a/docs/examples/htmltidy.c
+++ b/docs/examples/htmltidy.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/htmltitle.cpp b/docs/examples/htmltitle.cpp
index b5c78f7..ee3e023 100644
--- a/docs/examples/htmltitle.cpp
+++ b/docs/examples/htmltitle.cpp
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -272,7 +272,7 @@
// Initialize CURL connection
if(!init(conn, argv[1])) {
- fprintf(stderr, "Connection initializion failed\n");
+ fprintf(stderr, "Connection initialization failed\n");
exit(EXIT_FAILURE);
}
diff --git a/docs/examples/http-options.c b/docs/examples/http-options.c
new file mode 100644
index 0000000..964e0ef
--- /dev/null
+++ b/docs/examples/http-options.c
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Issue an HTTP 'OPTIONS *' request
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "OPTIONS");
+
+ /* issue an OPTIONS * request (no leading slash) */
+ curl_easy_setopt(curl, CURLOPT_REQUEST_TARGET, "*");
+
+ /* if this operation fails, allow risking a memory leak and do quick exit
+ from libcurl as this will exit() anyway */
+ curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L);
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ return 0;
+}
diff --git a/docs/examples/http-post.c b/docs/examples/http-post.c
index df0e5a7..2cacefe 100644
--- a/docs/examples/http-post.c
+++ b/docs/examples/http-post.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,7 +40,7 @@
curl = curl_easy_init();
if(curl) {
/* First set the URL that is about to receive our POST. This URL can
- just as well be a https:// URL if that is what should receive the
+ just as well be an https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi");
/* Now specify the POST data */
diff --git a/docs/examples/http2-download.c b/docs/examples/http2-download.c
index e88f578..a2291a8 100644
--- a/docs/examples/http2-download.c
+++ b/docs/examples/http2-download.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -170,13 +170,12 @@
curl_easy_setopt(hnd, CURLOPT_DEBUGFUNCTION, my_trace);
curl_easy_setopt(hnd, CURLOPT_DEBUGDATA, t);
+ /* enlarge the receive buffer for potentially higher transfer speeds */
+ curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 100000L);
+
/* HTTP/2 please */
curl_easy_setopt(hnd, 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);
-
#if (CURLPIPE_MULTIPLEX > 0)
/* wait for pipe connection to confirm */
curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
diff --git a/docs/examples/http2-pushinmemory.c b/docs/examples/http2-pushinmemory.c
index 78273c9..c982bd5 100644
--- a/docs/examples/http2-pushinmemory.c
+++ b/docs/examples/http2-pushinmemory.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/http2-serverpush.c b/docs/examples/http2-serverpush.c
index f279355..7524c62 100644
--- a/docs/examples/http2-serverpush.c
+++ b/docs/examples/http2-serverpush.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -130,7 +130,7 @@
#define OUTPUTFILE "dl"
-static int setup(CURL *hnd)
+static int setup(CURL *hnd, const char *url)
{
FILE *out = fopen(OUTPUTFILE, "wb");
if(!out)
@@ -141,7 +141,7 @@
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, out);
/* set the same URL */
- curl_easy_setopt(hnd, CURLOPT_URL, "https://localhost:8443/index.html");
+ curl_easy_setopt(hnd, CURLOPT_URL, url);
/* please be verbose */
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
@@ -211,12 +211,16 @@
/*
* Download a file over HTTP/2, take care of server push.
*/
-int main(void)
+int main(int argc, char *argv[])
{
CURL *easy;
CURLM *multi_handle;
int transfers = 1; /* we start with one */
struct CURLMsg *m;
+ const char *url = "https://localhost:8443/index.html";
+
+ if(argc == 2)
+ url = argv[1];
/* init a multi stack */
multi_handle = curl_multi_init();
@@ -224,7 +228,7 @@
easy = curl_easy_init();
/* set options */
- if(setup(easy)) {
+ if(setup(easy, url)) {
fprintf(stderr, "failed\n");
return 1;
}
diff --git a/docs/examples/http2-upload.c b/docs/examples/http2-upload.c
index d0d5469..5889d0c 100644
--- a/docs/examples/http2-upload.c
+++ b/docs/examples/http2-upload.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/http3-present.c b/docs/examples/http3-present.c
index 3e18920..56ba0f5 100644
--- a/docs/examples/http3-present.c
+++ b/docs/examples/http3-present.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/http3.c b/docs/examples/http3.c
index 6463ccf..900e119 100644
--- a/docs/examples/http3.c
+++ b/docs/examples/http3.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,10 +37,9 @@
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- /* Forcing HTTP/3 will make the connection fail if the server is not
- accessible over QUIC + HTTP/3 on the given host and port.
- Consider using CURLOPT_ALTSVC instead! */
- curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_3);
+ /* Use HTTP/3 but fallback to earlier HTTP if necessary */
+ curl_easy_setopt(curl, CURLOPT_HTTP_VERSION,
+ (long)CURL_HTTP_VERSION_3);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
diff --git a/docs/examples/httpcustomheader.c b/docs/examples/httpcustomheader.c
index c72a474..a388167 100644
--- a/docs/examples/httpcustomheader.c
+++ b/docs/examples/httpcustomheader.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/httpput-postfields.c b/docs/examples/httpput-postfields.c
index 7c85a01..98d7c3d 100644
--- a/docs/examples/httpput-postfields.c
+++ b/docs/examples/httpput-postfields.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,11 +37,13 @@
"small: to wit, a workhouse; and in this workhouse was born; on a day and "
"date which I need not trouble myself to repeat, inasmuch as it can be of "
"no possible consequence to the reader, in this stage of the business at "
- "all events; the item of mortality whose name is prefixed to the head of "
- "this chapter.";
+ "all events; the item of mortality whose name is prefixed";
+
+/* ... to the head of this chapter. String cut off to stick within the C90
+ 509 byte limit. */
/*
- * This example shows a HTTP PUT operation that sends a fixed buffer with
+ * This example shows an HTTP PUT operation that sends a fixed buffer with
* CURLOPT_POSTFIELDS to the URL given as an argument.
*/
diff --git a/docs/examples/httpput.c b/docs/examples/httpput.c
index 00ad99c..b9a6c87 100644
--- a/docs/examples/httpput.c
+++ b/docs/examples/httpput.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
#include <curl/curl.h>
/*
- * This example shows a HTTP PUT operation. PUTs a file given as a command
+ * This example shows an HTTP PUT operation. PUTs a file given as a command
* line argument to the URL also given on the command line.
*
* This example also uses its own read callback.
@@ -101,8 +101,8 @@
/* now specify which file to upload */
curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);
- /* provide the size of the upload, we specicially typecast the value
- to curl_off_t since we must be sure to use the correct data size */
+ /* provide the size of the upload, we typecast the value to curl_off_t
+ since we must be sure to use the correct data size */
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
(curl_off_t)file_info.st_size);
diff --git a/docs/examples/https.c b/docs/examples/https.c
index 7be330a..2a34e37 100644
--- a/docs/examples/https.c
+++ b/docs/examples/https.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -63,6 +63,9 @@
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
#endif
+ /* cache the CA cert bundle in memory for a week */
+ curl_easy_setopt(curl, CURLOPT_CA_CACHE_TIMEOUT, 604800L);
+
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
diff --git a/docs/examples/imap-append.c b/docs/examples/imap-append.c
index b66d868..33566bb 100644
--- a/docs/examples/imap-append.c
+++ b/docs/examples/imap-append.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example showing how to send emails
+ * Send email with IMAP
* </DESC>
*/
@@ -49,11 +49,11 @@
"Message-ID: "
"<dcd7cb36-11db-487a-9f3a-e652a9458efd@rfcpedant.example.org>\r\n"
"Subject: IMAP example message\r\n"
- "\r\n" /* empty line to divide headers from body, see RFC5322 */
+ "\r\n" /* empty line to divide headers from body, see RFC 5322 */
"The body of the message starts here.\r\n"
"\r\n"
"It could be a lot of lines, could be MIME encoded, whatever.\r\n"
- "Check RFC5322.\r\n";
+ "Check RFC 5322.\r\n";
struct upload_status {
size_t bytes_read;
@@ -99,10 +99,8 @@
curl_easy_setopt(curl, CURLOPT_USERNAME, "user");
curl_easy_setopt(curl, CURLOPT_PASSWORD, "secret");
- /* This will create a new message 100. Note that you should perform an
- * EXAMINE command to obtain the UID of the next message to create and a
- * SELECT to ensure you are creating the message in the OUTBOX. */
- curl_easy_setopt(curl, CURLOPT_URL, "imap://imap.example.com/100");
+ /* This will create a new message in folder "Sent". */
+ curl_easy_setopt(curl, CURLOPT_URL, "imap://imap.example.com/Sent");
/* 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
diff --git a/docs/examples/imap-authzid.c b/docs/examples/imap-authzid.c
index 62eca4a..af07320 100644
--- a/docs/examples/imap-authzid.c
+++ b/docs/examples/imap-authzid.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example showing how to retreieve emails from a shared mailed box
+ * Retrieve emails from a shared IMAP mailbox
* </DESC>
*/
diff --git a/docs/examples/imap-copy.c b/docs/examples/imap-copy.c
index 81ec5be..0920f09 100644
--- a/docs/examples/imap-copy.c
+++ b/docs/examples/imap-copy.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example showing how to copy an email from one folder to another
+ * Copy an email from one IMAP folder to another
* </DESC>
*/
diff --git a/docs/examples/imap-create.c b/docs/examples/imap-create.c
index 12e7113..6a9b565 100644
--- a/docs/examples/imap-create.c
+++ b/docs/examples/imap-create.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example showing how to create a new folder
+ * Create a new IMAP folder
* </DESC>
*/
diff --git a/docs/examples/imap-delete.c b/docs/examples/imap-delete.c
index 467b060..e43ab2e 100644
--- a/docs/examples/imap-delete.c
+++ b/docs/examples/imap-delete.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example showing how to delete a folder
+ * Delete an IMAP folder
* </DESC>
*/
diff --git a/docs/examples/imap-examine.c b/docs/examples/imap-examine.c
index 68cc636..34217bf 100644
--- a/docs/examples/imap-examine.c
+++ b/docs/examples/imap-examine.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example showing how to obtain information about a folder
+ * Obtain information about an IMAP folder
* </DESC>
*/
diff --git a/docs/examples/imap-fetch.c b/docs/examples/imap-fetch.c
index d6237c3..3361d7c 100644
--- a/docs/examples/imap-fetch.c
+++ b/docs/examples/imap-fetch.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example showing how to retreieve emails
+ * Retrieve IMAP emails
* </DESC>
*/
diff --git a/docs/examples/imap-list.c b/docs/examples/imap-list.c
index 85bddac..2f3780f 100644
--- a/docs/examples/imap-list.c
+++ b/docs/examples/imap-list.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example to list the folders within a mailbox
+ * List the folders within an IMAP mailbox
* </DESC>
*/
diff --git a/docs/examples/imap-lsub.c b/docs/examples/imap-lsub.c
index 1b22fa1..9cb87fe 100644
--- a/docs/examples/imap-lsub.c
+++ b/docs/examples/imap-lsub.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example to list the subscribed folders
+ * List the subscribed IMAP folders
* </DESC>
*/
diff --git a/docs/examples/imap-multi.c b/docs/examples/imap-multi.c
index 3b5c633..6a5f4b0 100644
--- a/docs/examples/imap-multi.c
+++ b/docs/examples/imap-multi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example using the multi interface
+ * Get IMAP email with the multi interface
* </DESC>
*/
diff --git a/docs/examples/imap-noop.c b/docs/examples/imap-noop.c
index ee1a777..9e5a3da 100644
--- a/docs/examples/imap-noop.c
+++ b/docs/examples/imap-noop.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example showing how to perform a noop
+ * Perform an IMAP noop
* </DESC>
*/
diff --git a/docs/examples/imap-search.c b/docs/examples/imap-search.c
index 7b175b2..141b06f 100644
--- a/docs/examples/imap-search.c
+++ b/docs/examples/imap-search.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example showing how to search for new emails
+ * Search for new IMAP emails
* </DESC>
*/
diff --git a/docs/examples/imap-ssl.c b/docs/examples/imap-ssl.c
index 5b0befb..51d2d1d 100644
--- a/docs/examples/imap-ssl.c
+++ b/docs/examples/imap-ssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example using SSL
+ * IMAP with implicit SSL
* </DESC>
*/
diff --git a/docs/examples/imap-store.c b/docs/examples/imap-store.c
index 6a4c756..d04a607 100644
--- a/docs/examples/imap-store.c
+++ b/docs/examples/imap-store.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example showing how to modify the properties of an email
+ * Modify the properties of an email over IMAP
* </DESC>
*/
diff --git a/docs/examples/imap-tls.c b/docs/examples/imap-tls.c
index dbebbc7..5a47e4d 100644
--- a/docs/examples/imap-tls.c
+++ b/docs/examples/imap-tls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * IMAP example using TLS
+ * IMAP using TLS
* </DESC>
*/
diff --git a/docs/examples/ipv6.c b/docs/examples/ipv6.c
new file mode 100644
index 0000000..c9b4b1f
--- /dev/null
+++ b/docs/examples/ipv6.c
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * HTTP GET to an IPv6 address with specific scope
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+#ifndef WIN32
+#include <net/if.h>
+#endif
+
+int main(void)
+{
+#ifndef WIN32
+ /* Windows users need to find how to use if_nametoindex() */
+ CURL *curl;
+ CURLcode res;
+
+ curl = curl_easy_init();
+ if(curl) {
+ long my_scope_id;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ my_scope_id = if_nametoindex("eth0");
+ curl_easy_setopt(curl, CURLOPT_ADDRESS_SCOPE, my_scope_id);
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+#endif
+ return 0;
+}
+
diff --git a/docs/examples/makefile.dj b/docs/examples/makefile.dj
deleted file mode 100644
index 9f0de66..0000000
--- a/docs/examples/makefile.dj
+++ /dev/null
@@ -1,57 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-
-TOPDIR = ../..
-
-include $(TOPDIR)/packages/DOS/common.dj
-
-CFLAGS += -DFALSE=0 -DTRUE=1
-
-LIBS = $(TOPDIR)/lib/libcurl.a
-
-ifeq ($(USE_SSL),1)
- LIBS += $(OPENSSL_ROOT)/lib/libssl.a $(OPENSSL_ROOT)/lib/libcrypt.a
-endif
-
-ifeq ($(USE_IDNA),1)
- LIBS += $(LIBIDN_ROOT)/lib/dj_obj/libidn.a -liconv
-endif
-
-LIBS += $(WATT32_ROOT)/lib/libwatt.a $(ZLIB_ROOT)/libz.a
-
-include Makefile.inc
-
-PROGRAMS = $(patsubst %,%.exe,$(check_PROGRAMS))
-
-all: $(PROGRAMS)
- @echo Welcome to libcurl example program
-
-%.exe: %.c
- $(CC) $(CFLAGS) -o $@ $^ $(LIBS)
- @echo
-
-clean vclean realclean:
- - rm -f $(PROGRAMS) depend.dj
-
--include depend.dj
diff --git a/docs/examples/maxconnects.c b/docs/examples/maxconnects.c
new file mode 100644
index 0000000..84fefd7
--- /dev/null
+++ b/docs/examples/maxconnects.c
@@ -0,0 +1,66 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) James Fuller, <jim@webcomposite.com>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Set maximum number of persistent connections to 1.
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl = curl_easy_init();
+ if(curl) {
+ const char *urls[] = { "https://example.com",
+ "https://curl.se",
+ "https://www.example/",
+ NULL /* end of list */
+ };
+ int i = 0;
+
+ /* Change the maximum number of persistent connection */
+ curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, 1L);
+
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+ /* loop over the URLs */
+ while(urls[i]) {
+ curl_easy_setopt(curl, CURLOPT_URL, urls[i]);
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+ i++;
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ return 0;
+}
diff --git a/docs/examples/multi-app.c b/docs/examples/multi-app.c
index 8136238..3dbc464 100644
--- a/docs/examples/multi-app.c
+++ b/docs/examples/multi-app.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -38,7 +38,7 @@
#include <curl/curl.h>
/*
- * Download a HTTP file and upload an FTP file simultaneously.
+ * Download an HTTP file and upload an FTP file simultaneously.
*/
#define HANDLECOUNT 2 /* Number of simultaneous transfers */
diff --git a/docs/examples/multi-debugcallback.c b/docs/examples/multi-debugcallback.c
index 16d5d56..8bdb588 100644
--- a/docs/examples/multi-debugcallback.c
+++ b/docs/examples/multi-debugcallback.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,13 +36,10 @@
/* curl stuff */
#include <curl/curl.h>
-typedef char bool;
#define TRUE 1
-static
-void dump(const char *text,
- FILE *stream, unsigned char *ptr, size_t size,
- bool nohex)
+static void dump(const char *text, FILE *stream, unsigned char *ptr,
+ size_t size, char nohex)
{
size_t i;
size_t c;
@@ -126,7 +123,7 @@
}
/*
- * Simply download a HTTP file.
+ * Simply download an HTTP file.
*/
int main(void)
{
diff --git a/docs/examples/multi-double.c b/docs/examples/multi-double.c
index b9bba52..62295a9 100644
--- a/docs/examples/multi-double.c
+++ b/docs/examples/multi-double.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/multi-event.c b/docs/examples/multi-event.c
index 4f61f5e..5a24bb2 100644
--- a/docs/examples/multi-event.c
+++ b/docs/examples/multi-event.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/multi-formadd.c b/docs/examples/multi-formadd.c
index b5b6d8a..801b61e 100644
--- a/docs/examples/multi-formadd.c
+++ b/docs/examples/multi-formadd.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,6 +26,11 @@
* </DESC>
*/
+/*
+ * Warning: this example uses the deprecated form api. See "multi-post.c"
+ * for a similar example using the mime api.
+ */
+
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
@@ -49,14 +54,14 @@
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "sendfile",
- CURLFORM_FILE, "postit2.c",
+ CURLFORM_FILE, "multi-formadd.c",
CURLFORM_END);
/* Fill in the filename field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "filename",
- CURLFORM_COPYCONTENTS, "postit2.c",
+ CURLFORM_COPYCONTENTS, "multi-formadd.c",
CURLFORM_END);
/* Fill in the submit field too, even if this is rarely needed */
diff --git a/docs/examples/multi-legacy.c b/docs/examples/multi-legacy.c
index f9bc699..f36139f 100644
--- a/docs/examples/multi-legacy.c
+++ b/docs/examples/multi-legacy.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -38,7 +38,7 @@
#include <curl/curl.h>
/*
- * Download a HTTP file and upload an FTP file simultaneously.
+ * Download an HTTP file and upload an FTP file simultaneously.
*/
#define HANDLECOUNT 2 /* Number of simultaneous transfers */
@@ -102,7 +102,7 @@
if(timeout.tv_sec > 1)
timeout.tv_sec = 1;
else
- timeout.tv_usec = (curl_timeo % 1000) * 1000;
+ timeout.tv_usec = (int)(curl_timeo % 1000) * 1000;
}
/* get file descriptors from the transfers */
diff --git a/docs/examples/multi-post.c b/docs/examples/multi-post.c
index c141c68..112f3c0 100644
--- a/docs/examples/multi-post.c
+++ b/docs/examples/multi-post.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/multi-single.c b/docs/examples/multi-single.c
index 373ede3..c593362 100644
--- a/docs/examples/multi-single.c
+++ b/docs/examples/multi-single.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@
#include <curl/curl.h>
/*
- * Simply download a HTTP file.
+ * Simply download an HTTP file.
*/
int main(void)
{
diff --git a/docs/examples/multi-uv.c b/docs/examples/multi-uv.c
index fe7b357..6581b9f 100644
--- a/docs/examples/multi-uv.c
+++ b/docs/examples/multi-uv.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/multithread.c b/docs/examples/multithread.c
index 4f2c855..cc4ce7c 100644
--- a/docs/examples/multithread.c
+++ b/docs/examples/multithread.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
*
***************************************************************************/
/* <DESC>
- * A multi-threaded example that uses pthreads to fetch several files at once
+ * A multi-threaded program using pthreads to fetch several files at once
* </DESC>
*/
diff --git a/docs/examples/opensslthreadlock.c b/docs/examples/opensslthreadlock.c
deleted file mode 100644
index a7de777..0000000
--- a/docs/examples/opensslthreadlock.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-/* <DESC>
- * one way to set the necessary OpenSSL locking callbacks if you want to do
- * multi-threaded transfers with HTTPS/FTPS with libcurl built to use OpenSSL.
- * </DESC>
- */
-/*
- * This is not a complete stand-alone example.
- *
- * Author: Jeremy Brown
- */
-
-#include <stdio.h>
-#include <pthread.h>
-#include <openssl/err.h>
-
-#define MUTEX_TYPE pthread_mutex_t
-#define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
-#define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
-#define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
-#define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
-#define THREAD_ID pthread_self()
-
-
-void handle_error(const char *file, int lineno, const char *msg)
-{
- fprintf(stderr, "** %s:%d %s\n", file, lineno, msg);
- ERR_print_errors_fp(stderr);
- /* exit(-1); */
-}
-
-/* This array will store all of the mutexes available to OpenSSL. */
-static MUTEX_TYPE *mutex_buf = NULL;
-
-static void locking_function(int mode, int n, const char *file, int line)
-{
- if(mode & CRYPTO_LOCK)
- MUTEX_LOCK(mutex_buf[n]);
- else
- MUTEX_UNLOCK(mutex_buf[n]);
-}
-
-static unsigned long id_function(void)
-{
- return ((unsigned long)THREAD_ID);
-}
-
-int thread_setup(void)
-{
- int i;
-
- mutex_buf = malloc(CRYPTO_num_locks() * sizeof(MUTEX_TYPE));
- if(!mutex_buf)
- return 0;
- for(i = 0; i < CRYPTO_num_locks(); i++)
- MUTEX_SETUP(mutex_buf[i]);
- CRYPTO_set_id_callback(id_function);
- CRYPTO_set_locking_callback(locking_function);
- return 1;
-}
-
-int thread_cleanup(void)
-{
- int i;
-
- if(!mutex_buf)
- return 0;
- CRYPTO_set_id_callback(NULL);
- CRYPTO_set_locking_callback(NULL);
- for(i = 0; i < CRYPTO_num_locks(); i++)
- MUTEX_CLEANUP(mutex_buf[i]);
- free(mutex_buf);
- mutex_buf = NULL;
- return 1;
-}
diff --git a/docs/examples/parseurl.c b/docs/examples/parseurl.c
index d6682d7..688336f 100644
--- a/docs/examples/parseurl.c
+++ b/docs/examples/parseurl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -74,7 +74,7 @@
curl_free(path);
}
- fail:
+fail:
curl_url_cleanup(h); /* free url handle */
return 0;
}
diff --git a/docs/examples/persistent.c b/docs/examples/persistent.c
index 6ddfc40..2b6eb46 100644
--- a/docs/examples/persistent.c
+++ b/docs/examples/persistent.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/pop3-authzid.c b/docs/examples/pop3-authzid.c
index 8e0c2f2..a948e95 100644
--- a/docs/examples/pop3-authzid.c
+++ b/docs/examples/pop3-authzid.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * POP3 example showing how to retrieve emails from a shared mailbox
+ * Retrieve emails from a shared POP3 mailbox
* </DESC>
*/
diff --git a/docs/examples/pop3-dele.c b/docs/examples/pop3-dele.c
index d0281cb..fe3795c 100644
--- a/docs/examples/pop3-dele.c
+++ b/docs/examples/pop3-dele.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * POP3 example showing how to delete emails
+ * Delete POP3 emails
* </DESC>
*/
diff --git a/docs/examples/pop3-list.c b/docs/examples/pop3-list.c
index 991ff24..2e8b3ba 100644
--- a/docs/examples/pop3-list.c
+++ b/docs/examples/pop3-list.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * POP3 example to list the contents of a mailbox
+ * List the contents of a POP3 mailbox
* </DESC>
*/
diff --git a/docs/examples/pop3-multi.c b/docs/examples/pop3-multi.c
index 69a1088..b4fad19 100644
--- a/docs/examples/pop3-multi.c
+++ b/docs/examples/pop3-multi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * POP3 example using the multi interface
+ * Get POP3 email using the multi interface
* </DESC>
*/
diff --git a/docs/examples/pop3-noop.c b/docs/examples/pop3-noop.c
index a3ecb88..16181d2 100644
--- a/docs/examples/pop3-noop.c
+++ b/docs/examples/pop3-noop.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * POP3 example showing how to perform a noop
+ * Perform a POP3 noop
* </DESC>
*/
diff --git a/docs/examples/pop3-retr.c b/docs/examples/pop3-retr.c
index 1df0657..4940e07 100644
--- a/docs/examples/pop3-retr.c
+++ b/docs/examples/pop3-retr.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * POP3 example showing how to retrieve emails
+ * Retrieve POP3 email
* </DESC>
*/
diff --git a/docs/examples/pop3-ssl.c b/docs/examples/pop3-ssl.c
index 6f3455a..b9a7588 100644
--- a/docs/examples/pop3-ssl.c
+++ b/docs/examples/pop3-ssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * POP3 example using SSL
+ * Get POP3 email using implicit SSL
* </DESC>
*/
diff --git a/docs/examples/pop3-stat.c b/docs/examples/pop3-stat.c
index 3df3571..419859b 100644
--- a/docs/examples/pop3-stat.c
+++ b/docs/examples/pop3-stat.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * POP3 example showing how to obtain message statistics
+ * Obtain POP3 message statistics
* </DESC>
*/
diff --git a/docs/examples/pop3-tls.c b/docs/examples/pop3-tls.c
index d58b5e4..976ce4a 100644
--- a/docs/examples/pop3-tls.c
+++ b/docs/examples/pop3-tls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * POP3 example using TLS
+ * POP3 using TLS
* </DESC>
*/
diff --git a/docs/examples/pop3-top.c b/docs/examples/pop3-top.c
index c63b43c..7ceba88 100644
--- a/docs/examples/pop3-top.c
+++ b/docs/examples/pop3-top.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/pop3-uidl.c b/docs/examples/pop3-uidl.c
index 308de3b..496e5b0 100644
--- a/docs/examples/pop3-uidl.c
+++ b/docs/examples/pop3-uidl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * POP3 example to list the contents of a mailbox by unique ID
+ * List the contents of a POP3 mailbox by unique ID
* </DESC>
*/
diff --git a/docs/examples/post-callback.c b/docs/examples/post-callback.c
index dabcef0..a802c35 100644
--- a/docs/examples/post-callback.c
+++ b/docs/examples/post-callback.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -101,7 +101,7 @@
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
/*
- If you use POST to a HTTP 1.1 server, you can send data without knowing
+ If you use POST to an HTTP 1.1 server, you can send data without knowing
the size before starting the POST if you use chunked encoding. You
enable this by adding a header like "Transfer-Encoding: chunked" with
CURLOPT_HTTPHEADER. With HTTP 1.0 or without chunked transfer, you must
diff --git a/docs/examples/postinmemory.c b/docs/examples/postinmemory.c
index bbe1457..1610ad5 100644
--- a/docs/examples/postinmemory.c
+++ b/docs/examples/postinmemory.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
*
***************************************************************************/
/* <DESC>
- * Make a HTTP POST with data from memory and receive response in memory.
+ * Make an HTTP POST with data from memory and receive response in memory.
* </DESC>
*/
#include <stdio.h>
diff --git a/docs/examples/postit2-formadd.c b/docs/examples/postit2-formadd.c
index 8f50928..27761fc 100644
--- a/docs/examples/postit2-formadd.c
+++ b/docs/examples/postit2-formadd.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,8 +25,13 @@
* HTTP Multipart formpost with file upload and two additional parts.
* </DESC>
*/
-/* Example code that uploads a file name 'foo' to a remote script that accepts
- * "HTML form based" (as described in RFC1738) uploads using HTTP POST.
+
+/*
+ * Example code that uploads a file name 'foo' to a remote script that accepts
+ * "HTML form based" (as described in RFC 1738) uploads using HTTP POST.
+ *
+ * Warning: this example uses the deprecated form api. See "postit2.c"
+ * for a similar example using the mime api.
*
* The imaginary form we will fill in looks like:
*
@@ -35,7 +40,6 @@
* Enter file name: <input type="text" name="filename" size="30">
* <input type="submit" value="send" name="submit">
* </form>
- *
*/
#include <stdio.h>
@@ -59,14 +63,14 @@
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "sendfile",
- CURLFORM_FILE, "postit2.c",
+ CURLFORM_FILE, "postit2-formadd.c",
CURLFORM_END);
/* Fill in the filename field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "filename",
- CURLFORM_COPYCONTENTS, "postit2.c",
+ CURLFORM_COPYCONTENTS, "postit2-formadd.c",
CURLFORM_END);
diff --git a/docs/examples/postit2.c b/docs/examples/postit2.c
index 5e9c609..a1fb12b 100644
--- a/docs/examples/postit2.c
+++ b/docs/examples/postit2.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,7 +26,7 @@
* </DESC>
*/
/* Example code that uploads a file name 'foo' to a remote script that accepts
- * "HTML form based" (as described in RFC1738) uploads using HTTP POST.
+ * "HTML form based" (as described in RFC 1738) uploads using HTTP POST.
*
* The imaginary form we will fill in looks like:
*
diff --git a/docs/examples/progressfunc.c b/docs/examples/progressfunc.c
index be32b67..e164f03 100644
--- a/docs/examples/progressfunc.c
+++ b/docs/examples/progressfunc.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/chkdecimalpoint.c b/docs/examples/protofeats.c
similarity index 61%
copy from tests/libtest/chkdecimalpoint.c
copy to docs/examples/protofeats.c
index 0ff0b7d..3e76221 100644
--- a/tests/libtest/chkdecimalpoint.c
+++ b/docs/examples/protofeats.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,23 +21,32 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
+/* <DESC>
+ * Outputs all protocols and features supported
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
-#include "curl_printf.h"
-
-#include <string.h>
-#include <locale.h>
-
-#define TOTAL_STR_LEN 4
+#if !CURL_AT_LEAST_VERSION(7,87,0)
+#error "too old libcurl"
+#endif
int main(void)
{
- char zero[TOTAL_STR_LEN] = {'\0'};
- int chars;
+ curl_version_info_data *ver;
+ const char *const *ptr;
- setlocale(LC_NUMERIC, "");
- chars = msnprintf(zero, TOTAL_STR_LEN, "%.1f", 0.0);
- if((chars == (TOTAL_STR_LEN - 1)) && (strcmp(zero, "0.0") == 0))
- return 0;
- else
- return 1;
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ ver = curl_version_info(CURLVERSION_NOW);
+ printf("Protocols:\n");
+ for(ptr = ver->protocols; *ptr; ++ptr)
+ printf(" %s\n", *ptr);
+ printf("Features:\n");
+ for(ptr = ver->feature_names; *ptr; ++ptr)
+ printf(" %s\n", *ptr);
+
+ curl_global_cleanup();
+ return 0;
}
diff --git a/docs/examples/resolve.c b/docs/examples/resolve.c
index 40bdfb3..a16f459 100644
--- a/docs/examples/resolve.c
+++ b/docs/examples/resolve.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/sendrecv.c b/docs/examples/sendrecv.c
index 7da740a..b935bee 100644
--- a/docs/examples/sendrecv.c
+++ b/docs/examples/sendrecv.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
*
***************************************************************************/
/* <DESC>
- * An example of curl_easy_send() and curl_easy_recv() usage.
+ * Demonstrate curl_easy_send() and curl_easy_recv() usage.
* </DESC>
*/
@@ -38,7 +38,7 @@
int res;
tv.tv_sec = timeout_ms / 1000;
- tv.tv_usec = (timeout_ms % 1000) * 1000;
+ tv.tv_usec = (int)(timeout_ms % 1000) * 1000;
FD_ZERO(&infd);
FD_ZERO(&outfd);
diff --git a/docs/examples/sepheaders.c b/docs/examples/sepheaders.c
index a398d05..0d090ed 100644
--- a/docs/examples/sepheaders.c
+++ b/docs/examples/sepheaders.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/sessioninfo.c b/docs/examples/sessioninfo.c
index 4a848b9..befb8f3 100644
--- a/docs/examples/sessioninfo.c
+++ b/docs/examples/sessioninfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/sftpget.c b/docs/examples/sftpget.c
index 05041b1..ac2c879 100644
--- a/docs/examples/sftpget.c
+++ b/docs/examples/sftpget.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/sftpuploadresume.c b/docs/examples/sftpuploadresume.c
index 7c72e5d..aabe5c3 100644
--- a/docs/examples/sftpuploadresume.c
+++ b/docs/examples/sftpuploadresume.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/shared-connection-cache.c b/docs/examples/shared-connection-cache.c
index ac9eb54..26bfb1a 100644
--- a/docs/examples/shared-connection-cache.c
+++ b/docs/examples/shared-connection-cache.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/simple.c b/docs/examples/simple.c
index 38134c3..8579b0b 100644
--- a/docs/examples/simple.c
+++ b/docs/examples/simple.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/simplepost.c b/docs/examples/simplepost.c
index 95564d7..89435af 100644
--- a/docs/examples/simplepost.c
+++ b/docs/examples/simplepost.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/simplessl.c b/docs/examples/simplessl.c
index 879672b..1be805c 100644
--- a/docs/examples/simplessl.c
+++ b/docs/examples/simplessl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/smooth-gtk-thread.c b/docs/examples/smooth-gtk-thread.c
index c992374..906660f 100644
--- a/docs/examples/smooth-gtk-thread.c
+++ b/docs/examples/smooth-gtk-thread.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/smtp-authzid.c b/docs/examples/smtp-authzid.c
index d48a811..3425d9a 100644
--- a/docs/examples/smtp-authzid.c
+++ b/docs/examples/smtp-authzid.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -57,11 +57,11 @@
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
"rfcpedant.example.org>\r\n"
"Subject: SMTP example message\r\n"
- "\r\n" /* empty line to divide headers from body, see RFC5322 */
+ "\r\n" /* empty line to divide headers from body, see RFC 5322 */
"The body of the message starts here.\r\n"
"\r\n"
"It could be a lot of lines, could be MIME encoded, whatever.\r\n"
- "Check RFC5322.\r\n";
+ "Check RFC 5322.\r\n";
struct upload_status {
size_t bytes_read;
diff --git a/docs/examples/smtp-expn.c b/docs/examples/smtp-expn.c
index 6d9d4a4..e8ba530 100644
--- a/docs/examples/smtp-expn.c
+++ b/docs/examples/smtp-expn.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * SMTP example showing how to expand an email mailing list
+ * Expand an SMTP email mailing list
* </DESC>
*/
diff --git a/docs/examples/smtp-mail.c b/docs/examples/smtp-mail.c
index 5f3fcfd..6d53770 100644
--- a/docs/examples/smtp-mail.c
+++ b/docs/examples/smtp-mail.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -54,11 +54,11 @@
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
"rfcpedant.example.org>\r\n"
"Subject: SMTP example message\r\n"
- "\r\n" /* empty line to divide headers from body, see RFC5322 */
+ "\r\n" /* empty line to divide headers from body, see RFC 5322 */
"The body of the message starts here.\r\n"
"\r\n"
"It could be a lot of lines, could be MIME encoded, whatever.\r\n"
- "Check RFC5322.\r\n";
+ "Check RFC 5322.\r\n";
struct upload_status {
size_t bytes_read;
diff --git a/docs/examples/smtp-mime.c b/docs/examples/smtp-mime.c
index ce95582..8e19e7e 100644
--- a/docs/examples/smtp-mime.c
+++ b/docs/examples/smtp-mime.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * SMTP example showing how to send mime emails
+ * Send SMTP mime emails
* </DESC>
*/
@@ -102,6 +102,9 @@
recipients = curl_slist_append(recipients, CC);
curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
+ /* allow one of the recipients to fail and still consider it okay */
+ curl_easy_setopt(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS, 1L);
+
/* Build and set the message header list. */
for(cpp = headers_text; *cpp; cpp++)
headers = curl_slist_append(headers, *cpp);
diff --git a/docs/examples/smtp-multi.c b/docs/examples/smtp-multi.c
index 385827c..e5bc401 100644
--- a/docs/examples/smtp-multi.c
+++ b/docs/examples/smtp-multi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * SMTP example using the multi interface
+ * Send SMTP email with the multi interface
* </DESC>
*/
@@ -47,11 +47,11 @@
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
"rfcpedant.example.org>\r\n"
"Subject: SMTP example message\r\n"
- "\r\n" /* empty line to divide headers from body, see RFC5322 */
+ "\r\n" /* empty line to divide headers from body, see RFC 5322 */
"The body of the message starts here.\r\n"
"\r\n"
"It could be a lot of lines, could be MIME encoded, whatever.\r\n"
- "Check RFC5322.\r\n";
+ "Check RFC 5322.\r\n";
struct upload_status {
size_t bytes_read;
diff --git a/docs/examples/smtp-ssl.c b/docs/examples/smtp-ssl.c
index 70b2045..1c099a4 100644
--- a/docs/examples/smtp-ssl.c
+++ b/docs/examples/smtp-ssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * SMTP example using SSL
+ * Send SMTP email using implicit SSL
* </DESC>
*/
@@ -51,11 +51,11 @@
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
"rfcpedant.example.org>\r\n"
"Subject: SMTP example message\r\n"
- "\r\n" /* empty line to divide headers from body, see RFC5322 */
+ "\r\n" /* empty line to divide headers from body, see RFC 5322 */
"The body of the message starts here.\r\n"
"\r\n"
"It could be a lot of lines, could be MIME encoded, whatever.\r\n"
- "Check RFC5322.\r\n";
+ "Check RFC 5322.\r\n";
struct upload_status {
size_t bytes_read;
diff --git a/docs/examples/smtp-tls.c b/docs/examples/smtp-tls.c
index e30f478..a356491 100644
--- a/docs/examples/smtp-tls.c
+++ b/docs/examples/smtp-tls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * SMTP example using TLS
+ * Send SMTP email using implicit TLS
* </DESC>
*/
@@ -51,11 +51,11 @@
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
"rfcpedant.example.org>\r\n"
"Subject: SMTP example message\r\n"
- "\r\n" /* empty line to divide headers from body, see RFC5322 */
+ "\r\n" /* empty line to divide headers from body, see RFC 5322 */
"The body of the message starts here.\r\n"
"\r\n"
"It could be a lot of lines, could be MIME encoded, whatever.\r\n"
- "Check RFC5322.\r\n";
+ "Check RFC 5322.\r\n";
struct upload_status {
size_t bytes_read;
@@ -101,7 +101,7 @@
/* This is the URL for your mailserver. Note the use of port 587 here,
* instead of the normal SMTP port (25). Port 587 is commonly used for
- * secure mail submission (see RFC4403), but you should use whatever
+ * secure mail submission (see RFC 4403), but you should use whatever
* matches your server configuration. */
curl_easy_setopt(curl, CURLOPT_URL, "smtp://mainserver.example.net:587");
diff --git a/docs/examples/smtp-vrfy.c b/docs/examples/smtp-vrfy.c
index e6815b6..64d9310 100644
--- a/docs/examples/smtp-vrfy.c
+++ b/docs/examples/smtp-vrfy.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
***************************************************************************/
/* <DESC>
- * SMTP example showing how to verify an email address
+ * Verify an SMTP email address
* </DESC>
*/
diff --git a/docs/examples/sslbackend.c b/docs/examples/sslbackend.c
index e07d190..7674473 100644
--- a/docs/examples/sslbackend.c
+++ b/docs/examples/sslbackend.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/synctime.c b/docs/examples/synctime.c
index b617dd6..1c0579a 100644
--- a/docs/examples/synctime.c
+++ b/docs/examples/synctime.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/threaded-ssl.c b/docs/examples/threaded-ssl.c
index 09292c4..f58e447 100644
--- a/docs/examples/threaded-ssl.c
+++ b/docs/examples/threaded-ssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/unixsocket.c b/docs/examples/unixsocket.c
new file mode 100644
index 0000000..53c5fd2
--- /dev/null
+++ b/docs/examples/unixsocket.c
@@ -0,0 +1,67 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Access HTTP server over unix domain socket
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+#ifdef USE_ABSTRACT
+/*
+ * The abstract socket namespace is a nonportable Linux extension. The name
+ * has no connection with filesystem pathnames.
+ */
+#define ABSTRACT "http-unix-domain"
+#else
+#define PATH "/tmp/http-unix-domain"
+#endif
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
+
+#ifdef USE_ABSTRACT
+ curl_easy_setopt(curl, CURLOPT_ABSTRACT_UNIX_SOCKET, ABSTRACT);
+#else
+ curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, PATH);
+#endif
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ return 0;
+}
diff --git a/docs/examples/url2file.c b/docs/examples/url2file.c
index c01bcf3..f95d574 100644
--- a/docs/examples/url2file.c
+++ b/docs/examples/url2file.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/examples/urlapi.c b/docs/examples/urlapi.c
index 11962ab..2ed78eb 100644
--- a/docs/examples/urlapi.c
+++ b/docs/examples/urlapi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -58,6 +58,9 @@
curl_easy_setopt(curl, CURLOPT_CURLU, urlp);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+ /* only allow HTTP, TFTP and SFTP */
+ curl_easy_setopt(curl, CURLOPT_PROTOCOLS_STR, "http,tftp,sftp");
+
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
@@ -67,7 +70,7 @@
goto cleanup;
}
- cleanup:
+cleanup:
curl_url_cleanup(urlp);
curl_easy_cleanup(curl);
return 0;
diff --git a/docs/examples/usercertinmem.c b/docs/examples/usercertinmem.c
index 89a0c3c..12a2b79 100644
--- a/docs/examples/usercertinmem.c
+++ b/docs/examples/usercertinmem.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -94,7 +94,7 @@
"omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\n"\
"-----END CERTIFICATE-----\n";
-/*replace the XXX with the actual RSA key*/
+/* replace the XXX with the actual RSA key */
const char *mykey =
"-----BEGIN RSA PRIVATE KEY-----\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
@@ -133,25 +133,25 @@
printf("PEM_read_bio_X509 failed...\n");
}
- /*tell SSL to use the X509 certificate*/
+ /* tell SSL to use the X509 certificate */
ret = SSL_CTX_use_certificate((SSL_CTX*)sslctx, cert);
if(ret != 1) {
printf("Use certificate failed\n");
}
- /*create a bio for the RSA key*/
+ /* create a bio for the RSA key */
kbio = BIO_new_mem_buf((char *)mykey, -1);
if(!kbio) {
printf("BIO_new_mem_buf failed\n");
}
- /*read the key bio into an RSA object*/
+ /* read the key bio into an RSA object */
rsa = PEM_read_bio_RSAPrivateKey(kbio, NULL, 0, NULL);
if(!rsa) {
printf("Failed to create key bio\n");
}
- /*tell SSL to use the RSA key from memory*/
+ /* tell SSL to use the RSA key from memory */
ret = SSL_CTX_use_RSAPrivateKey((SSL_CTX*)sslctx, rsa);
if(ret != 1) {
printf("Use Key failed\n");
@@ -192,7 +192,7 @@
curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
/* both VERIFYPEER and VERIFYHOST are set to 0 in this case because there is
- no CA certificate*/
+ no CA certificate */
curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, 0L);
diff --git a/docs/examples/version-check.pl b/docs/examples/version-check.pl
index aca37995..932d154 100755
--- a/docs/examples/version-check.pl
+++ b/docs/examples/version-check.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/docs/examples/websocket-cb.c b/docs/examples/websocket-cb.c
new file mode 100644
index 0000000..7adbf44
--- /dev/null
+++ b/docs/examples/websocket-cb.c
@@ -0,0 +1,68 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * WebSocket download-only using write callback
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+static size_t writecb(char *b, size_t size, size_t nitems, void *p)
+{
+ CURL *easy = 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");
+ fprintf(stderr, "Bytes: %u", (unsigned int)(nitems * size));
+ for(i = 0; i < nitems; i++)
+ fprintf(stderr, "%02x ", (unsigned char)b[i]);
+ return nitems;
+}
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "wss://example.com");
+
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
+ /* pass the easy handle to the callback */
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl);
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ return 0;
+}
diff --git a/docs/examples/websocket.c b/docs/examples/websocket.c
new file mode 100644
index 0000000..52a0903
--- /dev/null
+++ b/docs/examples/websocket.c
@@ -0,0 +1,131 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * WebSocket using CONNECT_ONLY
+ * </DESC>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <curl/curl.h>
+
+static int ping(CURL *curl, const char *send_payload)
+{
+ size_t sent;
+ CURLcode result =
+ curl_ws_send(curl, send_payload, strlen(send_payload), &sent, 0,
+ CURLWS_PING);
+ return (int)result;
+}
+
+static int recv_pong(CURL *curl, const char *exected_payload)
+{
+ size_t rlen;
+ const struct curl_ws_frame *meta;
+ char buffer[256];
+ CURLcode result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
+ if(!result) {
+ if(meta->flags & CURLWS_PONG) {
+ int same = 0;
+ fprintf(stderr, "ws: got PONG back\n");
+ if(rlen == strlen(exected_payload)) {
+ if(!memcmp(exected_payload, buffer, rlen)) {
+ fprintf(stderr, "ws: got the same payload back\n");
+ same = 1;
+ }
+ }
+ if(!same)
+ fprintf(stderr, "ws: did NOT get the same payload back\n");
+ }
+ else {
+ fprintf(stderr, "recv_pong: got %u bytes rflags %x\n", (int)rlen,
+ meta->flags);
+ }
+ }
+ fprintf(stderr, "ws: curl_ws_recv returned %u, received %u\n",
+ (unsigned int)result, (unsigned int)rlen);
+ return (int)result;
+}
+
+static int recv_any(CURL *curl)
+{
+ size_t rlen;
+ const struct curl_ws_frame *meta;
+ char buffer[256];
+ CURLcode result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
+ if(result)
+ return result;
+
+ return 0;
+}
+
+/* close the connection */
+static void websocket_close(CURL *curl)
+{
+ size_t sent;
+ (void)curl_ws_send(curl, "", 0, &sent, 0, CURLWS_CLOSE);
+}
+
+static void websocket(CURL *curl)
+{
+ int i = 0;
+ do {
+ recv_any(curl);
+ if(ping(curl, "foobar"))
+ return;
+ if(recv_pong(curl, "foobar")) {
+ return;
+ }
+ sleep(2);
+ } while(i++ < 10);
+ websocket_close(curl);
+}
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "wss://example.com");
+
+ curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); /* websocket style */
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+ else {
+ /* connected and ready */
+ websocket(curl);
+ }
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ return 0;
+}
diff --git a/docs/examples/xmlstream.c b/docs/examples/xmlstream.c
index ae5963b..76a8e48 100644
--- a/docs/examples/xmlstream.c
+++ b/docs/examples/xmlstream.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/docs/libcurl/.gitignore b/docs/libcurl/.gitignore
index 5deb37f..fd35ad0 100644
--- a/docs/libcurl/.gitignore
+++ b/docs/libcurl/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/docs/libcurl/ABI.md b/docs/libcurl/ABI.md
index b70e18a..408ea10 100644
--- a/docs/libcurl/ABI.md
+++ b/docs/libcurl/ABI.md
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 1998 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
@@ -26,11 +26,11 @@
we do not break the ABI so you can *always* upgrade to a later version without
any loss or change in functionality.
-## Soname Bumps
+## SONAME Bumps
Whenever there are changes done to the library that will cause an ABI
breakage, that may require your application to get attention or possibly be
- changed to adhere to new things, we will bump the soname. Then the library
+ changed to adhere to new things, we will bump the SONAME. Then the library
will get a different output name and thus can in fact be installed in
parallel with an older installed lib (on most systems). Thus, old
applications built against the previous ABI version will remain working and
@@ -39,8 +39,8 @@
During the first seven years of libcurl releases, there have only been four
ABI breakages.
- We are determined to bump the SONAME as rarely as possible. Ideally, we
- never do it again.
+ We are determined to bump the SONAME as rarely as possible. Ideally, we never
+ do it again.
## Downgrades
@@ -50,11 +50,11 @@
that going backwards may get you in a situation where you pick a libcurl that
does not support the options your application needs. Or possibly you even
downgrade so far so you cross an ABI break border and thus a different
- soname, and then your application may need to adapt to the modified ABI.
+ SONAME, and then your application may need to adapt to the modified ABI.
## History
- The previous major library soname number bumps (breaking backwards
+ The previous major library SONAME number bumps (breaking backwards
compatibility) happened the following times:
0 - libcurl 7.1, August 2000
diff --git a/docs/libcurl/CMakeLists.txt b/docs/libcurl/CMakeLists.txt
index e90d9bb..c83b5c9 100644
--- a/docs/libcurl/CMakeLists.txt
+++ b/docs/libcurl/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/docs/libcurl/Makefile.am b/docs/libcurl/Makefile.am
index aa0eda0..8d512a6 100644
--- a/docs/libcurl/Makefile.am
+++ b/docs/libcurl/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/docs/libcurl/Makefile.inc b/docs/libcurl/Makefile.inc
index f1e79ab..35122e7 100644
--- a/docs/libcurl/Makefile.inc
+++ b/docs/libcurl/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2008 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -85,6 +85,8 @@
curl_multi_timeout.3 \
curl_multi_wakeup.3 \
curl_multi_wait.3 \
+ curl_pushheader_bynum.3 \
+ curl_pushheader_byname.3 \
curl_share_cleanup.3 \
curl_share_init.3 \
curl_share_setopt.3 \
@@ -102,6 +104,9 @@
curl_url_strerror.3 \
curl_version.3 \
curl_version_info.3 \
+ curl_ws_meta.3 \
+ curl_ws_recv.3 \
+ curl_ws_send.3 \
libcurl-easy.3 \
libcurl-env.3 \
libcurl-errors.3 \
@@ -112,4 +117,5 @@
libcurl-thread.3 \
libcurl-tutorial.3 \
libcurl-url.3 \
+ libcurl-ws.3 \
libcurl.3
diff --git a/docs/libcurl/curl_easy_cleanup.3 b/docs/libcurl/curl_easy_cleanup.3
index ba8f82a..3ddafad 100644
--- a/docs/libcurl/curl_easy_cleanup.3
+++ b/docs/libcurl/curl_easy_cleanup.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH curl_easy_cleanup 3 "22 Aug 2007" "libcurl 7.17.0" "libcurl Manual"
+.TH curl_easy_cleanup 3 "22 Aug 2007" "libcurl" "libcurl"
.SH NAME
curl_easy_cleanup - End a libcurl easy handle
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_easy_duphandle.3 b/docs/libcurl/curl_easy_duphandle.3
index a1a561e..af97729 100644
--- a/docs/libcurl/curl_easy_duphandle.3
+++ b/docs/libcurl/curl_easy_duphandle.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_easy_duphandle 3 "19 Sep 2014" "libcurl" "libcurl Manual"
+.TH curl_easy_duphandle 3 "19 Sep 2014" "libcurl" "libcurl"
.SH NAME
curl_easy_duphandle - Clone a libcurl session handle
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_easy_escape.3 b/docs/libcurl/curl_easy_escape.3
index 35ad2cb..55a0eaa 100644
--- a/docs/libcurl/curl_easy_escape.3
+++ b/docs/libcurl/curl_easy_escape.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH curl_easy_escape 3 "7 April 2006" "libcurl 7.15.4" "libcurl Manual"
+.TH curl_easy_escape 3 "7 April 2006" "libcurl" "libcurl"
.SH NAME
curl_easy_escape - URL encodes the given string
.SH SYNOPSIS
@@ -35,12 +35,16 @@
This function converts the given input \fIstring\fP to a URL encoded string
and returns that as a new allocated string. All input characters that are not
a-z, A-Z, 0-9, '-', '.', '_' or '~' are converted to their "URL escaped"
-version (%NN where NN is a two-digit hexadecimal number).
+version (\fB%NN\fP where \fBNN\fP is a two-digit hexadecimal number).
If \fIlength\fP is set to 0 (zero), \fIcurl_easy_escape(3)\fP uses strlen() on
the input \fIstring\fP to find out the size. This function does not accept
input strings longer than \fBCURL_MAX_INPUT_LENGTH\fP (8 MB).
+Since 7.82.0, the \fBcurl\fP parameter is ignored. Prior to that there was
+per-handle character conversion support for some very old operating systems
+such as TPF, but it was otherwise ignored.
+
You must \fIcurl_free(3)\fP the returned string when you are done with it.
.SH ENCODING
libcurl is typically not aware of, nor does it care about, character
diff --git a/docs/libcurl/curl_easy_getinfo.3 b/docs/libcurl/curl_easy_getinfo.3
index 77ce622..e684a85 100644
--- a/docs/libcurl/curl_easy_getinfo.3
+++ b/docs/libcurl/curl_easy_getinfo.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH curl_easy_getinfo 3 "11 Feb 2009" "libcurl 7.19.4" "libcurl Manual"
+.TH curl_easy_getinfo 3 "11 Feb 2009" "libcurl" "libcurl"
.SH NAME
curl_easy_getinfo - extract information from a curl handle
.SH SYNOPSIS
@@ -33,12 +33,11 @@
.fi
.SH DESCRIPTION
Request internal information from the curl session with this function. The
-third argument \fBMUST\fP be a pointer to a long, a pointer to a char *, a
-pointer to a struct curl_slist * or a pointer to a double (as this
-documentation describes further down). The data pointed-to will be filled in
-accordingly and can be relied upon only if the function returns CURLE_OK. Use
-this function AFTER a performed transfer if you want to get transfer related
-data.
+third argument \fBMUST\fP be pointing to the specific type of the used option
+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. Use this function AFTER a performed transfer if you want to get
+transfer related data.
You should not free the memory returned by this function unless it is
explicitly mentioned below.
@@ -170,7 +169,7 @@
Content type from the Content-Type header.
See \fICURLINFO_CONTENT_TYPE(3)\fP
.IP CURLINFO_RETRY_AFTER
-The value from the from the Retry-After header.
+The value from the Retry-After header.
See \fICURLINFO_RETRY_AFTER(3)\fP
.IP CURLINFO_PRIVATE
User's private data pointer.
@@ -203,7 +202,7 @@
List of all known cookies.
See \fICURLINFO_COOKIELIST(3)\fP
.IP CURLINFO_LASTSOCKET
-Last socket used.
+(Deprecated) Last socket used.
See \fICURLINFO_LASTSOCKET(3)\fP
.IP CURLINFO_ACTIVESOCKET
The session's active socket.
@@ -243,11 +242,17 @@
RTSP CSeq last received.
See \fICURLINFO_RTSP_CSEQ_RECV(3)\fP
.IP CURLINFO_PROTOCOL
-The protocol used for the connection. (Added in 7.52.0)
+(Deprecated) The protocol used for the connection. (Added in 7.52.0)
See \fICURLINFO_PROTOCOL(3)\fP
.IP CURLINFO_SCHEME
The scheme used for the connection. (Added in 7.52.0)
See \fICURLINFO_SCHEME(3)\fP
+.IP CURLINFO_CONN_ID
+The ID of the last connection used by the transfer. (Added in 8.2.0)
+See \fICURLINFO_CONN_ID(3)\fP
+.IP CURLINFO_XFER_ID
+The ID of the transfer. (Added in 8.2.0)
+See \fICURLINFO_XFER_ID(3)\fP
.SH TIMES
.nf
An overview of the six time values available from curl_easy_getinfo()
diff --git a/docs/libcurl/curl_easy_header.3 b/docs/libcurl/curl_easy_header.3
index 85a1e7d..1455648 100644
--- a/docs/libcurl/curl_easy_header.3
+++ b/docs/libcurl/curl_easy_header.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_easy_header 3 "13 March 2022" "libcurl 7.83.0" "libcurl Manual"
+.TH curl_easy_header 3 "13 March 2022" "libcurl" "libcurl"
.SH NAME
curl_easy_header - get an HTTP header
.SH SYNOPSIS
@@ -37,7 +37,7 @@
.SH DESCRIPTION
\fIcurl_easy_header(3)\fP returns a pointer to a "curl_header" struct in
\fBhout\fP with data for the HTTP response header \fIname\fP. The case
-insensitive nul-terminated header name should be specified without colon.
+insensitive null-terminated header name should be specified without colon.
\fIindex\fP 0 means asking for the first instance of the header. If the
returned header struct has \fBamount\fP set larger than 1, it means there are
@@ -94,7 +94,7 @@
The data \fBvalue\fP field points to, comes exactly as delivered over the
network but with leading and trailing whitespace and newlines stripped
-off. The `value` data is nul-terminated. For legacy HTTP/1 "folded headers",
+off. The `value` data is null-terminated. For legacy HTTP/1 "folded headers",
this API provides the full single value in an unfolded manner with a single
whitespace between the lines.
@@ -122,7 +122,7 @@
.IP CURLH_1XX
The header arrived in an HTTP 1xx response. A 1xx response is an "intermediate"
response that might happen before the "real" response.
-.IP CURLH_PSUEDO
+.IP CURLH_PSEUDO
The header is an HTTP/2 or HTTP/3 pseudo header
.SH EXAMPLE
.nf
@@ -134,20 +134,7 @@
Added in 7.83.0. Officially supported since 7.84.0.
.SH RETURN VALUE
This function returns a CURLHcode indicating success or error.
-.IP "CURLHE_BADINDEX (1)"
-There is no header with the requested index.
-.IP "CURLHE_MISSING (2)"
-No such header exists.
-.IP "CURLHE_NOHEADERS (3)"
-No headers at all have been recorded.
-.IP "CURLHE_NOREQUEST (4)"
-There was no such request number.
-.IP "CURLHE_OUT_OF_MEMORY (5)"
-Out of resources
-.IP "CURLHE_BAD_ARGUMENT (6)"
-One or more of the given arguments are bad.
-.IP "CURLHE_NOT_BUILT_IN (7)"
-HTTP or the header API has been disabled in the build.
.SH "SEE ALSO"
.BR curl_easy_nextheader "(3), " curl_easy_perform "(3), "
-.BR CURLOPT_HEADERFUNCTION "(3), " CURLINFO_CONTENT_TYPE "(3) "
+.BR CURLOPT_HEADERFUNCTION "(3), " CURLINFO_CONTENT_TYPE "(3), "
+.BR libcurl-errors "(3) "
diff --git a/docs/libcurl/curl_easy_init.3 b/docs/libcurl/curl_easy_init.3
index 65b7d2f..457ebc7 100644
--- a/docs/libcurl/curl_easy_init.3
+++ b/docs/libcurl/curl_easy_init.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_easy_init 3 "4 March 2002" "libcurl 7.8.1" "libcurl Manual"
+.TH curl_easy_init 3 "4 March 2002" "libcurl" "libcurl"
.SH NAME
curl_easy_init - Start a libcurl easy session
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_easy_nextheader.3 b/docs/libcurl/curl_easy_nextheader.3
index 7980eb4..8f892f9 100644
--- a/docs/libcurl/curl_easy_nextheader.3
+++ b/docs/libcurl/curl_easy_nextheader.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_easy_nextheader 3 "13 March 2022" "libcurl 7.83.0" "libcurl Manual"
+.TH curl_easy_nextheader 3 "13 March 2022" "libcurl" "libcurl"
.SH NAME
curl_easy_nextheader - get the next HTTP header
.SH SYNOPSIS
@@ -73,14 +73,14 @@
/* extract the normal headers from the first request */
while((h = curl_easy_nextheader(easy, CURLH_HEADER, 0, prev))) {
- print "%s: %s\\n", h->name, h->value);
+ printf("%s: %s\\n", h->name, h->value);
prev = h;
}
/* extract the normal headers + 1xx + trailers from the last request */
unsigned int origin = CURLH_HEADER| CURLH_1XX | CURLH_TRAILER;
while((h = curl_easy_nextheader(easy, origin, -1, prev))) {
- print "%s: %s\\n", h->name, h->value);
+ printf("%s: %s\\n", h->name, h->value);
prev = h;
}
.fi
diff --git a/docs/libcurl/curl_easy_option_by_id.3 b/docs/libcurl/curl_easy_option_by_id.3
index f0a460d..373e786 100644
--- a/docs/libcurl/curl_easy_option_by_id.3
+++ b/docs/libcurl/curl_easy_option_by_id.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_easy_option_by_id 3 "27 Aug 2020" "libcurl 7.73.0" "libcurl Manual"
+.TH curl_easy_option_by_id 3 "27 Aug 2020" "libcurl" "libcurl"
.SH NAME
curl_easy_option_by_id - find an easy setopt option by id
.SH SYNOPSIS
@@ -31,8 +31,8 @@
const struct curl_easyoption *curl_easy_option_by_id(CURLoption id);
.fi
.SH DESCRIPTION
-Given a CURLoption \fBid\fP, this function returns a pointer to the
-curl_easyoption struct, holding information about the
+Given a \fICURLoption\fP \fBid\fP, this function returns a pointer to the
+\fIcurl_easyoption\fP struct, holding information about the
\fIcurl_easy_setopt(3)\fP option using that id. The option id is the CURLOPT_
prefix ones provided in the standard curl/curl.h header file. This function
will return the non-aliases version for the cases where there is an alias
@@ -49,7 +49,7 @@
.SH AVAILABILITY
This function was added in libcurl 7.73.0
.SH RETURN VALUE
-A pointer to the curl_easyoption struct for the option or NULL.
+A pointer to the \fIcurl_easyoption\fP struct for the option or NULL.
.SH "SEE ALSO"
.BR curl_easy_option_by_name "(3)," curl_easy_option_next "(3),"
.BR curl_easy_setopt "(3),"
diff --git a/docs/libcurl/curl_easy_option_by_name.3 b/docs/libcurl/curl_easy_option_by_name.3
index f2abfbc..031bab1 100644
--- a/docs/libcurl/curl_easy_option_by_name.3
+++ b/docs/libcurl/curl_easy_option_by_name.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_easy_option_by_name 3 "27 Aug 2020" "libcurl 7.73.0" "libcurl Manual"
+.TH curl_easy_option_by_name 3 "27 Aug 2020" "libcurl" "libcurl"
.SH NAME
curl_easy_option_by_name - find an easy setopt option by name
.SH SYNOPSIS
@@ -31,10 +31,11 @@
const struct curl_easyoption *curl_easy_option_by_name(const char *name);
.fi
.SH DESCRIPTION
-Given a \fBname\fP, this function returns a pointer to the curl_easyoption
-struct, holding information about the \fIcurl_easy_setopt(3)\fP option using
-that name. The name should be specified without the "CURLOPT_" prefix and the
-name comparison is made case insensitive.
+Given a \fBname\fP, this function returns a pointer to the
+\fIcurl_easyoption\fP struct, holding information about the
+\fIcurl_easy_setopt(3)\fP option using that name. The name should be specified
+without the "CURLOPT_" prefix and the name comparison is made case
+insensitive.
If libcurl has no option with the given name, this function returns NULL.
.SH EXAMPLE
@@ -47,7 +48,7 @@
.SH AVAILABILITY
This function was added in libcurl 7.73.0
.SH RETURN VALUE
-A pointer to the curl_easyoption struct for the option or NULL.
+A pointer to the \fIcurl_easyoption\fP struct for the option or NULL.
.SH "SEE ALSO"
.BR curl_easy_option_next "(3)," curl_easy_option_by_id "(3),"
.BR curl_easy_setopt "(3),"
diff --git a/docs/libcurl/curl_easy_option_next.3 b/docs/libcurl/curl_easy_option_next.3
index fa73ccc..a3e122a 100644
--- a/docs/libcurl/curl_easy_option_next.3
+++ b/docs/libcurl/curl_easy_option_next.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_easy_option_next 3 "27 Aug 2020" "libcurl 7.73.0" "libcurl Manual"
+.TH curl_easy_option_next 3 "27 Aug 2020" "libcurl" "libcurl"
.SH NAME
curl_easy_option_next - iterate over easy setopt options
.SH SYNOPSIS
@@ -33,7 +33,7 @@
CURLOT_VALUES, /* (a defined set or bitmask) */
CURLOT_OFF_T, /* curl_off_t (a range of values) */
CURLOT_OBJECT, /* pointer (void *) */
- CURLOT_STRING, /* (char * to zero terminated buffer) */
+ CURLOT_STRING, /* (char * to null-terminated buffer) */
CURLOT_SLIST, /* (struct curl_slist *) */
CURLOT_CBPTR, /* (void * passed as-is to a callback) */
CURLOT_BLOB, /* blob (struct curl_blob *) */
@@ -53,7 +53,7 @@
curl_easy_option_next(const struct curl_easyoption *prev);
.fi
.SH DESCRIPTION
-This function returns a pointer to the first or the next curl_easyoption
+This function returns a pointer to the first or the next \fIcurl_easyoption\fP
struct, providing an ability to iterate over all known options for
\fIcurl_easy_setopt(3)\fP in this instance of libcurl.
@@ -79,8 +79,8 @@
.SH AVAILABILITY
This function was added in libcurl 7.73.0
.SH RETURN VALUE
-A pointer to the curl_easyoption struct for the next option or NULL if no more
-options.
+A pointer to the \fIcurl_easyoption\fP struct for the next option or NULL if
+no more options.
.SH "SEE ALSO"
.BR curl_easy_option_by_name "(3)," curl_easy_option_by_id "(3),"
.BR curl_easy_setopt "(3),"
diff --git a/docs/libcurl/curl_easy_pause.3 b/docs/libcurl/curl_easy_pause.3
index f8385bb..822b81c 100644
--- a/docs/libcurl/curl_easy_pause.3
+++ b/docs/libcurl/curl_easy_pause.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_easy_pause 3 "17 Dec 2007" "libcurl 7.18.0" "libcurl Manual"
+.TH curl_easy_pause 3 "17 Dec 2007" "libcurl" "libcurl"
.SH NAME
curl_easy_pause - pause and unpause a connection
.SH SYNOPSIS
@@ -45,8 +45,11 @@
function from another thread. To unpause, you may for example call it from the
progress callback (\fICURLOPT_PROGRESSFUNCTION(3)\fP).
-When this function is called to unpause receiving, the chance is high that you
-will get your write callback called before this function returns.
+When this function is called to unpause receiving, the write callback might
+get called before this function returns to deliver cached content. When
+libcurl delivers such cached data to the write callback, it will be delivered
+as fast as possible, which may overstep the boundary set in
+\fICURLOPT_MAX_RECV_SPEED_LARGE(3)\fP etc.
The \fBhandle\fP argument identifies the transfer you want to pause or
unpause.
diff --git a/docs/libcurl/curl_easy_perform.3 b/docs/libcurl/curl_easy_perform.3
index ac63203..f685790 100644
--- a/docs/libcurl/curl_easy_perform.3
+++ b/docs/libcurl/curl_easy_perform.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_easy_perform 3 "5 Mar 2001" "libcurl 7.7" "libcurl Manual"
+.TH curl_easy_perform 3 "5 Mar 2001" "libcurl" "libcurl"
.SH NAME
curl_easy_perform - perform a blocking file transfer
.SH SYNOPSIS
@@ -74,7 +74,7 @@
.SH AVAILABILITY
Always
.SH RETURN VALUE
-CURLE_OK (0) means everything was ok, non-zero means an error occurred as
+CURLE_OK (0) means everything was OK, non-zero means an error occurred as
.I <curl/curl.h>
defines - see \fIlibcurl-errors(3)\fP. If the \fICURLOPT_ERRORBUFFER(3)\fP was
set with \fIcurl_easy_setopt(3)\fP there will be a readable error message in
diff --git a/docs/libcurl/curl_easy_recv.3 b/docs/libcurl/curl_easy_recv.3
index 22e128f..2abb494 100644
--- a/docs/libcurl/curl_easy_recv.3
+++ b/docs/libcurl/curl_easy_recv.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH curl_easy_recv 3 "29 April 2008" "libcurl 7.18.2" "libcurl Manual"
+.TH curl_easy_recv 3 "29 April 2008" "libcurl" "libcurl"
.SH NAME
curl_easy_recv - receives raw data on an "easy" connection
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_easy_reset.3 b/docs/libcurl/curl_easy_reset.3
index a46b543..f083bc4 100644
--- a/docs/libcurl/curl_easy_reset.3
+++ b/docs/libcurl/curl_easy_reset.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_easy_reset 3 "31 July 2004" "libcurl 7.12.1" "libcurl Manual"
+.TH curl_easy_reset 3 "31 July 2004" "libcurl" "libcurl"
.SH NAME
curl_easy_reset - reset all options of a libcurl session handle
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_easy_send.3 b/docs/libcurl/curl_easy_send.3
index ce7e0d9..91e7190 100644
--- a/docs/libcurl/curl_easy_send.3
+++ b/docs/libcurl/curl_easy_send.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH curl_easy_send 3 "29 April 2008" "libcurl 7.18.2" "libcurl Manual"
+.TH curl_easy_send 3 "29 April 2008" "libcurl" "libcurl"
.SH NAME
curl_easy_send - sends raw data over an "easy" connection
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
index c98c300..784495d 100644
--- a/docs/libcurl/curl_easy_setopt.3
+++ b/docs/libcurl/curl_easy_setopt.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH curl_easy_setopt 3 "25 Jun 2014" "libcurl 7.38.0" "libcurl Manual"
+.TH curl_easy_setopt 3 "25 Jun 2014" "libcurl" "libcurl"
.SH NAME
curl_easy_setopt \- set options for a curl easy handle
.SH SYNOPSIS
@@ -83,9 +83,11 @@
.IP CURLOPT_READDATA
Data pointer to pass to the read callback. See \fICURLOPT_READDATA(3)\fP
.IP CURLOPT_IOCTLFUNCTION
-Callback for I/O operations. See \fICURLOPT_IOCTLFUNCTION(3)\fP
+\fBDeprecated option\fP Callback for I/O operations.
+See \fICURLOPT_IOCTLFUNCTION(3)\fP
.IP CURLOPT_IOCTLDATA
-Data pointer to pass to the I/O callback. See \fICURLOPT_IOCTLDATA(3)\fP
+\fBDeprecated option\fP Data pointer to pass to the I/O callback.
+See \fICURLOPT_IOCTLDATA(3)\fP
.IP CURLOPT_SEEKFUNCTION
Callback for seek operations. See \fICURLOPT_SEEKFUNCTION(3)\fP
.IP CURLOPT_SEEKDATA
@@ -103,7 +105,8 @@
.IP CURLOPT_CLOSESOCKETDATA
Data pointer to pass to the close socket callback. See \fICURLOPT_CLOSESOCKETDATA(3)\fP
.IP CURLOPT_PROGRESSFUNCTION
-OBSOLETE callback for progress meter. See \fICURLOPT_PROGRESSFUNCTION(3)\fP
+\fBOBSOLETE\fP callback for progress meter.
+See \fICURLOPT_PROGRESSFUNCTION(3)\fP
.IP CURLOPT_PROGRESSDATA
Data pointer to pass to the progress meter callback. See \fICURLOPT_PROGRESSDATA(3)\fP
.IP CURLOPT_XFERINFOFUNCTION
@@ -123,11 +126,14 @@
.IP CURLOPT_SSL_CTX_DATA
Data pointer to pass to the SSL context callback. See \fICURLOPT_SSL_CTX_DATA(3)\fP
.IP CURLOPT_CONV_TO_NETWORK_FUNCTION
-Callback for code base conversion. See \fICURLOPT_CONV_TO_NETWORK_FUNCTION(3)\fP
+\fBOBSOLETE\fP Callback for code base conversion.
+See \fICURLOPT_CONV_TO_NETWORK_FUNCTION(3)\fP
.IP CURLOPT_CONV_FROM_NETWORK_FUNCTION
-Callback for code base conversion. See \fICURLOPT_CONV_FROM_NETWORK_FUNCTION(3)\fP
+\fBOBSOLETE\fP Callback for code base conversion.
+See \fICURLOPT_CONV_FROM_NETWORK_FUNCTION(3)\fP
.IP CURLOPT_CONV_FROM_UTF8_FUNCTION
-Callback for code base conversion. See \fICURLOPT_CONV_FROM_UTF8_FUNCTION(3)\fP
+\fBOBSOLETE\fP Callback for code base conversion.
+See \fICURLOPT_CONV_FROM_UTF8_FUNCTION(3)\fP
.IP CURLOPT_INTERLEAVEFUNCTION
Callback for RTSP interleaved data. See \fICURLOPT_INTERLEAVEFUNCTION(3)\fP
.IP CURLOPT_INTERLEAVEDATA
@@ -167,9 +173,14 @@
.IP CURLOPT_PATH_AS_IS
Disable squashing /../ and /./ sequences in the path. See \fICURLOPT_PATH_AS_IS(3)\fP
.IP CURLOPT_PROTOCOLS
-Allowed protocols. See \fICURLOPT_PROTOCOLS(3)\fP
+\fBDeprecated option\fP Allowed protocols. See \fICURLOPT_PROTOCOLS(3)\fP
+.IP CURLOPT_PROTOCOLS_STR
+Allowed protocols. See \fICURLOPT_PROTOCOLS_STR(3)\fP
.IP CURLOPT_REDIR_PROTOCOLS
-Protocols to allow redirects to. See \fICURLOPT_REDIR_PROTOCOLS(3)\fP
+\fBDeprecated option\fP Protocols to allow redirects to. See
+\fICURLOPT_REDIR_PROTOCOLS(3)\fP
+.IP CURLOPT_REDIR_PROTOCOLS_STR
+Protocols to allow redirects to. See \fICURLOPT_REDIR_PROTOCOLS_STR(3)\fP
.IP CURLOPT_DEFAULT_PROTOCOL
Default protocol. See \fICURLOPT_DEFAULT_PROTOCOL(3)\fP
.IP CURLOPT_PROXY
@@ -189,13 +200,16 @@
.IP CURLOPT_SOCKS5_AUTH
Socks5 authentication methods. See \fICURLOPT_SOCKS5_AUTH(3)\fP
.IP CURLOPT_SOCKS5_GSSAPI_SERVICE
-Socks5 GSSAPI service name. \fICURLOPT_SOCKS5_GSSAPI_SERVICE(3)\fP
+\fBDeprecated option\fP Socks5 GSSAPI service name.
+See \fICURLOPT_SOCKS5_GSSAPI_SERVICE(3)\fP
.IP CURLOPT_SOCKS5_GSSAPI_NEC
Socks5 GSSAPI NEC mode. See \fICURLOPT_SOCKS5_GSSAPI_NEC(3)\fP
.IP CURLOPT_PROXY_SERVICE_NAME
Proxy authentication service name. \fICURLOPT_PROXY_SERVICE_NAME(3)\fP
.IP CURLOPT_HAPROXYPROTOCOL
Send an HAProxy PROXY protocol v1 header. See \fICURLOPT_HAPROXYPROTOCOL(3)\fP
+.IP CURLOPT_HAPROXY_CLIENT_IP
+Spoof the client IP in an HAProxy PROXY protocol v1 header. See \fICURLOPT_HAPROXY_CLIENT_IP(3)\fP
.IP CURLOPT_SERVICE_NAME
Authentication service name. \fICURLOPT_SERVICE_NAME(3)\fP
.IP CURLOPT_INTERFACE
@@ -207,7 +221,8 @@
.IP CURLOPT_DNS_CACHE_TIMEOUT
Timeout for DNS cache. See \fICURLOPT_DNS_CACHE_TIMEOUT(3)\fP
.IP CURLOPT_DNS_USE_GLOBAL_CACHE
-OBSOLETE Enable global DNS cache. See \fICURLOPT_DNS_USE_GLOBAL_CACHE(3)\fP
+\fBOBSOLETE\fP Enable global DNS cache.
+See \fICURLOPT_DNS_USE_GLOBAL_CACHE(3)\fP
.IP CURLOPT_DOH_URL
Use this DoH server for name resolves. See \fICURLOPT_DOH_URL(3)\fP
.IP CURLOPT_BUFFERSIZE
@@ -215,7 +230,7 @@
.IP CURLOPT_PORT
Port number to connect to. See \fICURLOPT_PORT(3)\fP
.IP CURLOPT_TCP_FASTOPEN
-Enable TFO, TCP Fast Open. See \fICURLOPT_TCP_FASTOPEN(3)\fP
+Enable TCP Fast Open. See \fICURLOPT_TCP_FASTOPEN(3)\fP
.IP CURLOPT_TCP_NODELAY
Disable the Nagle algorithm. See \fICURLOPT_TCP_NODELAY(3)\fP
.IP CURLOPT_ADDRESS_SCOPE
@@ -289,7 +304,7 @@
.IP CURLOPT_POSTREDIR
How to act on redirects after POST. See \fICURLOPT_POSTREDIR(3)\fP
.IP CURLOPT_PUT
-Issue an HTTP PUT request. See \fICURLOPT_PUT(3)\fP
+\fBDeprecated option\fP Issue an HTTP PUT request. See \fICURLOPT_PUT(3)\fP
.IP CURLOPT_POST
Issue an HTTP POST request. See \fICURLOPT_POST(3)\fP
.IP CURLOPT_POSTFIELDS
@@ -301,7 +316,8 @@
.IP CURLOPT_COPYPOSTFIELDS
Send a POST with this data - and copy it. See \fICURLOPT_COPYPOSTFIELDS(3)\fP
.IP CURLOPT_HTTPPOST
-Multipart formpost HTTP POST. See \fICURLOPT_HTTPPOST(3)\fP
+\fBDeprecated option\fP Multipart formpost HTTP POST.
+See \fICURLOPT_HTTPPOST(3)\fP
.IP CURLOPT_REFERER
Referer: header. See \fICURLOPT_REFERER(3)\fP
.IP CURLOPT_USERAGENT
@@ -378,8 +394,9 @@
Address of the recipients. See \fICURLOPT_MAIL_RCPT(3)\fP
.IP CURLOPT_MAIL_AUTH
Authentication address. See \fICURLOPT_MAIL_AUTH(3)\fP
-.IP CURLOPT_MAIL_RCPT_ALLLOWFAILS
-Allow RCPT TO command to fail for some recipients. See \fICURLOPT_MAIL_RCPT_ALLLOWFAILS(3)\fP
+.IP CURLOPT_MAIL_RCPT_ALLOWFAILS
+Allow RCPT TO command to fail for some recipients. See
+\fICURLOPT_MAIL_RCPT_ALLOWFAILS(3)\fP
.SH TFTP OPTIONS
.IP CURLOPT_TFTP_BLKSIZE
TFTP block size. See \fICURLOPT_TFTP_BLKSIZE(3)\fP
@@ -397,15 +414,15 @@
.IP CURLOPT_APPEND
Append to remote file. See \fICURLOPT_APPEND(3)\fP
.IP CURLOPT_FTP_USE_EPRT
-Use EPTR. See \fICURLOPT_FTP_USE_EPRT(3)\fP
+Use EPRT. See \fICURLOPT_FTP_USE_EPRT(3)\fP
.IP CURLOPT_FTP_USE_EPSV
Use EPSV. See \fICURLOPT_FTP_USE_EPSV(3)\fP
.IP CURLOPT_FTP_USE_PRET
Use PRET. See \fICURLOPT_FTP_USE_PRET(3)\fP
.IP CURLOPT_FTP_CREATE_MISSING_DIRS
Create missing directories on the remote server. See \fICURLOPT_FTP_CREATE_MISSING_DIRS(3)\fP
-.IP CURLOPT_FTP_RESPONSE_TIMEOUT
-Timeout for FTP responses. See \fICURLOPT_FTP_RESPONSE_TIMEOUT(3)\fP
+.IP CURLOPT_SERVER_RESPONSE_TIMEOUT
+Timeout for server responses. See \fICURLOPT_SERVER_RESPONSE_TIMEOUT(3)\fP
.IP CURLOPT_FTP_ALTERNATIVE_TO_USER
Alternative to USER. See \fICURLOPT_FTP_ALTERNATIVE_TO_USER(3)\fP
.IP CURLOPT_FTP_SKIP_PASV_IP
@@ -447,7 +464,7 @@
.IP CURLOPT_RESUME_FROM_LARGE
Resume a transfer. See \fICURLOPT_RESUME_FROM_LARGE(3)\fP
.IP CURLOPT_CURLU
-Set URL to work on with CURLU *. See \fICURLOPT_CURLU(3)\fP
+Set URL to work on with a URL handle. See \fICURLOPT_CURLU(3)\fP
.IP CURLOPT_CUSTOMREQUEST
Custom request/method. See \fICURLOPT_CUSTOMREQUEST(3)\fP
.IP CURLOPT_FILETIME
@@ -564,7 +581,7 @@
.IP CURLOPT_SSL_ENABLE_ALPN
Enable use of ALPN. See \fICURLOPT_SSL_ENABLE_ALPN(3)\fP
.IP CURLOPT_SSL_ENABLE_NPN
-Enable use of NPN. See \fICURLOPT_SSL_ENABLE_NPN(3)\fP
+\fBOBSOLETE\fP Enable use of NPN. See \fICURLOPT_SSL_ENABLE_NPN(3)\fP
.IP CURLOPT_SSLENGINE
Use identifier with SSL engine. See \fICURLOPT_SSLENGINE(3)\fP
.IP CURLOPT_SSLENGINE_DEFAULT
@@ -618,6 +635,8 @@
Certificate Revocation List. See \fICURLOPT_CRLFILE(3)\fP
.IP CURLOPT_PROXY_CRLFILE
Proxy Certificate Revocation List. See \fICURLOPT_PROXY_CRLFILE(3)\fP
+.IP CURLOPT_CA_CACHE_TIMEOUT
+Timeout for CA cache. See \fICURLOPT_CA_CACHE_TIMEOUT(3)\fP
.IP CURLOPT_CERTINFO
Extract certificate info. See \fICURLOPT_CERTINFO(3)\fP
.IP CURLOPT_PINNEDPUBLICKEY
@@ -626,9 +645,10 @@
Set the proxy's pinned SSL public key. See
\fICURLOPT_PROXY_PINNEDPUBLICKEY(3)\fP
.IP CURLOPT_RANDOM_FILE
-Provide source for entropy random data. See \fICURLOPT_RANDOM_FILE(3)\fP
+\fBOBSOLETE\fP Provide source for entropy random data.
+See \fICURLOPT_RANDOM_FILE(3)\fP
.IP CURLOPT_EGDSOCKET
-Identify EGD socket for entropy. See \fICURLOPT_EGDSOCKET(3)\fP
+\fBOBSOLETE\fP Identify EGD socket for entropy. See \fICURLOPT_EGDSOCKET(3)\fP
.IP CURLOPT_SSL_CIPHER_LIST
Ciphers to use. See \fICURLOPT_SSL_CIPHER_LIST(3)\fP
.IP CURLOPT_PROXY_SSL_CIPHER_LIST
@@ -670,6 +690,9 @@
Callback for checking host key handling. See \fICURLOPT_SSH_HOSTKEYFUNCTION(3)\fP
.IP CURLOPT_SSH_HOSTKEYDATA
Custom pointer to pass to ssh host key callback. See \fICURLOPT_SSH_HOSTKEYDATA(3)\fP
+.SH WEBSOCKET
+.IP CURLOPT_WS_OPTIONS
+Set WebSocket options. See \fICURLOPT_WS_OPTIONS(3)\fP
.SH OTHER OPTIONS
.IP CURLOPT_PRIVATE
Private pointer to store. See \fICURLOPT_PRIVATE(3)\fP
@@ -679,6 +702,8 @@
Mode for creating new remote files. See \fICURLOPT_NEW_FILE_PERMS(3)\fP
.IP CURLOPT_NEW_DIRECTORY_PERMS
Mode for creating new remote directories. See \fICURLOPT_NEW_DIRECTORY_PERMS(3)\fP
+.IP CURLOPT_QUICK_EXIT
+To be set by toplevel tools like "curl" to skip lengthy cleanups when they are about to call exit() anyway. See \fICURLOPT_QUICK_EXIT(3)\fP
.SH TELNET OPTIONS
.IP CURLOPT_TELNETOPTIONS
TELNET options. See \fICURLOPT_TELNETOPTIONS(3)\fP
diff --git a/docs/libcurl/curl_easy_strerror.3 b/docs/libcurl/curl_easy_strerror.3
index eda4f8d..a80a199 100644
--- a/docs/libcurl/curl_easy_strerror.3
+++ b/docs/libcurl/curl_easy_strerror.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_easy_strerror 3 "26 Apr 2004" "libcurl 7.12" "libcurl Manual"
+.TH curl_easy_strerror 3 "26 Apr 2004" "libcurl" "libcurl"
.SH NAME
curl_easy_strerror - return string describing error code
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_easy_unescape.3 b/docs/libcurl/curl_easy_unescape.3
index ef11fad..c6033f5 100644
--- a/docs/libcurl/curl_easy_unescape.3
+++ b/docs/libcurl/curl_easy_unescape.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,31 +22,34 @@
.\" *
.\" **************************************************************************
.\"
-.TH curl_easy_unescape 3 "7 April 2006" "libcurl 7.15.4" "libcurl Manual"
+.TH curl_easy_unescape 3 "7 April 2006" "libcurl" "libcurl"
.SH NAME
curl_easy_unescape - URL decodes the given string
.SH SYNOPSIS
.nf
#include <curl/curl.h>
-char *curl_easy_unescape(CURL *curl, const char *url,
+char *curl_easy_unescape(CURL *curl, const char *input,
int inlength, int *outlength);
.fi
.SH DESCRIPTION
-This function converts the given URL encoded input string 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.
+This function converts the URL encoded string \fBinput\fP to a "plain string"
+and returns that in an allocated memory area. All input characters that are URL
+encoded (%XX where XX is a two-digit hexadecimal number) are converted to their
+binary versions.
If the \fBlength\fP argument is set to 0 (zero), \fIcurl_easy_unescape(3)\fP
-will use strlen() on the input \fIurl\fP string to find out the size.
+will use strlen() on \fBinput\fP to find out the size.
If \fBoutlength\fP is non-NULL, the function will write the length of the
-returned string in the integer it points to. This allows an escaped string
-containing %00 to still get used properly after unescaping. Since this is a
-pointer to an \fIint\fP type, it can only return a value up to INT_MAX so no
-longer string can be unescaped if the string length is returned in this
-parameter.
+returned string in the integer it points to. This allows proper handling even
+for strings containing %00. Since this is a pointer to an \fIint\fP type, it
+can only return a value up to \fIINT_MAX\fP so no longer string can be
+returned in this parameter.
+
+Since 7.82.0, the \fBcurl\fP parameter is ignored. Prior to that there was
+per-handle character conversion support for some very old operating systems
+such as TPF, but it was otherwise ignored.
You must \fIcurl_free(3)\fP the returned string when you are done with it.
.SH EXAMPLE
diff --git a/docs/libcurl/curl_easy_upkeep.3 b/docs/libcurl/curl_easy_upkeep.3
index c32c72d..ade0a5d 100644
--- a/docs/libcurl/curl_easy_upkeep.3
+++ b/docs/libcurl/curl_easy_upkeep.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH curl_easy_upkeep 3 "31 Oct 2018" "libcurl 7.62.0" "libcurl Manual"
+.TH curl_easy_upkeep 3 "31 Oct 2018" "libcurl" "libcurl"
.SH NAME
curl_easy_upkeep - Perform any connection upkeep checks.
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_escape.3 b/docs/libcurl/curl_escape.3
index 8e8b2f1..1b29c8e 100644
--- a/docs/libcurl/curl_escape.3
+++ b/docs/libcurl/curl_escape.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,25 +21,25 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_escape 3 "6 March 2002" "libcurl 7.9" "libcurl Manual"
+.TH curl_escape 3 "6 March 2002" "libcurl" "libcurl"
.SH NAME
curl_escape - URL encodes the given string
.SH SYNOPSIS
.nf
#include <curl/curl.h>
-char *curl_escape(const char *url, int length);
+char *curl_escape(const char *string, int length);
.fi
.SH DESCRIPTION
Obsolete function. Use \fIcurl_easy_escape(3)\fP instead!
-This function will convert the given input string to an URL encoded string and
-return that as a new allocated string. All input characters that are not a-z,
-A-Z or 0-9 will be converted to their "URL escaped" version (%NN where NN is a
-two-digit hexadecimal number).
+This function will convert the given input \fBstring\fP to a URL encoded string
+and return that as a new allocated string. All input characters that are not
+a-z, A-Z or 0-9 will be converted to their "URL escaped" version (\fB%NN\fP
+where \fBNN\fP is a two-digit hexadecimal number).
-If the \fBlengthf\fP argument is set to 0, curl_escape() will use strlen() on
-the input \fBurl\fP string to find out the size.
+If the \fBlength\fP argument is set to 0, \fIcurl_escape(3)\fP will use
+strlen() on \fBstring\fP to find out the size.
You must \fIcurl_free(3)\fP the returned string when you are done with it.
.SH EXAMPLE
diff --git a/docs/libcurl/curl_formadd.3 b/docs/libcurl/curl_formadd.3
index f9997e2..280ffad 100644
--- a/docs/libcurl/curl_formadd.3
+++ b/docs/libcurl/curl_formadd.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,9 +21,9 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_formadd 3 "24 June 2002" "libcurl 7.9.8" "libcurl Manual"
+.TH curl_formadd 3 "24 June 2002" "libcurl" "libcurl"
.SH NAME
-curl_formadd - add a section to a multipart/formdata HTTP POST
+curl_formadd - add a section to a multipart form POST
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -32,15 +32,14 @@
struct curl_httppost **lastitem, ...);
.fi
.SH DESCRIPTION
-This function is deprecated. Do not use. See \fIcurl_mime_init(3)\fP instead.
+\fBThis function is deprecated.\fP Use \fIcurl_mime_init(3)\fP instead.
-curl_formadd() is used to append sections when building a multipart/formdata
-HTTP POST (sometimes referred to as RFC2388-style posts). Append one section
-at a time until you have added all the sections you want included and then you
-pass the \fIfirstitem\fP pointer as parameter to \fICURLOPT_HTTPPOST(3)\fP.
-\fIlastitem\fP is set after each \fIcurl_formadd(3)\fP call and on repeated
-invokes it should be left as set to allow repeated invokes to find the end of
-the list faster.
+curl_formadd() is used to append sections when building a multipart form
+post. Append one section at a time until you have added all the sections you
+want included and then you pass the \fIfirstitem\fP pointer as parameter to
+\fICURLOPT_HTTPPOST(3)\fP. \fIlastitem\fP is set after each
+\fIcurl_formadd(3)\fP call and on repeated invokes it should be left as set to
+allow repeated invokes to find the end of the list faster.
After the \fIlastitem\fP pointer follow the real arguments.
@@ -52,7 +51,7 @@
Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
You can disable this header with \fICURLOPT_HTTPHEADER(3)\fP as usual.
-First, there are some basics you need to understand about multipart/formdata
+First, there are some basics you need to understand about multipart form
posts. Each part consists of at least a NAME and a CONTENTS part. If the part
is made for file upload, there are also a stored CONTENT-TYPE and a FILENAME.
Below, we will discuss what options you use to set these properties in the
@@ -65,14 +64,15 @@
.IP CURLFORM_COPYNAME
followed by a string which provides the \fIname\fP of this part. libcurl
copies the string so your application does not need to keep it around after
-this function call. If the name is not NUL-terminated, you must set its length
-with \fBCURLFORM_NAMELENGTH\fP. The \fIname\fP is not allowed to contain
-zero-valued bytes. The copied data will be freed by \fIcurl_formfree(3)\fP.
+this function call. If the name is not null-terminated, you must set its
+length with \fBCURLFORM_NAMELENGTH\fP. The \fIname\fP is not allowed to
+contain zero-valued bytes. The copied data will be freed by
+\fIcurl_formfree(3)\fP.
.IP CURLFORM_PTRNAME
followed by a string which provides the \fIname\fP of this part. libcurl
will use the pointer and refer to the data in your application, so you
must make sure it remains until curl no longer needs it. If the name
-is not NUL-terminated, you must set its length with \fBCURLFORM_NAMELENGTH\fP.
+is not null-terminated, you must set its length with \fBCURLFORM_NAMELENGTH\fP.
The \fIname\fP is not allowed to contain zero-valued bytes.
.IP CURLFORM_COPYCONTENTS
followed by a pointer to the contents of this part, the actual data
@@ -82,11 +82,11 @@
set the length of the name with \fBCURLFORM_CONTENTSLENGTH\fP. The copied
data will be freed by \fIcurl_formfree(3)\fP.
.IP CURLFORM_PTRCONTENTS
-followed by a pointer to the contents of this part, the actual data
-to send away. libcurl will use the pointer and refer to the data in your
-application, so you must make sure it remains until curl no longer needs it.
-If the data is not NUL-terminated, or if you would like it to contain zero bytes,
-you must set its length with \fBCURLFORM_CONTENTSLENGTH\fP.
+followed by a pointer to the contents of this part, the actual data to send
+away. libcurl will use the pointer and refer to the data in your application,
+so you must make sure it remains until curl no longer needs it. If the data
+is not null-terminated, or if you would like it to contain zero bytes, you
+must set its length with \fBCURLFORM_CONTENTSLENGTH\fP.
.IP CURLFORM_CONTENTLEN
followed by a curl_off_t value giving the length of the contents. Note that
for \fICURLFORM_STREAM\fP contents, this option is mandatory.
@@ -157,10 +157,10 @@
.IP CURLFORM_ARRAY
Another possibility to send options to curl_formadd() is the
\fBCURLFORM_ARRAY\fP option, that passes a struct curl_forms array pointer as
-its value. Each curl_forms structure element has a CURLformoption and a char
-pointer. The final element in the array must be a CURLFORM_END. All available
-options can be used in an array, except the CURLFORM_ARRAY option itself. The
-last argument in such an array must always be \fBCURLFORM_END\fP.
+its value. Each curl_forms structure element has a \fICURLformoption\fP and a
+char pointer. The final element in the array must be a CURLFORM_END. All
+available options can be used in an array, except the CURLFORM_ARRAY option
+itself. The last argument in such an array must always be \fBCURLFORM_END\fP.
.IP CURLFORM_CONTENTHEADER
specifies extra headers for the form POST section. This takes a curl_slist
prepared in the usual way using \fBcurl_slist_append\fP and appends the list
@@ -168,15 +168,16 @@
the POST occurs, if you free it before the post completes you may experience
problems.
-When you have passed the HttpPost pointer to \fIcurl_easy_setopt(3)\fP (using
-the \fICURLOPT_HTTPPOST(3)\fP option), you must not free the list until after
-you have called \fIcurl_easy_cleanup(3)\fP for the curl handle.
+When you have passed the \fIstruct curl_httppost\fP pointer to
+\fIcurl_easy_setopt(3)\fP (using the \fICURLOPT_HTTPPOST(3)\fP option), you
+must not free the list until after you have called \fIcurl_easy_cleanup(3)\fP
+for the curl handle.
See example below.
.SH EXAMPLE
.nf
- struct curl_httppost* post = NULL;
- struct curl_httppost* last = NULL;
+ struct curl_httppost *post = NULL;
+ struct curl_httppost *last = NULL;
char namebuffer[] = "name buffer";
long namelength = strlen(namebuffer);
char buffer[] = "test buffer";
@@ -259,7 +260,7 @@
determined, resulting in a chunked encoding transfer. Backslashes and
double quotes in field and file names are now escaped before transmission.
.SH RETURN VALUE
-0 means everything was ok, non-zero means an error occurred corresponding
+0 means everything was OK, non-zero means an error occurred corresponding
to a CURL_FORMADD_* constant defined in
.I <curl/curl.h>
.SH "SEE ALSO"
diff --git a/docs/libcurl/curl_formfree.3 b/docs/libcurl/curl_formfree.3
index 89dfdbc..83e768e 100644
--- a/docs/libcurl/curl_formfree.3
+++ b/docs/libcurl/curl_formfree.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,9 +21,9 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_formfree 3 "6 April 2001" "libcurl 7.7.1" "libcurl Manual"
+.TH curl_formfree 3 "6 April 2001" "libcurl" "libcurl"
.SH NAME
-curl_formfree - free a previously build multipart/formdata HTTP POST chain
+curl_formfree - free a previously build multipart form post chain
.SH SYNOPSIS
.nf
#include <curl/curl.h>
diff --git a/docs/libcurl/curl_formget.3 b/docs/libcurl/curl_formget.3
index 5b57c38..d8687e0 100644
--- a/docs/libcurl/curl_formget.3
+++ b/docs/libcurl/curl_formget.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,9 +21,9 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_formget 3 "20 June 2006" "libcurl 7.15.5" "libcurl Manual"
+.TH curl_formget 3 "20 June 2006" "libcurl" "libcurl"
.SH NAME
-curl_formget - serialize a previously built multipart/formdata HTTP POST chain
+curl_formget - serialize a previously built multipart form POST chain
.SH SYNOPSIS
.nf
.B #include <curl/curl.h>
@@ -67,6 +67,6 @@
This function was added in libcurl 7.15.5. The form API is deprecated in
libcurl 7.56.0.
.SH RETURN VALUE
-0 means everything was ok, non-zero means an error occurred
+0 means everything was OK, non-zero means an error occurred
.SH "SEE ALSO"
.BR curl_formadd "(3), " curl_mime_init "(3)"
diff --git a/docs/libcurl/curl_free.3 b/docs/libcurl/curl_free.3
index 2f38401..361749f 100644
--- a/docs/libcurl/curl_free.3
+++ b/docs/libcurl/curl_free.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,14 +21,14 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_free 3 "12 Aug 2003" "libcurl 7.10" "libcurl Manual"
+.TH curl_free 3 "12 Aug 2003" "libcurl" "libcurl"
.SH NAME
curl_free - reclaim memory that has been obtained through a libcurl call
.SH SYNOPSIS
.nf
#include <curl/curl.h>
-void curl_free(char *ptr);
+void curl_free(void *ptr);
.fi
.SH DESCRIPTION
curl_free reclaims memory that has been obtained through a libcurl call. Use
diff --git a/docs/libcurl/curl_getdate.3 b/docs/libcurl/curl_getdate.3
index fe7c12f..43d46f9 100644
--- a/docs/libcurl/curl_getdate.3
+++ b/docs/libcurl/curl_getdate.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_getdate 3 "12 Aug 2005" "libcurl 7.0" "libcurl Manual"
+a.TH curl_getdate 3 "12 Aug 2005" "libcurl" "libcurl"
.SH NAME
curl_getdate - Convert a date string to number of seconds
.SH SYNOPSIS
@@ -45,9 +45,9 @@
items:
.TP 0.8i
.B calendar date items
-Can be specified several ways. Month names can only be three-letter english
-abbreviations, numbers can be zero-prefixed and the year may use 2 or 4 digits.
-Examples: 06 Nov 1994, 06-Nov-94 and Nov-94 6.
+Can be specified several ways. Month names can only be three-letter English
+abbreviations, numbers can be zero-prefixed and the year may use 2 or 4
+digits. Examples: 06 Nov 1994, 06-Nov-94 and Nov-94 6.
.TP
.B time of the day items
This string specifies the time on a given day. You must specify it with 6
@@ -61,7 +61,7 @@
.TP
.B day of the week items
Specifies a day of the week. Days of the week may be spelled out in full
-(using english): `Sunday', `Monday', etc or they may be abbreviated to their
+(using English): `Sunday', `Monday', etc or they may be abbreviated to their
first three letters. This is usually not info that adds anything.
.TP
.B pure numbers
@@ -97,8 +97,9 @@
.SH STANDARDS
This parser handles date formats specified in RFC 822 (including the update in
RFC 1123) using time zone name or time zone delta and RFC 850 (obsoleted by
-RFC 1036) and ANSI C's asctime() format. These formats are the only ones RFC
-7231 says HTTP applications may use.
+RFC 1036) and ANSI C's \fIasctime()\fP format.
+
+These formats are the only ones RFC 7231 says HTTP applications may use.
.SH AVAILABILITY
Always
.SH RETURN VALUE
diff --git a/docs/libcurl/curl_getenv.3 b/docs/libcurl/curl_getenv.3
index bcce866..de50a80 100644
--- a/docs/libcurl/curl_getenv.3
+++ b/docs/libcurl/curl_getenv.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_getenv 3 "30 April 2004" "libcurl 7.12" "libcurl Manual"
+.TH curl_getenv 3 "30 April 2004" "libcurl" "libcurl"
.SH NAME
curl_getenv - return value for environment name
.SH SYNOPSIS
@@ -45,9 +45,7 @@
}
.fi
.SH AVAILABILITY
-This function will be removed from the public libcurl API in a near future. It
-will instead be made "available" by source code access only, and then as
-curlx_getenv().
+Always
.SH RETURN VALUE
A pointer to a null-terminated string or NULL if it failed to find the
specified name.
diff --git a/docs/libcurl/curl_global_cleanup.3 b/docs/libcurl/curl_global_cleanup.3
index 983f034..790ad86 100644
--- a/docs/libcurl/curl_global_cleanup.3
+++ b/docs/libcurl/curl_global_cleanup.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_global_cleanup 3 "17 Feb 2006" "libcurl 7.8" "libcurl Manual"
+.TH curl_global_cleanup 3 "17 Feb 2006" "libcurl" "libcurl"
.SH NAME
curl_global_cleanup - global libcurl cleanup
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_global_init.3 b/docs/libcurl/curl_global_init.3
index fd33ccd..2ce0e75 100644
--- a/docs/libcurl/curl_global_init.3
+++ b/docs/libcurl/curl_global_init.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_global_init 3 "11 May 2004" "libcurl 7.12" "libcurl Manual"
+.TH curl_global_init 3 "11 May 2004" "libcurl" "libcurl"
.SH NAME
curl_global_init - Global libcurl initialization
.SH SYNOPSIS
@@ -57,9 +57,9 @@
similarly thread unsafe, it could conflict with any other thread that uses
these other libraries.
-If you are initializing libcurl from a Windows DLL you should not initialize it
-from DllMain or a static initializer because Windows holds the loader lock
-during that time and it could cause a deadlock.
+If you are initializing libcurl from a Windows DLL you should not initialize
+it from \fIDllMain\fP or a static initializer because Windows holds the loader
+lock during that time and it could cause a deadlock.
See the description in \fIlibcurl(3)\fP of global environment requirements for
details of how to use this function.
@@ -89,7 +89,7 @@
behaviors. This option exists for when the initialization is handled outside
of libcurl so there's no need for libcurl to do it again.
.IP CURL_GLOBAL_NOTHING
-Initialise nothing extra. This sets no bit.
+Initialize nothing extra. This sets no bit.
.IP CURL_GLOBAL_DEFAULT
A sensible default. It will init both SSL and Win32. Right now, this equals
the functionality of the \fBCURL_GLOBAL_ALL\fP mask.
diff --git a/docs/libcurl/curl_global_init_mem.3 b/docs/libcurl/curl_global_init_mem.3
index c4f49b5..3e90840 100644
--- a/docs/libcurl/curl_global_init_mem.3
+++ b/docs/libcurl/curl_global_init_mem.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_global_init_mem 3 "10 May 2004" "libcurl 7.12.0" "libcurl Manual"
+.TH curl_global_init_mem 3 "10 May 2004" "libcurl" "libcurl"
.SH NAME
curl_global_init_mem - Global libcurl initialization with memory callbacks
.SH SYNOPSIS
@@ -72,7 +72,7 @@
.SH AVAILABILITY
Added in 7.12.0
.SH RETURN VALUE
-CURLE_OK (0) means everything was ok, non-zero means an error occurred as
+CURLE_OK (0) means everything was OK, non-zero means an error occurred as
\fI<curl/curl.h>\fP defines - see \fIlibcurl-errors(3)\fP.
.SH "SEE ALSO"
.BR curl_global_init "(3), "
diff --git a/docs/libcurl/curl_global_sslset.3 b/docs/libcurl/curl_global_sslset.3
index 1b99f96..17ea484 100644
--- a/docs/libcurl/curl_global_sslset.3
+++ b/docs/libcurl/curl_global_sslset.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_global_sslset 3 "15 July 2017" "libcurl 7.56" "libcurl Manual"
+.TH curl_global_sslset 3 "15 July 2017" "libcurl" "libcurl"
.SH NAME
curl_global_sslset - Select SSL backend to use with libcurl
.SH SYNOPSIS
@@ -35,7 +35,7 @@
typedef enum {
CURLSSLBACKEND_NONE = 0,
- CURLSSLBACKEND_OPENSSL = 1,
+ CURLSSLBACKEND_OPENSSL = 1, /* or one of its forks */
CURLSSLBACKEND_GNUTLS = 2,
CURLSSLBACKEND_NSS = 3,
CURLSSLBACKEND_GSKIT = 5,
@@ -45,8 +45,9 @@
CURLSSLBACKEND_SECURETRANSPORT = 9,
CURLSSLBACKEND_AXTLS = 10, /* deprecated */
CURLSSLBACKEND_MBEDTLS = 11,
- CURLSSLBACKEND_MESALINK = 12,
- CURLSSLBACKEND_BEARSSL = 13
+ CURLSSLBACKEND_MESALINK = 12, /* deprecated */
+ CURLSSLBACKEND_BEARSSL = 13,
+ CURLSSLBACKEND_RUSTLS = 14
} curl_sslbackend;
CURLsslset curl_global_sslset(curl_sslbackend id,
@@ -64,17 +65,17 @@
both \fIid\fP and \fIname\fP are specified, the \fIname\fP will be ignored.
If neither \fIid\fP nor \fPname\fP are specified, the function will fail with
-CURLSSLSET_UNKNOWN_BACKEND and set the \fIavail\fP pointer to the
+\fBCURLSSLSET_UNKNOWN_BACKEND\fP and set the \fIavail\fP pointer to the
NULL-terminated list of available backends. The available backends are those
that this particular build of libcurl supports.
Since libcurl 7.60.0, the \fIavail\fP pointer will always be set to the list
of alternatives if non-NULL.
-Upon success, the function returns CURLSSLSET_OK.
+Upon success, the function returns \fBCURLSSLSET_OK\fP.
If the specified SSL backend is not available, the function returns
-CURLSSLSET_UNKNOWN_BACKEND and sets the \fIavail\fP pointer to a
+\fBCURLSSLSET_UNKNOWN_BACKEND\fP and sets the \fIavail\fP pointer to a
NULL-terminated list of available SSL backends. In this case, you may call the
function again to try to select a different backend.
@@ -88,6 +89,15 @@
If this is not thread-safe, you must not call this function when any other
thread in the program (i.e. a thread sharing the same memory) is running.
This does not just mean no other thread that is using libcurl.
+.SH OpenSSL
+The name "OpenSSL" is used for all versions of OpenSSL and its associated
+forks/flavors in this function. OpenSSL, BoringSSL, libressl, quictls and
+AmiSSL are all supported by libcurl, but in the eyes of
+\fIcurl_global_sslset(3)\fP they are all just "OpenSSL". They all mostly
+provide the same API.
+
+\fIcurl_version_info(3)\fP can return more specific info about the exact
+OpenSSL flavor and version number is use.
.SH EXAMPLE
.nf
/* choose a specific backend */
@@ -105,7 +115,8 @@
This function was added in libcurl 7.56.0. Before this version, there was no
support for choosing SSL backends at runtime.
.SH RETURN VALUE
-If this function returns CURLSSLSET_OK, the backend was successfully selected.
+If this function returns \fICURLSSLSET_OK\fP, the backend was successfully
+selected.
If the chosen backend is unknown (or support for the chosen backend has not
been compiled into libcurl), the function returns
diff --git a/docs/libcurl/curl_mime_addpart.3 b/docs/libcurl/curl_mime_addpart.3
index 0eb3b62..50abf4a 100644
--- a/docs/libcurl/curl_mime_addpart.3
+++ b/docs/libcurl/curl_mime_addpart.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_mime_addpart 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.TH curl_mime_addpart 3 "22 August 2017" "libcurl" "libcurl"
.SH NAME
curl_mime_addpart - append a new empty part to a mime structure
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_mime_data.3 b/docs/libcurl/curl_mime_data.3
index 7d94a45..a418ffc 100644
--- a/docs/libcurl/curl_mime_data.3
+++ b/docs/libcurl/curl_mime_data.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_mime_data 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.TH curl_mime_data 3 "22 August 2017" "libcurl" "libcurl"
.SH NAME
curl_mime_data - set a mime part's body data from memory
.SH SYNOPSIS
@@ -34,12 +34,15 @@
.SH DESCRIPTION
\fIcurl_mime_data(3)\fP sets a mime part's body content from memory data.
-\fIdata\fP points to the data bytes: those are copied to the part and their
-storage may safely be reused after call.
-\fIdatasize\fP is the number of data bytes: it can be set to
+\fIpart\fP is the mime part to assign contents to, created with
+\fIcurl_mime_addpart(3)\fP.
+
+\fIdata\fP points to the data that gets copied by this function. The storage
+may safely be reused after the call.
+
+\fIdatasize\fP is the number of bytes \fIdata\fP points to. It can be set to
\fICURL_ZERO_TERMINATED\fP to indicate \fIdata\fP is a null-terminated
character string.
-\fIpart\fP is the part's to assign contents to.
Setting a part's contents multiple times is valid: only the value set by the
last call is retained. It is possible to unassign part's contents by setting
diff --git a/docs/libcurl/curl_mime_data_cb.3 b/docs/libcurl/curl_mime_data_cb.3
index 8882ebb..260eafc 100644
--- a/docs/libcurl/curl_mime_data_cb.3
+++ b/docs/libcurl/curl_mime_data_cb.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_mime_data_cb 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.TH curl_mime_data_cb 3 "22 August 2017" "libcurl" "libcurl"
.SH NAME
curl_mime_data_cb - set a callback-based data source for a mime part's body
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_mime_encoder.3 b/docs/libcurl/curl_mime_encoder.3
index 2034824..dfe388c 100644
--- a/docs/libcurl/curl_mime_encoder.3
+++ b/docs/libcurl/curl_mime_encoder.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_mime_encoder 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.TH curl_mime_encoder 3 "22 August 2017" "libcurl" "libcurl"
.SH NAME
curl_mime_encoder - set a mime part's encoder and content transfer encoding
.SH SYNOPSIS
@@ -67,7 +67,7 @@
If the original data is already encoded in such a scheme, a custom
\fIContent-Transfer-Encoding\fP header should be added with
-\FIcurl_mime_headers\fP() instead of setting a part encoder.
+\fIcurl_mime_headers\fP() instead of setting a part encoder.
Encoding should not be applied to multiparts, thus the use of this
function on a part with content set with \fIcurl_mime_subparts\fP() is
diff --git a/docs/libcurl/curl_mime_filedata.3 b/docs/libcurl/curl_mime_filedata.3
index ade613e..0ef8725 100644
--- a/docs/libcurl/curl_mime_filedata.3
+++ b/docs/libcurl/curl_mime_filedata.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_mime_filedata 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.TH curl_mime_filedata 3 "22 August 2017" "libcurl" "libcurl"
.SH NAME
curl_mime_filedata - set a mime part's body data from a file contents
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_mime_filename.3 b/docs/libcurl/curl_mime_filename.3
index f63d70d..9d62bdf 100644
--- a/docs/libcurl/curl_mime_filename.3
+++ b/docs/libcurl/curl_mime_filename.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_mime_filename 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.TH curl_mime_filename 3 "22 August 2017" "libcurl" "libcurl"
.SH NAME
curl_mime_filename - set a mime part's remote file name
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_mime_free.3 b/docs/libcurl/curl_mime_free.3
index 63d8dc9..b3be926 100644
--- a/docs/libcurl/curl_mime_free.3
+++ b/docs/libcurl/curl_mime_free.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_mime_free 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.TH curl_mime_free 3 "22 August 2017" "libcurl" "libcurl"
.SH NAME
curl_mime_free - free a previously built mime structure
.SH SYNOPSIS
@@ -36,9 +36,9 @@
be called when the data has been used, which typically means after
\fIcurl_easy_perform(3)\fP has been called.
-The handle to free is the one you passed to
-the \fICURLOPT_MIMEPOST(3)\fP option: attached subparts mime structures must
-not be explicitly freed as they are by the top structure freeing.
+The handle to free is the one you passed to the \fICURLOPT_MIMEPOST(3)\fP
+option: attached sub part mime structures must not be explicitly freed as they
+are by the top structure freeing.
\fBmime\fP is the handle as returned from a previous call to
\fIcurl_mime_init(3)\fP and may be NULL.
diff --git a/docs/libcurl/curl_mime_headers.3 b/docs/libcurl/curl_mime_headers.3
index 86c0382..87df9db 100644
--- a/docs/libcurl/curl_mime_headers.3
+++ b/docs/libcurl/curl_mime_headers.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_mime_headers 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.TH curl_mime_headers 3 "22 August 2017" "libcurl" "libcurl"
.SH NAME
curl_mime_headers - set a mime part's custom headers
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_mime_init.3 b/docs/libcurl/curl_mime_init.3
index 9ee466f..8ce7407 100644
--- a/docs/libcurl/curl_mime_init.3
+++ b/docs/libcurl/curl_mime_init.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_mime_init 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.TH curl_mime_init 3 "22 August 2017" "libcurl" "libcurl"
.SH NAME
curl_mime_init - create a mime handle
.SH SYNOPSIS
@@ -31,11 +31,14 @@
curl_mime *curl_mime_init(CURL *easy_handle);
.fi
.SH DESCRIPTION
-\fIcurl_mime_init(3)\fP creates a handle to a new empty mime structure
-intended to be used with \fIeasy_handle\fP. This mime structure can be
-subsequently filled using the mime API, then attached to \fIeasy_handle\fP
-using option \fICURLOPT_MIMEPOST(3)\fP within a \fIcurl_easy_setopt(3)\fP
-call.
+\fIcurl_mime_init(3)\fP creates a handle to a new empty mime structure.
+This mime structure can be subsequently filled using the mime API, then
+attached to some easy handle using option \fICURLOPT_MIMEPOST(3)\fP within
+a \fIcurl_easy_setopt(3)\fP call or added as a multipart in another mime
+handle's part using \fIcurl_mime_subparts(3)\fP.
+
+\fIeasy_handle\fP is used for part separator randomization and error
+reporting. Since 7.87.0, it does not need to be the final target handle.
Using a mime handle is the recommended way to post an HTTP form, format and
send a multi-part email with SMTP or upload such an email to an IMAP server.
@@ -65,5 +68,6 @@
A mime struct handle, or NULL upon failure.
.SH "SEE ALSO"
.BR curl_mime_addpart "(3),"
+.BR curl_mime_subparts "(3),"
.BR curl_mime_free "(3),"
.BR CURLOPT_MIMEPOST "(3)"
diff --git a/docs/libcurl/curl_mime_name.3 b/docs/libcurl/curl_mime_name.3
index 385d9f8..fd9e3a0 100644
--- a/docs/libcurl/curl_mime_name.3
+++ b/docs/libcurl/curl_mime_name.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_mime_name 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.TH curl_mime_name 3 "22 August 2017" "libcurl" "libcurl"
.SH NAME
curl_mime_name - set a mime part's name
.SH SYNOPSIS
@@ -41,7 +41,7 @@
The name string is copied into the part, thus the associated storage may
safely be released or reused after call. Setting a part's name multiple times
is valid: only the value set by the last call is retained. It is possible to
-"unname" a part by setting \fIname\fP to NULL.
+reset the name of a part by setting \fIname\fP to NULL.
.SH EXAMPLE
.nf
curl_mime *mime;
diff --git a/docs/libcurl/curl_mime_subparts.3 b/docs/libcurl/curl_mime_subparts.3
index 6d1daaf..e3f3a60 100644
--- a/docs/libcurl/curl_mime_subparts.3
+++ b/docs/libcurl/curl_mime_subparts.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,9 +21,9 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_mime_subparts 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.TH curl_mime_subparts 3 "22 August 2017" "libcurl" "libcurl"
.SH NAME
-curl_mime_subparts - set subparts of a multipart mime part
+curl_mime_subparts - set sub-parts of a multipart mime part
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -36,7 +36,7 @@
\fIpart\fP is a handle to the multipart part.
-\fIsubparts\fP is a mime structure handle holding the subparts. After
+\fIsubparts\fP is a mime structure handle holding the sub-parts. After
\fIcurl_mime_subparts\fP succeeds, the mime structure handle belongs to the
multipart part and must not be freed explicitly. It may however be updated by
subsequent calls to mime API functions.
diff --git a/docs/libcurl/curl_mime_type.3 b/docs/libcurl/curl_mime_type.3
index de9c036..83eb639 100644
--- a/docs/libcurl/curl_mime_type.3
+++ b/docs/libcurl/curl_mime_type.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_mime_type 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.TH curl_mime_type 3 "22 August 2017" "libcurl" "libcurl"
.SH NAME
curl_mime_type - set a mime part's content type
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_mprintf.3 b/docs/libcurl/curl_mprintf.3
index f124f3a..720632e 100644
--- a/docs/libcurl/curl_mprintf.3
+++ b/docs/libcurl/curl_mprintf.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_printf 3 "30 April 2004" "libcurl 7.12" "libcurl Manual"
+.TH curl_printf 3 "30 April 2004" "libcurl" "libcurl"
.SH NAME
curl_maprintf, curl_mfprintf, curl_mprintf, curl_msnprintf, curl_msprintf
curl_mvaprintf, curl_mvfprintf, curl_mvprintf, curl_mvsnprintf,
@@ -64,9 +64,9 @@
\fBcurl_mvsprintf()\fP, \fBcurl_mvsnprintf()\fP are equivalent to the
functions \fBcurl_mprintf()\fP, \fBcurl_mfprintf()\fP, \fBcurl_msprintf()\fP,
\fBcurl_msnprintf()\fP, respectively, except that they are called with a
-va_list instead of a variable number of arguments. These functions do not
-call the va_end macro. Because they invoke the va_arg macro, the value of ap
-is undefined after the call.
+\fIva_list\fP instead of a variable number of arguments. These functions do
+not call the \fIva_end\fP macro. Because they invoke the \fIva_arg\fP macro,
+the value of \fIap\fP is undefined after the call.
The functions \fBcurl_maprintf()\fP and \fBcurl_mvaprintf()\fP return the
output string as pointer to a newly allocated memory area. The returned string
@@ -93,21 +93,21 @@
argument is required, by writing "%m$" instead of '%' and "*m$" instead
of '*', where the decimal integer m denotes the position in the argument list
of the desired argument, indexed starting from 1. Thus,
-
+.nf
curl_mprintf("%*d", width, num);
-
+.fi
and
-
+.nf
curl_mprintf("%2$*1$d", width, num);
-
+.fi
are equivalent. The second style allows repeated references to the same
argument.
If the style using '$' is used, it must be used throughout for all conversions
taking an argument and all width and precision arguments, but it may be mixed
with "%%" formats, which do not consume an argument. There may be no gaps in
-the numbers of argu‐ ments specified using '$'; for example, if arguments 1
-and 3 are specified, argument 2 must also be specified somewhere in the format
+the numbers of arguments specified using '$'; for example, if arguments 1 and
+3 are specified, argument 2 must also be specified somewhere in the format
string.
.SH "Flag characters"
@@ -139,17 +139,17 @@
field width, it will be padded with spaces on the left (or right, if the
left-adjustment flag has been given). Instead of a decimal digit string one
may write "*" or "*m$" (for some decimal integer m) to specify that the field
-width is given in the next argument, or in the m-th argument, respec‐ tively,
-which must be of type int. A negative field width is taken as a '-' flag
-followed by a positive field width. In no case does a nonexistent or small
-field width cause truncation of a field; if the result of a conversion is
-wider than the field width, the field is expanded to contain the conversion
-result.
+width is given in the next argument, or in the \fIm-th\fP argument,
+respectively, which must be of type int. A negative field width is taken as
+a '-' flag followed by a positive field width. In no case does a nonexistent
+or small field width cause truncation of a field; if the result of a
+conversion is wider than the field width, the field is expanded to contain the
+conversion result.
.SH "Precision"
An optional precision in the form of a period ('.') followed by an optional
decimal digit string. Instead of a decimal digit string one may write "*" or
"*m$" (for some decimal integer m) to specify that the precision is given in
-the next argument, or in the m-th argument, respectively, which must be of
+the next argument, or in the \fIm-th\fP argument, respectively, which must be of
type int. If the precision is given as just '.', the precision is taken to be
zero. A negative precision is taken as if the precision were omitted. This
gives the minimum number of digits to appear for \fBd\fP, \fBi\fP, \fBo\fP,
@@ -198,18 +198,18 @@
.B o, u, x, X
The unsigned int argument is converted to unsigned octal (o), unsigned decimal
(u), or unsigned hexadecimal (\fBx\fP and \fBX\fP) notation. The letters
-abcdef are used for \fBx\fP conversions; the letters ABCDEF are used for
-\fBX\fP conversions. The precision, if any, gives the minimum number of digits
-that must appear; if the converted value requires fewer digits, it is padded
-on the left with zeros. The default precision is 1. When 0 is printed with
-an explicit precision 0, the output is empty.
+\fIabcdef\fP are used for \fBx\fP conversions; the letters \fIABCDEF\fP are
+used for \fBX\fP conversions. The precision, if any, gives the minimum number
+of digits that must appear; if the converted value requires fewer digits, it
+is padded on the left with zeros. The default precision is 1. When 0 is
+printed with an explicit precision 0, the output is empty.
.TP
.B e, E
-The double argument is rounded and output in the style "[-]d.ddde±dd"
+The double argument is rounded and output in the style \fB"[-]d.ddde±dd"\fP
.TP
.B f, F
-The double argument is rounded and output to decimal notiation in the style
-[-]ddd.ddd.
+The double argument is rounded and output to decimal notation in the style
+\fB"[-]ddd.ddd"\fP.
.TP
.B g, G
The double argument is converted in style f or e.
@@ -219,12 +219,12 @@
is written.
.TP
.B s
-The const char * argument is expected to be a pointer to an array of character
-type (pointer to a string). Characters from the array are written up to (but
-not including) a terminating null byte. If a precision is specified, no more
-than the number specified are written. If a precision is given, no null byte
-need be present; if the precision is not specified, or is greater than the
-size of the array, the array must contain a terminating null byte.
+The \fIconst char *\fP argument is expected to be a pointer to an array of
+character type (pointer to a string). Characters from the array are written up
+to (but not including) a terminating null byte. If a precision is specified,
+no more than the number specified are written. If a precision is given, no
+null byte need be present; if the precision is not specified, or is greater
+than the size of the array, the array must contain a terminating null byte.
.TP
.B p
The \fIvoid *\fP pointer argument is printed in hexadecimal.
@@ -237,8 +237,8 @@
A '%' is written. No argument is converted.
.SH EXAMPLE
.nf
- mprintf("My name is %s\\n", name);
- mprintf("Pi is almost %f\\n", 25/8);
+ curl_mprintf("My name is %s\\n", name);
+ curl_mprintf("Pi is almost %f\\n", 25/8);
.fi
.SH AVAILABILITY
These functions will be removed from the public libcurl API in the future. Do
diff --git a/docs/libcurl/curl_multi_add_handle.3 b/docs/libcurl/curl_multi_add_handle.3
index 93b6e4a..685cf53 100644
--- a/docs/libcurl/curl_multi_add_handle.3
+++ b/docs/libcurl/curl_multi_add_handle.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_add_handle 3 "4 March 2002" "libcurl 7.9.5" "libcurl Manual"
+.TH curl_multi_add_handle 3 "4 March 2002" "libcurl" "libcurl"
.SH NAME
curl_multi_add_handle - add an easy handle to a multi session
.SH SYNOPSIS
@@ -77,7 +77,7 @@
curl_multi_add_handle(multi_handle, http_handle2);
.fi
.SH AVAILABILITY
-ADded in 7.9.6
+Added in 7.9.6
.SH RETURN VALUE
CURLMcode type, general libcurl multi interface error code.
.SH "SEE ALSO"
diff --git a/docs/libcurl/curl_multi_assign.3 b/docs/libcurl/curl_multi_assign.3
index 147e2e3..0544dc5 100644
--- a/docs/libcurl/curl_multi_assign.3
+++ b/docs/libcurl/curl_multi_assign.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_assign 3 "9 Jul 2006" "libcurl 7.16.0" "libcurl Manual"
+.TH curl_multi_assign 3 "9 Jul 2006" "libcurl" "libcurl"
.SH NAME
curl_multi_assign \- set data to associate with an internal socket
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_multi_cleanup.3 b/docs/libcurl/curl_multi_cleanup.3
index 09a44cd..91e205b 100644
--- a/docs/libcurl/curl_multi_cleanup.3
+++ b/docs/libcurl/curl_multi_cleanup.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_cleanup 3 "1 March 2002" "libcurl 7.9.5" "libcurl Manual"
+.TH curl_multi_cleanup 3 "1 March 2002" "libcurl" "libcurl"
.SH NAME
curl_multi_cleanup - close down a multi session
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_multi_fdset.3 b/docs/libcurl/curl_multi_fdset.3
index 9c83344..c0eb575 100644
--- a/docs/libcurl/curl_multi_fdset.3
+++ b/docs/libcurl/curl_multi_fdset.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_fdset 3 "2 Jan 2006" "libcurl 7.16.0" "libcurl Manual"
+.TH curl_multi_fdset 3 "2 Jan 2006" "libcurl" "libcurl"
.SH NAME
curl_multi_fdset - extracts file descriptor information from a multi handle
.SH SYNOPSIS
@@ -36,23 +36,23 @@
.ad
.SH DESCRIPTION
This function extracts file descriptor information from a given multi_handle.
-libcurl returns its fd_set sets. The application can use these to select() on,
-but be sure to FD_ZERO them before calling this function as
+libcurl returns its \fIfd_set\fP sets. The application can use these to
+select() on, but be sure to \fIFD_ZERO\fP them before calling this function as
\fIcurl_multi_fdset(3)\fP only adds its own descriptors, it does not zero or
otherwise remove any others. The \fIcurl_multi_perform(3)\fP function should
be called as soon as one of them is ready to be read from or written to.
If the \fIread_fd_set\fP argument is not a null pointer, it points to an
-object of type fd_set that on returns specifies the file descriptors to be
-checked for being ready to read.
+object of type \fBfd_set\fP that on returns specifies the file descriptors to
+be checked for being ready to read.
If the \fIwrite_fd_set\fP argument is not a null pointer, it points to an
-object of type fd_set that on return specifies the file descriptors to be
-checked for being ready to write.
+object of type \fBfd_set\fP that on return specifies the file descriptors to
+be checked for being ready to write.
If the \fIexc_fd_set\fP argument is not a null pointer, it points to an object
-of type fd_set that on return specifies the file descriptors to be checked for
-error conditions pending.
+of type \fBfd_set\fP that on return specifies the file descriptors to be
+checked for error conditions pending.
If no file descriptors are set by libcurl, \fImax_fd\fP will contain -1 when
this function returns. Otherwise it will contain the highest descriptor number
@@ -67,16 +67,17 @@
When doing select(), you should use \fIcurl_multi_timeout(3)\fP to figure out
how long to wait for action. Call \fIcurl_multi_perform(3)\fP even if no
-activity has been seen on the fd_sets after the timeout expires as otherwise
-internal retries and timeouts may not work as you would think and want.
+activity has been seen on the \fBfd_sets\fP after the timeout expires as
+otherwise internal retries and timeouts may not work as you would think and
+want.
If one of the sockets used by libcurl happens to be larger than what can be
-set in an fd_set, which on POSIX systems means that the file descriptor is
-larger than FD_SETSIZE, then libcurl will try to not set it. Setting a too
-large file descriptor in an fd_set implies an out of bounds write which can
-cause crashes, or worse. The effect of NOT storing it will possibly save you
-from the crash, but will make your program NOT wait for sockets it should wait
-for...
+set in an \fBfd_set\fP, which on POSIX systems means that the file descriptor
+is larger than \fBFD_SETSIZE\fP, then libcurl will try to not set it. Setting
+a too large file descriptor in an \fBfd_set\fP implies an out of bounds write
+which can cause crashes, or worse. The effect of NOT storing it will possibly
+save you from the crash, but will make your program NOT wait for sockets it
+should wait for...
.SH EXAMPLE
.nf
/* get file descriptors from the transfers */
@@ -93,7 +94,7 @@
.SH AVAILABILITY
Added in 7.9.6
.SH RETURN VALUE
-CURLMcode type, general libcurl multi interface error code. See
+\fBCURLMcode\fP type, general libcurl multi interface error code. See
\fIlibcurl-errors(3)\fP
.SH "SEE ALSO"
.BR curl_multi_cleanup "(3), " curl_multi_init "(3), "
diff --git a/docs/libcurl/curl_multi_info_read.3 b/docs/libcurl/curl_multi_info_read.3
index bb66ef1..dbdae13 100644
--- a/docs/libcurl/curl_multi_info_read.3
+++ b/docs/libcurl/curl_multi_info_read.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,9 +21,9 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_info_read 3 "18 Dec 2004" "libcurl 7.10.3" "libcurl Manual"
+.TH curl_multi_info_read 3 "18 Dec 2004" "libcurl" "libcurl"
.SH NAME
-curl_multi_info_read - read multi stack informationals
+curl_multi_info_read - read multi stack information
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -31,10 +31,10 @@
CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue);
.fi
.SH DESCRIPTION
-Ask the multi handle if there are any messages/informationals from the
-individual transfers. Messages may include informationals such as an error
-code from the transfer or just the fact that a transfer is completed. More
-details on these should be written down as well.
+Ask the multi handle if there are any messages from the individual
+transfers. Messages may include information such as an error code from the
+transfer or just the fact that a transfer is completed. More details on these
+should be written down as well.
Repeated calls to this function will return a new struct each time, until a
NULL is returned as a signal that there is no more to get at this point. The
@@ -50,10 +50,10 @@
calling \fIcurl_multi_cleanup(3)\fP, \fIcurl_multi_remove_handle(3)\fP or
\fIcurl_easy_cleanup(3)\fP.
-The 'CURLMsg' struct is simple and only contains basic information. If more
-involved information is wanted, the particular "easy handle" is present in
-that struct and can be used in subsequent regular \fIcurl_easy_getinfo(3)\fP
-calls (or similar):
+The \fICURLMsg\fP struct is simple and only contains basic information. If
+more involved information is wanted, the particular "easy handle" is present
+in that struct and can be used in subsequent regular
+\fIcurl_easy_getinfo(3)\fP calls (or similar):
.nf
struct CURLMsg {
diff --git a/docs/libcurl/curl_multi_init.3 b/docs/libcurl/curl_multi_init.3
index 6e21226..aa0ba3b 100644
--- a/docs/libcurl/curl_multi_init.3
+++ b/docs/libcurl/curl_multi_init.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_init 3 "1 March 2002" "libcurl 7.9.5" "libcurl Manual"
+.TH curl_multi_init 3 "1 March 2002" "libcurl" "libcurl"
.SH NAME
curl_multi_init - create a multi handle
.SH SYNOPSIS
@@ -31,9 +31,9 @@
CURLM *curl_multi_init();
.fi
.SH DESCRIPTION
-This function returns a CURLM handle to be used as input to all the other
-multi-functions, sometimes referred to as a multi handle in some places in the
-documentation. This init call MUST have a corresponding call to
+This function returns a pointer to a \fICURLM\fP handle to be used as input to
+all the other multi-functions, sometimes referred to as a multi handle in some
+places in the documentation. This init call MUST have a corresponding call to
\fIcurl_multi_cleanup(3)\fP when the operation is complete.
.SH EXAMPLE
.nf
diff --git a/docs/libcurl/curl_multi_perform.3 b/docs/libcurl/curl_multi_perform.3
index fe8221a..adf735f 100644
--- a/docs/libcurl/curl_multi_perform.3
+++ b/docs/libcurl/curl_multi_perform.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,9 +21,9 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_perform 3 "1 March 2002" "libcurl 7.9.5" "libcurl Manual"
+.TH curl_multi_perform 3 "1 March 2002" "libcurl" "libcurl"
.SH NAME
-curl_multi_perform - reads/writes available data from each easy handle
+curl_multi_perform - reads/writes available data from easy handles
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -32,7 +32,7 @@
.fi
.SH DESCRIPTION
This function performs transfers on all the added handles that need attention
-in an non-blocking fashion. The easy handles have previously been added to the
+in a non-blocking fashion. The easy handles have previously been added to the
multi handle with \fIcurl_multi_add_handle(3)\fP.
When an application has found out there's data available for the multi_handle
diff --git a/docs/libcurl/curl_multi_poll.3 b/docs/libcurl/curl_multi_poll.3
index ab01821..618cdef 100644
--- a/docs/libcurl/curl_multi_poll.3
+++ b/docs/libcurl/curl_multi_poll.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_poll 3 "29 Jul 2019" "libcurl 7.66.0" "libcurl Manual"
+.TH curl_multi_poll 3 "29 Jul 2019" "libcurl" "libcurl"
.SH NAME
curl_multi_poll - polls on all easy handles in a multi handle
.SH SYNOPSIS
@@ -43,7 +43,8 @@
instead to make sure timeout accuracy is reasonably kept.
The calling application may pass additional curl_waitfd structures which are
-similar to \fIpoll(2)\fP's pollfd structure to be waited on in the same call.
+similar to \fIpoll(2)\fP's \fIpollfd\fP structure to be waited on in the same
+call.
On completion, if \fInumfds\fP is non-NULL, it will be populated with the
total number of file descriptors on which interesting events occurred. This
diff --git a/docs/libcurl/curl_multi_remove_handle.3 b/docs/libcurl/curl_multi_remove_handle.3
index 9543ece..7d135e6 100644
--- a/docs/libcurl/curl_multi_remove_handle.3
+++ b/docs/libcurl/curl_multi_remove_handle.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_remove_handle 3 "6 March 2002" "libcurl 7.9.5" "libcurl Manual"
+.TH curl_multi_remove_handle 3 "6 March 2002" "libcurl" "libcurl"
.SH NAME
curl_multi_remove_handle - remove an easy handle from a multi session
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_multi_setopt.3 b/docs/libcurl/curl_multi_setopt.3
index ef366ab..dca0ee1 100644
--- a/docs/libcurl/curl_multi_setopt.3
+++ b/docs/libcurl/curl_multi_setopt.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_setopt 3 "4 Nov 2014" "libcurl 7.39.0" "libcurl Manual"
+.TH curl_multi_setopt 3 "4 Nov 2014" "libcurl" "libcurl"
.SH NAME
curl_multi_setopt \- set options for a curl multi handle
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_multi_socket.3 b/docs/libcurl/curl_multi_socket.3
index b0fb699..7cc6b29 100644
--- a/docs/libcurl/curl_multi_socket.3
+++ b/docs/libcurl/curl_multi_socket.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_socket 3 "9 Jul 2006" "libcurl 7.16.0" "libcurl Manual"
+.TH curl_multi_socket 3 "9 Jul 2006" "libcurl" "libcurl"
.SH NAME
curl_multi_socket \- reads/writes available data
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_multi_socket_action.3 b/docs/libcurl/curl_multi_socket_action.3
index 8513e52..5391f49 100644
--- a/docs/libcurl/curl_multi_socket_action.3
+++ b/docs/libcurl/curl_multi_socket_action.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_socket_action 3 "9 Jul 2006" "libcurl 7.16.0" "libcurl Manual"
+.TH curl_multi_socket_action 3 "9 Jul 2006" "libcurl" "libcurl"
.SH NAME
curl_multi_socket_action \- reads/writes available data given an action
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_multi_strerror.3 b/docs/libcurl/curl_multi_strerror.3
index e4349c9..9bc805f 100644
--- a/docs/libcurl/curl_multi_strerror.3
+++ b/docs/libcurl/curl_multi_strerror.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_strerror 3 "26 Apr 2004" "libcurl 7.12" "libcurl Manual"
+.TH curl_multi_strerror 3 "26 Apr 2004" "libcurl" "libcurl"
.SH NAME
curl_multi_strerror - return string describing error code
.SH SYNOPSIS
@@ -29,8 +29,8 @@
.B #include <curl/curl.h>
.BI "const char *curl_multi_strerror(CURLMcode " errornum ");"
.SH DESCRIPTION
-The curl_multi_strerror() function returns a string describing the CURLMcode
-error code passed in the argument \fIerrornum\fP.
+The curl_multi_strerror() function returns a string describing the
+\fICURLMcode\fP error code passed in the argument \fIerrornum\fP.
.SH EXAMPLE
.nf
int still_running;
diff --git a/docs/libcurl/curl_multi_timeout.3 b/docs/libcurl/curl_multi_timeout.3
index 4406b32..a9c364b 100644
--- a/docs/libcurl/curl_multi_timeout.3
+++ b/docs/libcurl/curl_multi_timeout.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_timeout 3 "2 Jan 2006" "libcurl 7.16.0" "libcurl Manual"
+.TH curl_multi_timeout 3 "2 Jan 2006" "libcurl" "libcurl"
.SH NAME
curl_multi_timeout \- how long to wait for action before proceeding
.SH SYNOPSIS
@@ -45,9 +45,9 @@
of milliseconds at this moment. If 0, it means you should proceed immediately
without waiting for anything. If it returns -1, there's no timeout at all set.
-An application that uses the multi_socket API SHOULD NOT use this function, but
-SHOULD instead use \fIcurl_multi_setopt(3)\fP and its
-\fPCURLMOPT_TIMERFUNCTION\fP option for proper and desired behavior.
+An application that uses the multi_socket API SHOULD NOT use this function,
+but SHOULD instead use the \fICURLMOPT_TIMERFUNCTION(3)\fP option for proper
+and desired behavior.
Note: if libcurl returns a -1 timeout here, it just means that libcurl
currently has no stored timeout value. You must not wait too long (more than a
@@ -69,9 +69,11 @@
select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
.fi
.SH TYPICAL USAGE
-Call \fIcurl_multi_timeout(3)\fP, then wait for action on the sockets. You
-figure out which sockets to wait for by calling \fIcurl_multi_fdset(3)\fP or
-by a previous call to \fIcurl_multi_socket(3)\fP.
+Call \fIcurl_multi_timeout(3)\fP, then wait for action on the sockets. Figure
+out which sockets to wait for by calling \fIcurl_multi_fdset(3)\fP.
+
+When there is activity or timeout, call \fIcurl_multi_perform(3)\fP and then
+loop - until all transfers are complete.
.SH AVAILABILITY
This function was added in libcurl 7.15.4.
.SH RETURN VALUE
diff --git a/docs/libcurl/curl_multi_wait.3 b/docs/libcurl/curl_multi_wait.3
index ec55dd9..b145022 100644
--- a/docs/libcurl/curl_multi_wait.3
+++ b/docs/libcurl/curl_multi_wait.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_wait 3 "12 Jul 2012" "libcurl 7.28.0" "libcurl Manual"
+.TH curl_multi_wait 3 "12 Jul 2012" "libcurl" "libcurl"
.SH NAME
curl_multi_wait - polls on all easy handles in a multi handle
.SH SYNOPSIS
@@ -42,8 +42,9 @@
shorter expiry time than \fItimeout_ms\fP, that shorter time will be used
instead to make sure timeout accuracy is reasonably kept.
-The calling application may pass additional curl_waitfd structures which are
-similar to \fIpoll(2)\fP's pollfd structure to be waited on in the same call.
+The calling application may pass additional \fIcurl_waitfd\fP structures which
+are similar to \fIpoll(2)\fP's \fIpollfd\fP structure to be waited on in the
+same call.
On completion, if \fInumfds\fP is non-NULL, it will be populated with the
total number of file descriptors on which interesting events occurred. This
@@ -66,14 +67,14 @@
};
.fi
.IP CURL_WAIT_POLLIN
-Bit flag to curl_waitfd.events indicating the socket should poll on read
+Bit flag to \fIcurl_waitfd.events\fP indicating the socket should poll on read
events such as new data received.
.IP CURL_WAIT_POLLPRI
-Bit flag to curl_waitfd.events indicating the socket should poll on high
+Bit flag to \fIcurl_waitfd.events\fP indicating the socket should poll on high
priority read events such as out of band data.
.IP CURL_WAIT_POLLOUT
-Bit flag to curl_waitfd.events indicating the socket should poll on write
-events such as the socket being clear to write without blocking.
+Bit flag to \fIcurl_waitfd.events\fP indicating the socket should poll on
+write events such as the socket being clear to write without blocking.
.SH EXAMPLE
.nf
CURL *easy_handle;
@@ -122,4 +123,4 @@
CURLMcode type, general libcurl multi interface error code. See
\fIlibcurl-errors(3)\fP
.SH "SEE ALSO"
-.BR curl_multi_fdset "(3), " curl_multi_perform "(3)", curl_multi_poll "(3) ",
+.BR curl_multi_fdset "(3), " curl_multi_perform "(3), " curl_multi_poll "(3), "
diff --git a/docs/libcurl/curl_multi_wakeup.3 b/docs/libcurl/curl_multi_wakeup.3
index 89a3d2e..c22f22f 100644
--- a/docs/libcurl/curl_multi_wakeup.3
+++ b/docs/libcurl/curl_multi_wakeup.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_multi_wakeup 3 "17 Nov 2019" "libcurl 7.68.0" "libcurl Manual"
+.TH curl_multi_wakeup 3 "17 Nov 2019" "libcurl" "libcurl"
.SH NAME
curl_multi_wakeup - wakes up a sleeping curl_multi_poll call
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_pushheader_byname.3 b/docs/libcurl/curl_pushheader_byname.3
new file mode 100644
index 0000000..683a48d
--- /dev/null
+++ b/docs/libcurl/curl_pushheader_byname.3
@@ -0,0 +1,80 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.TH curl_pushheader_byname 3 "9 Jun 2023" "libcurl" "libcurl"
+.SH NAME
+curl_pushheader_byname - get a push header by name
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+char *curl_pushheader_byname(struct curl_pushheaders *h, const char *name);
+.fi
+.SH DESCRIPTION
+This is a function that is only functional within a
+\fICURLMOPT_PUSHFUNCTION(3)\fP callback. It makes no sense to try to use it
+elsewhere and it has no function then.
+
+It returns the value for the given header field name (or NULL) for the
+incoming server push request. This is a shortcut so that the application does
+not have to loop through all headers to find the one it is interested in. The
+data this function points to will be freed when this callback returns. If more
+than one header field use the same name, this returns only the first one.
+
+.SH EXAMPLE
+.nf
+int curl_push_callback(CURL *parent,
+ CURL *easy,
+ size_t num_headers,
+ struct curl_pushheaders *headers,
+ void *clientp)
+{
+ char *headp;
+ int *transfers = (int *)clientp;
+ FILE *out;
+ headp = curl_pushheader_byname(headers, ":path");
+ if(headp && !strncmp(headp, "/push-", 6)) {
+ fprintf(stderr, "The PATH is %s\\n", headp);
+
+ /* save the push here */
+ out = fopen("pushed-stream", "wb");
+
+ /* write to this file */
+ curl_easy_setopt(easy, CURLOPT_WRITEDATA, out);
+
+ (*transfers)++; /* one more */
+
+ return CURL_PUSH_OK;
+ }
+ return CURL_PUSH_DENY;
+}
+
+curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, curl_push_callback);
+curl_multi_setopt(multi, CURLMOPT_PUSHDATA, &counter);
+.fi
+.SH AVAILABILITY
+Added in 7.44.0
+.SH RETURN VALUE
+Returns a pointer to the header field content or NULL.
+.SH "SEE ALSO"
+.BR CURLMOPT_PUSHFUNCTION "(3)," curl_pushheader_bynum "(3), "
diff --git a/docs/libcurl/curl_pushheader_bynum.3 b/docs/libcurl/curl_pushheader_bynum.3
new file mode 100644
index 0000000..a51b8d7
--- /dev/null
+++ b/docs/libcurl/curl_pushheader_bynum.3
@@ -0,0 +1,70 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.TH curl_pushheader_bynum 3 "9 Jun 2023" "libcurl" "libcurl"
+.SH NAME
+curl_pushheader_bynum - get a push header by index
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num);
+.fi
+.SH DESCRIPTION
+This is a function that is only functional within a
+\fICURLMOPT_PUSHFUNCTION(3)\fP callback. It makes no sense to try to use it
+elsewhere and it has no function then.
+
+It returns the value for the header field at the given index \fBnum\fP, for
+the incoming server push request or NULL. The data pointed will be freed when
+this callback returns. The returned pointer points to a "name:value" string
+that will be freed when this callback returns.
+
+.SH EXAMPLE
+.nf
+/* output all the incoming push request headers */
+int curl_push_callback(CURL *parent,
+ CURL *easy,
+ size_t num_headers,
+ struct curl_pushheaders *headers,
+ void *clientp)
+{
+ sizt_t i = 0;
+ char *field;
+ do {
+ field = curl_pushheader_bynum(headers, i);
+ if(field)
+ fprintf(stderr, "Push header: %s\\n", field);
+ i++;
+ } while(field);
+ return CURL_PUSH_OK; /* permission granted */
+}
+
+curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, curl_push_callback);
+.fi
+.SH AVAILABILITY
+Added in 7.44.0
+.SH RETURN VALUE
+Returns a pointer to the header field content or NULL.
+.SH "SEE ALSO"
+.BR CURLMOPT_PUSHFUNCTION "(3)," curl_pushheader_byname "(3),"
diff --git a/docs/libcurl/curl_share_cleanup.3 b/docs/libcurl/curl_share_cleanup.3
index 2346712..eaa5da1 100644
--- a/docs/libcurl/curl_share_cleanup.3
+++ b/docs/libcurl/curl_share_cleanup.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_share_cleanup 3 "8 Aug 2003" "libcurl 7.10.7" "libcurl Manual"
+.TH curl_share_cleanup 3 "8 Aug 2003" "libcurl" "libcurl"
.SH NAME
curl_share_cleanup - Clean up a shared object
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_share_init.3 b/docs/libcurl/curl_share_init.3
index a1a3af3..3ef4d4c 100644
--- a/docs/libcurl/curl_share_init.3
+++ b/docs/libcurl/curl_share_init.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_share_init 3 "Aug 3, 2003" "libcurl 7.10.7" "libcurl Manual"
+.TH curl_share_init 3 "Aug 3, 2003" "libcurl" "libcurl"
.SH NAME
curl_share_init - Create a shared object
.SH SYNOPSIS
@@ -31,10 +31,11 @@
CURLSH *curl_share_init();
.fi
.SH DESCRIPTION
-This function returns a CURLSH handle to be used as input to all the other
-share-functions, sometimes referred to as a share handle in some places in the
-documentation. This init call MUST have a corresponding call to
-\fIcurl_share_cleanup\fP when all operations using the share are complete.
+This function returns a pointer to a \fICURLSH\fP handle to be used as input
+to all the other share-functions, sometimes referred to as a share handle in
+some places in the documentation. This init call MUST have a corresponding
+call to \fIcurl_share_cleanup(3)\fP when all operations using the share are
+complete.
This \fIshare handle\fP is what you pass to curl using the
\fICURLOPT_SHARE(3)\fP option with \fIcurl_easy_setopt(3)\fP, to make that
diff --git a/docs/libcurl/curl_share_setopt.3 b/docs/libcurl/curl_share_setopt.3
index aef3d51..6f7af15 100644
--- a/docs/libcurl/curl_share_setopt.3
+++ b/docs/libcurl/curl_share_setopt.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_share_setopt 3 "8 Aug 2003" "libcurl 7.10.7" "libcurl Manual"
+.TH curl_share_setopt 3 "8 Aug 2003" "libcurl" "libcurl"
.SH NAME
curl_share_setopt - Set options for a shared object
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_share_strerror.3 b/docs/libcurl/curl_share_strerror.3
index 0c4824c..0e3f1c9 100644
--- a/docs/libcurl/curl_share_strerror.3
+++ b/docs/libcurl/curl_share_strerror.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_share_strerror 3 "Apr 26, 2004" "libcurl 7.12" "libcurl Manual"
+.TH curl_share_strerror 3 "Apr 26, 2004" "libcurl" "libcurl"
.SH NAME
curl_share_strerror - return string describing error code
.SH SYNOPSIS
@@ -29,8 +29,8 @@
.B #include <curl/curl.h>
.BI "const char *curl_share_strerror(CURLSHcode " errornum ");"
.SH DESCRIPTION
-The curl_share_strerror() function returns a string describing the CURLSHcode
-error code passed in the argument \fIerrornum\fP.
+The \fIcurl_share_strerror(3)\fP function returns a string describing the
+\fICURLSHcode\fP error code passed in the argument \fIerrornum\fP.
.SH EXAMPLE
.nf
CURLSHcode sh;
diff --git a/docs/libcurl/curl_slist_append.3 b/docs/libcurl/curl_slist_append.3
index ba664b1..807f02e 100644
--- a/docs/libcurl/curl_slist_append.3
+++ b/docs/libcurl/curl_slist_append.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_slist_append 3 "19 Jun 2003" "libcurl 7.10.4" "libcurl Manual"
+.TH curl_slist_append 3 "19 Jun 2003" "libcurl" "libcurl"
.SH NAME
curl_slist_append - add a string to an slist
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_slist_free_all.3 b/docs/libcurl/curl_slist_free_all.3
index 222d6db..6850503 100644
--- a/docs/libcurl/curl_slist_free_all.3
+++ b/docs/libcurl/curl_slist_free_all.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_slist_free_all 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
+.TH curl_slist_free_all 3 "5 March 2001" "libcurl" "libcurl"
.SH NAME
curl_slist_free_all - free an entire curl_slist list
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_strequal.3 b/docs/libcurl/curl_strequal.3
index 531bcaa..c66c652 100644
--- a/docs/libcurl/curl_strequal.3
+++ b/docs/libcurl/curl_strequal.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_strequal 3 "30 April 2004" "libcurl 7.12" "libcurl Manual"
+.TH curl_strequal 3 "30 April 2004" "libcurl" "libcurl"
.SH NAME
curl_strequal, curl_strnequal - case insensitive string comparisons
.SH SYNOPSIS
@@ -39,7 +39,7 @@
identical.
.sp
The \fBcurl_strnequal()\fP function is similar, except it only compares the
-first \fIlenght\fP characters of \fIstr1\fP.
+first \fIlength\fP characters of \fIstr1\fP.
.sp
These functions are provided by libcurl to enable applications to compare
strings in a truly portable manner. There are no standard portable case
@@ -52,9 +52,7 @@
printf("Name and input matches in the 5 first bytes\\n");
.fi
.SH AVAILABILITY
-These functions will be removed from the public libcurl API in a near
-future. They will instead be made "available" by source code access only, and
-then as curlx_strequal() and curlx_strenqual().
+Always
.SH RETURN VALUE
Non-zero if the strings are identical. Zero if they are not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/curl_unescape.3 b/docs/libcurl/curl_unescape.3
index cf54225..5aef2e9 100644
--- a/docs/libcurl/curl_unescape.3
+++ b/docs/libcurl/curl_unescape.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,25 +21,25 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_unescape 3 "22 March 2001" "libcurl 7.7" "libcurl Manual"
+.TH curl_unescape 3 "22 March 2001" "libcurl" "libcurl"
.SH NAME
curl_unescape - URL decodes the given string
.SH SYNOPSIS
.nf
#include <curl/curl.h>
-char *curl_unescape( const char *url, int length);
+char *curl_unescape(const char *input, int length);
.fi
.SH DESCRIPTION
Obsolete function. Use \fIcurl_easy_unescape(3)\fP instead!
-This function will convert the given URL encoded input string to a "plain
+This function will convert the URL encoded string \fBinput\fP to a "plain
string" and return that as a new allocated string. All input characters that
are URL encoded (%XX where XX is a two-digit hexadecimal number) will be
converted to their plain text versions.
-If the 'length' argument is set to 0, curl_unescape() will use strlen() on the
-input 'url' string to find out the size.
+If the \fBlength\fP argument is set to 0, \fIcurl_unescape(3)\fP will use
+strlen() on \fBinput\fP to find out the size.
You must \fIcurl_free(3)\fP the returned string when you are done with it.
.SH EXAMPLE
diff --git a/docs/libcurl/curl_url.3 b/docs/libcurl/curl_url.3
index b761e61..a7143b0 100644
--- a/docs/libcurl/curl_url.3
+++ b/docs/libcurl/curl_url.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,9 +21,9 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_url 3 "6 Aug 2018" "libcurl" "libcurl Manual"
+.TH curl_url 3 "6 Aug 2018" "libcurl" "libcurl"
.SH NAME
-curl_url - returns a new CURLU handle
+curl_url - returns a new URL handle
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -31,8 +31,8 @@
CURLU *curl_url();
.fi
.SH DESCRIPTION
-This function will allocates and returns a pointer to a fresh CURLU handle, to
-be used for further use of the URL API.
+This function will allocates and returns a pointer to a fresh \fICURLU\fP
+handle, to be used for further use of the URL API.
.SH EXAMPLE
.nf
CURLUcode rc;
diff --git a/docs/libcurl/curl_url_cleanup.3 b/docs/libcurl/curl_url_cleanup.3
index eb16235..2e32668 100644
--- a/docs/libcurl/curl_url_cleanup.3
+++ b/docs/libcurl/curl_url_cleanup.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,9 +21,9 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_url_cleanup 3 "6 Aug 2018" "libcurl" "libcurl Manual"
+.TH curl_url_cleanup 3 "6 Aug 2018" "libcurl" "libcurl"
.SH NAME
-curl_url_cleanup - free a CURLU handle
+curl_url_cleanup - free the URL handle
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -31,7 +31,10 @@
void curl_url_cleanup(CURLU *handle);
.fi
.SH DESCRIPTION
-Frees all the resources associated with the given CURLU handle!
+Frees all the resources associated with the given \fICURLU\fP handle!
+
+Passing in a NULL pointer in \fIhandle\fP will make this function return
+immediately with no action.
.SH EXAMPLE
.nf
CURLU *url = curl_url();
diff --git a/docs/libcurl/curl_url_dup.3 b/docs/libcurl/curl_url_dup.3
index 7eff4ab..f04f6bb 100644
--- a/docs/libcurl/curl_url_dup.3
+++ b/docs/libcurl/curl_url_dup.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,9 +21,9 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_url_dup 3 "6 Aug 2018" "libcurl" "libcurl Manual"
+.TH curl_url_dup 3 "6 Aug 2018" "libcurl" "libcurl"
.SH NAME
-curl_url_dup - duplicate a CURLU handle
+curl_url_dup - duplicate a URL handle
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -31,9 +31,9 @@
CURLU *curl_url_dup(CURLU *inhandle);
.fi
.SH DESCRIPTION
-Duplicates a given CURLU \fIinhandle\fP and all its contents and returns a
-pointer to a new CURLU handle. The new handle also needs to be freed with
-\fIcurl_url_cleanup(3)\fP.
+Duplicates a given \fICURLU\fP \fIinhandle\fP and all its contents and returns
+a pointer to a new \fICURLU\fP handle. The new handle also needs to be freed
+with \fIcurl_url_cleanup(3)\fP.
.SH EXAMPLE
.nf
CURLUcode rc;
diff --git a/docs/libcurl/curl_url_get.3 b/docs/libcurl/curl_url_get.3
index 88a96b3..ba66971 100644
--- a/docs/libcurl/curl_url_get.3
+++ b/docs/libcurl/curl_url_get.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_url_get 3 "6 Aug 2018" "libcurl" "libcurl Manual"
+.TH curl_url_get 3 "6 Aug 2018" "libcurl" "libcurl"
.SH NAME
curl_url_get - extract a part from a URL
.SH SYNOPSIS
@@ -41,6 +41,10 @@
below) and \fIpart\fP points to a 'char *' to get updated to point to a newly
allocated string with the contents.
+The URL API has no particular maximum length for URL fiends. In the real
+world, excessively long field in URLs will cause problems even if this API
+accepts them. This function can return very large ones.
+
The \fIflags\fP argument is a bitmask with individual features.
The returned part pointer must be freed with \fIcurl_free(3)\fP after use.
@@ -58,7 +62,7 @@
.IP CURLU_URLDECODE
Asks \fIcurl_url_get(3)\fP to URL decode the contents before returning it. It
will not attempt to decode the scheme, the port number or the full URL.
-´
+
The query component will also get plus-to-space conversion as a bonus when
this bit is set.
@@ -76,30 +80,53 @@
Note that even when not asking for URL encoding, the '%' (byte 37) will be URL
encoded to make sure the host name remains valid.
+.IP CURLU_PUNYCODE
+If set and \fICURLU_URLENCODE\fP is not set, and asked to retrieve the
+\fBCURLUPART_HOST\fP or \fBCURLUPART_URL\fP parts, libcurl returns the host
+name in its punycode version if it contains any non-ASCII octets (and is an
+IDN name).
+
+If libcurl is built without IDN capabilities, using this bit will make
+\fIcurl_url_get(3)\fP return \fICURLUE_LACKS_IDN\fP if the host name contains
+anything outside the ASCII range.
+
+(Added in curl 7.88.0)
.SH PARTS
.IP CURLUPART_URL
When asked to return the full URL, \fIcurl_url_get(3)\fP will return a
normalized and possibly cleaned up version of what was previously parsed.
+
+We advise using the \fICURLU_PUNYCODE\fP option to get the URL as "normalized"
+as possible since IDN allows host names to be written in many different ways
+that still end up the same punycode version.
.IP CURLUPART_SCHEME
Scheme cannot be URL decoded on get.
.IP CURLUPART_USER
.IP CURLUPART_PASSWORD
.IP CURLUPART_OPTIONS
+The options field is an optional field that might follow the password in the
+userinfo part. It is only recognized/used when parsing URLs for the following
+schemes: pop3, smtp and imap. The URL API still allows users to set and get
+this field independently of scheme when not parsing full URLs.
.IP CURLUPART_HOST
-The host name. If it is an IPv6 numeric address, the zoneid will not be part
+The host name. If it is an IPv6 numeric address, the zone id will not be part
of it but is provided separately in \fICURLUPART_ZONEID\fP. IPv6 numerical
addresses are returned within brackets ([]).
+
+IPv6 names are normalized when set, which should make them as short as
+possible while maintaining correct syntax.
.IP CURLUPART_ZONEID
If the host name is a numeric IPv6 address, this field might also be set.
.IP CURLUPART_PORT
-Port cannot be URL decoded on get.
+A port cannot be URL decoded on get. This number is returned in a string just
+like all other parts. That string is guaranteed to hold a valid port number in
+ASCII using base 10.
.IP CURLUPART_PATH
-\fIpart\fP will be '/' even if no path is supplied in the URL.
+The \fIpart\fP will be '/' even if no path is supplied in the URL. A URL path
+always starts with a slash.
.IP CURLUPART_QUERY
-The initial question mark that denotes the beginning of the query part is
-a delimiter only.
-It is not part of the query contents.
-
+The initial question mark that denotes the beginning of the query part is a
+delimiter only. It is not part of the query contents.
A not-present query will lead \fIpart\fP to be set to NULL.
A zero-length query will lead \fIpart\fP to be set to a zero-length string.
@@ -107,6 +134,8 @@
The query part will also get pluses converted to space when asked to URL
decode on get with the CURLU_URLDECODE bit.
.IP CURLUPART_FRAGMENT
+The initial hash sign that denotes the beginning of the fragment is a
+delimiter only. It is not part of the fragment contents.
.SH EXAMPLE
.nf
CURLUcode rc;
diff --git a/docs/libcurl/curl_url_set.3 b/docs/libcurl/curl_url_set.3
index bbea5de..cffe745 100644
--- a/docs/libcurl/curl_url_set.3
+++ b/docs/libcurl/curl_url_set.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_url_set 3 "6 Aug 2018" "libcurl" "libcurl Manual"
+.TH curl_url_set 3 "6 Aug 2018" "libcurl" "libcurl"
.SH NAME
curl_url_set - set a URL part
.SH SYNOPSIS
@@ -46,7 +46,7 @@
call.
Setting a part to a NULL pointer will effectively remove that part's contents
-from the CURLU handle.
+from the \fICURLU\fP handle.
By default, this API only accepts URLs using schemes for protocols that are
supported built-in. To make libcurl parse URLs generically even for schemes it
@@ -54,6 +54,15 @@
set. Otherwise, this function returns \fICURLUE_UNSUPPORTED_SCHEME\fP on URL
schemes it does not recognize.
+This function call has no particular maximum length for any provided input
+string. In the real world, excessively long field in URLs will cause problems
+even if this API accepts them.
+
+When setting or updating contents of individual URL parts, this API might
+accept data that would not be otherwise possible to set in the string when it
+gets populated as a result of a full URL parse. Beware. If done so, extracting
+a full URL later on from such components might render an invalid URL.
+
The \fIflags\fP argument is a bitmask with independent features.
.SH PARTS
.IP CURLUPART_URL
@@ -66,16 +75,25 @@
Pass a pointer to a null-terminated string to the \fIurl\fP parameter. The
string must point to a correctly formatted "RFC 3986+" URL or be a NULL
pointer.
+
+Unless \fICURLU_NO_AUTHORITY\fP is set, a blank host name is not allowed in
+the URL.
.IP CURLUPART_SCHEME
Scheme cannot be URL decoded on set. libcurl only accepts setting schemes up
to 40 bytes long.
.IP CURLUPART_USER
.IP CURLUPART_PASSWORD
.IP CURLUPART_OPTIONS
+The options field is an optional field that might follow the password in the
+userinfo part. It is only recognized/used when parsing URLs for the following
+schemes: pop3, smtp and imap. This function however allows users to
+independently set this field at will.
.IP CURLUPART_HOST
The host name. If it is IDNA the string must then be encoded as your locale
says or UTF-8 (when WinIDN is used). If it is a bracketed IPv6 numeric address
it may contain a zone id (or you can use CURLUPART_ZONEID).
+
+Unless \fICURLU_NO_AUTHORITY\fP is set, a blank host name is not allowed to set.
.IP CURLUPART_ZONEID
If the host name is a numeric IPv6 address, this field can also be set.
.IP CURLUPART_PORT
@@ -83,25 +101,28 @@
string and the decimal number must be between 1 and 65535. Anything else will
return an error.
.IP CURLUPART_PATH
-If a path is set in the URL without a leading slash, a slash will be inserted
-automatically when this URL is read from the handle.
+If a path is set in the URL without a leading slash, a slash will be prepended
+automatically.
.IP CURLUPART_QUERY
The query part will also get spaces converted to pluses when asked to URL
-encode on set with the CURLU_URLENCODE bit.
+encode on set with the \fICURLU_URLENCODE\fP bit.
-If used together with the \fICURLU_APPENDQUERY\fP bit, the provided part will
-be appended on the end of the existing query - and if the previous part did not
-end with an ampersand (&), an ampersand will be inserted before the new
-appended part.
-
-When \fICURLU_APPENDQUERY\fP is used together with \fICURLU_URLENCODE\fP, the
-first '=' symbol will not be URL encoded.
+If used together with the \fICURLU_APPENDQUERY\fP bit, the provided part is
+appended on the end of the existing query.
The question mark in the URL is not part of the actual query contents.
.IP CURLUPART_FRAGMENT
The hash sign in the URL is not part of the actual fragment contents.
.SH FLAGS
The flags argument is zero, one or more bits set in a bitmask.
+.IP CURLU_APPENDQUERY
+Can be used when setting the \fICURLUPART_QUERY\fP component. The provided new
+part will then instead be appended at the end of the existing query - and if
+the previous part did not end with an ampersand (&), an ampersand gets
+inserted before the new appended part.
+
+When \fICURLU_APPENDQUERY\fP is used together with \fICURLU_URLENCODE\fP, the
+first '=' symbol will not be URL encoded.
.IP CURLU_NON_SUPPORT_SCHEME
If set, allows \fIcurl_url_set(3)\fP to set a non-supported scheme.
.IP CURLU_URLENCODE
@@ -136,7 +157,7 @@
dot-slash and dot-dot etc. The same option used for transfers is called
\fICURLOPT_PATH_AS_IS(3)\fP.
.IP CURLU_ALLOW_SPACE
-If set, a the URL parser allows space (ASCII 32) where possible. The URL
+If set, the URL parser allows space (ASCII 32) where possible. The URL
syntax does normally not allow spaces anywhere, but they should be encoded as
%20 or '+'. When spaces are allowed, they are still not allowed in the scheme.
When space is used and allowed in a URL, it will be stored as-is unless
@@ -144,6 +165,10 @@
space before stored. This affects how the URL will be constructed when
\fIcurl_url_get(3)\fP is subsequently used to extract the full URL or
individual parts. (Added in 7.78.0)
+.IP CURLU_DISALLOW_USER
+If set, the URL parser will not accept embedded credentials for the
+\fBCURLUPART_URL\fP, and will instead return \fBCURLUE_USER_NOT_ALLOWED\fP for
+such URLs.
.SH EXAMPLE
.nf
CURLUcode rc;
@@ -159,13 +184,12 @@
.SH AVAILABILITY
Added in 7.62.0. CURLUPART_ZONEID was added in 7.65.0.
.SH RETURN VALUE
-Returns a CURLUcode error value, which is CURLUE_OK (0) if everything went
-fine. See the \fIlibcurl-errors(3)\fP man page for the full list with
+Returns a \fICURLUcode\fP error value, which is CURLUE_OK (0) if everything
+went fine. See the \fIlibcurl-errors(3)\fP man page for the full list with
descriptions.
-A URL string passed on to \fIcurl_url_set(3)\fP for the \fBCURLUPART_URL\fP
-part, must be shorter than 8000000 bytes otherwise it returns
-\fBCURLUE_MALFORMED_INPUT\fP (added in 7.65.0).
+The input string passed to \fIcurl_url_set(3)\fP must be shorter than eight
+million bytes. Otherwise this function returns \fBCURLUE_MALFORMED_INPUT\fP.
If this function returns an error, no URL part is set.
.SH "SEE ALSO"
diff --git a/docs/libcurl/curl_url_strerror.3 b/docs/libcurl/curl_url_strerror.3
index aaa541e..269705a 100644
--- a/docs/libcurl/curl_url_strerror.3
+++ b/docs/libcurl/curl_url_strerror.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_url_strerror 3 "21 Aug 2021" "libcurl 7.80.0" "libcurl Manual"
+.TH curl_url_strerror 3 "21 Aug 2021" "libcurl" "libcurl"
.SH NAME
curl_url_strerror - return string describing error code
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_version.3 b/docs/libcurl/curl_version.3
index aa13164..ec4bd53 100644
--- a/docs/libcurl/curl_version.3
+++ b/docs/libcurl/curl_version.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH curl_version 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
+.TH curl_version 3 "5 March 2001" "libcurl" "libcurl"
.SH NAME
curl_version - returns the libcurl version string
.SH SYNOPSIS
diff --git a/docs/libcurl/curl_version_info.3 b/docs/libcurl/curl_version_info.3
index 2a27c99..7755b16 100644
--- a/docs/libcurl/curl_version_info.3
+++ b/docs/libcurl/curl_version_info.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,14 +22,14 @@
.\" *
.\" **************************************************************************
.\"
-.TH curl_version_info 3 "2 Nov 2014" "libcurl 7.40.0" "libcurl Manual"
+.TH curl_version_info 3 "2 Nov 2014" "libcurl" "libcurl"
.SH NAME
curl_version_info - returns runtime libcurl version info
.SH SYNOPSIS
.nf
#include <curl/curl.h>
-curl_version_info_data *curl_version_info( CURLversion age);
+curl_version_info_data *curl_version_info(CURLversion age);
.fi
.SH DESCRIPTION
Returns a pointer to a filled in static struct with information about various
@@ -46,6 +46,10 @@
or not, instead of using compile-time checks, as dynamic/DLL libraries can be
changed independent of applications.
+This function can alter the returned static data as long as
+\fIcurl_global_init\fP has not been called. It is therefore not thread-safe
+before libcurl initialization occurs.
+
The curl_version_info_data struct looks like this
.nf
@@ -106,6 +110,9 @@
/* when 'age' is CURLVERSION_TENTH or higher (>= 7.77.0), the members
below exist */
const char *gsasl_version; /* human readable string. */
+ /* when 'age' is CURLVERSION_ELEVENTH or higher (>= 7.87.0), the members
+ below exist */
+ const char *const *feature_names; /* Feature names. */
} curl_version_info_data;
.fi
@@ -124,102 +131,170 @@
was built for. As discovered by a configure script or set by the build
environment.
-\fIfeatures\fP can have none, one or more bits set, and the currently defined
-bits are:
+\fIfeatures\fP is a bit mask representing available features. It can
+have none, one or more bits set.
+The use of this field is deprecated: use \fIfeature_names\fP instead.
+The feature names description below lists the associated bits.
+
+\fIfeature_names\fP is a pointer to an array of string pointers, containing the
+names of the features that libcurl supports. The array is terminated by a NULL
+entry. Currently defined names are:
.RS
-.IP CURL_VERSION_ALTSVC
+.IP """alt-svc"""
+\fIfeatures\fP mask bit: CURL_VERSION_ALTSVC
+.br
HTTP Alt-Svc parsing and the associated options (Added in 7.64.1)
-.IP CURL_VERSION_ASYNCHDNS
+.IP """AsynchDNS"""
+\fIfeatures\fP mask bit: CURL_VERSION_ASYNCHDNS
+.br
libcurl was built with support for asynchronous name lookups, which allows
more exact timeouts (even on Windows) and less blocking when using the multi
interface. (added in 7.10.7)
-.IP CURL_VERSION_BROTLI
+.IP """brotli"""
+\fIfeatures\fP mask bit: CURL_VERSION_BROTLI
+.br
supports HTTP Brotli content encoding using libbrotlidec (Added in 7.57.0)
-.IP CURL_VERSION_ZSTD
-supports HTTP zstd content encoding using zstd library (Added in 7.72.0)
-.IP CURL_VERSION_CONV
-libcurl was built with support for character conversions, as provided by the
-CURLOPT_CONV_* callbacks. (Added in 7.15.4)
-.IP CURL_VERSION_CURLDEBUG
-libcurl was built with memory tracking debug capabilities. This is mainly of
-interest for libcurl hackers. (added in 7.19.6)
-.IP CURL_VERSION_DEBUG
+.IP """Debug"""
+\fIfeatures\fP mask bit: CURL_VERSION_DEBUG
+.br
libcurl was built with debug capabilities (added in 7.10.6)
-.IP CURL_VERSION_GSASL
+.IP """gsasl"""
+\fIfeatures\fP mask bit: CURL_VERSION_GSASL
+.br
libcurl was built with libgsasl and thus with some extra SCRAM-SHA
authentication methods. (added in 7.76.0)
-.IP CURL_VERSION_GSSAPI
+.IP """GSS-API"""
+\fIfeatures\fP mask bit: CURL_VERSION_GSSAPI
+.br
libcurl was built with support for GSS-API. This makes libcurl use provided
functions for Kerberos and SPNEGO authentication. It also allows libcurl
to use the current user credentials without the app having to pass them on.
(Added in 7.38.0)
-.IP CURL_VERSION_GSSNEGOTIATE
-supports HTTP GSS-Negotiate (added in 7.10.6)
-.IP CURL_VERSION_HSTS
+.IP """HSTS"""
+\fIfeatures\fP mask bit: CURL_VERSION_HSTS
+.br
libcurl was built with support for HSTS (HTTP Strict Transport Security)
(Added in 7.74.0)
-.IP CURL_VERSION_HTTPS_PROXY
-libcurl was built with support for HTTPS-proxy.
-(Added in 7.52.0)
-.IP CURL_VERSION_HTTP2
+.IP """HTTP2"""
+\fIfeatures\fP mask bit: CURL_VERSION_HTTP2
+.br
libcurl was built with support for HTTP2.
(Added in 7.33.0)
-.IP CURL_VERSION_HTTP3
+.IP """HTTP3"""
+\fIfeatures\fP mask bit: CURL_VERSION_HTTP3
+.br
HTTP/3 and QUIC support are built-in (Added in 7.66.0)
-.IP CURL_VERSION_IDN
+.IP """HTTPS-proxy"""
+\fIfeatures\fP mask bit: CURL_VERSION_HTTPS_PROXY
+.br
+libcurl was built with support for HTTPS-proxy.
+(Added in 7.52.0)
+.IP """IDN"""
+\fIfeatures\fP mask bit: CURL_VERSION_IDN
+.br
libcurl was built with support for IDNA, domain names with international
letters. (Added in 7.12.0)
-.IP CURL_VERSION_IPV6
+.IP """IPv6"""
+\fIfeatures\fP mask bit: CURL_VERSION_IPV6
+.br
supports IPv6
-.IP CURL_VERSION_KERBEROS4
-supports Kerberos V4 (when using FTP). Legacy bit. Deprecated since 7.33.0.
-.IP CURL_VERSION_KERBEROS5
+.IP """Kerberos"""
+\fIfeatures\fP mask bit: CURL_VERSION_KERBEROS5
+.br
supports Kerberos V5 authentication for FTP, IMAP, LDAP, POP3, SMTP and
SOCKSv5 proxy. (Added in 7.40.0)
-.IP CURL_VERSION_LARGEFILE
+.IP """Largefile"""
+\fIfeatures\fP mask bit: CURL_VERSION_LARGEFILE
+.br
libcurl was built with support for large files. (Added in 7.11.1)
-.IP CURL_VERSION_UNICODE
-libcurl was built with Unicode support on Windows. This makes non-ASCII
-characters work in filenames and options passed to libcurl. (Added in 7.72.0)
-.IP CURL_VERSION_LIBZ
+.IP """libz"""
+\fIfeatures\fP mask bit: CURL_VERSION_LIBZ
+.br
supports HTTP deflate using libz (Added in 7.10)
-.IP CURL_VERSION_MULTI_SSL
+.IP """MultiSSL"""
+\fIfeatures\fP mask bit: CURL_VERSION_MULTI_SSL
+.br
libcurl was built with multiple SSL backends. For details, see
\fIcurl_global_sslset(3)\fP.
(Added in 7.56.0)
-.IP CURL_VERSION_NTLM
+.IP """NTLM"""
+\fIfeatures\fP mask bit: CURL_VERSION_NTLM
+.br
supports HTTP NTLM (added in 7.10.6)
-.IP CURL_VERSION_NTLM_WB
+.IP """NTLM_WB"""
+\fIfeatures\fP mask bit: CURL_VERSION_NTLM_WB
+.br
libcurl was built with support for NTLM delegation to a winbind helper.
(Added in 7.22.0)
-.IP CURL_VERSION_PSL
+.IP """PSL"""
+\fIfeatures\fP mask bit: CURL_VERSION_PSL
+.br
libcurl was built with support for Mozilla's Public Suffix List. This makes
libcurl ignore cookies with a domain that is on the list.
(Added in 7.47.0)
-.IP CURL_VERSION_SPNEGO
+.IP """SPNEGO"""
+\fIfeatures\fP mask bit: CURL_VERSION_SPNEGO
+.br
libcurl was built with support for SPNEGO authentication (Simple and Protected
GSS-API Negotiation Mechanism, defined in RFC 2478.) (added in 7.10.8)
-.IP CURL_VERSION_SSL
+.IP """SSL"""
+\fIfeatures\fP mask bit: CURL_VERSION_SSL
+.br
supports SSL (HTTPS/FTPS) (Added in 7.10)
-.IP CURL_VERSION_SSPI
+.IP """SSPI"""
+\fIfeatures\fP mask bit: CURL_VERSION_SSPI
+.br
libcurl was built with support for SSPI. This is only available on Windows and
makes libcurl use Windows-provided functions for Kerberos, NTLM, SPNEGO and
Digest authentication. It also allows libcurl to use the current user
credentials without the app having to pass them on. (Added in 7.13.2)
-.IP CURL_VERSION_THREADSAFE
+.IP """threadsafe"""
+\fIfeatures\fP mask bit: CURL_VERSION_THREADSAFE
+.br
libcurl was built with thread-safety support (Atomic or SRWLOCK) to protect
-curl initialisation. (Added in 7.84.0)
-See \fIlibcurl-thread(3)\fP
-.IP CURL_VERSION_TLSAUTH_SRP
+curl initialization. (Added in 7.84.0) See \fIlibcurl-thread(3)\fP
+.IP """TLS-SRP"""
+\fIfeatures\fP mask bit: CURL_VERSION_TLSAUTH_SRP
+.br
libcurl was built with support for TLS-SRP (in one or more of the built-in TLS
backends). (Added in 7.21.4)
-.IP CURL_VERSION_UNIX_SOCKETS
+.IP """TrackMemory"""
+\fIfeatures\fP mask bit: CURL_VERSION_CURLDEBUG
+.br
+libcurl was built with memory tracking debug capabilities. This is mainly of
+interest for libcurl hackers. (added in 7.19.6)
+.IP """Unicode"""
+\fIfeatures\fP mask bit: CURL_VERSION_UNICODE
+.br
+libcurl was built with Unicode support on Windows. This makes non-ASCII
+characters work in filenames and options passed to libcurl. (Added in 7.72.0)
+.IP """UnixSockets"""
+\fIfeatures\fP mask bit: CURL_VERSION_UNIX_SOCKETS
+.br
libcurl was built with support for Unix domain sockets.
(Added in 7.40.0)
+.IP """zstd"""
+\fIfeatures\fP mask bit: CURL_VERSION_ZSTD
+.br
+supports HTTP zstd content encoding using zstd library (Added in 7.72.0)
+.IP none
+\fIfeatures\fP mask bit: CURL_VERSION_CONV
+.br
+libcurl was built with support for character conversions, as provided by the
+CURLOPT_CONV_* callbacks. Always 0 since 7.82.0. (Added in 7.15.4)
+.IP none
+\fIfeatures\fP mask bit: CURL_VERSION_GSSNEGOTIATE
+.br
+supports HTTP GSS-Negotiate (added in 7.10.6, deprecated in 7.38.0)
+.IP none
+\fIfeatures\fP mask bit: CURL_VERSION_KERBEROS4
+.br
+supports Kerberos V4 (when using FTP). Legacy bit. Deprecated since 7.33.0.
.RE
+
\fIssl_version\fP is an ASCII string for the TLS library name + version
used. If libcurl has no SSL support, this is NULL. For example "Schannel",
-\&"SecureTransport" or "OpenSSL/1.1.0g".
+\&"Secure Transport" or "OpenSSL/1.1.0g".
\fIssl_version_num\fP is always 0.
@@ -236,7 +311,7 @@
printf("libcurl version %u.%u.%u\\n",
(ver->version_num >> 16) & 0xff,
(ver->version_num >> 8) & 0xff,
- ver->version_num & 0xff,
+ ver->version_num & 0xff);
.fi
.SH AVAILABILITY
Added in 7.10
diff --git a/docs/libcurl/curl_ws_meta.3 b/docs/libcurl/curl_ws_meta.3
new file mode 100644
index 0000000..891ee7b
--- /dev/null
+++ b/docs/libcurl/curl_ws_meta.3
@@ -0,0 +1,118 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.\"
+.TH curl_ws_meta 3 "12 Jun 2022" "libcurl" "libcurl"
+.SH NAME
+curl_ws_meta - meta data WebSocket information
+.SH SYNOPSIS
+.nf
+#include <curl/easy.h>
+
+struct curl_ws_frame {
+ int age; /* zero */
+ int flags; /* See the CURLWS_* defines */
+ curl_off_t offset; /* the offset of this data into the frame */
+ curl_off_t bytesleft; /* number of pending bytes left of the payload */
+};
+
+const struct curl_ws_frame *curl_ws_meta(CURL *curl);
+.fi
+.SH DESCRIPTION
+This function call is EXPERIMENTAL.
+
+When the write callback (\fICURLOPT_WRITEFUNCTION(3)\fP) is invoked on
+received WebSocket traffic, \fIcurl_ws_meta(3)\fP can be called from within
+the callback to provide additional information about the current frame.
+
+This function only works from within the callback, and only when receiving
+WebSocket data.
+
+This function requires an easy handle as input argument for libcurl to know
+what transfer the question is about, but as there is no such pointer provided
+to the callback by libcurl itself, applications that want to use
+\fIcurl_ws_meta(3)\fP need to pass it on to the callback on its own.
+
+.SH "struct fields"
+.IP age
+This field specify the age of this struct. It is always zero for now.
+.IP flags
+This is a bitmask with individual bits set that describes the WebSocket
+data. See the list below.
+.IP offset
+When this frame is a continuation of fragment data already delivered, this is
+the offset into the final fragment where this piece belongs.
+.IP bytesleft
+If this is not a complete fragment, the \fIbytesleft\fP field informs about
+how many additional bytes are expected to arrive before this fragment is
+complete.
+.SH FLAGS
+.IP CURLWS_TEXT
+The buffer contains text data. Note that this makes a difference to WebSocket
+but libcurl itself will not make any verification of the content or
+precautions that you actually receive valid UTF-8 content.
+.IP CURLWS_BINARY
+This is binary data.
+.IP CURLWS_CONT
+This is not the final fragment of the message, it implies that there will be
+another fragment coming as part of the same message.
+.IP CURLWS_CLOSE
+This transfer is now closed.
+.IP CURLWS_PING
+This as an incoming ping message, that expects a pong response.
+.SH EXAMPLE
+.nf
+
+/* we pass a pointer to this struct to the callback */
+struct customdata {
+ CURL *easy;
+ void *ptr;
+};
+
+static size_t writecb(unsigned char *buffer,
+ size_t size, size_t nitems, void *p)
+{
+ struct customdata *c = (struct customdata *)p;
+ const struct curl_ws_frame *m = curl_ws_meta(c->easy);
+
+ /* m->flags tells us about the traffic */
+}
+
+{
+ struct customdata custom;
+ custom.easy = easy;
+ custom.ptr = NULL;
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &custom);
+}
+.fi
+.SH AVAILABILITY
+Added in 7.86.0.
+.SH RETURN VALUE
+This function returns a pointer to a \fIcurl_ws_frame\fP struct with read-only
+information that is valid for this specific callback invocation. If it cannot
+return this information, or if the function is called in the wrong context, it
+returns NULL.
+.SH "SEE ALSO"
+.BR curl_easy_setopt "(3), " curl_easy_getinfo "(3), "
+.BR curl_ws_send "(3), " curl_ws_recv "(3), " libcurl-ws "(3), "
diff --git a/docs/libcurl/curl_ws_recv.3 b/docs/libcurl/curl_ws_recv.3
new file mode 100644
index 0000000..4fc683a
--- /dev/null
+++ b/docs/libcurl/curl_ws_recv.3
@@ -0,0 +1,69 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.\"
+.TH curl_ws_recv 3 "12 Jun 2022" "libcurl" "libcurl"
+.SH NAME
+curl_ws_recv - receive WebSocket data
+.SH SYNOPSIS
+.nf
+#include <curl/easy.h>
+
+CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
+ size_t *recv, const struct curl_ws_frame **meta);
+.fi
+.SH DESCRIPTION
+This function call is EXPERIMENTAL.
+
+Retrieves as much as possible of a received WebSocket data fragment into the
+\fBbuffer\fP, but not more than \fBbuflen\fP bytes. \fIrecv\fP is set to the
+number of bytes actually stored.
+
+If there is more fragment data to deliver than what fits in the provided
+\fIbuffer\fP, libcurl returns a full buffer and the application needs to call
+this function again to continue draining the buffer.
+
+The \fImeta\fP pointer gets set to point to a \fIconst struct curl_ws_frame\fP
+that contains information about the received data. See the
+\fIcurl_ws_meta(3)\fP for details on that struct.
+.SH EXAMPLE
+.nf
+ size_t rlen;
+ const struct curl_ws_frame *meta;
+ char buffer[256];
+ CURLcode result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
+.fi
+.SH AVAILABILITY
+Added in 7.86.0.
+.SH RETURN VALUE
+Returns \fBCURLE_OK\fP if everything is okay, and a non-zero number for
+errors. Returns \fBCURLE_GOT_NOTHING\fP if the associated connection is
+closed.
+
+Instead of blocking, the function returns \fBCURLE_AGAIN\fP. The correct
+behavior is then to wait for the socket to signal readability before calling
+this function again.
+.SH "SEE ALSO"
+.BR curl_easy_setopt "(3), " curl_easy_perform "(3), "
+.BR curl_easy_getinfo "(3), "
+.BR curl_ws_send "(3), " libcurl-ws "(3), "
diff --git a/docs/libcurl/curl_ws_send.3 b/docs/libcurl/curl_ws_send.3
new file mode 100644
index 0000000..3519d79
--- /dev/null
+++ b/docs/libcurl/curl_ws_send.3
@@ -0,0 +1,101 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.\"
+.TH curl_ws_send 3 "12 Jun 2022" "libcurl" "libcurl"
+.SH NAME
+curl_ws_send - send WebSocket data
+.SH SYNOPSIS
+.nf
+#include <curl/easy.h>
+
+CURLcode curl_ws_send(CURL *curl, const void *buffer, size_t buflen,
+ size_t *sent, curl_off_t fragsize,
+ unsigned int flags);
+.fi
+.SH DESCRIPTION
+This function call is EXPERIMENTAL.
+
+Send the specific message fragment over an established WebSocket
+connection. The \fIbuffer\fP holds the data to send and it is \fIbuflen\fP
+number of payload bytes in that memory area.
+
+\fIsent\fP is returned as the number of payload bytes actually sent.
+
+To send a (huge) fragment using multiple calls with partial content per
+invoke, set the \fICURLWS_OFFSET\fP bit and the \fIfragsize\fP argument as the
+total expected size for the first part, then set the \fICURLWS_OFFSET\fP with
+a zero \fIfragsize\fP for the following parts.
+
+If not sending a partial fragment or if this is raw mode, \fIfragsize\fP
+should be set to zero.
+
+If \fBCURLWS_RAW_MODE\fP is enabled in \fICURLOPT_WS_OPTIONS(3)\fP, the
+\fBflags\fP argument should be set to 0.
+
+To send a message consisting of multiple frames, set the \fICURLWS_CONT\fP bit
+in all frames except the final one.
+.SH FLAGS
+.IP CURLWS_TEXT
+The buffer contains text data. Note that this makes a difference to WebSocket
+but libcurl itself will not make any verification of the content or
+precautions that you actually send valid UTF-8 content.
+.IP CURLWS_BINARY
+This is binary data.
+.IP CURLWS_CONT
+This is not the final fragment of the message, which implies that there will
+be another fragment coming as part of the same message where this bit is not
+set.
+.IP CURLWS_CLOSE
+Close this transfer.
+.IP CURLWS_PING
+This is a ping.
+.IP CURLWS_PONG
+This is a pong.
+.IP CURLWS_OFFSET
+The provided data is only a partial fragment and there will be more in a
+following call to \fIcurl_ws_send()\fP. When sending only a piece of the
+fragment like this, the \fIfragsize\fP must be provided with the total
+expected fragment size in the first call and it needs to be zero in subsequent
+calls.
+.SH EXAMPLE
+.nf
+int ping(CURL *curl, const char *send_payload)
+{
+ size_t sent;
+ CURLcode result =
+ curl_ws_send(curl, send_payload, strlen(send_payload), &sent, 0,
+ CURLWS_PING);
+ return (int)result;
+}
+.fi
+.SH AVAILABILITY
+Added in 7.86.0.
+.SH RETURN VALUE
+\fICURLE_OK\fP (zero) means that the data was sent properly, non-zero means an
+error occurred as \fI<curl/curl.h>\fP defines. See the \fIlibcurl-errors(3)\fP
+man page for the full list with descriptions.
+.SH "SEE ALSO"
+.BR curl_easy_setopt "(3), " curl_easy_perform "(3), "
+.BR curl_easy_getinfo "(3), "
+.BR curl_ws_recv "(3), " libcurl-ws "(3), "
diff --git a/docs/libcurl/libcurl-easy.3 b/docs/libcurl/libcurl-easy.3
index 79eb6d9..fe4fbc7 100644
--- a/docs/libcurl/libcurl-easy.3
+++ b/docs/libcurl/libcurl-easy.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH libcurl 3 "19 Sep 2014" "libcurl" "libcurl easy interface"
+.TH libcurl 3 "19 Sep 2014" "libcurl" "libcurl"
.SH NAME
libcurl-easy \- easy interface overview
.SH DESCRIPTION
diff --git a/docs/libcurl/libcurl-env.3 b/docs/libcurl/libcurl-env.3
index 6cae1c7..2e00459 100644
--- a/docs/libcurl/libcurl-env.3
+++ b/docs/libcurl/libcurl-env.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH libcurl-env 3 "20 January 2018" "libcurl 7.58.0" "libcurl environment variables"
+.TH libcurl-env 3 "20 January 2018" "libcurl" "libcurl"
.SH NAME
libcurl-env \- environment variables libcurl understands
.SH DESCRIPTION
@@ -50,8 +50,8 @@
libcurl, this variable's selection will be used. Setting a name that is not a
built-in alternative will make libcurl stay with the default.
-SSL backend names (case-insensitive): bearssl, gnutls, gskit, mbedtls,
-nss, openssl, rustls, schannel, secure-transport, wolfssl
+SSL backend names (case-insensitive): BearSSL, GnuTLS, gskit, mbedTLS,
+nss, OpenSSL, rustls, Schannel, Secure-Transport, wolfSSL
.IP HOME
When the netrc feature is used (\fICURLOPT_NETRC(3)\fP), this variable is
checked as the primary way to find the "current" home directory in which
@@ -61,13 +61,14 @@
checked as the secondary way to find the "current" home directory (on Windows
only) in which the .netrc file is likely to exist.
.IP LOGNAME
-User name to use when invoking the ntlm-wb tool, if NTLMUSER was not set.
+User name to use when invoking the \fIntlm-wb\fP tool, if \fINTLMUSER\fP was
+not set.
.IP NO_PROXY
This has the same functionality as the \fICURLOPT_NOPROXY(3)\fP option: it
gives libcurl a comma-separated list of host name patterns for which libcurl
should not use a proxy.
.IP NTLMUSER
-User name to use when invoking the ntlm-wb tool.
+User name to use when invoking the \fIntlm-wb\fP tool.
.IP SSLKEYLOGFILE
When set and libcurl runs with a SSL backend that supports this feature,
libcurl will save SSL secrets into the given file name. Using those SSL
@@ -77,8 +78,8 @@
When libcurl runs with the NSS backends for TLS features, this variable is
used to find the directory for NSS PKI database instead of the built-in.
.IP USER
-User name to use when invoking the ntlm-wb tool, if NTLMUSER and LOGNAME
-were not set.
+User name to use when invoking the \fIntlm-wb\fP tool, if \fINTLMUSER\fP and
+\fILOGNAME\fP were not set.
.SH "Debug Variables"
There's a set of variables only recognized and used if libcurl was built
"debug enabled", which should never be true for a library used in production.
@@ -93,6 +94,7 @@
.IP "CURL_TRACE"
Debug-only variable. Used for debugging the lib/ldap implementation.
.IP "CURL_NTLM_WB_FILE"
-Debug-only variable. Used to set to a debug-version of the ntlm-wb executable.
+Debug-only variable. Used to set to a debug-version of the \fIntlm-wb\fP
+executable.
.IP "CURL_OPENLDAP_TRACE"
-Debug-only variable. Used for debugging the lib/openldap.c implementation.
+Debug-only variable. Used for debugging the OpenLDAP implementation.
diff --git a/docs/libcurl/libcurl-errors.3 b/docs/libcurl/libcurl-errors.3
index c5a8663..41743b9 100644
--- a/docs/libcurl/libcurl-errors.3
+++ b/docs/libcurl/libcurl-errors.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH libcurl-errors 3 "23 Nov 2021" "libcurl 7.81.0" "libcurl errors"
+.TH libcurl-errors 3 "23 Nov 2021" "libcurl" "libcurl"
.SH NAME
libcurl-errors \- error codes in libcurl
.SH DESCRIPTION
@@ -56,13 +56,13 @@
enabled or explicitly disabled when libcurl was built and in order to get it
to function you have to get a rebuilt libcurl.
.IP "CURLE_COULDNT_RESOLVE_PROXY (5)"
-Couldn't resolve proxy. The given proxy host could not be resolved.
+Could not resolve proxy. The given proxy host could not be resolved.
.IP "CURLE_COULDNT_RESOLVE_HOST (6)"
-Couldn't resolve host. The given remote host was not resolved.
+Could not resolve host. The given remote host was not resolved.
.IP "CURLE_COULDNT_CONNECT (7)"
Failed to connect() to host or proxy.
.IP "CURLE_WEIRD_SERVER_REPLY (8)"
-The server sent data libcurl could not parse. This error code was known as as
+The server sent data libcurl could not parse. This error code was known as
\fICURLE_FTP_WEIRD_SERVER_REPLY\fP before 7.51.0.
.IP "CURLE_REMOTE_ACCESS_DENIED (9)"
We were denied access to the resource given in the URL. For FTP, this occurs
@@ -96,6 +96,8 @@
.IP "CURLE_FTP_COULDNT_RETR_FILE (19)"
This was either a weird reply to a 'RETR' command or a zero byte transfer
complete.
+.IP "Obsolete error (20)"
+Not used in modern versions.
.IP "CURLE_QUOTE_ERROR (21)"
When sending custom "QUOTE" commands to the remote server, one of the commands
returned an error code that was 400 or higher (for FTP) or otherwise
@@ -106,6 +108,8 @@
.IP "CURLE_WRITE_ERROR (23)"
An error occurred when writing received data to a local file, or an error was
returned to libcurl from a write callback.
+.IP "Obsolete error (24)"
+Not used in modern versions.
.IP "CURLE_UPLOAD_FAILED (25)"
Failed starting the upload. For FTP, the server typically denied the STOR
command. The error buffer usually contains the server's explanation for this.
@@ -118,6 +122,8 @@
.IP "CURLE_OPERATION_TIMEDOUT (28)"
Operation timeout. The specified time-out period was reached according to the
conditions.
+.IP "Obsolete error (29)"
+Not used in modern versions.
.IP "CURLE_FTP_PORT_FAILED (30)"
The FTP PORT command returned error. This mostly happens when you have not
specified a good enough address for libcurl to use. See
@@ -125,6 +131,8 @@
.IP "CURLE_FTP_COULDNT_USE_REST (31)"
The FTP REST command returned error. This should never happen if the server is
sane.
+.IP "Obsolete error (32)"
+Not used in modern versions.
.IP "CURLE_RANGE_ERROR (33)"
The server does not support or accept range requests.
.IP "CURLE_HTTP_POST_ERROR (34)"
@@ -144,16 +152,22 @@
LDAP cannot bind. LDAP bind operation failed.
.IP "CURLE_LDAP_SEARCH_FAILED (39)"
LDAP search failed.
+.IP "Obsolete error (40)"
+Not used in modern versions.
.IP "CURLE_FUNCTION_NOT_FOUND (41)"
Function not found. A required zlib function was not found.
.IP "CURLE_ABORTED_BY_CALLBACK (42)"
Aborted by callback. A callback returned "abort" to libcurl.
.IP "CURLE_BAD_FUNCTION_ARGUMENT (43)"
A function was called with a bad parameter.
+.IP "Obsolete error (44)"
+Not used in modern versions.
.IP "CURLE_INTERFACE_FAILED (45)"
Interface error. A specified outgoing interface could not be used. Set which
interface to use for outgoing connections' source IP address with
\fICURLOPT_INTERFACE(3)\fP.
+.IP "Obsolete error (46)"
+Not used in modern versions.
.IP "CURLE_TOO_MANY_REDIRECTS (47)"
Too many redirects. When following redirects, libcurl hit the maximum amount.
Set your limit with \fICURLOPT_MAXREDIRS(3)\fP.
@@ -165,6 +179,8 @@
.IP "CURLE_SETOPT_OPTION_SYNTAX (49)"
An option passed in to a setopt was wrongly formatted. See error message for
details about what option.
+.IP "Obsolete errors (50-51)"
+Not used in modern versions.
.IP "CURLE_GOT_NOTHING (52)"
Nothing was returned from the server, and under the circumstances, getting
nothing is considered an error.
@@ -176,18 +192,20 @@
Failed sending network data.
.IP "CURLE_RECV_ERROR (56)"
Failure with receiving network data.
+.IP "Obsolete error (57)"
+Not used in modern versions.
.IP "CURLE_SSL_CERTPROBLEM (58)"
problem with the local client certificate.
.IP "CURLE_SSL_CIPHER (59)"
-Couldn't use specified cipher.
+Could not use specified cipher.
.IP "CURLE_PEER_FAILED_VERIFICATION (60)"
-The remote server's SSL certificate or SSH md5 fingerprint was deemed not OK.
+The remote server's SSL certificate or SSH fingerprint was deemed not OK.
This error code has been unified with CURLE_SSL_CACERT since 7.62.0. Its
previous value was 51.
.IP "CURLE_BAD_CONTENT_ENCODING (61)"
Unrecognized transfer encoding.
-.IP "CURLE_LDAP_INVALID_URL (62)"
-This error code is deprecated since 7.82.0 and cannot be returned anymore.
+.IP "Obsolete error (62)"
+Not used in modern versions.
.IP "CURLE_FILESIZE_EXCEEDED (63)"
Maximum file size exceeded.
.IP "CURLE_USE_SSL_FAILED (64)"
@@ -213,10 +231,8 @@
File already exists and will not be overwritten.
.IP "CURLE_TFTP_NOSUCHUSER (74)"
This error should never be returned by a properly functioning TFTP server.
-.IP "CURLE_CONV_FAILED (75)"
-Character conversion failed.
-.IP "CURLE_CONV_REQD (76)"
-Caller must register conversion callbacks.
+.IP "Obsolete error (75-76)"
+Not used in modern versions.
.IP "CURLE_SSL_CACERT_BADFILE (77)"
Problem with reading the SSL CA cert (path? access rights?)
.IP "CURLE_REMOTE_FILE_NOT_FOUND (78)"
@@ -236,8 +252,8 @@
.IP "CURLE_FTP_PRET_FAILED (84)"
The FTP server does not understand the PRET command at all or does not support
the given argument. Be careful when using \fICURLOPT_CUSTOMREQUEST(3)\fP, a
-custom LIST command will be sent with PRET CMD before PASV as well. (Added in
-7.20.0)
+custom LIST command will be sent with the PRET command before PASV as
+well. (Added in 7.20.0)
.IP "CURLE_RTSP_CSEQ_ERROR (85)"
Mismatch of RTSP CSeq numbers.
.IP "CURLE_RTSP_SESSION_ERROR (86)"
@@ -265,6 +281,9 @@
.IP "CURLE_QUIC_CONNECT_ERROR (96)"
QUIC connection error. This error may be caused by an SSL library error. QUIC
is the protocol used for HTTP/3 transfers.
+.IP "CURLE_PROXY (97)"
+Proxy handshake error. \fICURLINFO_PROXY_ERROR(3)\fP provides extra details on
+the specific problem.
.IP "CURLE_SSL_CLIENTCERT (98)"
SSL Client Certificate required.
.IP "CURLE_UNRECOVERABLE_POLL (99)"
@@ -282,12 +301,12 @@
\fIcurl_multi_perform(3)\fP, but in later versions this return code is never
used.
.IP "CURLM_CALL_MULTI_SOCKET (-1)"
-An alias for CURLM_CALL_MULTI_PERFORM. Never returned by modern libcurl
+An alias for \fICURLM_CALL_MULTI_PERFORM\fP. Never returned by modern libcurl
versions.
.IP "CURLM_OK (0)"
Things are fine.
.IP "CURLM_BAD_HANDLE (1)"
-The passed-in handle is not a valid CURLM handle.
+The passed-in handle is not a valid \fICURLM\fP handle.
.IP "CURLM_BAD_EASY_HANDLE (2)"
An easy handle was not good/valid. It could mean that it is not an easy handle
at all, or possibly that the handle already is in use by this or another multi
@@ -308,7 +327,7 @@
.IP "CURLM_RECURSIVE_API_CALL (8)"
An API function was called from inside a callback.
.IP "CURLM_WAKEUP_FAILURE (9)"
-Wakeup is unavailable or failed.
+Wake up is unavailable or failed.
.IP "CURLM_BAD_FUNCTION_ARGUMENT (10)"
A function was called with a bad parameter.
.IP "CURLM_ABORTED_BY_CALLBACK (11)"
@@ -316,8 +335,8 @@
.IP "CURLM_UNRECOVERABLE_POLL (12)"
An internal call to poll() or select() returned error that is not recoverable.
.SH "CURLSHcode"
-The "share" interface will return a CURLSHcode to indicate when an error has
-occurred. Also consider \fIcurl_share_strerror(3)\fP.
+The "share" interface will return a \fBCURLSHcode\fP to indicate when an error
+has occurred. Also consider \fIcurl_share_strerror(3)\fP.
.IP "CURLSHE_OK (0)"
All fine. Proceed as usual.
.IP "CURLSHE_BAD_OPTION (1)"
@@ -333,10 +352,12 @@
The requested sharing could not be done because the library you use do not have
that particular feature enabled. (Added in 7.23.0)
.SH "CURLUcode"
-The URL interface will return a CURLUcode to indicate when an error has
+The URL interface will return a \fICURLUcode\fP to indicate when an error has
occurred. Also consider \fIcurl_url_strerror(3)\fP.
+.IP "CURLUE_OK (0)"
+All fine. Proceed as usual.
.IP "CURLUE_BAD_HANDLE (1)"
-An invalid CURLU pointer was passed as argument.
+An invalid URL handle was passed as argument.
.IP "CURLUE_BAD_PARTPOINTER (2)"
An invalid 'part' argument was passed as argument.
.IP "CURLUE_MALFORMED_INPUT (3)"
@@ -370,7 +391,7 @@
.IP "CURLUE_NO_FRAGMENT (17)"
There is no fragment part in the URL.
.IP "CURLUE_NO_ZONEID (18)"
-There is no zoneid set in the URL.
+There is no zone id set in the URL.
.IP "CURLUE_BAD_FILE_URL (19)"
The file:// URL is invalid.
.IP "CURLUE_BAD_FRAGMENT (20)"
@@ -393,6 +414,23 @@
The URL contained an invalid number of slashes.
.IP "CURLUE_BAD_USER (29)"
The user part of the URL contained bad or invalid characters.
+.SH "CURLHcode"
+The header interface returns a \fICURLHcode\fP to indicate when an error has
+occurred.
+.IP "CURLHE_BADINDEX (1)"
+There is no header with the requested index.
+.IP "CURLHE_MISSING (2)"
+No such header exists.
+.IP "CURLHE_NOHEADERS (3)"
+No headers at all have been recorded.
+.IP "CURLHE_NOREQUEST (4)"
+There was no such request number.
+.IP "CURLHE_OUT_OF_MEMORY (5)"
+Out of resources
+.IP "CURLHE_BAD_ARGUMENT (6)"
+One or more of the given arguments are bad.
+.IP "CURLHE_NOT_BUILT_IN (7)"
+HTTP support or the header API has been disabled in the build.
.SH "SEE ALSO"
.BR curl_easy_strerror "(3), " curl_multi_strerror "(3), "
.BR curl_share_strerror "(3), " curl_url_strerror "(3), "
diff --git a/docs/libcurl/libcurl-multi.3 b/docs/libcurl/libcurl-multi.3
index 61fa9c6..fb1fe4a 100644
--- a/docs/libcurl/libcurl-multi.3
+++ b/docs/libcurl/libcurl-multi.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH libcurl-multi 3 "19 Sep 2014" "libcurl" "libcurl multi interface"
+.TH libcurl-multi 3 "19 Sep 2014" "libcurl" "libcurl"
.SH NAME
libcurl-multi \- how to use the multi interface
.SH DESCRIPTION
@@ -58,7 +58,7 @@
handle. You create all the easy handles you need, and setup the appropriate
options for each easy handle using \fIcurl_easy_setopt(3)\fP.
-There are two flavours of the multi interface, the select() oriented one and
+There are two flavors of the multi interface, the select() oriented one and
the event based one we call multi_socket. You will benefit from reading
through the description of both versions to fully understand how they work and
differentiate. We start out with the select() oriented version.
@@ -89,7 +89,7 @@
invoked to transfer data or do other work. The most convenient way is to use
\fIcurl_multi_poll(3)\fP that will help you wait until the application should
call libcurl again. The older API to accomplish the same thing is
-\fIcurl_multi_fdset(3)\fP that extracts fd_sets from libcurl to use in
+\fIcurl_multi_fdset(3)\fP that extracts \fIfd_sets\fP from libcurl to use in
select() or poll() calls in order to get to know when the transfers in the
multi stack might need attention. Both these APIs allow for your program to
wait for input on your own private file descriptors at the same time.
@@ -160,10 +160,11 @@
losing performance.
When you have added your initial set of handles, you call
-\fIcurl_multi_socket_action(3)\fP with CURL_SOCKET_TIMEOUT set in the sockfd
-argument, and you will get callbacks call that sets you up and you then continue
-to call \fIcurl_multi_socket_action(3)\fP accordingly when you get activity on
-the sockets you have been asked to wait on, or if the timeout timer expires.
+\fIcurl_multi_socket_action(3)\fP with CURL_SOCKET_TIMEOUT set in the
+\fIsockfd\fP argument, and you will get callbacks call that sets you up and
+you then continue to call \fIcurl_multi_socket_action(3)\fP accordingly when
+you get activity on the sockets you have been asked to wait on, or if the
+timeout timer expires.
You can poll \fIcurl_multi_info_read(3)\fP to see if any transfer has
completed, as it then has a message saying so.
diff --git a/docs/libcurl/libcurl-security.3 b/docs/libcurl/libcurl-security.3
index 7e54031..8d20a3d 100644
--- a/docs/libcurl/libcurl-security.3
+++ b/docs/libcurl/libcurl-security.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH libcurl-security 3 "13 Feb 2018" "libcurl" "libcurl security"
+.TH libcurl-security 3 "13 Feb 2018" "libcurl" "libcurl"
.SH NAME
libcurl-security \- security considerations when using libcurl
.SH "Security"
@@ -45,7 +45,7 @@
.SH "Command Lines"
If you use a command line tool (such as curl) that uses libcurl, and you give
options to the tool on the command line those options can get read by other
-users of your system when they use 'ps' or other tools to list currently
+users of your system when they use \fIps\fP or other tools to list currently
running processes.
To avoid these problems, never feed sensitive things to programs using command
@@ -76,23 +76,22 @@
does not let snoopers see your password: Digest, CRAM-MD5, Kerberos, SPNEGO or
NTLM authentication. Or even better: use authenticated protocols that protect
the entire connection and everything sent over it.
-.SH "Un-authenticated Connections"
+.SH "Unauthenticated Connections"
Protocols that do not have any form of cryptographic authentication cannot
with any certainty know that they communicate with the right remote server.
If your application is using a fixed scheme or fixed host name, it is not safe
-as long as the connection is un-authenticated. There can be a
-man-in-the-middle or in fact the whole server might have been replaced by an
-evil actor.
+as long as the connection is unauthenticated. There can be a man-in-the-middle
+or in fact the whole server might have been replaced by an evil actor.
-Un-authenticated protocols are unsafe. The data that comes back to curl may
+Unauthenticated protocols are unsafe. The data that comes back to curl may
have been injected by an attacker. The data that curl sends might be modified
before it reaches the intended server. If it even reaches the intended server
at all.
Remedies:
.IP "Restrict operations to authenticated transfers"
-Ie use authenticated protocols protected with HTTPS or SSH.
+Use authenticated protocols protected with HTTPS or SSH.
.IP "Make sure the server's certificate etc is verified"
Never ever switch off certificate verification.
.SH "Redirects"
@@ -106,7 +105,7 @@
files from the local filesystem. If the application returns the data back to
the user (as would happen in some kinds of CGI scripts), an attacker could
leverage this to read otherwise forbidden data (e.g.
-file://localhost/etc/passwd).
+\fBfile://localhost/etc/passwd\fP).
If authentication credentials are stored in the ~/.netrc file, or Kerberos is
in use, any other URL type (not just file:) that requires authentication is
@@ -116,7 +115,7 @@
In the same way, if an unencrypted SSH private key has been configured for the
user running the libcurl application, SCP: or SFTP: URLs could access password
or private-key protected resources,
-e.g. sftp://user@some-internal-server/etc/passwd
+e.g. \fBsftp://user@some-internal-server/etc/passwd\fP
The \fICURLOPT_REDIR_PROTOCOLS(3)\fP and \fICURLOPT_NETRC(3)\fP options can be
used to mitigate against this kind of attack.
@@ -137,26 +136,26 @@
\fICURLOPT_HTTPHEADER(3)\fP, \fICURLOPT_PROXYHEADER(3)\fP,
\fICURLOPT_COOKIE(3)\fP, \fICURLOPT_USERAGENT(3)\fP, \fICURLOPT_REFERER(3)\fP
and \fICURLOPT_RANGE(3)\fP, libcurl will send the headers as-is and will not
-apply any special sanitization or normalization to them.
+apply any special sanitation or normalization to them.
If you allow untrusted user input into these options without sanitizing CRLF
-sequences in them, someone malicious may be able to modify the request in a way
-you didn't intend such as injecting new headers.
+sequences in them, someone malicious may be able to modify the request in a
+way you did not intend such as injecting new headers.
.SH "Local Resources"
A user who can control the DNS server of a domain being passed in within a URL
can change the address of the host to a local, private address which a
server-side libcurl-using application could then use. e.g. the innocuous URL
-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 \fICURLOPT_OPENSOCKETFUNCTION(3)\fP
-or \fICURLOPT_PREREQFUNCTION(3)\fP and checking the address before a
-connection.
+\fBhttp://fuzzybunnies.example.com/\fP could actually resolve to the IP
+address of a server behind a firewall, such as 127.0.0.1 or
+10.1.2.3. Applications can mitigate against this by setting a
+\fICURLOPT_OPENSOCKETFUNCTION(3)\fP or \fICURLOPT_PREREQFUNCTION(3)\fP and
+checking the address before a connection.
All the malicious scenarios regarding redirected URLs apply just as well to
non-redirected URLs, if the user is allowed to specify an arbitrary URL that
could point to a private resource. For example, a web app providing a
-translation service might happily translate file://localhost/etc/passwd and
-display the result. Applications can mitigate against this with the
+translation service might happily translate \fBfile://localhost/etc/passwd\fP
+and display the result. Applications can mitigate against this with the
\fICURLOPT_PROTOCOLS(3)\fP option as well as by similar mitigation techniques
for redirections.
@@ -183,16 +182,16 @@
.SH "IPv6 Addresses"
libcurl will normally handle IPv6 addresses transparently and just as easily
as IPv4 addresses. That means that a sanitizing function that filters out
-addresses like 127.0.0.1 is not sufficient--the equivalent IPv6 addresses ::1,
-::, 0:00::0:1, ::127.0.0.1 and ::ffff:7f00:1 supplied somehow by an attacker
-would all bypass a naive filter and could allow access to undesired local
-resources. IPv6 also has special address blocks like link-local and site-local
-that generally should not be accessed by a server-side libcurl-using
-application. A poorly configured firewall installed in a data center,
-organization or server may also be configured to limit IPv4 connections but
-leave IPv6 connections wide open. In some cases, setting
-\fICURLOPT_IPRESOLVE(3)\fP to CURL_IPRESOLVE_V4 can be used to limit resolved
-addresses to IPv4 only and bypass these issues.
+addresses like 127.0.0.1 is not sufficient--the equivalent IPv6 addresses
+\fB::1\fP, \fB::\fP, \fB0:00::0:1\fP, \fB::127.0.0.1\fP and
+\fB::ffff:7f00:1\fP supplied somehow by an attacker would all bypass a naive
+filter and could allow access to undesired local resources. IPv6 also has
+special address blocks like link-local and site-local that generally should
+not be accessed by a server-side libcurl-using application. A poorly
+configured firewall installed in a data center, organization or server may
+also be configured to limit IPv4 connections but leave IPv6 connections wide
+open. In some cases, setting \fICURLOPT_IPRESOLVE(3)\fP to CURL_IPRESOLVE_V4
+can be used to limit resolved addresses to IPv4 only and bypass these issues.
.SH Uploads
When uploading, a redirect can cause a local (or remote) file to be
overwritten. Applications must not allow any unsanitized URL to be passed in
@@ -223,9 +222,9 @@
.SH "Dangerous SCP URLs"
SCP URLs can contain raw commands within the scp: URL, which is a side effect
of how the SCP protocol is designed. e.g.
-
+.nf
scp://user:pass@host/a;date >/tmp/test;
-
+.fi
Applications must not allow unsanitized SCP: URLs to be passed in for
downloads.
.SH "file://"
@@ -305,13 +304,13 @@
When performing an FTP transfer, two TCP connections are used: one for setting
up the transfer and one for the actual data.
-FTP is not only un-authenticated, but the setting up of the second transfer is
+FTP is not only unauthenticated, but the setting up of the second transfer is
also a weak spot. The second connection to use for data, is either setup with
the PORT/EPRT command that makes the server connect back to the client on the
given IP+PORT, or with PASV/EPSV that makes the server setup a port to listen
to and tells the client to connect to a given IP+PORT.
-Again, un-authenticated means that the connection might be meddled with by a
+Again, unauthenticated means that the connection might be meddled with by a
man-in-the-middle or that there's a malicious server pretending to be the
right one.
@@ -360,7 +359,8 @@
a file name. An application could also use \fICURLINFO_EFFECTIVE_URL(3)\fP to
generate a file name from a server-supplied redirect URL. Special care must be
taken to sanitize such names to avoid the possibility of a malicious server
-supplying one like "/etc/passwd", "\\autoexec.bat", "prn:" or even ".bashrc".
+supplying one like \fB"/etc/passwd"\fP, \fB"\\autoexec.bat"\fP, \fB"prn:"\fP
+or even \fB".bashrc"\fP.
.SH "Server Certificates"
A secure application should never use the \fICURLOPT_SSL_VERIFYPEER(3)\fP
option to disable certificate validation. There are numerous attacks that are
@@ -384,7 +384,7 @@
To avoid this problem, you must of course use your common sense. Often, you
can just edit out the sensitive data or just search/replace your true
information with faked data.
-.SH "Setuid applications using libcurl"
+.SH "setuid applications using libcurl"
libcurl-using applications that set the 'setuid' bit to run with elevated or
modified rights also implicitly give that extra power to libcurl and this
should only be done after careful considerations.
@@ -396,16 +396,16 @@
etc), it should be noted that libcurl still might understand proxy environment
variables that allow the user to redirect libcurl operations to use a proxy
controlled by the user.
-.SH "File descriptors, fork and ntlm_wb"
-An application that uses libcurl and invokes `fork()` will get all file
+.SH "File descriptors, fork and NTLM"
+An application that uses libcurl and invokes \fIfork()\fP will get all file
descriptors duplicated in the child process, including the ones libcurl
created.
-libcurl itself uses `fork()` and `execl()` if told to use the
-`CURLAUTH_NTLM_WB` authentication method which then will invoke the helper
+libcurl itself uses \fIfork()\fP and \fIexecl()\fP if told to use the
+\fBCURLAUTH_NTLM_WB\fP authentication method which then will invoke the helper
command in a child process with file descriptors duplicated. Make sure that
only the trusted and reliable helper program is invoked!
-.SH_"Secrets in memory"
+.SH "Secrets in memory"
When applications pass user names, passwords or other sensitive data to
libcurl to be used for upcoming transfers, those secrets will be kept around
as-is in memory. In many cases they will be stored in heap for as long as the
@@ -416,7 +416,7 @@
Further, when eventually closing a handle and the secrets are no longer
needed, libcurl does not explicitly clear memory before freeing it, so
-crendentials may be left in freed data.
+credentials may be left in freed data.
.SH "Report Security Problems"
Should you detect or just suspect a security problem in libcurl or curl,
contact the project curl security team immediately. See
diff --git a/docs/libcurl/libcurl-share.3 b/docs/libcurl/libcurl-share.3
index 88a3c52..26b95d9 100644
--- a/docs/libcurl/libcurl-share.3
+++ b/docs/libcurl/libcurl-share.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH libcurl-share 3 "8 Aug 2003" "libcurl 7.10.7" "libcurl share interface"
+.TH libcurl-share 3 "8 Aug 2003" "libcurl" "libcurl"
.SH NAME
libcurl-share \- how to use the share interface
.SH DESCRIPTION
diff --git a/docs/libcurl/libcurl-thread.3 b/docs/libcurl/libcurl-thread.3
index 1b00b90..8612de6 100644
--- a/docs/libcurl/libcurl-thread.3
+++ b/docs/libcurl/libcurl-thread.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2015 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH libcurl-thread 3 "13 Jul 2015" "libcurl" "libcurl thread safety"
+.TH libcurl-thread 3 "13 Jul 2015" "libcurl" "libcurl"
.SH NAME
libcurl-thread \- libcurl thread safety
.SH "Multi-threading with libcurl"
@@ -30,13 +30,17 @@
to provide your own locking should you meet any of the thread safety exceptions
below.
-\fBHandles.\fP You must \fBnever\fP share the same handle in multiple threads.
-You can pass the handles around among threads, but you must never use a single
-handle from more than one thread at any given time.
-
-\fBShared objects.\fP You can share certain data between multiple handles by
-using the share interface but you must provide your own locking and set
+.SH "Handles"
+You must \fBnever\fP share the same handle in multiple threads. You can pass
+the handles around among threads, but you must never use a single handle from
+more than one thread at any given time.
+.SH "Shared objects"
+You can share certain data between multiple handles by using the share
+interface but you must provide your own locking and set
\fIcurl_share_setopt(3)\fP CURLSHOPT_LOCKFUNC and CURLSHOPT_UNLOCKFUNC.
+
+Note that some items are specifically documented as not thread-safe in the
+share API (the connection pool and HSTS cache for example).
.SH TLS
If you are accessing HTTPS or FTPS URLs in a multi-threaded manner, you are
then of course using the underlying SSL library multi-threaded and those libs
@@ -67,8 +71,9 @@
The engine is used by libcurl in a way that is fully thread-safe.
.IP BoringSSL
The engine is used by libcurl in a way that is fully thread-safe.
-.SH "Other areas of caution"
-.IP Signals
+.IP AWS-LC
+The engine is used by libcurl in a way that is fully thread-safe.
+.SH "Signals"
Signals are used for timing out name resolves (during DNS lookup) - when built
without using either the c-ares or threaded resolver backends. When using
multiple threads you should set the \fICURLOPT_NOSIGNAL(3)\fP option to 1L for
@@ -84,19 +89,20 @@
trigger). Note that setting \fICURLOPT_NOSIGNAL(3)\fP to 0L will not work in a
threaded situation as there will be race where libcurl risks restoring the
former signal handler while another thread should still ignore it.
-.IP "Name resolving"
-\fBgethostby* functions and other system calls.\fP These functions, provided
-by your operating system, must be thread safe. It is important that libcurl
-can find and use thread safe versions of these and other system calls, as
-otherwise it cannot function fully thread safe. Some operating systems are
-known to have faulty thread implementations. We have previously received
-problem reports on *BSD (at least in the past, they may be working fine these
-days). Some operating systems that are known to have solid and working thread
-support are Linux, Solaris and Windows.
-.IP "curl_global_* functions"
+.SH "Name resolving"
+The \fBgethostbyname\fP or \fBgetaddrinfo\fP and other name resolving system
+calls used by libcurl are provided by your operating system and must be thread
+safe. It is important that libcurl can find and use thread safe versions of
+these and other system calls, as otherwise it cannot function fully thread
+safe. Some operating systems are known to have faulty thread
+implementations. We have previously received problem reports on *BSD (at least
+in the past, they may be working fine these days). Some operating systems that
+are known to have solid and working thread support are Linux, Solaris and
+Windows.
+.SH "curl_global_* functions"
These functions are thread-safe since libcurl 7.84.0 if
-\fIcurl_version_info(3)\fP has the CURL_VERSION_THREADSAFE feature bit set
-(most platforms).
+\fIcurl_version_info(3)\fP has the \fBCURL_VERSION_THREADSAFE\fP feature bit
+set (most platforms).
If these functions are not thread-safe and you are using libcurl with multiple
threads it is especially important that before use you call
@@ -105,9 +111,11 @@
fail-safe initialization that takes place the first time
\fIcurl_easy_init(3)\fP is called. For an in-depth explanation refer to
\fIlibcurl(3)\fP section \fBGLOBAL CONSTANTS\fP.
-.IP "Memory functions"
+.SH "Memory functions"
These functions, provided either by your operating system or your own
replacements, must be thread safe. You can use \fIcurl_global_init_mem(3)\fP
to set your own replacement memory functions.
-.IP "Non-safe functions"
+.SH "Non-safe functions"
\fICURLOPT_DNS_USE_GLOBAL_CACHE(3)\fP is not thread-safe.
+
+\fIcurl_version_info(3)\fP is not thread-safe before libcurl initialization.
diff --git a/docs/libcurl/libcurl-tutorial.3 b/docs/libcurl/libcurl-tutorial.3
index 73b8cab..88c64b6 100644
--- a/docs/libcurl/libcurl-tutorial.3
+++ b/docs/libcurl/libcurl-tutorial.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH libcurl-tutorial 3 "19 Sep 2014" "libcurl" "libcurl programming"
+.TH libcurl-tutorial 3 "19 Sep 2014" "libcurl" "libcurl"
.SH NAME
libcurl-tutorial \- libcurl programming tutorial
.SH "Objective"
@@ -49,9 +49,9 @@
Your compiler needs to know where the libcurl headers are located. Therefore
you must set your compiler's include path to point to the directory where you
installed them. The 'curl-config'[3] tool can be used to get this information:
-
-$ curl-config --cflags
-
+.nf
+ $ curl-config --cflags
+.fi
.IP "Linking the Program with libcurl"
When having compiled the program, you need to link your object files to create
a single executable. For that to succeed, you need to link with libcurl and
@@ -59,9 +59,9 @@
OpenSSL libraries, but even some standard OS libraries may be needed on the
command line. To figure out which flags to use, once again the 'curl-config'
tool comes to the rescue:
-
-$ curl-config --libs
-
+.nf
+ $ curl-config --libs
+.fi
.IP "SSL or Not"
libcurl can be built and customized in many ways. One of the things that
varies from different libraries and builds is the support for SSL-based
@@ -69,10 +69,10 @@
properly at build-time, libcurl will be built with SSL support. To figure out
if an installed libcurl has been built with SSL support enabled, use
\&'curl-config' like this:
-
-$ curl-config --feature
-
-And if SSL is supported, the keyword 'SSL' will be written to stdout,
+.nf
+ $ curl-config --feature
+.fi
+And if SSL is supported, the keyword \fISSL\fP will be written to stdout,
possibly together with a few other features that could be either on or off on
for different libcurls.
@@ -95,9 +95,9 @@
The program must initialize some of the libcurl functionality globally. That
means it should be done exactly once, no matter how many times you intend to
use the library. Once for your program's entire life time. This is done using
-
+.nf
curl_global_init()
-
+.fi
and it takes one parameter which is a bit pattern that tells libcurl what to
initialize. Using \fICURL_GLOBAL_ALL\fP will make it initialize all known
internal sub modules, and might be a good default option. The current two bits
@@ -155,9 +155,9 @@
must never share the same handle in multiple threads.
Get an easy handle with
-
- easyhandle = curl_easy_init();
-
+.nf
+ handle = curl_easy_init();
+.fi
It returns an easy handle. Using that you proceed to the next step: setting
up your preferred actions. A handle is just a logic entity for the upcoming
transfer or series of transfers.
@@ -190,19 +190,19 @@
that needs this transfer, I assume that you would like to get the data passed
to you directly instead of simply getting it passed to stdout. So, you write
your own function that matches this prototype:
-
+.nf
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
-
+.fi
You tell libcurl to pass all data to this function by issuing a function
similar to this:
-
- curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, write_data);
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data);
+.fi
You can control what data your callback function gets in the fourth argument
by setting another property:
-
- curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, &internal_struct);
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, &internal_struct);
+.fi
Using that property, you can easily pass local data between your application
and the function that gets invoked by libcurl. libcurl itself will not touch the
data you pass with \fICURLOPT_WRITEDATA(3)\fP.
@@ -229,9 +229,9 @@
There are of course many more options you can set, and we will get back to a few
of them later. Let's instead continue to the actual transfer:
-
- success = curl_easy_perform(easyhandle);
-
+.nf
+ success = curl_easy_perform(handle);
+.fi
\fIcurl_easy_perform(3)\fP will connect to the remote site, do the necessary
commands and receive the transfer. Whenever it receives data, it calls the
callback function we previously set. The function may get one byte at a time,
@@ -301,30 +301,30 @@
data by asking us for it. To make it do that, we set the read callback and
the custom pointer libcurl will pass to our read callback. The read callback
should have a prototype similar to:
-
+.nf
size_t function(char *bufptr, size_t size, size_t nitems, void *userp);
-
-Where bufptr is the pointer to a buffer we fill in with data to upload and
-size*nitems is the size of the buffer and therefore also the maximum amount
-of data we can return to libcurl in this call. The 'userp' pointer is the
-custom pointer we set to point to a struct of ours to pass private data
+.fi
+Where \fIbufptr\fP is the pointer to a buffer we fill in with data to upload
+and \fIsize*nitems\fP is the size of the buffer and therefore also the maximum
+amount of data we can return to libcurl in this call. The \fIuserp\fP pointer
+is the custom pointer we set to point to a struct of ours to pass private data
between the application and the callback.
+.nf
+ curl_easy_setopt(handle, CURLOPT_READFUNCTION, read_function);
- curl_easy_setopt(easyhandle, CURLOPT_READFUNCTION, read_function);
-
- curl_easy_setopt(easyhandle, CURLOPT_READDATA, &filedata);
-
+ curl_easy_setopt(handle, CURLOPT_READDATA, &filedata);
+.fi
Tell libcurl that we want to upload:
-
- curl_easy_setopt(easyhandle, CURLOPT_UPLOAD, 1L);
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L);
+.fi
A few protocols will not behave properly when uploads are done without any prior
knowledge of the expected file size. So, set the upload file size using the
\fICURLOPT_INFILESIZE_LARGE(3)\fP for all known file sizes like this[1]:
.nf
/* in this example, file_size must be an curl_off_t variable */
- curl_easy_setopt(easyhandle, CURLOPT_INFILESIZE_LARGE, file_size);
+ curl_easy_setopt(handle, CURLOPT_INFILESIZE_LARGE, file_size);
.fi
When you call \fIcurl_easy_perform(3)\fP this time, it will perform all the
@@ -342,9 +342,9 @@
Most protocols support that you specify the name and password in the URL
itself. libcurl will detect this and use them accordingly. This is written
like this:
-
+.nf
protocol://user:password@example.com/path/
-
+.fi
If you need any odd letters in your user name or password, you should enter
them URL encoded, as %XX where XX is a two-digit hexadecimal number.
@@ -352,29 +352,29 @@
password as shown embedded in the URL can instead get set with the
\fICURLOPT_USERPWD(3)\fP option. The argument passed to libcurl should be a
char * to a string in the format "user:password". In a manner like this:
-
- curl_easy_setopt(easyhandle, CURLOPT_USERPWD, "myname:thesecret");
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_USERPWD, "myname:thesecret");
+.fi
Another case where name and password might be needed at times, is for those
users who need to authenticate themselves to a proxy they use. libcurl offers
another option for this, the \fICURLOPT_PROXYUSERPWD(3)\fP. It is used quite
similar to the \fICURLOPT_USERPWD(3)\fP option like this:
-
- curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, "myname:thesecret");
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, "myname:thesecret");
+.fi
There's a long time Unix "standard" way of storing FTP user names and
passwords, namely in the $HOME/.netrc file (on Windows, libcurl also checks
-the %USERPROFILE% environment variable if %HOME% is unset, and tries
-_netrc as name). The file should be made private so that only the user may
-read it (see also the "Security Considerations" chapter),
-as it might contain the password in plain text. libcurl has the
-ability to use this file to figure out what set of user name and password to
-use for a particular host. As an extension to the normal functionality,
-libcurl also supports this file for non-FTP protocols such as HTTP. To make
-curl use this file, use the \fICURLOPT_NETRC(3)\fP option:
-
- curl_easy_setopt(easyhandle, CURLOPT_NETRC, 1L);
-
+the \fI%USERPROFILE% environment\fP variable if \fI%HOME%\fP is unset, and
+tries "_netrc" as name). The file should be made private so that only the user
+may read it (see also the "Security Considerations" chapter), as it might
+contain the password in plain text. libcurl has the ability to use this file
+to figure out what set of user name and password to use for a particular
+host. As an extension to the normal functionality, libcurl also supports this
+file for non-FTP protocols such as HTTP. To make curl use this file, use the
+\fICURLOPT_NETRC(3)\fP option:
+.nf
+ curl_easy_setopt(handle, CURLOPT_NETRC, 1L);
+.fi
And a basic example of how such a .netrc file may look like:
.nf
@@ -389,9 +389,9 @@
you are using an SSL private key for secure transfers.
To pass the known private key password to libcurl:
-
- curl_easy_setopt(easyhandle, CURLOPT_KEYPASSWD, "keypassword");
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_KEYPASSWD, "keypassword");
+.fi
.SH "HTTP Authentication"
The previous chapter showed how to set user name and password for getting
URLs that require authentication. When using the HTTP protocol, there are
@@ -403,23 +403,22 @@
At the time of this writing, libcurl can be built to use: Basic, Digest, NTLM,
Negotiate (SPNEGO). You can tell libcurl which one to use
with \fICURLOPT_HTTPAUTH(3)\fP as in:
-
- curl_easy_setopt(easyhandle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+.fi
And when you send authentication to a proxy, you can also set authentication
type the same way but instead with \fICURLOPT_PROXYAUTH(3)\fP:
-
- curl_easy_setopt(easyhandle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
+.fi
Both these options allow you to set multiple types (by ORing them together),
to make libcurl pick the most secure one out of the types the server/proxy
claims to support. This method does however add a round-trip since libcurl
must first ask the server what it supports:
-
- curl_easy_setopt(easyhandle, CURLOPT_HTTPAUTH,
- CURLAUTH_DIGEST|CURLAUTH_BASIC);
-
-For convenience, you can use the 'CURLAUTH_ANY' define (instead of a list
+.nf
+ curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
+.fi
+For convenience, you can use the \fICURLAUTH_ANY\fP define (instead of a list
with specific types) which allows libcurl to use whatever method it wants.
When asking for multiple types, libcurl will pick the available one it
@@ -436,10 +435,10 @@
.nf
char *data="name=daniel&project=curl";
- curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, data);
- curl_easy_setopt(easyhandle, CURLOPT_URL, "http://posthere.com/");
+ curl_easy_setopt(handle, CURLOPT_POSTFIELDS, data);
+ curl_easy_setopt(handle, CURLOPT_URL, "http://posthere.com/");
- curl_easy_perform(easyhandle); /* post away! */
+ curl_easy_perform(handle); /* post away! */
.fi
Simple enough, huh? Since you set the POST options with the
@@ -458,15 +457,15 @@
headers = curl_slist_append(headers, "Content-Type: text/xml");
/* post binary data */
- curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, binaryptr);
+ curl_easy_setopt(handle, CURLOPT_POSTFIELDS, binaryptr);
/* set the size of the postfields data */
- curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDSIZE, 23L);
+ curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, 23L);
/* pass our list of custom made headers */
- curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers);
+ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
- curl_easy_perform(easyhandle); /* post away! */
+ curl_easy_perform(handle); /* post away! */
curl_slist_free_all(headers); /* free the header list */
.fi
@@ -474,18 +473,18 @@
While the simple examples above cover the majority of all cases where HTTP
POST operations are required, they do not do multi-part formposts. Multi-part
formposts were introduced as a better way to post (possibly large) binary data
-and were first documented in the RFC1867 (updated in RFC2388). they are called
-multi-part because they are built by a chain of parts, each part being a single
-unit of data. Each part has its own name and contents. You can in fact create
-and post a multi-part formpost with the regular libcurl POST support described
-above, but that would require that you build a formpost yourself and provide
-to libcurl. To make that easier, libcurl provides a MIME API consisting in
-several functions: using those, you can create and fill a multi-part form.
-Function \fIcurl_mime_init(3)\fP creates a multi-part body; you can then
-append new parts to a multi-part body using \fIcurl_mime_addpart(3)\fP.
-There are three possible data sources for a part: memory using
-\fIcurl_mime_data(3)\fP, file using \fIcurl_mime_filedata(3)\fP and
-user-defined data read callback using \fIcurl_mime_data_cb(3)\fP.
+and were first documented in the RFC 1867 (updated in RFC 2388). they are
+called multi-part because they are built by a chain of parts, each part being
+a single unit of data. Each part has its own name and contents. You can in
+fact create and post a multi-part formpost with the regular libcurl POST
+support described above, but that would require that you build a formpost
+yourself and provide to libcurl. To make that easier, libcurl provides a MIME
+API consisting in several functions: using those, you can create and fill a
+multi-part form. Function \fIcurl_mime_init(3)\fP creates a multi-part body;
+you can then append new parts to a multi-part body using
+\fIcurl_mime_addpart(3)\fP. There are three possible data sources for a part:
+memory using \fIcurl_mime_data(3)\fP, file using \fIcurl_mime_filedata(3)\fP
+and user-defined data read callback using \fIcurl_mime_data_cb(3)\fP.
\fIcurl_mime_name(3)\fP sets a part's (i.e.: form field) name, while
\fIcurl_mime_filename(3)\fP fills in the remote file name. With
\fIcurl_mime_type(3)\fP, you can tell the MIME type of a part,
@@ -497,7 +496,7 @@
and then a file with binary contents and uploads the whole thing.
.nf
- curl_mime *multipart = curl_mime_init(easyhandle);
+ curl_mime *multipart = curl_mime_init(handle);
curl_mimepart *part = curl_mime_addpart(multipart);
curl_mime_name(part, "name");
curl_mime_data(part, "daniel", CURL_ZERO_TERMINATED);
@@ -509,9 +508,9 @@
curl_mime_filedata(part, "curl.png");
/* Set the form info */
- curl_easy_setopt(easyhandle, CURLOPT_MIMEPOST, multipart);
+ curl_easy_setopt(handle, CURLOPT_MIMEPOST, multipart);
- curl_easy_perform(easyhandle); /* post away! */
+ curl_easy_perform(handle); /* post away! */
/* free the post data again */
curl_mime_free(multipart);
@@ -553,9 +552,9 @@
CURLFORM_FILECONTENT, "curl.png", CURLFORM_END);
/* Set the form info */
- curl_easy_setopt(easyhandle, CURLOPT_HTTPPOST, post);
+ curl_easy_setopt(handle, CURLOPT_HTTPPOST, post);
- curl_easy_perform(easyhandle); /* post away! */
+ curl_easy_perform(handle); /* post away! */
/* free the post data again */
curl_formfree(post);
@@ -580,20 +579,20 @@
CURLFORM_CONTENTHEADER, headers,
CURLFORM_END);
- curl_easy_perform(easyhandle); /* post away! */
+ curl_easy_perform(handle); /* post away! */
curl_formfree(post); /* free post */
curl_slist_free_all(headers); /* free custom header list */
.fi
-Since all options on an easyhandle are "sticky", they remain the same until
+Since all options on an easy handle are "sticky", they remain the same until
changed even if you do call \fIcurl_easy_perform(3)\fP, you may need to tell
curl to go back to a plain GET request if you intend to do one as your next
-request. You force an easyhandle to go back to GET by using the
+request. You force an easy handle to go back to GET by using the
\fICURLOPT_HTTPGET(3)\fP option:
-
- curl_easy_setopt(easyhandle, CURLOPT_HTTPGET, 1L);
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_HTTPGET, 1L);
+.fi
Just setting \fICURLOPT_POSTFIELDS(3)\fP to "" or NULL will *not* stop libcurl
from doing a POST. It will just make it POST without any data to send!
@@ -602,7 +601,7 @@
.br
- The easy handle must be created before building the multi-part.
.br
-- The multi-part is always created by a call to curl_mime_init(easyhandle).
+- The multi-part is always created by a call to curl_mime_init(handle).
.br
- Each part is created by a call to curl_mime_addpart(multipart).
.br
@@ -669,7 +668,7 @@
translated to two distinct parts with the same name.
.nf
- curl_easy_setopt(easyhandle, CURLOPT_READFUNCTION, myreadfunc);
+ curl_easy_setopt(handle, CURLOPT_READFUNCTION, myreadfunc);
curl_formadd(&post, &last,
CURLFORM_COPYNAME, "stream",
CURLFORM_STREAM, arg,
@@ -804,40 +803,40 @@
.IP "Proxy Options"
To tell libcurl to use a proxy at a given port number:
-
- curl_easy_setopt(easyhandle, CURLOPT_PROXY, "proxy-host.com:8080");
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_PROXY, "proxy-host.com:8080");
+.fi
Some proxies require user authentication before allowing a request, and you
pass that information similar to this:
-
- curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, "user:password");
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, "user:password");
+.fi
If you want to, you can specify the host name only in the
\fICURLOPT_PROXY(3)\fP option, and set the port number separately with
\fICURLOPT_PROXYPORT(3)\fP.
Tell libcurl what kind of proxy it is with \fICURLOPT_PROXYTYPE(3)\fP (if not,
it will default to assume an HTTP proxy):
-
- curl_easy_setopt(easyhandle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
+.fi
.IP "Environment Variables"
libcurl automatically checks and uses a set of environment variables to know
what proxies to use for certain protocols. The names of the variables are
-following an ancient de facto standard and are built up as "[protocol]_proxy"
-(note the lower casing). Which makes the variable \&'http_proxy' checked for a
-name of a proxy to use when the input URL is HTTP. Following the same rule,
-the variable named 'ftp_proxy' is checked for FTP URLs. Again, the proxies are
-always HTTP proxies, the different names of the variables simply allows
-different HTTP proxies to be used.
+following an old tradition and are built up as "[protocol]_proxy" (note the
+lower casing). Which makes the variable \&'http_proxy' checked for a name of a
+proxy to use when the input URL is HTTP. Following the same rule, the variable
+named 'ftp_proxy' is checked for FTP URLs. Again, the proxies are always HTTP
+proxies, the different names of the variables simply allows different HTTP
+proxies to be used.
The proxy environment variable contents should be in the format
-\&"[protocol://][user:password@]machine[:port]". Where the protocol:// part is
-simply ignored if present (so http://proxy and bluerk://proxy will do the
-same) and the optional port number specifies on which port the proxy operates
-on the host. If not specified, the internal default port number will be used
-and that is most likely *not* the one you would like it to be.
+\&"[protocol://][user:password@]machine[:port]". Where the protocol:// part
+specifies which type of proxy it is, and the optional port number specifies on
+which port the proxy operates. If not specified, the internal default port
+number will be used and that is most likely not the one you would like it to
+be.
There are two special environment variables. 'all_proxy' is what sets proxy
for any URL in case the protocol specific variable was not set, and
@@ -859,7 +858,7 @@
Opening an SSL connection over an HTTP proxy is therefore a matter of asking the
proxy for a straight connection to the target host on a specified port. This
-is made with the HTTP request CONNECT. ("please mr proxy, connect me to that
+is made with the HTTP request CONNECT. ("please dear proxy, connect me to that
remote host").
Because of the nature of this operation, where the proxy has no idea what kind
@@ -884,9 +883,9 @@
rarely allowed.
Tell libcurl to use proxy tunneling like this:
-
- curl_easy_setopt(easyhandle, CURLOPT_HTTPPROXYTUNNEL, 1L);
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_HTTPPROXYTUNNEL, 1L);
+.fi
In fact, there might even be times when you want to do plain HTTP
operations using a tunnel like this, as it then enables you to operate on
the remote server instead of asking the proxy to do so. libcurl will not
@@ -970,7 +969,7 @@
.IP "Expect"
When doing POST requests, libcurl sets this header to \&"100-continue" to ask
the server for an "OK" message before it proceeds with sending the data part
-of the post. If the POSTed data amount is deemed "small", libcurl will not use
+of the post. If the posted data amount is deemed "small", libcurl will not use
this header.
.SH "Customizing Operations"
@@ -988,9 +987,9 @@
If just changing the actual HTTP request keyword is what you want, like when
GET, HEAD or POST is not good enough for you, \fICURLOPT_CUSTOMREQUEST(3)\fP
is there for you. It is simple to use:
-
- curl_easy_setopt(easyhandle, CURLOPT_CUSTOMREQUEST, "MYOWNREQUEST");
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "MYOWNREQUEST");
+.fi
When using the custom request, you change the request keyword of the actual
request you are performing. Thus, by default you make a GET request but you can
also make a POST operation (as described before) and then replace the POST
@@ -1008,9 +1007,9 @@
headers = curl_slist_append(headers, "X-silly-content: yes");
/* pass our list of custom made headers */
- curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers);
+ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
- curl_easy_perform(easyhandle); /* transfer http */
+ curl_easy_perform(handle); /* transfer http */
curl_slist_free_all(headers); /* free the header list */
.fi
@@ -1050,7 +1049,7 @@
getting 1.1-requests and when dealing with stubborn old things like that, you
can tell libcurl to use 1.0 instead by doing something like this:
- curl_easy_setopt(easyhandle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt(handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
.IP "FTP Custom Commands"
@@ -1058,10 +1057,10 @@
you want to make, for example, your FTP transfers to behave differently.
Sending custom commands to an FTP server means that you need to send the
-commands exactly as the FTP server expects them (RFC959 is a good guide here),
-and you can only use commands that work on the control-connection alone. All
-kinds of commands that require data interchange and thus need a
-data-connection must be left to libcurl's own judgement. Also be aware that
+commands exactly as the FTP server expects them (RFC 959 is a good guide
+here), and you can only use commands that work on the control-connection
+alone. All kinds of commands that require data interchange and thus need a
+data-connection must be left to libcurl's own judgment. Also be aware that
libcurl will do its best to change directory to the target directory before
doing any transfer, so if you change directory (with CWD or similar) you might
confuse libcurl and then it might not attempt to transfer the file in the
@@ -1073,9 +1072,9 @@
headers = curl_slist_append(headers, "DELE file-to-remove");
/* pass the list of custom commands to the handle */
- curl_easy_setopt(easyhandle, CURLOPT_QUOTE, headers);
+ curl_easy_setopt(handle, CURLOPT_QUOTE, headers);
- curl_easy_perform(easyhandle); /* transfer ftp data! */
+ curl_easy_perform(handle); /* transfer ftp data! */
curl_slist_free_all(headers); /* free the header list */
.fi
@@ -1121,9 +1120,9 @@
To just send whatever cookie you want to a server, you can use
\fICURLOPT_COOKIE(3)\fP to set a cookie string like this:
-
- curl_easy_setopt(easyhandle, CURLOPT_COOKIE, "name1=var1; name2=var2;");
-
+.nf
+ curl_easy_setopt(handle, CURLOPT_COOKIE, "name1=var1; name2=var2;");
+.fi
In many cases, that is not enough. You might want to dynamically save
whatever cookies the remote server passes to you, and make sure those cookies
are then used accordingly on later requests.
@@ -1215,17 +1214,17 @@
corresponding part header.
Upon sending such a message, libcurl prepends it with the header list
-set with \fICURLOPT_HTTPHEADER(3)\fP, as 0th-level mime part headers.
+set with \fICURLOPT_HTTPHEADER(3)\fP, as zero level mime part headers.
Here is an example building an email message with an inline plain/html text
alternative and a file attachment encoded in base64:
.nf
- curl_mime *message = curl_mime_init(easyhandle);
+ curl_mime *message = curl_mime_init(handle);
/* The inline part is an alternative proposing the html and the text
versions of the email. */
- curl_mime *alt = curl_mime_init(easyhandle);
+ curl_mime *alt = curl_mime_init(handle);
/* HTML message. */
curl_mimepart *part = curl_mime_addpart(alt);
@@ -1256,8 +1255,8 @@
headers = curl_slist_append(headers, "To: you@example.com");
/* Set these into the easy handle. */
- curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers);
- curl_easy_setopt(easyhandle, CURLOPT_MIMEPOST, mime);
+ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
+ curl_easy_setopt(handle, CURLOPT_MIMEPOST, mime);
.fi
It should be noted that appending a message to an IMAP directory requires
@@ -1331,8 +1330,8 @@
file descriptors or sockets to know when to call libcurl again. This also
makes it easy for you to wait and respond to actions on your own application's
sockets/handles. You figure out what to select() for by using
-\fIcurl_multi_fdset(3)\fP, that fills in a set of fd_set variables for you
-with the particular file descriptors libcurl uses for the moment.
+\fIcurl_multi_fdset(3)\fP, that fills in a set of \fIfd_set\fP variables for
+you with the particular file descriptors libcurl uses for the moment.
When you then call select(), it will return when one of the file handles signal
action and you then call \fIcurl_multi_perform(3)\fP to allow libcurl to do
diff --git a/docs/libcurl/libcurl-url.3 b/docs/libcurl/libcurl-url.3
index 0732f3e..2d63281 100644
--- a/docs/libcurl/libcurl-url.3
+++ b/docs/libcurl/libcurl-url.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH libcurl 3 "10 Sep 2018" "libcurl" "libcurl URL interface"
+.TH libcurl 3 "10 Sep 2018" "libcurl" "libcurl"
.SH NAME
libcurl-url \- URL interface overview
.SH DESCRIPTION
@@ -30,21 +30,23 @@
You still only include <curl/curl.h> in your code.
.SH CREATE
Create a handle that holds URL info and resources with \fIcurl_url(3)\fP:
-
+.nf
CURLU *h = curl_url();
+.fi
.SH CLEANUP
-When done with it, clean it up with \fIcurl_url_cleanup(3)\fP:
-
+When done with it, clean it up with \fIcurl_url_cleanup(3)\fP
+.nf
curl_url_cleanup(h);
+.fi
.SH DUPLICATE
When you need a copy of a handle, just duplicate it with \fIcurl_url_dup(3)\fP:
-
+.nf
CURLU *nh = curl_url_dup(h);
+.fi
.SH PARSING
-By "setting" a URL to the handle with \fIcurl_url_set(3)\fP, the URL is parsed
+By setting a URL to the handle with \fIcurl_url_set(3)\fP, the URL is parsed
and stored in the handle. If the URL is not syntactically correct it will
return an error instead.
-
.nf
rc = curl_url_set(h, CURLUPART_URL,
"https://example.com:449/foo/bar?name=moo", 0);
@@ -56,34 +58,36 @@
.SH REDIRECT
When a handle already contains info about a URL, setting a relative URL will
make it "redirect" to adapt to it.
-
+.nf
rc = curl_url_set(h, CURLUPART_URL, "../test?another", 0);
+.fi
.SH "GET URL"
-The `CURLU` handle represents a URL and you can easily extract that with
+The \fBCURLU\fP handle represents a URL and you can easily extract that with
\fIcurl_url_get(3)\fP:
-
+.nf
char *url;
rc = curl_url_get(h, CURLUPART_URL, &url, 0);
curl_free(url);
-
+.fi
The zero in the fourth argument is a bitmask for changing specific features.
.SH "GET PARTS"
When a URL has been parsed or parts have been set, you can extract those
pieces from the handle at any time.
.nf
+ rc = curl_url_get(h, CURLUPART_FRAGMENT, &fragment, 0);
rc = curl_url_get(h, CURLUPART_HOST, &host, 0);
+ rc = curl_url_get(h, CURLUPART_PASSWORD, &password, 0);
+ rc = curl_url_get(h, CURLUPART_PATH, &path, 0);
+ rc = curl_url_get(h, CURLUPART_PORT, &port, 0);
+ rc = curl_url_get(h, CURLUPART_QUERY, &query, 0);
rc = curl_url_get(h, CURLUPART_SCHEME, &scheme, 0);
rc = curl_url_get(h, CURLUPART_USER, &user, 0);
- rc = curl_url_get(h, CURLUPART_PASSWORD, &password, 0);
- rc = curl_url_get(h, CURLUPART_PORT, &port, 0);
- rc = curl_url_get(h, CURLUPART_PATH, &path, 0);
- rc = curl_url_get(h, CURLUPART_QUERY, &query, 0);
- rc = curl_url_get(h, CURLUPART_FRAGMENT, &fragment, 0);
+ rc = curl_url_get(h, CURLUPART_ZONEID, &zoneid, 0);
.fi
Extracted parts are not URL decoded unless the user also asks for it with the
-CURLU_URLDECODE flag set in the fourth bitmask argument.
+\fICURLU_URLDECODE\fP flag set in the fourth bitmask argument.
Remember to free the returned string with \fIcurl_free(3)\fP when you are done
with it!
@@ -92,38 +96,38 @@
instead of parsing such.
.nf
+ rc = curl_url_set(urlp, CURLUPART_FRAGMENT, "anchor", 0);
rc = curl_url_set(urlp, CURLUPART_HOST, "www.example.com", 0);
+ rc = curl_url_set(urlp, CURLUPART_PASSWORD, "doe", 0);
+ rc = curl_url_set(urlp, CURLUPART_PATH, "/index.html", 0);
+ rc = curl_url_set(urlp, CURLUPART_PORT, "443", 0);
+ rc = curl_url_set(urlp, CURLUPART_QUERY, "name=john", 0);
rc = curl_url_set(urlp, CURLUPART_SCHEME, "https", 0);
rc = curl_url_set(urlp, CURLUPART_USER, "john", 0);
- rc = curl_url_set(urlp, CURLUPART_PASSWORD, "doe", 0);
- rc = curl_url_set(urlp, CURLUPART_PORT, "443", 0);
- rc = curl_url_set(urlp, CURLUPART_PATH, "/index.html", 0);
- rc = curl_url_set(urlp, CURLUPART_QUERY, "name=john", 0);
- rc = curl_url_set(urlp, CURLUPART_FRAGMENT, "anchor", 0);
+ rc = curl_url_set(urlp, CURLUPART_ZONEID, "eth0", 0);
.fi
Set parts are not URL encoded unless the user asks for it with the
-`CURLU_URLENCODE` flag.
-.SH "APPENDQUERY"
+\fICURLU_URLENCODE\fP flag.
+.SH "CURLU_APPENDQUERY"
An application can append a string to the right end of the query part with the
-`CURLU_APPENDQUERY` flag to \fIcurl_url_set(3)\fP.
+\fICURLU_APPENDQUERY\fP flag to \fIcurl_url_set(3)\fP.
-Imagine a handle that holds the URL `https://example.com/?shoes=2`. An
-application can then add the string `hat=1` to the query part like this:
+Imagine a handle that holds the URL "https://example.com/?shoes=2". An
+application can then add the string "hat=1" to the query part like this:
.nf
rc = curl_url_set(urlp, CURLUPART_QUERY, "hat=1", CURLU_APPENDQUERY);
.fi
-It will even notice the lack of an ampersand (`&`) separator so it will inject
+It will even notice the lack of an ampersand (&) separator so it will inject
one too, and the handle's full URL will then equal
-`https://example.com/?shoes=2&hat=1`.
+"https://example.com/?shoes=2&hat=1".
The appended string can of course also get URL encoded on add, and if asked to
URL encode, the encoding process will skip the '=' character. For example,
-append `candy=N&N` to what we already have, and URL encode it to deal with the
+append "candy=N&N" to what we already have, and URL encode it to deal with the
ampersand in the data:
-
.nf
rc = curl_url_set(urlp, CURLUPART_QUERY, "candy=N&N",
CURLU_APPENDQUERY | CURLU_URLENCODE);
@@ -131,10 +135,13 @@
Now the URL looks like
.nf
- https://example.com/?shoes=2&hat=1&candy=N%26N`
+ https://example.com/?shoes=2&hat=1&candy=N%26N
.fi
-.SH AVALABILITY
+.SH AVAILABILITY
The URL API was introduced in libcurl 7.62.0.
+
+A URL with a literal IPv6 address can be parsed even when IPv6 support is not
+enabled.
.SH "SEE ALSO"
.BR curl_url "(3), " curl_url_cleanup "(3), " curl_url_get "(3), "
.BR curl_url_dup "(3), " curl_url_set "(3), " curl_url_strerror "(3), "
diff --git a/docs/libcurl/libcurl-ws.3 b/docs/libcurl/libcurl-ws.3
new file mode 100644
index 0000000..2634304
--- /dev/null
+++ b/docs/libcurl/libcurl-ws.3
@@ -0,0 +1,115 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.TH libcurl 3 "10 Sep 2018" "libcurl" "libcurl"
+.SH NAME
+libcurl-ws \- WebSocket interface overview
+.SH DESCRIPTION
+The WebSocket interface provides functions for receiving and sending WebSocket
+data.
+.SH INCLUDE
+You still only include <curl/curl.h> in your code.
+.SH SETUP
+WebSocket is also often known as \fIWebSockets\fP, in plural. It is done by
+upgrading a regular HTTP(S) GET request to a WebSocket connection.
+
+WebSocket is a TCP-like message-based communication protocol done over HTTP,
+specified in RFC 6455.
+
+To initiate a WebSocket session with libcurl, setup an easy handle to use a
+URL with a "WS://" or "WSS://" scheme. "WS" is for cleartext communication
+over HTTP and "WSS" is for doing WebSocket securely over HTTPS.
+
+A WebSocket request is done as an HTTP/1 GET request with an "Upgrade
+WebSocket" request header field. When the upgrade is accepted by the server,
+it responds with a 101 Switching and then the client can speak WebSocket with
+the server. The communication can happen in both directions at the same time.
+.SH MESSAGES
+WebSocket communication is message based. That means that both ends send and
+receive entire messages, not streams like TCP. A WebSocket message is sent
+over the wire in one or more frames. Each frame in a message can have a size
+up to 2^63 bytes.
+
+libcurl delivers WebSocket data as frame fragments. It might send a whole
+frame, but it might also deliver them in pieces depending on size and network
+patterns. It makes sure to provide the API user about the exact specifics
+about the fragment: type, offset, size and how much data there is pending to
+arrive for the same frame.
+
+A message has an unknown size until the last frame header for the message has
+been received since only frames have set sizes.
+.SH "Raw mode"
+libcurl can be told to speak WebSocket in "raw mode" by setting the
+\fBCURLWS_RAW_MODE\fP bit to the \fICURLOPT_WS_OPTIONS(3)\fP option.
+
+Raw WebSocket means that libcurl will pass on the data from the network
+without parsing it leaving that entirely to the application. This mode assumes
+that the user of this knows WebSocket and can parse and figure out the data
+all by itself.
+
+This mode is intended for applications that already have a WebSocket
+parser/engine that want to switch over to use libcurl for enabling WebSocket,
+but keep parts of the existing software architecture.
+.SH PING
+WebSocket is designed to allow long-lived sessions and in order to keep the
+connections alive, both ends can send PING messages for the other end to
+respond with a PONG.
+
+libcurl automatically responds to server PING messages with a PONG. It does
+not send any PING messages automatically.
+.SH MODELS
+Because of the many different ways WebSocket can be used, which is much more
+flexible than limited to plain downloads or uploads, libcurl offers two
+different API models to use it:
+
+1. Using a write callback with \fICURLOPT_WRITEFUNCTION(3)\fP much like other
+downloads for when the traffic is download oriented.
+
+2. Using \fICURLOPT_CONNECT_ONLY(3)\fP and use the WebSocket recv/send
+functions at will.
+.SH "Callback model"
+When a write callback is set and a WebSocket transfer is performed, the
+callback will be called to deliver all WebSocket data that arrives.
+
+The callback can then call \fIcurl_ws_meta(3)\fP to learn about the details of
+the incoming data fragment.
+.SH "CONNECT_ONLY model"
+By setting \fICURLOPT_CONNECT_ONLY(3)\fP to \fB2L\fP, the transfer will only
+establish and setup the WebSocket communication and then return control back
+to the application.
+
+Once such a setup has been successfully performed, the application can proceed
+and use \fIcurl_ws_recv(3)\fP and \fIcurl_ws_send(3)\fP freely to exchange
+WebSocket messages with the server.
+.SH AVAILABILITY
+The WebSocket API was introduced as experimental in 7.86.0 and is still
+experimental today.
+
+It is only built-in if explicitly opted in at build time. We discourage use of
+the WebSocket API in production because of its experimental state. We might
+change API, ABI and behavior before this "goes live".
+.SH "SEE ALSO"
+.BR curl_ws_meta "(3), " curl_ws_recv "(3), " curl_ws_send "(3), "
+.BR curl_easy_init "(3), " CURLOPT_CONNECT_ONLY "(3), "
+.BR CURLOPT_WRITEFUNCTION "(3)" CURLOPT_WS_OPTIONS "(3), "
+
diff --git a/docs/libcurl/libcurl.3 b/docs/libcurl/libcurl.3
index 5f3e264..ae8571a 100644
--- a/docs/libcurl/libcurl.3
+++ b/docs/libcurl/libcurl.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,28 +21,19 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH libcurl 3 "March 19, 2002" "libcurl 7.9.6" "libcurl overview"
+.TH libcurl 3 "March 19, 2002" "libcurl" "libcurl"
.SH NAME
libcurl \- client-side URL transfers
.SH DESCRIPTION
This is a short overview on how to use libcurl in your C programs. There are
specific man pages for each function mentioned in here. See
\fIlibcurl-easy(3)\fP, \fIlibcurl-multi(3)\fP, \fIlibcurl-share(3)\fP,
-\fIlibcurl-url(3)\fP and \fIlibcurl-tutorial(3)\fP for in-depth understanding
-on how to program with libcurl.
+\fIlibcurl-url(3)\fP, \fIlibcurl-ws(3)\fP and \fIlibcurl-tutorial(3)\fP for
+in-depth understanding on how to program with libcurl.
-There are many bindings available that bring libcurl access to your favourite
+There are many bindings available that bring libcurl access to your favorite
language. Look elsewhere for documentation on those.
-
-libcurl has a global constant environment that you must set up and maintain
-while using libcurl. This essentially means you call \fIcurl_global_init(3)\fP
-at the start of your program and \fIcurl_global_cleanup(3)\fP at the end. See
-\fBGLOBAL CONSTANTS\fP below for details.
-
-If libcurl was compiled with support for multiple SSL backends, the function
-\fIcurl_global_sslset(3)\fP can be called before \fIcurl_global_init(3)\fP
-to select the active SSL backend.
-
+.SH TRANSFERS
To transfer files, you create an "easy handle" using \fIcurl_easy_init(3)\fP
for a single individual transfer (in either direction). You then set your
desired set of options in that handle with \fIcurl_easy_setopt(3)\fP. Options
@@ -65,28 +56,29 @@
even to easily download multiple files simultaneously using a single
thread. See further details in the \fIlibcurl-multi(3)\fP man page.
+.SH "SUPPORT INTERFACES"
+There is also a series of other helpful functions and interface families to
+use, including these:
+.RS
+.IP curl_version_info()
+gets detailed libcurl (and other used libraries) version info. See
+\fIcurl_version_info(3)\fP
+.IP curl_getdate()
+converts a date string to time_t. See \fIcurl_getdate(3)\fP
+.IP curl_easy_getinfo()
+get information about a performed transfer. See \fIcurl_easy_getinfo(3)\fP
+.IP curl_mime_addpart()
+helps building an HTTP form POST. See \fIcurl_mime_addpart(3)\fP
+.IP curl_slist_append()
+builds a linked list. See \fIcurl_slist_append(3)\fP
+.IP Sharing data between transfers
You can have multiple easy handles share certain data, even if they are used
in different threads. This magic is setup using the share interface, as
described in the \fIlibcurl-share(3)\fP man page.
-
-There is also a series of other helpful functions to use, including these:
-.RS
-.IP curl_version_info()
-gets detailed libcurl (and other used libraries) version info
-.IP curl_getdate()
-converts a date string to time_t
-.IP curl_easy_getinfo()
-get information about a performed transfer
-.IP curl_formadd()
-helps building an HTTP form POST
-.IP curl_formfree()
-free a list built with \fIcurl_formadd(3)\fP
-.IP curl_slist_append()
-builds a linked list
-.IP curl_slist_free_all()
-frees a whole curl_slist
-.IP curl_url_set()
-parses a URL
+.IP "URL Parsing"
+URL parsing and manipulations. See \fIlibcurl-url(3)\fP
+.IP "WebSocket communication"
+See \fIlibcurl-ws(3)\fP
.RE
.SH "LINKING WITH LIBCURL"
@@ -154,6 +146,10 @@
allocate resources (e.g. the memory for the GNU TLS tree mentioned above), so
the companion function \fIcurl_global_cleanup(3)\fP releases them.
+If libcurl was compiled with support for multiple SSL backends, the function
+\fIcurl_global_sslset(3)\fP can be called before \fIcurl_global_init(3)\fP
+to select the active SSL backend.
+
The global constant functions are thread-safe since libcurl 7.84.0 if
\fIcurl_version_info(3)\fP has the CURL_VERSION_THREADSAFE feature bit set
(most platforms). Read \fIlibcurl-thread(3)\fP for thread safety guidelines.
@@ -205,8 +201,8 @@
\fIcurl_global_init(3)\fP and the destructor call \fIcurl_global_cleanup(3)\fP
and satisfy libcurl's requirements without your user having to think about it.
(Caveat: If you are initializing libcurl from a Windows DLL you should not
-initialize it from DllMain or a static initializer because Windows holds the
-loader lock during that time and it could cause a deadlock.)
+initialize it from \fIDllMain\fP or a static initializer because Windows holds
+the loader lock during that time and it could cause a deadlock.)
\fIcurl_global_init(3)\fP has an argument that tells what particular parts of
the global constant environment to set up. In order to successfully use any
diff --git a/docs/libcurl/libcurl.m4 b/docs/libcurl/libcurl.m4
index 0908a02..0e470ee 100644
--- a/docs/libcurl/libcurl.m4
+++ b/docs/libcurl/libcurl.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2006 - 2022, David Shaw <dshaw@jabberwocky.com>
+# Copyright (C) David Shaw <dshaw@jabberwocky.com>
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -199,9 +199,10 @@
_libcurl_save_libs=$LIBS
LIBS="$LIBS $LIBCURL"
- AC_CHECK_FUNC(curl_free,,
- AC_DEFINE(curl_free,free,
- [Define curl_free() as free() if our version of curl lacks curl_free.]))
+ AC_CHECK_DECL([curl_free],[],
+ [AC_DEFINE([curl_free],[free],
+ [Define curl_free() as free() if our version of curl lacks curl_free.])],
+ [[#include <curl/curl.h>]])
CPPFLAGS=$_libcurl_save_cppflags
LIBS=$_libcurl_save_libs
@@ -271,4 +272,4 @@
fi
unset _libcurl_with
-])dnl
+])
diff --git a/docs/libcurl/mksymbolsmanpage.pl b/docs/libcurl/mksymbolsmanpage.pl
index 8d1ddd0..a8cb10d 100755
--- a/docs/libcurl/mksymbolsmanpage.pl
+++ b/docs/libcurl/mksymbolsmanpage.pl
@@ -6,7 +6,7 @@
# * | (__| |_| | _ <| |___
# * \___|\___/|_| \_\_____|
# *
-# * Copyright (C) 2015 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
# *
# * This software is licensed as described in the file COPYING, which
# * you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@
.\\" * | (__| |_| | _ <| |___
.\\" * \\___|\\___/|_| \\_\\_____|
.\\" *
-.\\" * Copyright (C) 1998 - $year, Daniel Stenberg, <daniel\@haxx.se>, et al.
+.\\" * Copyright (C) Daniel Stenberg, <daniel\@haxx.se>, et al.
.\\" *
.\\" * This software is licensed as described in the file COPYING, which
.\\" * you should have received as part of this distribution. The terms
@@ -53,7 +53,7 @@
.\\" * SPDX-License-Identifier: curl
.\\" *
.\\" **************************************************************************
-.TH libcurl-symbols 3 "$date" "libcurl $version" "libcurl symbols"
+.TH libcurl-symbols 3 "$date" "libcurl" "libcurl"
.SH NAME
libcurl-symbols \\- libcurl symbol version information
.SH "libcurl symbols"
diff --git a/docs/libcurl/opts/CMakeLists.txt b/docs/libcurl/opts/CMakeLists.txt
index 10d8c5f..152a08a 100644
--- a/docs/libcurl/opts/CMakeLists.txt
+++ b/docs/libcurl/opts/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2009 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.3 b/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.3
index 04a6b71..fc89a01 100644
--- a/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.3
+++ b/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_ACTIVESOCKET 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_ACTIVESOCKET 3 "12 Sep 2015" "libcurl" "libcurl"
.SH NAME
CURLINFO_ACTIVESOCKET \- get the active socket
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.3 b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.3
index 3173a57..f1281f4 100644
--- a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.3
+++ b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_APPCONNECT_TIME 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_APPCONNECT_TIME 3 "28 Aug 2015" "libcurl" "libcurl"
.SH NAME
CURLINFO_APPCONNECT_TIME \- get the time until the SSL/SSH handshake is completed
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.3 b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.3
index 99f1e53..46ad323 100644
--- a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.3
+++ b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_APPCONNECT_TIME_T 3 "28 Apr 2018" "libcurl 7.61.0" "curl_easy_getinfo options"
+.TH CURLINFO_APPCONNECT_TIME_T 3 "28 Apr 2018" "libcurl" "libcurl"
.SH NAME
-CURLINFO_APPCONNECT_TIME_T \- get the time until the SSL/SSH handshake is completed
+CURLINFO_APPCONNECT_TIME_T \- time until the SSL/SSH handshake completed
.SH SYNOPSIS
.nf
#include <curl/curl.h>
diff --git a/docs/libcurl/opts/CURLINFO_CAINFO.3 b/docs/libcurl/opts/CURLINFO_CAINFO.3
index 3c620bb..094d4d0 100644
--- a/docs/libcurl/opts/CURLINFO_CAINFO.3
+++ b/docs/libcurl/opts/CURLINFO_CAINFO.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_CAINFO 3 "20 May 2022" "libcurl 7.84.0" "curl_easy_getinfo options"
+.TH CURLINFO_CAINFO 3 "20 May 2022" "libcurl" "libcurl"
.SH NAME
-CURLINFO_CAINFO \- get the default built-in CAINFO string
+CURLINFO_CAINFO \- get the default built-in CA certificate path
.SH SYNOPSIS
.nf
#include <curl/curl.h>
diff --git a/docs/libcurl/opts/CURLINFO_CAPATH.3 b/docs/libcurl/opts/CURLINFO_CAPATH.3
index a5d396d..cbe2619 100644
--- a/docs/libcurl/opts/CURLINFO_CAPATH.3
+++ b/docs/libcurl/opts/CURLINFO_CAPATH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_CAPATH 3 "20 May 2022" "libcurl 7.84.0" "curl_easy_getinfo options"
+.TH CURLINFO_CAPATH 3 "20 May 2022" "libcurl" "libcurl"
.SH NAME
-CURLINFO_CAPATH \- get the default built-in CAPATH string
+CURLINFO_CAPATH \- get the default built-in CA path string
.SH SYNOPSIS
.nf
#include <curl/curl.h>
diff --git a/docs/libcurl/opts/CURLINFO_CERTINFO.3 b/docs/libcurl/opts/CURLINFO_CERTINFO.3
index 550390a..ec8971a 100644
--- a/docs/libcurl/opts/CURLINFO_CERTINFO.3
+++ b/docs/libcurl/opts/CURLINFO_CERTINFO.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_CERTINFO 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_CERTINFO 3 "12 Sep 2015" "libcurl" "libcurl"
.SH NAME
CURLINFO_CERTINFO \- get the TLS certificate chain
.SH SYNOPSIS
@@ -33,13 +33,13 @@
struct curl_certinfo **chainp);
.fi
.SH DESCRIPTION
-Pass a pointer to a 'struct curl_certinfo *' and you will get it set to point to
-a struct that holds a number of linked lists with info about the certificate
-chain, assuming you had \fICURLOPT_CERTINFO(3)\fP enabled when the request was
-made. The struct reports how many certs it found and then you can extract info
-for each of those certs by following the linked lists. The info chain is
-provided in a series of data in the format "name:content" where the content is
-for the specific named data. See also the certinfo.c example.
+Pass a pointer to a \fIstruct curl_certinfo *\fP and you will get it set to
+point to a struct that holds a number of linked lists with info about the
+certificate chain, assuming you had \fICURLOPT_CERTINFO(3)\fP enabled when the
+request was made. The struct reports how many certs it found and then you can
+extract info for each of those certs by following the linked lists. The info
+chain is provided in a series of data in the format "name:content" where the
+content is for the specific named data. See also the \fIcertinfo.c\fP example.
.SH PROTOCOLS
All TLS-based
.SH EXAMPLE
diff --git a/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.3 b/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.3
index 241adf6..5bb2e4d 100644
--- a/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.3
+++ b/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_CONDITION_UNMET 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_CONDITION_UNMET 3 "1 Sep 2015" "libcurl" "libcurl"
.SH NAME
CURLINFO_CONDITION_UNMET \- get info on unmet time conditional or 304 HTTP response.
.SH SYNOPSIS
@@ -52,7 +52,8 @@
curl_easy_setopt(curl, CURLOPT_TIMEVALUE, 1577833200L);
/* If-Modified-Since the above time stamp */
- curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
+ curl_easy_setopt(curl, CURLOPT_TIMECONDITION,
+ (long)CURL_TIMECOND_IFMODSINCE);
/* Perform the request */
res = curl_easy_perform(curl);
diff --git a/docs/libcurl/opts/CURLINFO_CONNECT_TIME.3 b/docs/libcurl/opts/CURLINFO_CONNECT_TIME.3
index de81ff3..71d1b08 100644
--- a/docs/libcurl/opts/CURLINFO_CONNECT_TIME.3
+++ b/docs/libcurl/opts/CURLINFO_CONNECT_TIME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_CONNECT_TIME 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_CONNECT_TIME 3 "28 Aug 2015" "libcurl" "libcurl"
.SH NAME
CURLINFO_CONNECT_TIME \- get the time until connect
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.3 b/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.3
index c4b9309..c929ae8 100644
--- a/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.3
+++ b/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_CONNECT_TIME_T 3 "28 Apr 2018" "libcurl 7.61.0" "curl_easy_getinfo options"
+.TH CURLINFO_CONNECT_TIME_T 3 "28 Apr 2018" "libcurl" "libcurl"
.SH NAME
CURLINFO_CONNECT_TIME_T \- get the time until connect
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_CONN_ID.3 b/docs/libcurl/opts/CURLINFO_CONN_ID.3
new file mode 100644
index 0000000..f8e7a46
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CONN_ID.3
@@ -0,0 +1,69 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLINFO_CONN_ID 3 "07 June 2023" "libcurl" "libcurl"
+.SH NAME
+CURLINFO_CONN_ID \- get the ID of the last connection used by the handle
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONN_ID,
+ curl_off_t *conn_id);
+.fi
+.SH DESCRIPTION
+Pass a pointer to a \fIcurl_off_t\fP to receive the connection identifier last
+used by the handle. Stores -1 if there was no connection used.
+
+The connection id is unique among all connections using the same
+connection cache. This is implicitly the case for all connections in the
+same multi handle.
+
+.SH PROTOCOLS
+All
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ curl_off_t conn_id;
+ res = curl_easy_getinfo(curl, CURLINFO_CONN_ID, &conn_id);
+ if(!res) {
+ printf("Connection used: %" CURL_FORMAT_CURL_OFF_T "\\n", conn_id);
+ }
+ }
+}
+.fi
+.SH AVAILABILITY
+Added in 8.2.0
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR curl_easy_getinfo "(3), " curl_easy_setopt "(3), "
+.BR CURLINFO_XFER_ID "(3), "
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.3 b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.3
index 40bbe0b..a4bb274 100644
--- a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.3
+++ b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_CONTENT_LENGTH_DOWNLOAD 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_CONTENT_LENGTH_DOWNLOAD 3 "1 Sep 2015" "libcurl" "libcurl"
.SH NAME
CURLINFO_CONTENT_LENGTH_DOWNLOAD \- get content-length of download
.SH SYNOPSIS
@@ -61,7 +61,7 @@
}
.fi
.SH AVAILABILITY
-Added in 7.6.1
+Added in 7.6.1. Deprecated since 7.55.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3 b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3
index f852f46..8b77ce5 100644
--- a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3
+++ b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_CONTENT_LENGTH_DOWNLOAD_T 3 "25 May 2017" "libcurl 7.55.0" "curl_easy_getinfo options"
+.TH CURLINFO_CONTENT_LENGTH_DOWNLOAD_T 3 "25 May 2017" "libcurl" "libcurl"
.SH NAME
CURLINFO_CONTENT_LENGTH_DOWNLOAD_T \- get content-length of download
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.3 b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.3
index 43d6963..5237502 100644
--- a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.3
+++ b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_CONTENT_LENGTH_UPLOAD 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_CONTENT_LENGTH_UPLOAD 3 "1 Sep 2015" "libcurl" "libcurl"
.SH NAME
CURLINFO_CONTENT_LENGTH_UPLOAD \- get the specified size of the upload
.SH SYNOPSIS
@@ -60,7 +60,7 @@
}
.fi
.SH AVAILABILITY
-Added in 7.6.1
+Added in 7.6.1. Deprecated since 7.55.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.3 b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.3
index 9334d29..4df97eb 100644
--- a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.3
+++ b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_CONTENT_LENGTH_UPLOAD_T 3 "25 May 2017" "libcurl 7.55.0" "curl_easy_getinfo options"
+.TH CURLINFO_CONTENT_LENGTH_UPLOAD_T 3 "25 May 2017" "libcurl" "libcurl"
.SH NAME
CURLINFO_CONTENT_LENGTH_UPLOAD_T \- get the specified size of the upload
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3 b/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3
index c0b7bb6..4ee5b36 100644
--- a/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3
+++ b/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_CONTENT_TYPE 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_CONTENT_TYPE 3 "1 Sep 2015" "libcurl" "libcurl"
.SH NAME
CURLINFO_CONTENT_TYPE \- get Content-Type
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_COOKIELIST.3 b/docs/libcurl/opts/CURLINFO_COOKIELIST.3
index 7f66215..5dbd604 100644
--- a/docs/libcurl/opts/CURLINFO_COOKIELIST.3
+++ b/docs/libcurl/opts/CURLINFO_COOKIELIST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_COOKIELIST 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_COOKIELIST 3 "1 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_COOKIELIST \- get all known cookies
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.3 b/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.3
index ae79741..8895c56 100644
--- a/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.3
+++ b/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_EFFECTIVE_METHOD 3 "28 Aug 2015" "libcurl 7.72.0" "curl_easy_getinfo options"
+.TH CURLINFO_EFFECTIVE_METHOD 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_EFFECTIVE_METHOD \- get the last used HTTP method
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.3 b/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.3
index c98c320..7e95e90 100644
--- a/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.3
+++ b/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_EFFECTIVE_URL 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_EFFECTIVE_URL 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_EFFECTIVE_URL \- get the last used URL
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_FILETIME.3 b/docs/libcurl/opts/CURLINFO_FILETIME.3
index 68734d9..59e8e07 100644
--- a/docs/libcurl/opts/CURLINFO_FILETIME.3
+++ b/docs/libcurl/opts/CURLINFO_FILETIME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_FILETIME 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_FILETIME 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_FILETIME \- get the remote time of the retrieved document
.SH SYNOPSIS
@@ -33,7 +33,7 @@
.fi
.SH DESCRIPTION
Pass a pointer to a long to receive the remote time of the retrieved document
-(in number of seconds since 1 jan 1970 in the GMT/UTC time zone). If you get
+in number of seconds since January 1 1970 in the GMT/UTC time zone. If you get
-1, it can be because of many reasons (it might be unknown, the server might
hide it or the server does not support the command that tells document time
etc) and the time of the document is unknown.
diff --git a/docs/libcurl/opts/CURLINFO_FILETIME_T.3 b/docs/libcurl/opts/CURLINFO_FILETIME_T.3
index b3fc115..82057c2 100644
--- a/docs/libcurl/opts/CURLINFO_FILETIME_T.3
+++ b/docs/libcurl/opts/CURLINFO_FILETIME_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_FILETIME 3 "25 Jan 2018" "libcurl 7.59.0" "curl_easy_getinfo options"
+.TH CURLINFO_FILETIME 3 "25 Jan 2018" libcurl libcurl
.SH NAME
CURLINFO_FILETIME_T \- get the remote time of the retrieved document
.SH SYNOPSIS
@@ -34,10 +34,10 @@
.fi
.SH DESCRIPTION
Pass a pointer to a curl_off_t to receive the remote time of the retrieved
-document (in number of seconds since 1 jan 1970 in the GMT/UTC time zone). If
-you get -1, it can be because of many reasons (it might be unknown, the server
-might hide it or the server does not support the command that tells document
-time etc) and the time of the document is unknown.
+document in number of seconds since January 1 1970 in the GMT/UTC time
+zone. If you get -1, it can be because of many reasons (it might be unknown,
+the server might hide it or the server does not support the command that tells
+document time etc) and the time of the document is unknown.
You must ask libcurl to collect this information before the transfer is made,
by using the \fICURLOPT_FILETIME(3)\fP option to \fIcurl_easy_setopt(3)\fP or
diff --git a/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.3 b/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.3
index fa5cdac..016b97d 100644
--- a/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.3
+++ b/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_FTP_ENTRY_PATH 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_FTP_ENTRY_PATH 3 "12 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_FTP_ENTRY_PATH \- get entry path in FTP server
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_HEADER_SIZE.3 b/docs/libcurl/opts/CURLINFO_HEADER_SIZE.3
index 6e47265..5423e62 100644
--- a/docs/libcurl/opts/CURLINFO_HEADER_SIZE.3
+++ b/docs/libcurl/opts/CURLINFO_HEADER_SIZE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_HEADER_SIZE 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_HEADER_SIZE 3 "1 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_HEADER_SIZE \- get size of retrieved headers
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.3 b/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.3
index 09e05dd..6c8f828 100644
--- a/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.3
+++ b/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_HTTPAUTH_AVAIL 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_HTTPAUTH_AVAIL 3 "12 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_HTTPAUTH_AVAIL \- get available HTTP authentication methods
.SH SYNOPSIS
@@ -66,8 +66,8 @@
}
.fi
.SH AVAILABILITY
-Added RFC2617 in 7.10.8
-Added RFC7616 in 7.57.0
+Added RFC 2617 in 7.10.8
+Added RFC 7616 in 7.57.0
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.3 b/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.3
index eb7f069..976dec1 100644
--- a/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.3
+++ b/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_HTTP_CONNECTCODE 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_HTTP_CONNECTCODE 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_HTTP_CONNECTCODE \- get the CONNECT response code
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_HTTP_VERSION.3 b/docs/libcurl/opts/CURLINFO_HTTP_VERSION.3
index 5c3c155..79ffb7e 100644
--- a/docs/libcurl/opts/CURLINFO_HTTP_VERSION.3
+++ b/docs/libcurl/opts/CURLINFO_HTTP_VERSION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_HTTP_VERSION 3 "11 May 2016" "libcurl 7.50.0" "curl_easy_getinfo options"
+.TH CURLINFO_HTTP_VERSION 3 "11 May 2016" libcurl libcurl
.SH NAME
CURLINFO_HTTP_VERSION \- get the http version used in the connection
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_LASTSOCKET.3 b/docs/libcurl/opts/CURLINFO_LASTSOCKET.3
index e4749d7..8551289 100644
--- a/docs/libcurl/opts/CURLINFO_LASTSOCKET.3
+++ b/docs/libcurl/opts/CURLINFO_LASTSOCKET.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_LASTSOCKET 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_LASTSOCKET 3 "12 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_LASTSOCKET \- get the last socket used
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_LOCAL_IP.3 b/docs/libcurl/opts/CURLINFO_LOCAL_IP.3
index e9d4042..c275f22 100644
--- a/docs/libcurl/opts/CURLINFO_LOCAL_IP.3
+++ b/docs/libcurl/opts/CURLINFO_LOCAL_IP.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_LOCAL_IP 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_LOCAL_IP 3 "12 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_LOCAL_IP \- get local IP address of last connection
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_LOCAL_PORT.3 b/docs/libcurl/opts/CURLINFO_LOCAL_PORT.3
index 9d81cc1..d849a0d 100644
--- a/docs/libcurl/opts/CURLINFO_LOCAL_PORT.3
+++ b/docs/libcurl/opts/CURLINFO_LOCAL_PORT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_LOCAL_PORT 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_LOCAL_PORT 3 "12 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_LOCAL_PORT \- get the latest local port number
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.3 b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.3
index 6c42d62..d5a7fc7 100644
--- a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.3
+++ b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_NAMELOOKUP_TIME 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_NAMELOOKUP_TIME 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_NAMELOOKUP_TIME \- get the name lookup time
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.3 b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.3
index b1cbc2c..ecb8848 100644
--- a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.3
+++ b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_NAMELOOKUP_TIME_T 3 "28 Apr 2018" "libcurl 7.61.0" "curl_easy_getinfo options"
+.TH CURLINFO_NAMELOOKUP_TIME_T 3 "28 Apr 2018" libcurl libcurl
.SH NAME
CURLINFO_NAMELOOKUP_TIME_T \- get the name lookup time in microseconds
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.3 b/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.3
index 19dd930..b776e53 100644
--- a/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.3
+++ b/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_NUM_CONNECTS 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_NUM_CONNECTS 3 "12 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_NUM_CONNECTS \- get number of created connections
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_OS_ERRNO.3 b/docs/libcurl/opts/CURLINFO_OS_ERRNO.3
index 05cfb00..d61909a 100644
--- a/docs/libcurl/opts/CURLINFO_OS_ERRNO.3
+++ b/docs/libcurl/opts/CURLINFO_OS_ERRNO.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_OS_ERRNO 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_OS_ERRNO 3 "1 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_OS_ERRNO \- get errno number from last connect failure
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.3 b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.3
index 2b3e800..f3bf368 100644
--- a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.3
+++ b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_PRETRANSFER_TIME 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_PRETRANSFER_TIME 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_PRETRANSFER_TIME \- get the time until the file transfer start
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.3 b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.3
index 04579ce..ad2fcc1 100644
--- a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.3
+++ b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_PRETRANSFER_TIME_T 3 "28 Apr 2018" "libcurl 7.61.0" "curl_easy_getinfo options"
+.TH CURLINFO_PRETRANSFER_TIME_T 3 "28 Apr 2018" libcurl libcurl
.SH NAME
CURLINFO_PRETRANSFER_TIME_T \- get the time until the file transfer start
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_PRIMARY_IP.3 b/docs/libcurl/opts/CURLINFO_PRIMARY_IP.3
index 4109d39..35bab0d 100644
--- a/docs/libcurl/opts/CURLINFO_PRIMARY_IP.3
+++ b/docs/libcurl/opts/CURLINFO_PRIMARY_IP.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_PRIMARY_IP 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_PRIMARY_IP 3 "12 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_PRIMARY_IP \- get IP address of last connection
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.3 b/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.3
index 318d34f..445a4f5 100644
--- a/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.3
+++ b/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_PRIMARY_PORT 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_PRIMARY_PORT 3 "12 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_PRIMARY_PORT \- get the latest destination port number
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_PRIVATE.3 b/docs/libcurl/opts/CURLINFO_PRIVATE.3
index 632bc3d..bfe2e09 100644
--- a/docs/libcurl/opts/CURLINFO_PRIVATE.3
+++ b/docs/libcurl/opts/CURLINFO_PRIVATE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_PRIVATE 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_PRIVATE 3 "1 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_PRIVATE \- get the private pointer
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_PROTOCOL.3 b/docs/libcurl/opts/CURLINFO_PROTOCOL.3
index 7c11ed3..c0b77ac 100644
--- a/docs/libcurl/opts/CURLINFO_PROTOCOL.3
+++ b/docs/libcurl/opts/CURLINFO_PROTOCOL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_PROTOCOL 3 "23 November 2016" "libcurl 7.52.0" "curl_easy_getinfo options"
+.TH CURLINFO_PROTOCOL 3 "23 November 2016" libcurl libcurl
.SH NAME
CURLINFO_PROTOCOL \- get the protocol used in the connection
.SH SYNOPSIS
@@ -32,6 +32,10 @@
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROTOCOL, long *p);
.fi
.SH DESCRIPTION
+This option is deprecated. We strongly recommend using
+\fICURLINFO_SCHEME(3)\fP instead, because this option cannot return all
+possible protocols!
+
Pass a pointer to a long to receive the version used in the last http
connection. The returned value will be exactly one of the CURLPROTO_* values:
@@ -60,7 +64,7 @@
}
.fi
.SH AVAILABILITY
-Added in 7.52.0
+Added in 7.52.0. Deprecated since 7.85.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.3 b/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.3
index 0fed03f..a7f9097 100644
--- a/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.3
+++ b/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_PROXYAUTH_AVAIL 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_PROXYAUTH_AVAIL 3 "12 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_PROXYAUTH_AVAIL \- get available HTTP proxy authentication methods
.SH SYNOPSIS
@@ -68,8 +68,8 @@
}
.fi
.SH AVAILABILITY
-Added RFC2617 in 7.10.8
-Added RFC7616 in 7.57.0
+Added RFC 2617 in 7.10.8
+Added RFC 7616 in 7.57.0
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLINFO_PROXY_ERROR.3 b/docs/libcurl/opts/CURLINFO_PROXY_ERROR.3
index ffc551a..30a2f85 100644
--- a/docs/libcurl/opts/CURLINFO_PROXY_ERROR.3
+++ b/docs/libcurl/opts/CURLINFO_PROXY_ERROR.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_PROXY_ERROR 3 "3 Aug 2020" "libcurl 7.73.0" "curl_easy_getinfo options"
+.TH CURLINFO_PROXY_ERROR 3 "3 Aug 2020" libcurl libcurl
.SH NAME
CURLINFO_PROXY_ERROR \- get the detailed (SOCKS) proxy error
.SH SYNOPSIS
@@ -71,12 +71,11 @@
.fi
.SH DESCRIPTION
Pass a pointer to a long to receive a detailed error code when the most recent
-transfer returned a CURLE_PROXY error.
+transfer returned a \fBCURLE_PROXY\fP error. That error code will match the
+\fBCURLproxycode\fP set.
-The return value will match the CURLproxycode set.
-
-The returned value will be zero (equal to CURLPX_OK) if no such response code
-was available.
+The error code will be zero (\fBCURLPX_OK\fP) if no response code was
+available.
.SH PROTOCOLS
All that can be done over SOCKS
.SH EXAMPLE
diff --git a/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.3 b/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.3
index 4c9a8ac..e7039d3 100644
--- a/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.3
+++ b/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_PROXY_SSL_VERIFYRESULT 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_getinfo options"
+.TH CURLINFO_PROXY_SSL_VERIFYRESULT 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLINFO_PROXY_SSL_VERIFYRESULT \- get the result of the proxy certificate verification
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.3 b/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.3
index 0376798..3fe3c7d 100644
--- a/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.3
+++ b/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_REDIRECT_COUNT 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_REDIRECT_COUNT 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_REDIRECT_COUNT \- get the number of redirects
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.3 b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.3
index a39d43e..d558e9a 100644
--- a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.3
+++ b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_REDIRECT_TIME 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_REDIRECT_TIME 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_REDIRECT_TIME \- get the time for all redirection steps
.SH SYNOPSIS
@@ -35,8 +35,8 @@
.SH DESCRIPTION
Pass a pointer to a double to receive the total time, in seconds, it took for
all redirection steps include name lookup, connect, pretransfer and transfer
-before final transaction was started. CURLINFO_REDIRECT_TIME contains the
-complete execution time for multiple redirections.
+before final transaction was started. \fICURLINFO_REDIRECT_TIME(3)\fP contains
+the complete execution time for multiple redirections.
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.3 b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.3
index a1e0031..01d723c 100644
--- a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.3
+++ b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_REDIRECT_TIME_T 3 "28 Apr 2018" "libcurl 7.61.0" "curl_easy_getinfo options"
+.TH CURLINFO_REDIRECT_TIME_T 3 "28 Apr 2018" libcurl libcurl
.SH NAME
CURLINFO_REDIRECT_TIME_T \- get the time for all redirection steps
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_URL.3 b/docs/libcurl/opts/CURLINFO_REDIRECT_URL.3
index 63366a6..7acbe1d 100644
--- a/docs/libcurl/opts/CURLINFO_REDIRECT_URL.3
+++ b/docs/libcurl/opts/CURLINFO_REDIRECT_URL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_REDIRECT_URL 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_REDIRECT_URL 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_REDIRECT_URL \- get the URL a redirect would go to
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_REFERER.3 b/docs/libcurl/opts/CURLINFO_REFERER.3
index bc342b2..bdbfa4c 100644
--- a/docs/libcurl/opts/CURLINFO_REFERER.3
+++ b/docs/libcurl/opts/CURLINFO_REFERER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_REFERER 3 "11 Feb 2021" "libcurl 7.76.0" "curl_easy_getinfo options"
+.TH CURLINFO_REFERER 3 "11 Feb 2021" libcurl libcurl
.SH NAME
CURLINFO_REFERER \- get the referrer header
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.3 b/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.3
index fef978f..ce1282a 100644
--- a/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.3
+++ b/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_REQUEST_SIZE 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_REQUEST_SIZE 3 "1 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_REQUEST_SIZE \- get size of sent request
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3 b/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3
index 774c51a..e5ed112 100644
--- a/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3
+++ b/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_RESPONSE_CODE 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_RESPONSE_CODE 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_RESPONSE_CODE \- get the last response code
.SH SYNOPSIS
@@ -33,7 +33,7 @@
.fi
.SH DESCRIPTION
Pass a pointer to a long to receive the last received HTTP, FTP, SMTP or
-LDAP (openldap only) response code. This option was previously known as
+LDAP (OpenLDAP only) response code. This option was previously known as
CURLINFO_HTTP_CODE in libcurl 7.10.7 and earlier.
The stored value will be zero if no server response code has been received.
Note that a proxy's CONNECT response should
diff --git a/docs/libcurl/opts/CURLINFO_RETRY_AFTER.3 b/docs/libcurl/opts/CURLINFO_RETRY_AFTER.3
index 1475588..e3c24be 100644
--- a/docs/libcurl/opts/CURLINFO_RETRY_AFTER.3
+++ b/docs/libcurl/opts/CURLINFO_RETRY_AFTER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_RETRY_AFTER 3 "6 Aug 2019" "libcurl 7.66.0" "curl_easy_getinfo options"
+.TH CURLINFO_RETRY_AFTER 3 "6 Aug 2019" libcurl libcurl
.SH NAME
CURLINFO_RETRY_AFTER \- returns the Retry-After retry delay
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.3 b/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.3
index 5ab6f22..1c69d88 100644
--- a/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.3
+++ b/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_RTSP_CLIENT_CSEQ 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_RTSP_CLIENT_CSEQ 3 "1 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_RTSP_CLIENT_CSEQ \- get the next RTSP client CSeq
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.3 b/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.3
index 17efe83..804c3f8 100644
--- a/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.3
+++ b/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_RTSP_CSEQ_RECV 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_RTSP_CSEQ_RECV 3 "12 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_RTSP_CSEQ_RECV \- get the recently received CSeq
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.3 b/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.3
index e18acb2..bb7f45c 100644
--- a/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.3
+++ b/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_RTSP_SERVER_CSEQ 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_RTSP_SERVER_CSEQ 3 "1 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_RTSP_SERVER_CSEQ \- get the next RTSP server CSeq
.SH SYNOPSIS
@@ -36,7 +36,7 @@
Pass a pointer to a long to receive the next CSeq that will be expected by the
application.
-Llistening for server initiated requests is currently unimplemented!
+Listening for server initiated requests is not implemented!
Applications wishing to resume an RTSP session on another connection should
retrieve this info before closing the active connection.
diff --git a/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.3 b/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.3
index c6e2440..92cbb9c 100644
--- a/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.3
+++ b/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_RTSP_SESSION_ID 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_RTSP_SESSION_ID 3 "12 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_RTSP_SESSION_ID \- get RTSP session ID
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_SCHEME.3 b/docs/libcurl/opts/CURLINFO_SCHEME.3
index 086748c..049b5ec 100644
--- a/docs/libcurl/opts/CURLINFO_SCHEME.3
+++ b/docs/libcurl/opts/CURLINFO_SCHEME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_SCHEME 3 "23 November 2016" "libcurl 7.52.0" "curl_easy_getinfo options"
+.TH CURLINFO_SCHEME 3 "23 November 2016" libcurl libcurl
.SH NAME
CURLINFO_SCHEME \- get the URL scheme (sometimes called protocol) used in the connection
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.3 b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.3
index 81f702f..a18a89d 100644
--- a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.3
+++ b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_SIZE_DOWNLOAD 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_SIZE_DOWNLOAD 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_SIZE_DOWNLOAD \- get the number of downloaded bytes
.SH SYNOPSIS
@@ -62,7 +62,7 @@
}
.fi
.SH AVAILABILITY
-Added in 7.4.1
+Added in 7.4.1. Deprecated since 7.55.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.3 b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.3
index 04e6db0..63766a7 100644
--- a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.3
+++ b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_SIZE_DOWNLOAD_T 3 "25 May 2017" "libcurl 7.55.0" "curl_easy_getinfo options"
+.TH CURLINFO_SIZE_DOWNLOAD_T 3 "25 May 2017" libcurl libcurl
.SH NAME
CURLINFO_SIZE_DOWNLOAD_T \- get the number of downloaded bytes
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.3 b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.3
index 6026c3b..2d511ca 100644
--- a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.3
+++ b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_SIZE_UPLOAD 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_SIZE_UPLOAD 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_SIZE_UPLOAD \- get the number of uploaded bytes
.SH SYNOPSIS
@@ -59,7 +59,7 @@
}
.fi
.SH AVAILABILITY
-Added in 7.4.1
+Added in 7.4.1. Deprecated since 7.55.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.3 b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.3
index fda09af..10d9156 100644
--- a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.3
+++ b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_SIZE_UPLOAD_T 3 "25 May 2017" "libcurl 7.55.0" "curl_easy_getinfo options"
+.TH CURLINFO_SIZE_UPLOAD_T 3 "25 May 2017" libcurl libcurl
.SH NAME
CURLINFO_SIZE_UPLOAD_T \- get the number of uploaded bytes
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.3 b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.3
index 3abcef8..e5a910a 100644
--- a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.3
+++ b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_SPEED_DOWNLOAD 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_SPEED_DOWNLOAD 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_SPEED_DOWNLOAD \- get download speed
.SH SYNOPSIS
@@ -52,13 +52,13 @@
double speed;
res = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &speed);
if(!res) {
- printf("Download speed %.0f bytes/sec\\n", ul);
+ printf("Download speed %.0f bytes/sec\\n", speed);
}
}
}
.fi
.SH AVAILABILITY
-Added in 7.4.1
+Added in 7.4.1. Deprecated since 7.55.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.3 b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.3
index dba9e07..78998f5 100644
--- a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.3
+++ b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_SPEED_DOWNLOAD_T 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_SPEED_DOWNLOAD_T 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_SPEED_DOWNLOAD_T \- get download speed
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.3 b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.3
index 29c0e88..ff780cc 100644
--- a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.3
+++ b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_SPEED_UPLOAD 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_SPEED_UPLOAD 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_SPEED_UPLOAD \- get upload speed
.SH SYNOPSIS
@@ -51,13 +51,13 @@
double speed;
res = curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &speed);
if(!res) {
- printf("Upload speed %.0f bytes/sec\\n", ul);
+ printf("Upload speed %.0f bytes/sec\\n", speed);
}
}
}
.fi
.SH AVAILABILITY
-Added in
+Added in 7.4.1. Deprecated since 7.55.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.3 b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.3
index a2348a0..1a057ae 100644
--- a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.3
+++ b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_SPEED_UPLOAD_T 3 "25 May 2017" "libcurl 7.55.0" "curl_easy_getinfo options"
+.TH CURLINFO_SPEED_UPLOAD_T 3 "25 May 2017" libcurl libcurl
.SH NAME
CURLINFO_SPEED_UPLOAD_T \- get upload speed
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_SSL_ENGINES.3 b/docs/libcurl/opts/CURLINFO_SSL_ENGINES.3
index 242c591..29224c2 100644
--- a/docs/libcurl/opts/CURLINFO_SSL_ENGINES.3
+++ b/docs/libcurl/opts/CURLINFO_SSL_ENGINES.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_SSL_ENGINES 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_SSL_ENGINES 3 "1 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_SSL_ENGINES \- get an slist of OpenSSL crypto-engines
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.3 b/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.3
index 5bf2409..c078d3c 100644
--- a/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.3
+++ b/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_SSL_VERIFYRESULT 3 "1 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_SSL_VERIFYRESULT 3 "1 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_SSL_VERIFYRESULT \- get the result of the certificate verification
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.3 b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.3
index 9edb683..e58b496 100644
--- a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.3
+++ b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_STARTTRANSFER_TIME 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_STARTTRANSFER_TIME 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_STARTTRANSFER_TIME \- get the time until the first byte is received
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.3 b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.3
index 2941828..ce1537a 100644
--- a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.3
+++ b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_STARTTRANSFER_TIME_T 3 "28 Apr 2018" "libcurl 7.61.0" "curl_easy_getinfo options"
+.TH CURLINFO_STARTTRANSFER_TIME_T 3 "28 Apr 2018" libcurl libcurl
.SH NAME
CURLINFO_STARTTRANSFER_TIME_T \- get the time until the first byte is received
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_TLS_SESSION.3 b/docs/libcurl/opts/CURLINFO_TLS_SESSION.3
index cd06610..8278bb6 100644
--- a/docs/libcurl/opts/CURLINFO_TLS_SESSION.3
+++ b/docs/libcurl/opts/CURLINFO_TLS_SESSION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_TLS_SESSION 3 "12 Sep 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_TLS_SESSION 3 "12 Sep 2015" libcurl libcurl
.SH NAME
CURLINFO_TLS_SESSION \- get TLS session info
.SH SYNOPSIS
@@ -40,14 +40,14 @@
case of OpenSSL. If the session \fIbackend\fP is CURLSSLBACKEND_OPENSSL the
session \fIinternals\fP pointer varies depending on the option:
-CURLINFO_TLS_SESSION OpenSSL session \fIinternals\fP is SSL_CTX *.
+\fICURLINFO_TLS_SESSION(3)\fP OpenSSL session \fIinternals\fP is \fBSSL_CTX *\fP.
-CURLINFO_TLS_SSL_PTR OpenSSL session \fIinternals\fP is SSL *.
+\fICURLINFO_TLS_SSL_PTR(3)\fP OpenSSL session \fIinternals\fP is \fBSSL *\fP.
-You can obtain an SSL_CTX pointer from an SSL pointer using OpenSSL function
-SSL_get_SSL_CTX. Therefore unless you need compatibility with older versions of
-libcurl use \fICURLINFO_TLS_SSL_PTR(3)\fP. Refer to that document for more
-information.
+You can obtain an \fBSSL_CTX\fP pointer from an SSL pointer using OpenSSL
+function \fISSL_get_SSL_CTX(3)\fP. Therefore unless you need compatibility
+with older versions of libcurl use \fICURLINFO_TLS_SSL_PTR(3)\fP. Refer to
+that document for more information.
.SH PROTOCOLS
All TLS-based
.SH EXAMPLE
@@ -63,8 +63,8 @@
}
.fi
.SH AVAILABILITY
-Added in 7.34.0, and supported OpenSSL, GnuTLS, NSS and gskit only up until
-7.48.0 was released.
+Added in 7.34.0. Deprecated since 7.48.0 and supported OpenSSL, GnuTLS,
+NSS and gskit only up until this version was released.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.3 b/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.3
index 854d2ef..1c4d07a 100644
--- a/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.3
+++ b/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_TLS_SSL_PTR 3 "23 Feb 2016" "libcurl 7.48.0" "curl_easy_getinfo options"
+.TH CURLINFO_TLS_SSL_PTR 3 "23 Feb 2016" libcurl libcurl
.SH NAME
CURLINFO_TLS_SESSION, CURLINFO_TLS_SSL_PTR \- get TLS session info
.SH SYNOPSIS
@@ -38,9 +38,9 @@
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TLS_SESSION,
struct curl_tlssessioninfo **session);
.SH DESCRIPTION
-Pass a pointer to a 'struct curl_tlssessioninfo *'. The pointer will be
-initialized to refer to a 'struct curl_tlssessioninfo *' that will contain an
-enum indicating the SSL library used for the handshake and a pointer to the
+Pass a pointer to a \fIstruct curl_tlssessioninfo *\fP. The pointer will be
+initialized to refer to a \fIstruct curl_tlssessioninfo *\fP that will contain
+an enum indicating the SSL library used for the handshake and a pointer to the
respective internal TLS session structure of this underlying SSL library.
This option may be useful for example to extract certificate information in a
@@ -66,34 +66,32 @@
for the active ("in use") SSL connection, with the following underlying types:
.RS
.IP GnuTLS
-gnutls_session_t
+\fBgnutls_session_t\fP
.IP gskit
-gsk_handle
+\fBgsk_handle\fP
.IP NSS
-PRFileDesc *
+\fBPRFileDesc *\fP
.IP OpenSSL
-CURLINFO_TLS_SESSION: SSL_CTX *
+\fICURLINFO_TLS_SESSION(3)\fP: \fBSSL_CTX *\fP
-CURLINFO_TLS_SSL_PTR: SSL *
+\fICURLINFO_TLS_SSL_PTR(3)\fP: \fBSSL *\fP
.RE
Since 7.48.0 the \fIinternals\fP member can point to these other SSL backends
as well:
.RS
.IP mbedTLS
-mbedtls_ssl_context *
+\fBmbedTLS_ssl_context *\fP
.IP "Secure Channel"
-CtxtHandle *
+\fBCtxtHandle *\fP
.IP "Secure Transport"
-SSLContext *
+\fBSSLContext *\fP
.IP "wolfSSL"
-SSL *
-.IP "MesaLink"
-SSL *
+\fBSSL *\fP
.RE
If the \fIinternals\fP pointer is NULL then either the SSL backend is not
supported, an SSL session has not yet been established or the connection is no
-longer associated with the easy handle (eg curl_easy_perform has returned).
+longer associated with the easy handle (e.g. curl_easy_perform has returned).
.SH LIMITATIONS
This option has some limitations that could make it unsafe when it comes to
the manual verification of certificates.
@@ -104,7 +102,7 @@
a data channel and one or both may be over SSL. Currently there is no way to
retrieve a second in-use SSL session associated with an easy handle.
-This option has not been thoroughly tested with plaintext protocols that can
+This option has not been thoroughly tested with clear text protocols that can
be upgraded/downgraded to/from SSL: FTP, SMTP, POP3, IMAP when used with
\fICURLOPT_USE_SSL(3)\fP. Though you will be able to retrieve the SSL pointer,
it's possible that before you can do that data (including auth) may have
@@ -117,10 +115,10 @@
pointer, with the (possibly) changed certificate information.
If you are using OpenSSL or wolfSSL then \fICURLOPT_SSL_CTX_FUNCTION(3)\fP can
-be used to set a certificate verification callback in the CTX. That is safer
-than using this option to poll for certificate changes and does not suffer from
-any of the problems above. There is currently no way in libcurl to set a
-verification callback for the other SSL backends.
+be used to set a certificate verification callback. That is safer than using
+this option to poll for certificate changes and does not suffer from any of
+the problems above. There is currently no way in libcurl to set a verification
+callback for the other SSL backends.
How are you using this option? Are you affected by any of these limitations?
Please let us know by making a comment at
diff --git a/docs/libcurl/opts/CURLINFO_TOTAL_TIME.3 b/docs/libcurl/opts/CURLINFO_TOTAL_TIME.3
index d22f5a2..a652d45 100644
--- a/docs/libcurl/opts/CURLINFO_TOTAL_TIME.3
+++ b/docs/libcurl/opts/CURLINFO_TOTAL_TIME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_TOTAL_TIME 3 "28 Aug 2015" "libcurl 7.44.0" "curl_easy_getinfo options"
+.TH CURLINFO_TOTAL_TIME 3 "28 Aug 2015" libcurl libcurl
.SH NAME
CURLINFO_TOTAL_TIME \- get total time of previous transfer
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.3 b/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.3
index 3d5babf..29dbb09 100644
--- a/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.3
+++ b/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLINFO_TOTAL_TIME_T 3 "28 Apr 2018" "libcurl 7.61.0" "curl_easy_getinfo options"
+.TH CURLINFO_TOTAL_TIME_T 3 "28 Apr 2018" libcurl libcurl
.SH NAME
CURLINFO_TOTAL_TIME_T \- get total time of previous transfer in microseconds
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLINFO_XFER_ID.3 b/docs/libcurl/opts/CURLINFO_XFER_ID.3
new file mode 100644
index 0000000..8040d49
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_XFER_ID.3
@@ -0,0 +1,70 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLINFO_XFER_ID 3 "07 June 2023" "libcurl" "libcurl"
+.SH NAME
+CURLINFO_XFER_ID \- get the ID of a transfer
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_XFER_ID,
+ curl_off_t *xfer_id);
+.fi
+.SH DESCRIPTION
+Pass a pointer to a \fIcurl_off_t\fP to receive the identifier of the
+current/last transfer done with the handle. Stores -1 if no transfer
+has been started yet for the handle.
+
+The transfer id is unique among all transfers performed using the same
+connection cache. This is implicitly the case for all transfers in the
+same multi handle.
+
+.SH PROTOCOLS
+All
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ curl_off_t xfer_id;
+ res = curl_easy_getinfo(curl, CURLINFO_XFER_ID, &xfer_id);
+ if(!res) {
+ printf("Transfer ID: %" CURL_FORMAT_CURL_OFF_T "\\n", xfer_id);
+ }
+ }
+}
+.fi
+.SH AVAILABILITY
+Added in 8.2.0
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR curl_easy_getinfo "(3), " curl_easy_setopt "(3), "
+.BR CURLINFO_CONN_ID "(3), "
diff --git a/docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3 b/docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3
index 274c0a9..7d3b957 100644
--- a/docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3
+++ b/docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 3 "4 Nov 2014" "libcurl 7.39.0" "curl_multi_setopt options"
+.TH CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 3 "4 Nov 2014" libcurl libcurl
.SH NAME
CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE \- chunk length threshold for pipelining
.SH SYNOPSIS
@@ -35,11 +35,11 @@
.SH DESCRIPTION
No function since pipelining was removed in 7.62.0.
-Pass a long with a \fBsize\fP in bytes. If a pipelined connection is currently
-processing a chunked (Transfer-encoding: chunked) request with a current chunk
-length larger than \fICURLMOPT_CHUNK_LENGTH_PENALTY_SIZE(3)\fP, that pipeline
-will not be considered for additional requests, even if it is shorter than
-\fICURLMOPT_MAX_PIPELINE_LENGTH(3)\fP.
+Pass a long with a \fBsize\fP in bytes. If a transfer in a pipeline is
+currently processing a chunked (Transfer-encoding: chunked) request with a
+current chunk length larger than \fICURLMOPT_CHUNK_LENGTH_PENALTY_SIZE(3)\fP,
+that pipeline will not be considered for additional requests, even if it is
+shorter than \fICURLMOPT_MAX_PIPELINE_LENGTH(3)\fP.
.SH DEFAULT
The default value is 0, which means that the penalization is inactive.
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3 b/docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3
index d96a4f1..a361f62 100644
--- a/docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3
+++ b/docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 3 "4 Nov 2014" "libcurl 7.39.0" "curl_multi_setopt options"
+.TH CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 3 "4 Nov 2014" libcurl libcurl
.SH NAME
CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE \- size threshold for pipelining penalty
.SH SYNOPSIS
@@ -35,8 +35,8 @@
.SH DESCRIPTION
No function since pipelining was removed in 7.62.0.
-Pass a long with a \fBsize\fP in bytes. If a pipelined connection is currently
-processing a request with a Content-Length larger than this
+Pass a long with a \fBsize\fP in bytes. If a transfer in a pipeline is
+currently processing a request with a Content-Length larger than this
\fICURLMOPT_CONTENT_LENGTH_PENALTY_SIZE(3)\fP, that pipeline will then not be
considered for additional requests, even if it is shorter than
\fICURLMOPT_MAX_PIPELINE_LENGTH(3)\fP.
diff --git a/docs/libcurl/opts/CURLMOPT_MAXCONNECTS.3 b/docs/libcurl/opts/CURLMOPT_MAXCONNECTS.3
index 87d44a8..ceba353 100644
--- a/docs/libcurl/opts/CURLMOPT_MAXCONNECTS.3
+++ b/docs/libcurl/opts/CURLMOPT_MAXCONNECTS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_MAXCONNECTS 3 "17 Jun 2014" "libcurl 7.37.0" "curl_multi_setopt options"
+.TH CURLMOPT_MAXCONNECTS 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLMOPT_MAXCONNECTS \- size of connection cache
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.3 b/docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.3
index 725f98b..ece39d5 100644
--- a/docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.3
+++ b/docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_MAX_CONCURRENT_STREAMS 3 "06 Nov 2019" "libcurl 7.67.0" "curl_multi_setopt options"
+.TH CURLMOPT_MAX_CONCURRENT_STREAMS 3 "06 Nov 2019" libcurl libcurl
.SH NAME
CURLMOPT_MAX_CONCURRENT_STREAMS \- max concurrent streams for http2
.SH SYNOPSIS
@@ -38,8 +38,7 @@
support on connections done using HTTP/2.
Valid values range from 1 to 2147483647 (2^31 - 1) and defaults to 100. The
-value passed here would be honoured based on other system resources
-properties.
+value passed here would be honored based on other system resources properties.
.SH DEFAULT
100
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.3 b/docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.3
index 4c17289..49095e1 100644
--- a/docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.3
+++ b/docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_MAX_HOST_CONNECTIONS 3 "17 Jun 2014" "libcurl 7.37.0" "curl_multi_setopt options"
+.TH CURLMOPT_MAX_HOST_CONNECTIONS 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLMOPT_MAX_HOST_CONNECTIONS \- max number of connections to a single host
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.3 b/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.3
index 2bb8344..b17dbe9 100644
--- a/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.3
+++ b/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_MAX_PIPELINE_LENGTH 3 "4 Nov 2014" "libcurl 7.39.0" "curl_multi_setopt options"
+.TH CURLMOPT_MAX_PIPELINE_LENGTH 3 "4 Nov 2014" libcurl libcurl
.SH NAME
CURLMOPT_MAX_PIPELINE_LENGTH \- maximum number of requests in a pipeline
.SH SYNOPSIS
@@ -36,8 +36,8 @@
No function since pipelining was removed in 7.62.0.
Pass a long. The set \fBmax\fP number will be used as the maximum amount of
-outstanding requests in an HTTP/1.1 pipelined connection. This option is only
-used for HTTP/1.1 pipelining, not for HTTP/2 multiplexing.
+outstanding requests in an HTTP/1.1 pipeline. This option is only used for
+HTTP/1.1 pipelining, not for HTTP/2 multiplexing.
When this limit is reached, libcurl will use another connection to the same
host (see \fICURLMOPT_MAX_HOST_CONNECTIONS(3)\fP), or queue the request until
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.3 b/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.3
index 250899f..55ca1a2 100644
--- a/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.3
+++ b/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_MAX_TOTAL_CONNECTIONS 3 "4 Nov 2014" "libcurl 7.39.0" "curl_multi_setopt options"
+.TH CURLMOPT_MAX_TOTAL_CONNECTIONS 3 "4 Nov 2014" libcurl libcurl
.SH NAME
CURLMOPT_MAX_TOTAL_CONNECTIONS \- max simultaneously open connections
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLMOPT_PIPELINING.3 b/docs/libcurl/opts/CURLMOPT_PIPELINING.3
index e0be8e9..fb0a76f 100644
--- a/docs/libcurl/opts/CURLMOPT_PIPELINING.3
+++ b/docs/libcurl/opts/CURLMOPT_PIPELINING.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_PIPELINING 3 "17 Jun 2014" "libcurl 7.37.0" "curl_multi_setopt options"
+.TH CURLMOPT_PIPELINING 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLMOPT_PIPELINING \- enable HTTP pipelining and multiplexing
.SH SYNOPSIS
@@ -88,6 +88,5 @@
.BR CURLMOPT_PIPELINING_SITE_BL "(3), "
.BR CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE "(3), "
.BR CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE "(3), "
-.BR CURLMOPT_MAX_HOST_CONNECTIONS "(3), "
.BR CURLMOPT_MAXCONNECTS "(3), "
.BR CURLMOPT_MAX_HOST_CONNECTIONS "(3), "
diff --git a/docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.3 b/docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.3
index e68c575..f50efe8 100644
--- a/docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.3
+++ b/docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_PIPELINING_SERVER_BL 3 "4 Nov 2014" "libcurl 7.39.0" "curl_multi_setopt options"
+.TH CURLMOPT_PIPELINING_SERVER_BL 3 "4 Nov 2014" libcurl libcurl
.SH NAME
CURLMOPT_PIPELINING_SERVER_BL \- pipelining server block list
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.3 b/docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.3
index 3074ad6..08b8969 100644
--- a/docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.3
+++ b/docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_PIPELINING_SITE_BL 3 "4 Nov 2014" "libcurl 7.39.0" "curl_multi_setopt options"
+.TH CURLMOPT_PIPELINING_SITE_BL 3 "4 Nov 2014" libcurl libcurl
.SH NAME
CURLMOPT_PIPELINING_SITE_BL \- pipelining host block list
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLMOPT_PUSHDATA.3 b/docs/libcurl/opts/CURLMOPT_PUSHDATA.3
index 9ddc1fd..f393f4a 100644
--- a/docs/libcurl/opts/CURLMOPT_PUSHDATA.3
+++ b/docs/libcurl/opts/CURLMOPT_PUSHDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_PUSHDATA 3 "1 Jun 2015" "libcurl 7.44.0" "curl_multi_setopt options"
+.TH CURLMOPT_PUSHDATA 3 "1 Jun 2015" libcurl libcurl
.SH NAME
CURLMOPT_PUSHDATA \- pointer to pass to push callback
.SH SYNOPSIS
@@ -46,10 +46,10 @@
CURL *easy,
size_t num_headers,
struct curl_pushheaders *headers,
- void *userp)
+ void *clientp)
{
char *headp;
- int *transfers = (int *)userp;
+ int *transfers = (int *)clientp;
FILE *out;
headp = curl_pushheader_byname(headers, ":path");
if(headp && !strncmp(headp, "/push-", 6)) {
diff --git a/docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.3 b/docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.3
index 6889874..5bfe500 100644
--- a/docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.3
+++ b/docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,21 +22,18 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_PUSHFUNCTION 3 "1 Jun 2015" "libcurl 7.44.0" "curl_multi_setopt options"
+.TH CURLMOPT_PUSHFUNCTION 3 "1 Jun 2015" libcurl libcurl
.SH NAME
CURLMOPT_PUSHFUNCTION \- callback that approves or denies server pushes
.SH SYNOPSIS
.nf
#include <curl/curl.h>
-char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num);
-char *curl_pushheader_byname(struct curl_pushheaders *h, const char *name);
-
int curl_push_callback(CURL *parent,
CURL *easy,
size_t num_headers,
struct curl_pushheaders *headers,
- void *userp);
+ void *clientp);
CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PUSHFUNCTION,
curl_push_callback func);
@@ -49,9 +46,9 @@
The callback gets its arguments like this:
\fIparent\fP is the handle of the stream on which this push arrives. The new
-handle has been duphandle()d from the parent, meaning that it has gotten all
-its options inherited. It is then up to the application to alter any options
-if desired.
+handle has been duplicated from the parent, meaning that it has gotten all its
+options inherited. It is then up to the application to alter any options if
+desired.
\fIeasy\fP is a newly created handle that represents this upcoming transfer.
@@ -63,24 +60,19 @@
headers, the normal response headers will be provided in the header callback
as usual.
-\fIuserp\fP is the pointer set with \fICURLMOPT_PUSHDATA(3)\fP
+\fIclientp\fP is the pointer set with \fICURLMOPT_PUSHDATA(3)\fP
If the callback returns CURL_PUSH_OK, the 'easy' handle will be added to the
multi handle, the callback must not do that by itself.
The callback can access PUSH_PROMISE headers with two accessor
functions. These functions can only be used from within this callback and they
-can only access the PUSH_PROMISE headers. The normal response headers will be
-passed to the header callback for pushed streams just as for normal streams.
-.IP curl_pushheader_bynum
-Returns the header at index 'num' (or NULL). The returned pointer points to a
-"name:value" string that will be freed when this callback returns.
-.IP curl_pushheader_byname
-Returns the value for the given header name (or NULL). 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 pointed will be freed when this callback
-returns. If more than one header field use the same name, this returns only
-the first one.
+can only access the PUSH_PROMISE headers: \fIcurl_pushheader_byname(3)\fP and
+\fIcurl_pushheader_bynum(3)\fP. The normal response headers will be passed to
+the header callback for pushed streams just as for normal streams.
+
+The header fields can also be accessed with \fIcurl_easy_header(3)\fP,
+introduced in later libcurl versions.
.SH CALLBACK RETURN VALUE
.IP "CURL_PUSH_OK (0)"
The application has accepted the stream and it can now start receiving data,
@@ -104,10 +96,10 @@
CURL *easy,
size_t num_headers,
struct curl_pushheaders *headers,
- void *userp)
+ void *clientp)
{
char *headp;
- int *transfers = (int *)userp;
+ int *transfers = (int *)clientp;
FILE *out;
headp = curl_pushheader_byname(headers, ":path");
if(headp && !strncmp(headp, "/push-", 6)) {
diff --git a/docs/libcurl/opts/CURLMOPT_SOCKETDATA.3 b/docs/libcurl/opts/CURLMOPT_SOCKETDATA.3
index b3b2332..c2af856 100644
--- a/docs/libcurl/opts/CURLMOPT_SOCKETDATA.3
+++ b/docs/libcurl/opts/CURLMOPT_SOCKETDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_SOCKETDATA 3 "3 Nov 2014" "libcurl 7.39.0" "curl_multi_setopt options"
+.TH CURLMOPT_SOCKETDATA 3 "3 Nov 2014" libcurl libcurl
.SH NAME
CURLMOPT_SOCKETDATA \- custom pointer passed to the socket callback
.SH SYNOPSIS
@@ -35,7 +35,7 @@
\fICURLMOPT_SOCKETFUNCTION(3)\fP option.
This pointer will not be touched by libcurl but will only be passed in to the
-socket callbacks's \fBuserp\fP argument.
+socket callbacks's \fBclientp\fP argument.
.SH DEFAULT
NULL
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.3 b/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.3
index c0dbfbc..7e992c6 100644
--- a/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.3
+++ b/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_SOCKETFUNCTION 3 "3 Nov 2016" "libcurl 7.39.0" "curl_multi_setopt options"
+.TH CURLMOPT_SOCKETFUNCTION 3 "3 Nov 2016" libcurl libcurl
.SH NAME
CURLMOPT_SOCKETFUNCTION \- callback informed about what to wait for
.SH SYNOPSIS
@@ -32,7 +32,7 @@
int socket_callback(CURL *easy, /* easy handle */
curl_socket_t s, /* socket */
int what, /* describes the socket */
- void *userp, /* private callback pointer */
+ void *clientp, /* private callback pointer */
void *socketp); /* private socket pointer */
CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_SOCKETFUNCTION, socket_callback);
@@ -40,12 +40,16 @@
Pass a pointer to your callback function, which should match the prototype
shown above.
-When the \fIcurl_multi_socket_action(3)\fP function is called, it informs the
-application about updates in the socket (file descriptor) status by doing
-none, one, or multiple calls to the \fBsocket_callback\fP. The callback
-function gets status updates with changes since the previous time the callback
-was called. If the given callback pointer is set to NULL, no callback will be
-called.
+When the \fIcurl_multi_socket_action(3)\fP function is called, it uses this
+callback to inform the application about updates in the socket (file
+descriptor) status by doing none, one, or multiple calls to the
+\fBsocket_callback\fP. The callback function gets status updates with changes
+since the previous time the callback was called. If the given callback pointer
+is set to NULL, no callback will be called.
+
+libcurl then expects the application to monitor the sockets for the specific
+activities and tell libcurl again when something happens on one of them. Tell
+libcurl by calling \fIcurl_multi_socket_action(3)\fP.
.SH "CALLBACK ARGUMENTS"
\fIeasy\fP identifies the specific transfer for which this update is related.
@@ -59,7 +63,7 @@
callback returns error, \fBall\fP transfers currently in progress in this
multi handle will be aborted and fail.
-\fBuserp\fP is set with \fICURLMOPT_SOCKETDATA(3)\fP.
+\fBclientp\fP is set with \fICURLMOPT_SOCKETDATA(3)\fP.
\fBsocketp\fP is set with \fIcurl_multi_assign(3)\fP or will be NULL.
@@ -73,7 +77,8 @@
Wait for incoming and outgoing data. For the socket to become readable or
writable.
.IP CURL_POLL_REMOVE
-The specified socket/file descriptor is no longer used by libcurl.
+The specified socket/file descriptor is no longer used by libcurl for any
+active transfer. It might soon be added again.
.SH DEFAULT
NULL (no callback)
.SH PROTOCOLS
@@ -82,8 +87,8 @@
.nf
static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
{
- GlobalInfo *g = (GlobalInfo*) cbp;
- SockInfo *fdp = (SockInfo*) sockp;
+ GlobalInfo *g = cbp;
+ SockInfo *fdp = sockp;
if(what == CURL_POLL_REMOVE) {
remsock(fdp);
diff --git a/docs/libcurl/opts/CURLMOPT_TIMERDATA.3 b/docs/libcurl/opts/CURLMOPT_TIMERDATA.3
index 553d252..a1f9ec4 100644
--- a/docs/libcurl/opts/CURLMOPT_TIMERDATA.3
+++ b/docs/libcurl/opts/CURLMOPT_TIMERDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_TIMERDATA 3 "17 Jun 2014" "libcurl 7.37.0" "curl_multi_setopt options"
+.TH CURLMOPT_TIMERDATA 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLMOPT_TIMERDATA \- custom pointer to pass to timer callback
.SH SYNOPSIS
@@ -35,7 +35,7 @@
\fICURLMOPT_TIMERFUNCTION(3)\fP option.
This pointer will not be touched by libcurl but will only be passed in to the
-timer callbacks's \fBuserp\fP argument.
+timer callbacks's \fBclientp\fP argument.
.SH DEFAULT
NULL
.SH PROTOCOLS
@@ -53,9 +53,9 @@
return G_SOURCE_REMOVE;
}
-static int timerfunc(CURLM *multi, long timeout_ms, void *userp)
+static int timerfunc(CURLM *multi, long timeout_ms, void *clientp)
{
- guint *id = userp;
+ guint *id = clientp;
if(id)
g_source_remove(*id);
diff --git a/docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.3 b/docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.3
index 78c1e81..1bccb91 100644
--- a/docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.3
+++ b/docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLMOPT_TIMERFUNCTION 3 "17 Jun 2014" "libcurl 7.37.0" "curl_multi_setopt options"
+.TH CURLMOPT_TIMERFUNCTION 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLMOPT_TIMERFUNCTION \- callback to receive timeout values
.SH SYNOPSIS
@@ -31,7 +31,7 @@
int timer_callback(CURLM *multi, /* multi handle */
long timeout_ms, /* timeout in number of ms */
- void *userp); /* private callback pointer */
+ void *clientp); /* private callback pointer */
CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_TIMERFUNCTION, timer_callback);
.SH DESCRIPTION
@@ -52,7 +52,7 @@
The \fBtimer_callback\fP will only be called when the timeout expire time is
changed.
-The \fBuserp\fP pointer is set with \fICURLMOPT_TIMERDATA(3)\fP.
+The \fBclientp\fP pointer is set with \fICURLMOPT_TIMERDATA(3)\fP.
The timer callback should return 0 on success, and -1 on error. If this
callback returns error, \fBall\fP transfers currently in progress in this
@@ -82,9 +82,9 @@
return G_SOURCE_REMOVE;
}
-static int timerfunc(CURLM *multi, long timeout_ms, void *userp)
+static int timerfunc(CURLM *multi, long timeout_ms, void *clientp)
{
- guint *id = userp;
+ guint *id = clientp;
if(id)
g_source_remove(*id);
diff --git a/docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.3 b/docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.3
index 01691b1..a848348 100644
--- a/docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.3
+++ b/docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_ABSTRACT_UNIX_SOCKET 3 "08 Jan 2017" "libcurl 7.53.0" "curl_easy_setopt options"
+.TH CURLOPT_ABSTRACT_UNIX_SOCKET 3 "08 Jan 2017" libcurl libcurl
.SH NAME
CURLOPT_ABSTRACT_UNIX_SOCKET \- abstract Unix domain socket
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.3 b/docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.3
index bb0e378..5efd09f 100644
--- a/docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.3
+++ b/docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_ACCEPTTIMEOUT_MS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_ACCEPTTIMEOUT_MS 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_ACCEPTTIMEOUT_MS \- timeout waiting for FTP server to connect back
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.3 b/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.3
index 2f7ee96..8a2fd8d 100644
--- a/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.3
+++ b/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_ACCEPT_ENCODING 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_ACCEPT_ENCODING 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_ACCEPT_ENCODING \- automatic decompression of HTTP downloads
.SH SYNOPSIS
@@ -46,14 +46,12 @@
built-in supported encodings.
Alternatively, you can specify exactly the encoding or list of encodings you
-want in the response. Four encodings are supported: \fIidentity\fP, meaning
-non-compressed, \fIdeflate\fP which requests the server to compress its
-response using the zlib algorithm, \fIgzip\fP which requests the gzip
+want in the response. The following encodings are supported: \fIidentity\fP,
+meaning non-compressed, \fIdeflate\fP which requests the server to compress
+its response using the zlib algorithm, \fIgzip\fP which requests the gzip
algorithm, (since curl 7.57.0) \fIbr\fP which is brotli and (since curl
-7.72.0) \fIzstd\fP which is zstd. Provide them in the string as a
-comma-separated list of accepted encodings, like:
-
- "br, gzip, deflate".
+7.72.0) \fIzstd\fP which is zstd. Provide them in the string as a
+comma-separated list of accepted encodings, like: \fB"br, gzip, deflate"\fP.
Set \fICURLOPT_ACCEPT_ENCODING(3)\fP to NULL to explicitly disable it, which
makes libcurl not send an Accept-Encoding: header and not decompress received
diff --git a/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.3 b/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.3
index 6894ec2..e6a2226 100644
--- a/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.3
+++ b/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_ADDRESS_SCOPE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_ADDRESS_SCOPE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_ADDRESS_SCOPE \- scope id for IPv6 addresses
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_ALTSVC.3 b/docs/libcurl/opts/CURLOPT_ALTSVC.3
index 38c2bab..4f57ce1 100644
--- a/docs/libcurl/opts/CURLOPT_ALTSVC.3
+++ b/docs/libcurl/opts/CURLOPT_ALTSVC.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_ALTSVC 3 "5 Feb 2019" "libcurl 7.64.1" "curl_easy_setopt options"
+.TH CURLOPT_ALTSVC 3 "5 Feb 2019" libcurl libcurl
.SH NAME
CURLOPT_ALTSVC \- alt-svc cache file name
.SH SYNOPSIS
@@ -34,7 +34,7 @@
.SH DESCRIPTION
Pass in a pointer to a \fIfilename\fP to instruct libcurl to use that file as
the Alt-Svc cache to read existing cache contents from and possibly also write
-it back to a after a transfer, unless \fBCURLALTSVC_READONLYFILE\fP is set in
+it back to after a transfer, unless \fBCURLALTSVC_READONLYFILE\fP is set in
\fICURLOPT_ALTSVC_CTRL(3)\fP.
Specify a blank file name ("") to make libcurl not load from a file at all.
@@ -57,7 +57,7 @@
An example line could look like
- h2 www.example 8443 h3 quic.example 443 "20190808 06:18:37" 1 0
+ h2 www.example 8443 h3 second.example 443 "20190808 06:18:37" 1 0
The fields of that line are:
@@ -69,7 +69,7 @@
Port number for the source origin
.IP h3
ALPN id for the destination host
-.IP quic.example
+.IP second.example
Host name for the destination host
.IP 443
Port number for the destination host
diff --git a/docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.3 b/docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.3
index a3d3c88..4bff498 100644
--- a/docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.3
+++ b/docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_ALTSVC_CTRL 3 "5 Feb 2019" "libcurl 7.64.1" "curl_easy_setopt options"
+.TH CURLOPT_ALTSVC_CTRL 3 "5 Feb 2019" libcurl libcurl
.SH NAME
CURLOPT_ALTSVC_CTRL \- control alt-svc behavior
.SH SYNOPSIS
@@ -75,7 +75,7 @@
.nf
CURL *curl = curl_easy_init();
if(curl) {
- curl_easy_setopt(curl, CURLOPT_ALTSVC_CTRL, CURLALTSVC_H1);
+ curl_easy_setopt(curl, CURLOPT_ALTSVC_CTRL, (long)CURLALTSVC_H1);
curl_easy_setopt(curl, CURLOPT_ALTSVC, "altsvc-cache.txt");
curl_easy_perform(curl);
}
diff --git a/docs/libcurl/opts/CURLOPT_APPEND.3 b/docs/libcurl/opts/CURLOPT_APPEND.3
index c488fff..4e8d170 100644
--- a/docs/libcurl/opts/CURLOPT_APPEND.3
+++ b/docs/libcurl/opts/CURLOPT_APPEND.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_APPEND 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_APPEND 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_APPEND \- append to the remote file
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_AUTOREFERER.3 b/docs/libcurl/opts/CURLOPT_AUTOREFERER.3
index c403b79..2931a2d 100644
--- a/docs/libcurl/opts/CURLOPT_AUTOREFERER.3
+++ b/docs/libcurl/opts/CURLOPT_AUTOREFERER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_AUTOREFERER 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_AUTOREFERER 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_AUTOREFERER \- automatically update the referer header
.SH SYNOPSIS
@@ -32,9 +32,13 @@
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_AUTOREFERER, long autorefer);
.fi
.SH DESCRIPTION
-Pass a parameter set to 1 to enable this. When enabled, libcurl will
+Pass a long parameter set to 1 to enable this. When enabled, libcurl will
automatically set the Referer: header field in HTTP requests to the full URL
where it follows a Location: redirect.
+
+The automatic referer is set to the full previous URL even when redirects are
+done cross-origin or following redirects to insecure protocols. This is
+considered a minor privacy leak by some.
.SH DEFAULT
0, disabled
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_AWS_SIGV4.3 b/docs/libcurl/opts/CURLOPT_AWS_SIGV4.3
index 8dea327..cb14231 100644
--- a/docs/libcurl/opts/CURLOPT_AWS_SIGV4.3
+++ b/docs/libcurl/opts/CURLOPT_AWS_SIGV4.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_AWS_SIGV4 3 "03 Jun 2020" "libcurl 7.75.0" "curl_easy_setopt options"
+.TH CURLOPT_AWS_SIGV4 3 "03 Jun 2020" libcurl libcurl
.SH NAME
CURLOPT_AWS_SIGV4 \- V4 signature
.SH SYNOPSIS
@@ -35,8 +35,8 @@
Provides AWS V4 signature authentication on HTTP(S) header.
.PP
Pass a char * that is the collection of specific arguments are used for
-creating outgoing authentication headers.
-The format of the param option is:
+creating outgoing authentication headers. The format of the \fIparam\fP
+option is:
.IP provider1[:provider2[:region[:service]]]
.IP provider1,\ provider2
The providers arguments are used for generating some authentication parameters
@@ -50,38 +50,34 @@
.PP
NOTE: This call set \fICURLOPT_HTTPAUTH(3)\fP to CURLAUTH_AWS_SIGV4.
Calling \fICURLOPT_HTTPAUTH(3)\fP with CURLAUTH_AWS_SIGV4 is the same
-as calling this with "aws:amz" in parameter.
+as calling this with \fB"aws:amz"\fP in parameter.
.PP
Example with "Test:Try", when curl will do the algorithm, it will generate
-"TEST-HMAC-SHA256" for "Algorithm", "x-try-date" and "X-Try-Date" for "date",
-"test4_request" for "request type",
-"SignedHeaders=content-type;host;x-try-date" for "signed headers"
+\fB"TEST-HMAC-SHA256"\fP for "Algorithm", \fB"x-try-date"\fP and
+\fB"X-Try-Date"\fP for "date", \fB"test4_request"\fP for "request type",
+\fB"SignedHeaders=content-type;host;x-try-date"\fP for "signed headers"
.PP
If you use just "test", instead of "test:try",
test will be use for every strings generated
.SH DEFAULT
By default, the value of this parameter is NULL.
Calling \fICURLOPT_HTTPAUTH(3)\fP with CURLAUTH_AWS_SIGV4 is the same
-as calling this with "aws:amz" in parameter.
+as calling this with \fB"aws:amz"\fP in parameter.
.SH PROTOCOLS
HTTP
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();
-struct curl_slist *list = NULL;
-
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL,
"https://service.region.example.com/uri");
curl_easy_setopt(c, CURLOPT_AWS_SIGV4, "provider1:provider2");
- /* service and region also could be set in CURLOPT_AWS_SIGV4 */
- /*
+ /* service and region can also be set in CURLOPT_AWS_SIGV4 */
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/uri");
curl_easy_setopt(c, CURLOPT_AWS_SIGV4,
"provider1:provider2:region:service");
- */
curl_easy_setopt(c, CURLOPT_USERPWD, "MY_ACCESS_KEY:MY_SECRET_KEY");
curl_easy_perform(curl);
@@ -92,8 +88,18 @@
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH NOTES
-This option overrides the other auth types you might have set in CURL_HTTPAUTH
-which should be highlighted as this makes this auth method special.
-This method cannot be combined with other auth types.
+This option overrides the other auth types you might have set in
+\fICURLOPT_HTTPAUTH(3)\fP which should be highlighted as this makes this auth
+method special. This method cannot be combined with other auth types.
+.PP
+A sha256 checksum of the request payload is used as input to the signature
+calculation. For POST requests, this is a checksum of the provided
+\fICURLOPT_POSTFIELDS(3)\fP. Otherwise, it's the checksum of an empty buffer.
+For requests like PUT, you can provide your own checksum in an HTTP header named
+\fBx-provider2-content-sha256\fP.
+.PP
+For \fBaws:s3\fP, a \fBx-amz-content-sha256\fP header is added to every request
+if not already present. For s3 requests with unknown payload, this header takes
+the special value "UNSIGNED-PAYLOAD".
.SH "SEE ALSO"
.BR CURLOPT_HEADEROPT "(3), " CURLOPT_HTTPHEADER "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_BUFFERSIZE.3 b/docs/libcurl/opts/CURLOPT_BUFFERSIZE.3
index 3d93205..b7697d2 100644
--- a/docs/libcurl/opts/CURLOPT_BUFFERSIZE.3
+++ b/docs/libcurl/opts/CURLOPT_BUFFERSIZE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_BUFFERSIZE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_BUFFERSIZE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_BUFFERSIZE \- receive buffer size
.SH SYNOPSIS
@@ -41,11 +41,13 @@
actually get the given size.
This buffer size is by default \fICURL_MAX_WRITE_SIZE\fP (16kB). The maximum
-buffer size allowed to be set is \fICURL_MAX_READ_SIZE\fP (512kB). The minimum
+buffer size allowed to be set is \fICURL_MAX_READ_SIZE\fP (10MB). The minimum
buffer size allowed to be set is 1024.
DO NOT set this option on a handle that is currently used for an active
transfer as that may lead to unintended consequences.
+
+The maximum size was 512kB until 7.88.0.
.SH DEFAULT
CURL_MAX_WRITE_SIZE (16kB)
.SH PROTOCOLS
@@ -70,3 +72,4 @@
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
.BR CURLOPT_MAX_RECV_SPEED_LARGE "(3), " CURLOPT_WRITEFUNCTION "(3), "
+.BR CURLOPT_UPLOAD_BUFFERSIZE "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_CAINFO.3 b/docs/libcurl/opts/CURLOPT_CAINFO.3
index 39c443b..a236ec4 100644
--- a/docs/libcurl/opts/CURLOPT_CAINFO.3
+++ b/docs/libcurl/opts/CURLOPT_CAINFO.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CAINFO 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CAINFO 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CAINFO \- path to Certificate Authority (CA) bundle
.SH SYNOPSIS
@@ -39,12 +39,12 @@
server's certificate, \fICURLOPT_CAINFO(3)\fP need not even indicate an
accessible file.
-This option is by default set to the system path where libcurl's cacert bundle
-is assumed to be stored, as established at build time.
+This option is by default set to the system path where libcurl's CA
+certificate bundle is assumed to be stored, as established at build time.
If curl is built against the NSS SSL library, the NSS PEM PKCS#11 module
(libnsspem.so) needs to be available for this option to work properly.
-Starting with curl-7.55.0, if both \fICURLOPT_CAINFO(3)\fP and
+Starting with curl 7.55.0, if both \fICURLOPT_CAINFO(3)\fP and
\fICURLOPT_CAPATH(3)\fP are unset, NSS-linked libcurl tries to load
libnssckbi.so, which contains a more comprehensive set of trust information
than supported by nss-pem, because libnssckbi.so also includes information
@@ -79,12 +79,13 @@
}
.fi
.SH AVAILABILITY
-For the SSL engines that do not support certificate files the CURLOPT_CAINFO
-option is ignored. Schannel support added in libcurl 7.60.
+For the SSL engines that do not support certificate files the
+\fICURLOPT_CAINFO(3)\fP option is ignored. Schannel support added in libcurl
+7.60.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
.SH "SEE ALSO"
.BR CURLOPT_CAINFO_BLOB "(3), " CURLOPT_CAPATH "(3), "
.BR CURLOPT_SSL_VERIFYPEER "(3), " CURLOPT_SSL_VERIFYHOST "(3), "
-.BR CURLINFO_CAINFO "(3), "
+.BR CURLINFO_CAINFO "(3), " CURLOPT_CA_CACHE_TIMEOUT "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.3 b/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.3
index 6371a23..620aa4c 100644
--- a/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.3
+++ b/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CAINFO_BLOB 3 "31 March 2021" "libcurl 7.77.0" "curl_easy_setopt options"
+.TH CURLOPT_CAINFO_BLOB 3 "31 March 2021" libcurl libcurl
.SH NAME
CURLOPT_CAINFO_BLOB \- Certificate Authority (CA) bundle in PEM format
.SH SYNOPSIS
@@ -64,7 +64,7 @@
Added in 7.77.0.
This option is supported by the BearSSL (since 7.79.0), mbedTLS (since 7.81.0),
-rustls (since 7.82.0), OpenSSL, Secure Transport and Schannel backends.
+rustls (since 7.82.0), wolfSSL (since 8.2.0), OpenSSL, Secure Transport and Schannel backends.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_CAPATH.3 b/docs/libcurl/opts/CURLOPT_CAPATH.3
index 4842629..88ad011 100644
--- a/docs/libcurl/opts/CURLOPT_CAPATH.3
+++ b/docs/libcurl/opts/CURLOPT_CAPATH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CAPATH 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CAPATH 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CAPATH \- directory holding CA certificates
.SH SYNOPSIS
@@ -34,12 +34,12 @@
.SH DESCRIPTION
Pass a char * to a null-terminated string naming a directory holding multiple
CA certificates to verify the peer with. If libcurl is built against OpenSSL,
-the certificate directory must be prepared using the openssl c_rehash utility.
+the certificate directory must be prepared using the OpenSSL c_rehash utility.
This makes sense only when used in combination with the
\fICURLOPT_SSL_VERIFYPEER(3)\fP option.
The \fICURLOPT_CAPATH(3)\fP function apparently does not work in Windows due
-to some limitation in openssl.
+to some limitation in OpenSSL.
The application does not have to keep the string around after setting this
option.
diff --git a/docs/libcurl/opts/CURLOPT_CA_CACHE_TIMEOUT.3 b/docs/libcurl/opts/CURLOPT_CA_CACHE_TIMEOUT.3
new file mode 100644
index 0000000..d786ec0
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CA_CACHE_TIMEOUT.3
@@ -0,0 +1,78 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_CA_CACHE_TIMEOUT 3 "21 Dec 2022" libcurl libcurl
+.SH NAME
+CURLOPT_CA_CACHE_TIMEOUT \- life-time for cached certificate stores
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CA_CACHE_TIMEOUT, long age);
+.fi
+.SH DESCRIPTION
+Pass a long, this sets the timeout in seconds. This tells libcurl the maximum
+time any cached certificate store it has in memory may be kept and reused for
+new connections. Once the timeout has expired, a subsequent fetch requiring a
+certificate store will have to build a new one.
+
+Building a certificate store from a \fICURLOPT_CAINFO\fP file is a slow
+operation so curl may cache the generated certificate store internally to speed
+up future connections.
+
+Set to zero to completely disable caching, or set to -1 to retain the cached
+store remain forever. By default, libcurl caches this info for 24 hours.
+.SH DEFAULT
+86400 (24 hours)
+.SH PROTOCOLS
+All
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ /* only reuse certificate stores for a short time */
+ curl_easy_setopt(curl, CURLOPT_CA_CACHE_TIMEOUT, 60L);
+
+ ret = curl_easy_perform(curl);
+
+ /* in this second request, the cache will not be used if more than
+ sixty seconds have passed since the previous connection */
+ ret = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+This option was added in curl 7.87.0.
+
+Currently the only SSL backend to implement this certificate store caching
+functionality is the OpenSSL (and forks) backend.
+.SH RETURN VALUE
+Returns CURLE_OK
+.SH "SEE ALSO"
+.BR CURLOPT_CAINFO "(3), "
+.BR CURLOPT_CAINFO_BLOB "(3), " CURLOPT_CAPATH "(3), "
+.BR CURLOPT_SSL_VERIFYPEER "(3), " CURLOPT_SSL_VERIFYHOST "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_CERTINFO.3 b/docs/libcurl/opts/CURLOPT_CERTINFO.3
index ad65765..6a253a2 100644
--- a/docs/libcurl/opts/CURLOPT_CERTINFO.3
+++ b/docs/libcurl/opts/CURLOPT_CERTINFO.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CERTINFO 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CERTINFO 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CERTINFO \- request SSL certificate information
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.3
index 85fbfa2..6b914d5 100644
--- a/docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CHUNK_BGN_FUNCTION 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CHUNK_BGN_FUNCTION 3 "19 Jun 2014" libcurl libcurl
.SH NAME
-CURLOPT_CHUNK_BGN_FUNCTION \- callback before a transfer with FTP wildcardmatch
+CURLOPT_CHUNK_BGN_FUNCTION \- callback before a transfer with FTP wildcard match
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -68,14 +68,14 @@
This callback function gets called by libcurl before a part of the stream is
going to be transferred (if the transfer supports chunks).
-The \fItransfer_info\fP pointer will point to a struct curl_fileinfo with
-details about the file that is about to get transferred.
+The \fItransfer_info\fP pointer will point to a \fBcurl_fileinfo\fP struct
+with details about the file that is about to get transferred.
This callback makes sense only when using the \fICURLOPT_WILDCARDMATCH(3)\fP
option for now.
The target of transfer_info parameter is a "feature depended" structure. For
-the FTP wildcard download, the target is curl_fileinfo structure (see
+the FTP wildcard download, the target is \fBcurl_fileinfo\fP structure (see
\fIcurl/curl.h\fP). The parameter \fIptr\fP is a pointer given by
\fICURLOPT_CHUNK_DATA(3)\fP. The parameter remains contains number of chunks
remaining per the transfer. If the feature is not available, the parameter has
diff --git a/docs/libcurl/opts/CURLOPT_CHUNK_DATA.3 b/docs/libcurl/opts/CURLOPT_CHUNK_DATA.3
index 2c00a6c..ccff3e2 100644
--- a/docs/libcurl/opts/CURLOPT_CHUNK_DATA.3
+++ b/docs/libcurl/opts/CURLOPT_CHUNK_DATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CHUNK_DATA 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CHUNK_DATA 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CHUNK_DATA \- pointer passed to the FTP chunk callbacks
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.3
index 90afbc8..ea2b25b 100644
--- a/docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CHUNK_END_FUNCTION 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CHUNK_END_FUNCTION 3 "19 Jun 2014" libcurl libcurl
.SH NAME
-CURLOPT_CHUNK_END_FUNCTION \- callback after a transfer with FTP wildcardmatch
+CURLOPT_CHUNK_END_FUNCTION \- callback after a transfer with FTP wildcard match
.SH SYNOPSIS
.nf
#include <curl/curl.h>
diff --git a/docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.3 b/docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.3
index d3d4773..7fe14fc 100644
--- a/docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.3
+++ b/docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CLOSESOCKETDATA 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CLOSESOCKETDATA 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CLOSESOCKETDATA \- pointer passed to the socket close callback
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.3 b/docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.3
index d9a3e0f..e6bce8c 100644
--- a/docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CLOSESOCKETFUNCTION 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CLOSESOCKETFUNCTION 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CLOSESOCKETFUNCTION \- callback to socket close replacement
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.3 b/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.3
index b5ab64f..f15197f 100644
--- a/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.3
+++ b/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CONNECTTIMEOUT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CONNECTTIMEOUT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CONNECTTIMEOUT \- timeout for the connect phase
.SH SYNOPSIS
@@ -43,6 +43,9 @@
If both \fICURLOPT_CONNECTTIMEOUT(3)\fP and \fICURLOPT_CONNECTTIMEOUT_MS(3)\fP
are set, the value set last will be used.
+
+The "connection phase" is considered complete when the requested TCP, TLS or
+QUIC handshakes are done.
.SH DEFAULT
300
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.3 b/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.3
index 24c88b3..67ce3ec 100644
--- a/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.3
+++ b/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CONNECTTIMEOUT_MS 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CONNECTTIMEOUT_MS 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CONNECTTIMEOUT_MS \- timeout for the connect phase
.SH SYNOPSIS
@@ -44,6 +44,9 @@
If both \fICURLOPT_CONNECTTIMEOUT(3)\fP and \fICURLOPT_CONNECTTIMEOUT_MS(3)\fP
are set, the value set last will be used.
+
+The "connection phase" is considered complete when the requested TCP, TLS or
+QUIC handshakes are done.
.SH DEFAULT
300000
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.3 b/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.3
index 5f0413f..0366342 100644
--- a/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.3
+++ b/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CONNECT_ONLY 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CONNECT_ONLY 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CONNECT_ONLY \- stop when connected to target server
.SH SYNOPSIS
@@ -42,12 +42,22 @@
the application can obtain the most recently used socket for special data
transfers.
+Since 7.86.0, this option can be set to '2' and if HTTP or WebSocket are
+used, libcurl will do the request and read all response headers before handing
+over control to the application.
+
Transfers marked connect only will not reuse any existing connections and
connections marked connect only will not be allowed to get reused.
+
+If the connect only transfer is done using the multi interface, the particular
+easy handle must remain added to the multi handle for as long as the
+application wants to use it. Once it has been removed with
+\fIcurl_multi_remove_handle(3)\fP, \fIcurl_easy_send(3)\fP and
+\fIcurl_easy_recv(3)\fP do not function.
.SH DEFAULT
0
.SH PROTOCOLS
-HTTP, SMTP, POP3 and IMAP
+HTTP, SMTP, POP3 and IMAP. For WS and WSS starting in 7.86.0.
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();
diff --git a/docs/libcurl/opts/CURLOPT_CONNECT_TO.3 b/docs/libcurl/opts/CURLOPT_CONNECT_TO.3
index 8955dd7..89be2ba 100644
--- a/docs/libcurl/opts/CURLOPT_CONNECT_TO.3
+++ b/docs/libcurl/opts/CURLOPT_CONNECT_TO.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CONNECT_TO 3 "10 April 2016" "libcurl 7.49.0" "curl_easy_setopt options"
+.TH CURLOPT_CONNECT_TO 3 "10 April 2016" libcurl libcurl
.SH NAME
CURLOPT_CONNECT_TO \- connect to a specific host and port instead of the URL's host and port
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.3
index 55cf102..2d9fff1 100644
--- a/docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CONV_FROM_NETWORK_FUNCTION 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CONV_FROM_NETWORK_FUNCTION 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CONV_FROM_NETWORK_FUNCTION \- convert data from network to host encoding
.SH SYNOPSIS
@@ -38,7 +38,7 @@
shown above.
Applies to non-ASCII platforms. \fIcurl_version_info(3)\fP will return the
-CURL_VERSION_CONV feature bit set if this option is provided.
+\fBCURL_VERSION_CONV\fP feature bit set if this option is provided.
The data to be converted is in a buffer pointed to by the \fIptr\fP parameter.
The amount of data to convert is indicated by the \fIlength\fP parameter. The
@@ -54,10 +54,10 @@
If you set a callback pointer to NULL, or do not set it at all, the built-in
libcurl iconv functions will be used. If HAVE_ICONV was not defined when
libcurl was built, and no callback has been established, conversion will
-return the CURLE_CONV_REQD error code.
+return the \fBCURLE_CONV_REQD\fP error code.
-If HAVE_ICONV is defined, CURL_ICONV_CODESET_OF_HOST must also be defined.
-For example:
+If \fBHAVE_ICONV\fP is defined, \fBCURL_ICONV_CODESET_OF_HOST\fP must also be
+defined. For example:
\&#define CURL_ICONV_CODESET_OF_HOST "IBM-1047"
@@ -96,7 +96,7 @@
my_conv_from_ascii_to_ebcdic);
.fi
.SH AVAILABILITY
-Not available since 7.82.0
+Not available and deprecated since 7.82.0.
Available only if \fBCURL_DOES_CONVERSIONS\fP was defined when libcurl was
built.
diff --git a/docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.3
index a5479a2..af1a8fe 100644
--- a/docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CONV_FROM_UTF8_FUNCTION 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CONV_FROM_UTF8_FUNCTION 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CONV_FROM_UTF8_FUNCTION \- convert data from UTF8 to host encoding
.SH SYNOPSIS
@@ -94,7 +94,7 @@
my_conv_from_utf8_to_ebcdic);
.fi
.SH AVAILABILITY
-Not available since 7.82.0
+Not available and deprecated since 7.82.0.
Available only if \fBCURL_DOES_CONVERSIONS\fP was defined when libcurl was
built.
diff --git a/docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.3
index 0365524..4fd1243 100644
--- a/docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CONV_TO_NETWORK_FUNCTION 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CONV_TO_NETWORK_FUNCTION 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CONV_TO_NETWORK_FUNCTION \- convert data to network from host encoding
.SH SYNOPSIS
@@ -95,7 +95,7 @@
my_conv_from_ebcdic_to_ascii);
.fi
.SH AVAILABILITY
-Not available since 7.82.0
+Not available and deprecated since 7.82.0.
Available only if \fBCURL_DOES_CONVERSIONS\fP was defined when libcurl was
built.
diff --git a/docs/libcurl/opts/CURLOPT_COOKIE.3 b/docs/libcurl/opts/CURLOPT_COOKIE.3
index 6ff0826..2513de6 100644
--- a/docs/libcurl/opts/CURLOPT_COOKIE.3
+++ b/docs/libcurl/opts/CURLOPT_COOKIE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_COOKIE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_COOKIE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_COOKIE \- HTTP Cookie header
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_COOKIEFILE.3 b/docs/libcurl/opts/CURLOPT_COOKIEFILE.3
index 6f018d6..898d8e1 100644
--- a/docs/libcurl/opts/CURLOPT_COOKIEFILE.3
+++ b/docs/libcurl/opts/CURLOPT_COOKIEFILE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_COOKIEFILE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_COOKIEFILE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_COOKIEFILE \- file name to read cookies from
.SH SYNOPSIS
@@ -40,10 +40,9 @@
It also enables the cookie engine, making libcurl parse and send cookies on
subsequent requests with this handle.
-Given an empty or non-existing file or by passing the empty string ("") to
-this option, you can enable the cookie engine without reading any initial
-cookies. If you tell libcurl the file name is "-" (just a single minus sign),
-libcurl will instead read from stdin.
+By passing the empty string ("") to this option, you enable the cookie engine
+without reading any initial cookies. If you tell libcurl the file name is "-"
+(just a single minus sign), libcurl will instead read from stdin.
This option only \fBreads\fP cookies. To make libcurl write cookies to file,
see \fICURLOPT_COOKIEJAR(3)\fP.
@@ -61,6 +60,11 @@
Setting this option to NULL will (since 7.77.0) explicitly disable the cookie
engine and clear the list of files to read cookies from.
+.SH SECURITY
+This document previously mentioned how specifying a non-existing file can also
+enable the cookie engine. While true, we strongly advise against using that
+method as it is too hard to be sure what files will stay that way in the long
+run.
.SH DEFAULT
NULL
.SH PROTOCOLS
@@ -80,9 +84,8 @@
}
.fi
.SH "Cookie file format"
-The cookie file format and general cookie concepts in curl are described in
-the HTTP-COOKIES.md file, also hosted online here:
-https://curl.se/docs/http-cookies.html
+The cookie file format and general cookie concepts in curl are described
+online here: https://curl.se/docs/http-cookies.html
.SH AVAILABILITY
As long as HTTP is supported
.SH RETURN VALUE
diff --git a/docs/libcurl/opts/CURLOPT_COOKIEJAR.3 b/docs/libcurl/opts/CURLOPT_COOKIEJAR.3
index fa55426..2873573 100644
--- a/docs/libcurl/opts/CURLOPT_COOKIEJAR.3
+++ b/docs/libcurl/opts/CURLOPT_COOKIEJAR.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_COOKIEJAR 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_COOKIEJAR 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_COOKIEJAR \- file name to store cookies to
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_COOKIELIST.3 b/docs/libcurl/opts/CURLOPT_COOKIELIST.3
index 27502a3..849f62e 100644
--- a/docs/libcurl/opts/CURLOPT_COOKIELIST.3
+++ b/docs/libcurl/opts/CURLOPT_COOKIELIST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_COOKIELIST 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_COOKIELIST 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_COOKIELIST \- add to or manipulate cookies held in memory
.SH SYNOPSIS
@@ -107,17 +107,16 @@
curl_easy_cleanup(curl); /* cookies exported to cookies.txt */
.fi
.SH "Cookie file format"
-The cookie file format and general cookie concepts in curl are described in
-the HTTP-COOKIES.md file, also hosted online here:
-https://curl.se/docs/http-cookies.html
+The cookie file format and general cookie concepts in curl are described
+online here: https://curl.se/docs/http-cookies.html
.SH AVAILABILITY
-ALL was added in 7.14.1
+\fBALL\fP was added in 7.14.1
-SESS was added in 7.15.4
+\fBSESS\fP was added in 7.15.4
-FLUSH was added in 7.17.1
+\fBFLUSH\fP was added in 7.17.1
-RELOAD was added in 7.39.0
+\fBRELOAD\fP was added in 7.39.0
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_COOKIESESSION.3 b/docs/libcurl/opts/CURLOPT_COOKIESESSION.3
index 9e9d374..63f92bb 100644
--- a/docs/libcurl/opts/CURLOPT_COOKIESESSION.3
+++ b/docs/libcurl/opts/CURLOPT_COOKIESESSION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_COOKIESESSION 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_COOKIESESSION 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_COOKIESESSION \- start a new cookie session
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.3 b/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.3
index e8040c2..203326b 100644
--- a/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.3
+++ b/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_COPYPOSTFIELDS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_COPYPOSTFIELDS 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_COPYPOSTFIELDS \- have libcurl copy data to POST
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_CRLF.3 b/docs/libcurl/opts/CURLOPT_CRLF.3
index bd32ee7..5e8fedb 100644
--- a/docs/libcurl/opts/CURLOPT_CRLF.3
+++ b/docs/libcurl/opts/CURLOPT_CRLF.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CRLF 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CRLF 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CRLF \- CRLF conversion
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_CRLFILE.3 b/docs/libcurl/opts/CURLOPT_CRLFILE.3
index 6f48c43..3b1e024 100644
--- a/docs/libcurl/opts/CURLOPT_CRLFILE.3
+++ b/docs/libcurl/opts/CURLOPT_CRLFILE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CRLFILE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CRLFILE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CRLFILE \- Certificate Revocation List file
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_CURLU.3 b/docs/libcurl/opts/CURLOPT_CURLU.3
index 6e96fcd..670b136 100644
--- a/docs/libcurl/opts/CURLOPT_CURLU.3
+++ b/docs/libcurl/opts/CURLOPT_CURLU.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CURLU 3 "28 Oct 2018" "libcurl 7.63.0" "curl_easy_setopt options"
+.TH CURLOPT_CURLU 3 "28 Oct 2018" libcurl libcurl
.SH NAME
-CURLOPT_CURLU \- URL in CURLU * format
+CURLOPT_CURLU \- URL in URL handle format
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -33,7 +33,7 @@
.fi
.SH DESCRIPTION
Pass in a pointer to the \fIURL\fP to work with. The parameter should be a
-CURLU *. Setting \fICURLOPT_CURLU(3)\fP will explicitly override
+\fICURLU *\fP. Setting \fICURLOPT_CURLU(3)\fP will explicitly override
\fICURLOPT_URL(3)\fP.
\fICURLOPT_URL(3)\fP or \fICURLOPT_CURLU(3)\fP \fBmust\fP be set before a
diff --git a/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.3 b/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.3
index 065c408..21cf776 100644
--- a/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.3
+++ b/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_CUSTOMREQUEST 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_CUSTOMREQUEST 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_CUSTOMREQUEST \- custom request method
.SH SYNOPSIS
@@ -74,16 +74,16 @@
When you tell libcurl to use a custom request it will behave like a LIST or
RETR command was sent where it expects data to be returned by the server. As
such \fICURLOPT_NOBODY(3)\fP should be used when specifying commands such as
-DELE and NOOP for example.
+\fBDELE\fP and \fBNOOP\fP for example.
.IP SMTP
-Instead of a HELP or VRFY when issuing SMTP based requests.
+Instead of a \fBHELP\fP or \fBVRFY\fP when issuing SMTP based requests.
For example:
-Normally a multiline response is returned which can be used, in conjunction
+Normally a multi line response is returned which can be used, in conjunction
with \fICURLOPT_MAIL_RCPT(3)\fP, to specify an EXPN request. If the
\fICURLOPT_NOBODY(3)\fP option is specified then the request can be used to
-issue NOOP and RSET commands.
+issue \fBNOOP\fP and \fBRSET\fP commands.
The application does not have to keep the string around after setting this
option.
diff --git a/docs/libcurl/opts/CURLOPT_DEBUGDATA.3 b/docs/libcurl/opts/CURLOPT_DEBUGDATA.3
index 90b0b4e..300f50d 100644
--- a/docs/libcurl/opts/CURLOPT_DEBUGDATA.3
+++ b/docs/libcurl/opts/CURLOPT_DEBUGDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DEBUGDATA 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_DEBUGDATA 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_DEBUGDATA \- pointer passed to the debug callback
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3 b/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3
index 6afe1da..98eb378 100644
--- a/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DEBUGFUNCTION 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_DEBUGFUNCTION 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_DEBUGFUNCTION \- debug callback
.SH SYNOPSIS
@@ -44,7 +44,7 @@
curl_infotype type,
char *data,
size_t size,
- void *userptr);
+ void *clientp);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DEBUGFUNCTION,
debug_callback);
@@ -59,9 +59,9 @@
NOT be null-terminated, but will be exactly of the \fIsize\fP as told by the
\fIsize\fP argument.
-The \fIuserptr\fP argument is the pointer set with \fICURLOPT_DEBUGDATA(3)\fP.
+The \fIclientp\fP argument is the pointer set with \fICURLOPT_DEBUGDATA(3)\fP.
-Available curl_infotype values:
+Available \fBcurl_infotype\fP values:
.IP CURLINFO_TEXT
The data is informational text.
.IP CURLINFO_HEADER_IN
@@ -69,7 +69,10 @@
.IP CURLINFO_HEADER_OUT
The data is header (or header-like) data sent to the peer.
.IP CURLINFO_DATA_IN
-The data is protocol data received from the peer.
+The data is the unprocessed protocol data received from the peer. Even if the
+data is encoded or compressed, it will not be provided decoded nor
+decompressed to this callback. If you need the data in decoded and
+decompressed form, use \fICURLOPT_WRITEFUNCTION(3)\fP.
.IP CURLINFO_DATA_OUT
The data is protocol data sent to the peer.
.IP CURLINFO_SSL_DATA_OUT
@@ -117,15 +120,16 @@
static
int my_trace(CURL *handle, curl_infotype type,
char *data, size_t size,
- void *userp)
+ void *clientp)
{
const char *text;
(void)handle; /* prevent compiler warning */
- (void)userp;
+ (void)clientp;
switch (type) {
case CURLINFO_TEXT:
- fprintf(stderr, "== Info: %s", data);
+ fputs("== Info: ", stderr);
+ fwrite(data, size, 1, stderr);
default: /* in case a new one is introduced to shock us */
return 0;
diff --git a/docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.3 b/docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.3
index d0d26bd..303f371 100644
--- a/docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.3
+++ b/docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DEFAULT_PROTOCOL 3 "18 Aug 2015" "libcurl 7.45.0" "curl_easy_setopt options"
+.TH CURLOPT_DEFAULT_PROTOCOL 3 "18 Aug 2015" libcurl libcurl
.SH NAME
CURLOPT_DEFAULT_PROTOCOL \- default protocol to use if the URL is missing a
scheme name
@@ -43,11 +43,11 @@
pop3s, rtsp, scp, sftp, smb, smbs, smtp, smtps, telnet, tftp
An unknown or unsupported protocol causes error
-\fICURLE_UNSUPPORTED_PROTOCOL\fP when libcurl parses a schemeless URL. Parsing
-happens when \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP is
-called. The protocols supported by libcurl will vary depending on how it was
-built. Use \fIcurl_version_info(3)\fP if you need a list of protocol names
-supported by the build of libcurl that you are using.
+\fICURLE_UNSUPPORTED_PROTOCOL\fP when libcurl parses a URL without a
+scheme. Parsing happens when \fIcurl_easy_perform(3)\fP or
+\fIcurl_multi_perform(3)\fP is called. The protocols supported by libcurl will
+vary depending on how it was built. Use \fIcurl_version_info(3)\fP if you need
+a list of protocol names supported by the build of libcurl that you are using.
This option does not change the default proxy protocol (http).
diff --git a/docs/libcurl/opts/CURLOPT_DIRLISTONLY.3 b/docs/libcurl/opts/CURLOPT_DIRLISTONLY.3
index 15e3f3d..57c4cb5 100644
--- a/docs/libcurl/opts/CURLOPT_DIRLISTONLY.3
+++ b/docs/libcurl/opts/CURLOPT_DIRLISTONLY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DIRLISTONLY 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_DIRLISTONLY 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_DIRLISTONLY \- ask for names only in a directory listing
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.3 b/docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.3
index f331b1b..c7c9e69 100644
--- a/docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.3
+++ b/docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DISALLOW_USERNAME_IN_URL 3 "30 May 2018" "libcurl 7.61.0" "curl_easy_setopt options"
+.TH CURLOPT_DISALLOW_USERNAME_IN_URL 3 "30 May 2018" libcurl libcurl
.SH NAME
CURLOPT_DISALLOW_USERNAME_IN_URL \- disallow specifying username in the URL
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.3 b/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.3
index 1033393..1c60f5b 100644
--- a/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.3
+++ b/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DNS_CACHE_TIMEOUT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_DNS_CACHE_TIMEOUT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_DNS_CACHE_TIMEOUT \- life-time for DNS cache entries
.SH SYNOPSIS
@@ -37,15 +37,23 @@
caching, or set to -1 to make the cached entries remain forever. By default,
libcurl caches this info for 60 seconds.
+We recommend users not to tamper with this option unless strictly necessary.
+If you do, be careful of using large values that can make the cache size grow
+significantly if many different host names are used within that timeout
+period.
+
The name resolve functions of various libc implementations do not re-read name
server information unless explicitly told so (for example, by calling
\fIres_init(3)\fP). This may cause libcurl to keep using the older server even
if DHCP has updated the server info, and this may look like a DNS cache issue
to the casual libcurl-app user.
-Note that DNS entries have a "TTL" property but libcurl does not use that. This
-DNS cache timeout is entirely speculative that a name will resolve to the same
+DNS entries have a "TTL" property but libcurl does not use that. This DNS
+cache timeout is entirely speculative that a name will resolve to the same
address for a certain small amount of time into the future.
+
+Since version 8.1.0, libcurl prunes entries from the DNS cache if it exceeds
+30,000 entries no matter which timeout value is used.
.SH DEFAULT
60
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.3 b/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.3
index 699ed67..41d171b 100644
--- a/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.3
+++ b/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DNS_INTERFACE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_DNS_INTERFACE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_DNS_INTERFACE \- interface to speak DNS over
.SH SYNOPSIS
@@ -42,6 +42,7 @@
.SH DEFAULT
NULL
.SH PROTOCOLS
+All protocols except file:// - protocols that resolve host names.
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();
diff --git a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.3 b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.3
index 336b3b0..cce07f6 100644
--- a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.3
+++ b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DNS_LOCAL_IP4 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_DNS_LOCAL_IP4 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_DNS_LOCAL_IP4 \- IPv4 address to bind DNS resolves to
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.3 b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.3
index 13d937b..6fa5113 100644
--- a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.3
+++ b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DNS_LOCAL_IP6 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_DNS_LOCAL_IP6 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_DNS_LOCAL_IP6 \- IPv6 address to bind DNS resolves to
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_DNS_SERVERS.3 b/docs/libcurl/opts/CURLOPT_DNS_SERVERS.3
index ce65b90..4b0ebdb 100644
--- a/docs/libcurl/opts/CURLOPT_DNS_SERVERS.3
+++ b/docs/libcurl/opts/CURLOPT_DNS_SERVERS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DNS_SERVERS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_DNS_SERVERS 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_DNS_SERVERS \- DNS servers to use
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.3 b/docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.3
index 4e5a977..0c52ea0 100644
--- a/docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.3
+++ b/docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DNS_SHUFFLE_ADDRESSES 3 "3 March 2018" "libcurl 7.60.0" "curl_easy_setopt options"
+.TH CURLOPT_DNS_SHUFFLE_ADDRESSES 3 "3 March 2018" libcurl libcurl
.SH NAME
CURLOPT_DNS_SHUFFLE_ADDRESSES \- shuffle IP addresses for hostname
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.3 b/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.3
index 838fe52..790ceec 100644
--- a/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.3
+++ b/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DNS_USE_GLOBAL_CACHE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_DNS_USE_GLOBAL_CACHE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_DNS_USE_GLOBAL_CACHE \- global DNS cache
.SH SYNOPSIS
@@ -59,7 +59,7 @@
}
.fi
.SH AVAILABILITY
-Deprecated since 7.62.0. Has no function.
+Deprecated since 7.11.1. Function removed in 7.62.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.3 b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.3
index 4aa4653..ec4c395 100644
--- a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.3
+++ b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DOH_SSL_VERIFYHOST 3 "11 Feb 2021" "libcurl 7.76.0" "curl_easy_setopt options"
+.TH CURLOPT_DOH_SSL_VERIFYHOST 3 "11 Feb 2021" libcurl libcurl
.SH NAME
CURLOPT_DOH_SSL_VERIFYHOST \- verify the host name in the DoH SSL certificate
.SH SYNOPSIS
@@ -48,7 +48,8 @@
DoH URL to which you told Curl to connect.
When the \fIverify\fP value is set to 1L it is treated the same as 2L. However
-for consistency with the other VERIFYHOST options we suggest use 2 and not 1.
+for consistency with the other \fIVERIFYHOST\fP options we suggest use 2 and
+not 1.
When the \fIverify\fP value is set to 0L, the connection succeeds regardless of
the names used in the certificate. Use that ability with caution!
diff --git a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYPEER.3 b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYPEER.3
index 133f1f3..b802a6f 100644
--- a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYPEER.3
+++ b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYPEER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DOH_SSL_VERIFYPEER 3 "11 Feb 2021" "libcurl 7.76.0" "curl_easy_setopt options"
+.TH CURLOPT_DOH_SSL_VERIFYPEER 3 "11 Feb 2021" libcurl libcurl
.SH NAME
CURLOPT_DOH_SSL_VERIFYPEER \- verify the DoH SSL certificate
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYSTATUS.3 b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYSTATUS.3
index dac570d..5d47d40 100644
--- a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYSTATUS.3
+++ b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYSTATUS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DOH_SSL_VERIFYSTATUS 3 "11 Feb 2021" "libcurl 7.76.0" "curl_easy_setopt options"
+.TH CURLOPT_DOH_SSL_VERIFYSTATUS 3 "11 Feb 2021" libcurl libcurl
.SH NAME
CURLOPT_DOH_SSL_VERIFYSTATUS \- verify the DoH SSL certificate's status
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_DOH_URL.3 b/docs/libcurl/opts/CURLOPT_DOH_URL.3
index d5148d3..2f08155 100644
--- a/docs/libcurl/opts/CURLOPT_DOH_URL.3
+++ b/docs/libcurl/opts/CURLOPT_DOH_URL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_DOH_URL 3 "18 Jun 2018" "libcurl 7.62.0" "curl_easy_setopt options"
+.TH CURLOPT_DOH_URL 3 "18 Jun 2018" libcurl libcurl
.SH NAME
CURLOPT_DOH_URL \- provide the DNS-over-HTTPS URL
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_EGDSOCKET.3 b/docs/libcurl/opts/CURLOPT_EGDSOCKET.3
index 9e5cafb..7a2e75f 100644
--- a/docs/libcurl/opts/CURLOPT_EGDSOCKET.3
+++ b/docs/libcurl/opts/CURLOPT_EGDSOCKET.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_EGDSOCKET 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_EGDSOCKET 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_EGDSOCKET \- EGD socket path
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_ERRORBUFFER.3 b/docs/libcurl/opts/CURLOPT_ERRORBUFFER.3
index e799d51..83beeb5 100644
--- a/docs/libcurl/opts/CURLOPT_ERRORBUFFER.3
+++ b/docs/libcurl/opts/CURLOPT_ERRORBUFFER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_ERRORBUFFER 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_ERRORBUFFER 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_ERRORBUFFER \- error buffer for error messages
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.3 b/docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.3
index 1fc0cf6..78135c0 100644
--- a/docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.3
+++ b/docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_EXPECT_100_TIMEOUT_MS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_EXPECT_100_TIMEOUT_MS 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_EXPECT_100_TIMEOUT_MS \- timeout for Expect: 100-continue response
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_FAILONERROR.3 b/docs/libcurl/opts/CURLOPT_FAILONERROR.3
index a858bf7..966f301 100644
--- a/docs/libcurl/opts/CURLOPT_FAILONERROR.3
+++ b/docs/libcurl/opts/CURLOPT_FAILONERROR.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FAILONERROR 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FAILONERROR 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FAILONERROR \- request failure on HTTP response >= 400
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_FILETIME.3 b/docs/libcurl/opts/CURLOPT_FILETIME.3
index 83d2f04..12cad8c 100644
--- a/docs/libcurl/opts/CURLOPT_FILETIME.3
+++ b/docs/libcurl/opts/CURLOPT_FILETIME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FILETIME 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FILETIME 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FILETIME \- get the modification time of the remote resource
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_FNMATCH_DATA.3 b/docs/libcurl/opts/CURLOPT_FNMATCH_DATA.3
index 8f72756..ed61faf 100644
--- a/docs/libcurl/opts/CURLOPT_FNMATCH_DATA.3
+++ b/docs/libcurl/opts/CURLOPT_FNMATCH_DATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FNMATCH_DATA 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FNMATCH_DATA 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FNMATCH_DATA \- pointer passed to the fnmatch callback
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.3
index ac087c8..22ab4d8 100644
--- a/docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FNMATCH_FUNCTION 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FNMATCH_FUNCTION 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FNMATCH_FUNCTION \- wildcard match callback
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.3 b/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.3
index 0c2f4de..5be8c54 100644
--- a/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.3
+++ b/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FOLLOWLOCATION 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FOLLOWLOCATION 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FOLLOWLOCATION \- follow HTTP 3xx redirects
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_FORBID_REUSE.3 b/docs/libcurl/opts/CURLOPT_FORBID_REUSE.3
index 44c11d4..684fd71 100644
--- a/docs/libcurl/opts/CURLOPT_FORBID_REUSE.3
+++ b/docs/libcurl/opts/CURLOPT_FORBID_REUSE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FORBID_REUSE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FORBID_REUSE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FORBID_REUSE \- make connection get closed at once after use
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_FRESH_CONNECT.3 b/docs/libcurl/opts/CURLOPT_FRESH_CONNECT.3
index 6d01387..804ccf2 100644
--- a/docs/libcurl/opts/CURLOPT_FRESH_CONNECT.3
+++ b/docs/libcurl/opts/CURLOPT_FRESH_CONNECT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FRESH_CONNECT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FRESH_CONNECT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FRESH_CONNECT \- force a new connection to be used
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_FTPPORT.3 b/docs/libcurl/opts/CURLOPT_FTPPORT.3
index b81527d..fc1272b 100644
--- a/docs/libcurl/opts/CURLOPT_FTPPORT.3
+++ b/docs/libcurl/opts/CURLOPT_FTPPORT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FTPPORT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FTPPORT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FTPPORT \- make FTP transfer active
.SH SYNOPSIS
@@ -43,11 +43,11 @@
will not use PORT.
The address can be followed by a ':' to specify a port, optionally followed by
-a '-' to specify a port range. If the port specified is 0, the operating
-system will pick a free port. If a range is provided and all ports in the
+a '-' to specify a port range. If the port specified is 0, the operating
+system will pick a free port. If a range is provided and all ports in the
range are not available, libcurl will report CURLE_FTP_PORT_FAILED for the
-handle. Invalid port/range settings are ignored. IPv6 addresses followed by
-a port or portrange have to be in brackets. IPv6 addresses without port/range
+handle. Invalid port/range settings are ignored. IPv6 addresses followed by a
+port or port range have to be in brackets. IPv6 addresses without port/range
specifier can be in brackets.
Examples with specified ports:
@@ -59,6 +59,11 @@
[::1]:1234-4567
.fi
+We strongly advise against specifying the address with a name, as it causes
+libcurl to do a blocking name resolve call to retrieve the IP address. That
+name resolve operation will \fBnot\fP use DNS-over-HTTPS even if
+\fICURLOPT_DOH_URL(3)\fP is set.
+
You disable PORT again and go back to using the passive version by setting
this option to NULL.
diff --git a/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.3 b/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.3
index cdc499a..6a3ef05 100644
--- a/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.3
+++ b/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FTPSSLAUTH 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FTPSSLAUTH 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FTPSSLAUTH \- order in which to attempt TLS vs SSL
.SH SYNOPSIS
@@ -54,7 +54,7 @@
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);
+ curl_easy_setopt(curl, CURLOPT_FTPSSLAUTH, (long)CURLFTPAUTH_SSL);
ret = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
diff --git a/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.3 b/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.3
index 50db213..7acce08 100644
--- a/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.3
+++ b/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FTP_ACCOUNT 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FTP_ACCOUNT 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FTP_ACCOUNT \- account info for FTP
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.3 b/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.3
index 68e7364..79d7886 100644
--- a/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.3
+++ b/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2014, 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FTP_ALTERNATIVE_TO_USER 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FTP_ALTERNATIVE_TO_USER 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FTP_ALTERNATIVE_TO_USER \- command to use instead of USER with FTP
.SH SYNOPSIS
@@ -63,4 +63,4 @@
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
.SH "SEE ALSO"
-.BR CURLOPT_FTP_SKIP_PASV_IP "(3), " CURLOPT_FTP_RESPONSE_TIMEOUT "(3), "
+.BR CURLOPT_FTP_SKIP_PASV_IP "(3), " CURLOPT_SERVER_RESPONSE_TIMEOUT "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.3 b/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.3
index 3e6c960..6dd062f 100644
--- a/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.3
+++ b/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2014, 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FTP_CREATE_MISSING_DIRS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FTP_CREATE_MISSING_DIRS 3 "19 Jun 2014" libcurl libcurl
.SH NAME
-CURLOPT_FTP_CREATE_MISSING_DIRS \- create missing dirs for FTP and SFTP
+CURLOPT_FTP_CREATE_MISSING_DIRS \- create missing directories for FTP and SFTP
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -51,11 +51,11 @@
permissions prevents creation.
Setting \fIcreate\fP to \fICURLFTP_CREATE_DIR_RETRY\fP (2), tells libcurl to
-retry the CWD command again if the subsequent MKD command fails. This is
+retry the CWD command again if the subsequent \fBMKD\fP command fails. This is
especially useful if you are doing many simultaneous connections against the
same server and they all have this option enabled, as then CWD may first fail
-but then another connection does MKD before this connection and thus MKD fails
-but trying CWD works!
+but then another connection does \fBMKD\fP before this connection and thus
+\fBMKD\fP fails but trying CWD works!
.SH DEFAULT
CURLFTP_CREATE_DIR_NONE (0)
.SH PROTOCOLS
@@ -66,7 +66,7 @@
if(curl) {
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);
+ (long)CURLFTP_CREATE_DIR_RETRY);
ret = curl_easy_perform(curl);
diff --git a/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.3 b/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.3
index cfaab87..99caebf 100644
--- a/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.3
+++ b/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FTP_FILEMETHOD 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FTP_FILEMETHOD 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FTP_FILEMETHOD \- select directory traversing method for FTP
.SH SYNOPSIS
@@ -41,7 +41,7 @@
The argument should be one of the following alternatives:
.IP CURLFTPMETHOD_MULTICWD
libcurl does a single CWD operation for each path part in the given URL. For
-deep hierarchies this means many commands. This is how RFC1738 says it should
+deep hierarchies this means many commands. This is how RFC 1738 says it should
be done. This is the default but the slowest behavior.
.IP CURLFTPMETHOD_NOCWD
libcurl does no CWD at all. libcurl will do SIZE, RETR, STOR etc and give a
@@ -60,7 +60,7 @@
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/1/2/3/4/new.txt");
curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD,
- CURLFTPMETHOD_SINGLECWD);
+ (long)CURLFTPMETHOD_SINGLECWD);
ret = curl_easy_perform(curl);
diff --git a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3
index 7cf1536..86b2ed7 100644
--- a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3
+++ b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FTP_SKIP_PASV_IP 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FTP_SKIP_PASV_IP 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FTP_SKIP_PASV_IP \- ignore the IP address in the PASV response
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.3 b/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.3
index 3d3a68e..690d3a4 100644
--- a/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.3
+++ b/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FTP_SSL_CCC 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FTP_SSL_CCC 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FTP_SSL_CCC \- switch off SSL again with FTP after auth
.SH SYNOPSIS
@@ -55,7 +55,7 @@
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);
+ curl_easy_setopt(curl, CURLOPT_FTP_SSL_CCC, (long)CURLFTPSSL_CCC_ACTIVE);
ret = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
diff --git a/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.3 b/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.3
index 134bd86..a15c917 100644
--- a/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.3
+++ b/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FTP_USE_EPRT 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FTP_USE_EPRT 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FTP_USE_EPRT \- use EPRT for FTP
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.3 b/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.3
index a842d96..7b7d843 100644
--- a/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.3
+++ b/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FTP_USE_EPSV 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FTP_USE_EPSV 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FTP_USE_EPSV \- use EPSV for FTP
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.3 b/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.3
index 48304a3..478cf64 100644
--- a/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.3
+++ b/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FTP_USE_PRET 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_FTP_USE_PRET 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_FTP_USE_PRET \- use PRET for FTP
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.3 b/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.3
index a4ffa4e..66b7f49 100644
--- a/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.3
+++ b/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_GSSAPI_DELEGATION 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_GSSAPI_DELEGATION 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_GSSAPI_DELEGATION \- allowed GSS-API delegation
.SH SYNOPSIS
@@ -37,7 +37,7 @@
by default since 7.21.7. Set the parameter to
\fBCURLGSSAPI_DELEGATION_POLICY_FLAG\fP to delegate only if the OK-AS-DELEGATE
flag is set in the service ticket in case this feature is supported by the
-GSS-API implementation and the definition of GSS_C_DELEG_POLICY_FLAG was
+GSS-API implementation and the definition of \fIGSS_C_DELEG_POLICY_FLAG\fP was
available at compile-time.
.SH DEFAULT
CURLGSSAPI_DELEGATION_NONE
@@ -51,7 +51,7 @@
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);
+ (long)CURLGSSAPI_DELEGATION_POLICY_FLAG);
ret = curl_easy_perform(curl);
}
.fi
diff --git a/docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 b/docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3
index b2abceb..2057fbe 100644
--- a/docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3
+++ b/docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS 3 "1 Feb 2018" "libcurl 7.59.0" "curl_easy_setopt options"
+.TH CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS 3 "1 Feb 2018" libcurl libcurl
.SH NAME
-CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS \- head start for ipv6 for happy eyeballs
+CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS \- head start for IPv6 for happy eyeballs
.SH SYNOPSIS
.nf
#include <curl/curl.h>
diff --git a/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.3 b/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.3
index d99c335..dab0a1f 100644
--- a/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.3
+++ b/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HAPROXYPROTOCOL 3 "5 Feb 2018" "libcurl 7.60.0" "curl_easy_setopt options"
+.TH CURLOPT_HAPROXYPROTOCOL 3 "5 Feb 2018" libcurl libcurl
.SH NAME
CURLOPT_HAPROXYPROTOCOL \- send HAProxy PROXY protocol v1 header
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.3 b/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.3
new file mode 100644
index 0000000..6c54ee8
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.3
@@ -0,0 +1,63 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_HAPROXY_CLIENT_IP 3 "8 May 2023" libcurl libcurl
+.SH NAME
+CURLOPT_HAPROXY_CLIENT_IP \- set HAProxy PROXY protocol client IP
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HAPROXY_CLIENT_IP,
+ char *client_ip);
+.fi
+.SH DESCRIPTION
+When this parameter is set to a valid IPv4 or IPv6, the library will
+not send this address in the HAProxy PROXY protocol
+v1 header at beginning of the connection.
+
+This option is primarily useful when sending test requests to verify that
+a service is working as intended.
+
+.SH DEFAULT
+no HAProxy header will be sent
+.SH PROTOCOLS
+HTTP, HAProxy PROTOCOL
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_HAPROXY_CLIENT_IP, "1.1.1.1");
+ ret = curl_easy_perform(curl);
+}
+.fi
+.SH AVAILABILITY
+Along with HTTP. Added in 8.2.0.
+.SH RETURN VALUE
+Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
+.SH SEE ALSO
+.BR CURLOPT_PROXY "(3), "
+.BR CURLOPT_HAPROXYPROTOCOL "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_HEADER.3 b/docs/libcurl/opts/CURLOPT_HEADER.3
index aaea079..a86fa56 100644
--- a/docs/libcurl/opts/CURLOPT_HEADER.3
+++ b/docs/libcurl/opts/CURLOPT_HEADER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HEADER 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_HEADER 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_HEADER \- pass headers to the data stream
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_HEADERDATA.3 b/docs/libcurl/opts/CURLOPT_HEADERDATA.3
index ab04724..c5751be 100644
--- a/docs/libcurl/opts/CURLOPT_HEADERDATA.3
+++ b/docs/libcurl/opts/CURLOPT_HEADERDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HEADERDATA 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_HEADERDATA 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_HEADERDATA \- pointer to pass to header callback
.SH SYNOPSIS
@@ -40,6 +40,10 @@
If neither of those options are set, \fIpointer\fP must be a valid FILE * and
it will be used by a plain fwrite() to write headers to.
+
+If you are using libcurl as a win32 DLL, you \fBMUST\fP use a
+\fICURLOPT_WRITEFUNCTION(3)\fP or \fICURLOPT_HEADERFUNCTION(3)\fP if you set
+this option or you will experience crashes.
.SH DEFAULT
NULL
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3 b/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3
index 1aff4cf..92691f9 100644
--- a/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HEADERFUNCTION 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_HEADERFUNCTION 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_HEADERFUNCTION \- callback that receives header data
.SH SYNOPSIS
@@ -51,10 +51,12 @@
The pointer named \fIuserdata\fP is the one you set with the
\fICURLOPT_HEADERDATA(3)\fP option.
-This callback function must return the number of bytes actually taken care of.
-If that amount differs from the amount passed in to your function, it will signal
-an error to the library. This will cause the transfer to get aborted and the
-libcurl function in progress will return \fICURLE_WRITE_ERROR\fP.
+Your callback should return the number of bytes actually taken care of. If
+that amount differs from the amount passed to your callback function, it will
+signal an error condition to the library. This will cause the transfer to get
+aborted and the libcurl function used will return \fICURLE_WRITE_ERROR\fP.
+
+You can also abort the transfer by returning CURL_WRITEFUNC_ERROR. (7.87.0)
A complete HTTP header that is passed to this function can be up to
\fICURL_MAX_HTTP_HEADER\fP (100K) bytes and includes the final line terminator.
diff --git a/docs/libcurl/opts/CURLOPT_HEADEROPT.3 b/docs/libcurl/opts/CURLOPT_HEADEROPT.3
index fb8625b..499dcb6 100644
--- a/docs/libcurl/opts/CURLOPT_HEADEROPT.3
+++ b/docs/libcurl/opts/CURLOPT_HEADEROPT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HEADEROPT 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_HEADEROPT 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_HEADEROPT \- send HTTP headers to both proxy and host or separately
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_HSTS.3 b/docs/libcurl/opts/CURLOPT_HSTS.3
index f44f405..2d4eb94 100644
--- a/docs/libcurl/opts/CURLOPT_HSTS.3
+++ b/docs/libcurl/opts/CURLOPT_HSTS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HSTS 3 "5 Feb 2019" "libcurl 7.74.0" "curl_easy_setopt options"
+.TH CURLOPT_HSTS 3 "5 Feb 2019" libcurl libcurl
.SH NAME
CURLOPT_HSTS \- HSTS cache file name
.SH SYNOPSIS
@@ -50,8 +50,8 @@
[host] [stamp]
[host] is the domain name for the entry and the name is dot-prefixed if it is
-a includeSubDomain entry (if the entry is valid for all subdmains to the name
-as well or only for the exact name).
+an entry valid for all subdomains to the name as well or only for the exact
+name.
[stamp] is the time (in UTC) when the entry expires and it uses the format
\&"YYYYMMDD HH:MM:SS".
diff --git a/docs/libcurl/opts/CURLOPT_HSTSREADDATA.3 b/docs/libcurl/opts/CURLOPT_HSTSREADDATA.3
index 16f255d..cd82134 100644
--- a/docs/libcurl/opts/CURLOPT_HSTSREADDATA.3
+++ b/docs/libcurl/opts/CURLOPT_HSTSREADDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HSTSREADDATA 3 "14 Sep 2020" "libcurl 7.74.0" "curl_easy_setopt options"
+.TH CURLOPT_HSTSREADDATA 3 "14 Sep 2020" libcurl libcurl
.SH NAME
CURLOPT_HSTSREADDATA \- pointer passed to the HSTS read callback
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3 b/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3
index 2026124a..83c6f0a 100644
--- a/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HSTSREADFUNCTION 3 "14 Sep 2020" "libcurl 7.74.0" "curl_easy_setopt options"
+.TH CURLOPT_HSTSREADFUNCTION 3 "14 Sep 2020" libcurl libcurl
.SH NAME
CURLOPT_HSTSREADFUNCTION \- read callback for HSTS hosts
.SH SYNOPSIS
@@ -36,7 +36,7 @@
char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */
};
-CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *sts, void *userp);
+CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *sts, void *clientp);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSREADFUNCTION, hstsread);
.fi
@@ -46,14 +46,14 @@
This callback function gets called by libcurl repeatedly when it populates the
in-memory HSTS cache.
-Set the \fIuserp\fP argument with the \fICURLOPT_HSTSREADDATA(3)\fP option or
-it will be NULL.
+Set the \fIclientp\fP argument with the \fICURLOPT_HSTSREADDATA(3)\fP option
+or it will be NULL.
When this callback is invoked, the \fIsts\fP pointer points to a populated
-struct: Copy the host name to 'name' (no longer than 'namelen' bytes). Make it
-null-terminated. Set 'includeSubDomains' to TRUE or FALSE. Set 'expire' to a
-date stamp or a zero length string for *forever* (wrong date stamp format
-might cause the name to not get accepted)
+struct: Copy the host name to \fIname\fP (no longer than \fInamelen\fP
+bytes). Make it null-terminated. Set \fIincludeSubDomains\fP to TRUE or
+FALSE. Set \fIexpire\fP to a date stamp or a zero length string for *forever*
+(wrong date stamp format might cause the name to not get accepted)
The callback should return \fICURLSTS_OK\fP if it returns a name and is
prepared to be called again (for another host) or \fICURLSTS_DONE\fP if it has
diff --git a/docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.3 b/docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.3
index 6f05e48..49659b2 100644
--- a/docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.3
+++ b/docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HSTSWRITEDATA 3 "14 Sep 2020" "libcurl 7.74.0" "curl_easy_setopt options"
+.TH CURLOPT_HSTSWRITEDATA 3 "14 Sep 2020" libcurl libcurl
.SH NAME
CURLOPT_HSTSWRITEDATA \- pointer passed to the HSTS write callback
.SH SYNOPSIS
@@ -34,7 +34,7 @@
.SH DESCRIPTION
Data \fIpointer\fP to pass to the HSTS write function. If you use the
\fICURLOPT_HSTSWRITEFUNCTION(3)\fP option, this is the pointer you will get as
-input in the 4th argument to the callback.
+input in the fourth argument to the callback.
This option does not enable HSTS, you need to use \fICURLOPT_HSTS_CTRL(3)\fP to
do that.
diff --git a/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.3 b/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.3
index 5d7a8c4..2da223f 100644
--- a/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HSTSWRITEFUNCTION 3 "14 Sep 2020" "libcurl 7.74.0" "curl_easy_setopt options"
+.TH CURLOPT_HSTSWRITEFUNCTION 3 "14 Sep 2020" libcurl libcurl
.SH NAME
CURLOPT_HSTSWRITEFUNCTION \- write callback for HSTS hosts
.SH SYNOPSIS
@@ -42,7 +42,7 @@
};
CURLSTScode hstswrite(CURL *easy, struct curl_hstsentry *sts,
- struct curl_index *count, void *userp);
+ struct curl_index *count, void *clientp);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSWRITEFUNCTION, hstswrite);
.fi
@@ -53,14 +53,14 @@
application to store the in-memory HSTS cache when libcurl is about to discard
it.
-Set the \fIuserp\fP argument with the \fICURLOPT_HSTSWRITEDATA(3)\fP option or
-it will be NULL.
+Set the \fIclientp\fP argument with the \fICURLOPT_HSTSWRITEDATA(3)\fP option
+or it will be NULL.
When the callback is invoked, the \fIsts\fP pointer points to a populated
-struct: Read the host name to 'name' (it is 'namelen' bytes long and null
-terminated. The 'includeSubDomains' field is non-zero if the entry matches
-subdomains. The 'expire' string is a date stamp null-terminated string using
-the syntax YYYYMMDD HH:MM:SS.
+struct: Read the host name to 'name' (it is \fInamelen\fP bytes long and null
+terminated. The \fIincludeSubDomains\fP field is non-zero if the entry matches
+subdomains. The \fIexpire\fP string is a date stamp null-terminated string
+using the syntax YYYYMMDD HH:MM:SS.
The callback should return \fICURLSTS_OK\fP if it succeeded and is prepared to
be called again (for another host) or \fICURLSTS_DONE\fP if there's nothing
diff --git a/docs/libcurl/opts/CURLOPT_HSTS_CTRL.3 b/docs/libcurl/opts/CURLOPT_HSTS_CTRL.3
index 76f9004..8f7801d 100644
--- a/docs/libcurl/opts/CURLOPT_HSTS_CTRL.3
+++ b/docs/libcurl/opts/CURLOPT_HSTS_CTRL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022, 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HSTS_CTRL 3 "4 Sep 2020" "libcurl 7.74.0" "curl_easy_setopt options"
+.TH CURLOPT_HSTS_CTRL 3 "4 Sep 2020" libcurl libcurl
.SH NAME
CURLOPT_HSTS_CTRL \- control HSTS behavior
.SH SYNOPSIS
@@ -57,7 +57,7 @@
.nf
CURL *curl = curl_easy_init();
if(curl) {
- curl_easy_setopt(curl, CURLOPT_HSTS_CTRL, CURLHSTS_ENABLE);
+ curl_easy_setopt(curl, CURLOPT_HSTS_CTRL, (long)CURLHSTS_ENABLE);
curl_easy_perform(curl);
}
.fi
diff --git a/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3 b/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3
index 0ed43de..f3e1e62 100644
--- a/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3
+++ b/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HTTP09_ALLOWED 3 "17 Dec 2018" "libcurl 7.64.0" "curl_easy_setopt options"
+.TH CURLOPT_HTTP09_ALLOWED 3 "17 Dec 2018" libcurl libcurl
.SH NAME
CURLOPT_HTTP09_ALLOWED \- allow HTTP/0.9 response
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_HTTP200ALIASES.3 b/docs/libcurl/opts/CURLOPT_HTTP200ALIASES.3
index 9ad75c6..b0fde4d 100644
--- a/docs/libcurl/opts/CURLOPT_HTTP200ALIASES.3
+++ b/docs/libcurl/opts/CURLOPT_HTTP200ALIASES.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HTTP200ALIASES 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_HTTP200ALIASES 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_HTTP200ALIASES \- alternative matches for HTTP 200 OK
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_HTTPAUTH.3 b/docs/libcurl/opts/CURLOPT_HTTPAUTH.3
index 1984870..e7e1fea 100644
--- a/docs/libcurl/opts/CURLOPT_HTTPAUTH.3
+++ b/docs/libcurl/opts/CURLOPT_HTTPAUTH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HTTPAUTH 3 "2 Aug 2014" "libcurl 7.38.0" "curl_easy_setopt options"
+.TH CURLOPT_HTTPAUTH 3 "2 Aug 2014" libcurl libcurl
.SH NAME
CURLOPT_HTTPAUTH \- HTTP server authentication methods to try
.SH SYNOPSIS
@@ -49,12 +49,12 @@
the user name and password over the network in plain text, easily captured by
others.
.IP CURLAUTH_DIGEST
-HTTP Digest authentication. Digest authentication is defined in RFC2617 and
+HTTP Digest authentication. Digest authentication is defined in RFC 2617 and
is a more secure way to do authentication over public networks than the
regular old-fashioned Basic method.
.IP CURLAUTH_DIGEST_IE
HTTP Digest authentication with an IE flavor. Digest authentication is
-defined in RFC2617 and is a more secure way to do authentication over public
+defined in RFC 2617 and is a more secure way to do authentication over public
networks than the regular old-fashioned Basic method. The IE flavor is simply
that libcurl will use a special "quirk" that IE is known to have used before
version 7 and that some servers require the client to use.
@@ -78,11 +78,11 @@
.IP CURLAUTH_NTLM_WB
NTLM delegating to winbind helper. Authentication is performed by a separate
binary application that is executed when needed. The name of the application
-is specified at compile time but is typically /usr/bin/ntlm_auth
+is specified at compile time but is typically \fB/usr/bin/ntlm_auth\fP.
Note that libcurl will fork when necessary to run the winbind application and
-kill it when complete, calling waitpid() to await its exit when done. On POSIX
-operating systems, killing the process will cause a SIGCHLD signal to be
+kill it when complete, calling \fBwaitpid()\fP to await its exit when done. On
+POSIX operating systems, killing the process will cause a SIGCHLD signal to be
raised (regardless of whether \fICURLOPT_NOSIGNAL(3)\fP is set), which must be
handled intelligently by the application. In particular, the application must
not unconditionally call wait() in its SIGCHLD signal handler to avoid being
@@ -98,7 +98,7 @@
it finds most secure.
.IP CURLAUTH_ONLY
This is a meta symbol. OR this value together with a single specific auth
-value to force libcurl to probe for un-restricted auth and if not, only that
+value to force libcurl to probe for unrestricted auth and if not, only that
single auth algorithm is acceptable.
.IP CURLAUTH_AWS_SIGV4
provides AWS V4 signature authentication on HTTPS header
@@ -114,7 +114,7 @@
CURLcode ret;
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_HTTPAUTH, (long)CURLAUTH_ANY);
curl_easy_setopt(curl, CURLOPT_USERPWD, "james:bond");
ret = curl_easy_perform(curl);
}
diff --git a/docs/libcurl/opts/CURLOPT_HTTPGET.3 b/docs/libcurl/opts/CURLOPT_HTTPGET.3
index 759d0e2..19104fb 100644
--- a/docs/libcurl/opts/CURLOPT_HTTPGET.3
+++ b/docs/libcurl/opts/CURLOPT_HTTPGET.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HTTPGET 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_HTTPGET 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_HTTPGET \- ask for an HTTP GET request
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_HTTPHEADER.3 b/docs/libcurl/opts/CURLOPT_HTTPHEADER.3
index 933609f..c989b43 100644
--- a/docs/libcurl/opts/CURLOPT_HTTPHEADER.3
+++ b/docs/libcurl/opts/CURLOPT_HTTPHEADER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HTTPHEADER 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_HTTPHEADER 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_HTTPHEADER \- set of HTTP headers
.SH SYNOPSIS
@@ -37,6 +37,11 @@
proxy in your HTTP request. The same list can be used for both host and proxy
requests!
+When used within an IMAP or SMTP request to upload a MIME mail, the given
+header list establishes the document-level MIME headers to prepend to the
+uploaded document described by \fICURLOPT_MIMEPOST(3)\fP. This does not affect
+raw mail uploads.
+
The linked list should be a fully valid list of \fBstruct curl_slist\fP
structs properly filled in. Use \fIcurl_slist_append(3)\fP to create the list
and \fIcurl_slist_free_all(3)\fP to clean up an entire list. If you add a
@@ -45,16 +50,15 @@
(no data on the right side of the colon), the internally used header will get
disabled. With this option you can add new headers, replace internal headers
and remove internal headers. To add a header with no content (nothing to the
-right side of the colon), use the form 'MyHeader;' (note the ending
-semicolon).
+right side of the colon), use the form 'name;' (note the ending semicolon).
The headers included in the linked list \fBmust not\fP be CRLF-terminated,
because libcurl adds CRLF after each header item. Failure to comply with this
will result in strange bugs because the server will most likely ignore part of
the headers you specified.
-The first line in a request (containing the method, usually a GET or POST) is
-not a header and cannot be replaced using this option. Only the lines
+The first line in an HTTP request (containing the method, usually a GET or
+POST) is not a header and cannot be replaced using this option. Only the lines
following the request-line are headers. Adding this method line in this list
of headers will only cause your request to send an invalid header. Use
\fICURLOPT_CUSTOMREQUEST(3)\fP to change the method.
@@ -66,14 +70,14 @@
Pass a NULL to this option to reset back to no custom headers.
-The most commonly replaced headers have "shortcuts" in the options
+The most commonly replaced HTTP headers have "shortcuts" in the options
\fICURLOPT_COOKIE(3)\fP, \fICURLOPT_USERAGENT(3)\fP and
\fICURLOPT_REFERER(3)\fP. We recommend using those.
There's an alternative option that sets or replaces headers only for requests
that are sent with CONNECT to a proxy: \fICURLOPT_PROXYHEADER(3)\fP. Use
\fICURLOPT_HEADEROPT(3)\fP to control the behavior.
-.SH SPECIFIC HEADERS
+.SH SPECIFIC HTTP HEADERS
Setting some specific headers will cause libcurl to act differently.
.IP "Host:"
The specified host name will be used for cookie matching if the cookie engine
@@ -83,6 +87,24 @@
.IP "Transfer-Encoding: chunked"
Tells libcurl the upload is to be done using this chunked encoding instead of
providing the Content-Length: field in the request.
+.SH SPECIFIC MIME HEADERS
+When used to build a MIME e-mail for IMAP or SMTP, the following
+document-level headers can be set to override libcurl-generated values:
+.IP "Mime-Version:"
+Tells the parser at the receiving site how to interpret the MIME framing.
+It defaults to "1.0" and should normally not be altered.
+.IP "Content-Type:"
+Indicates the document's global structure type. By default, libcurl sets it
+to "multipart/mixed", describing a document made of independent parts. When a
+MIME mail is only composed of alternative representations of the same data
+(i.e.: HTML and plain text), this header must be set to "multipart/alternative".
+In all cases the value must be of the form "multipart/*" to respect the
+document structure and may not include the "boundary=" parameter.
+.P
+Other specific headers that do not have a libcurl default value but are
+strongly desired by mail delivery and user agents should also be included.
+These are "From:", "To:", "Date:" and "Subject:" among others and their
+presence and value is generally checked by anti-spam utilities.
.SH SECURITY CONCERNS
By default, this option makes libcurl send the given headers in all HTTP
requests done by this handle. You should therefore use this option with
@@ -109,7 +131,7 @@
.SH DEFAULT
NULL
.SH PROTOCOLS
-HTTP
+HTTP, IMAP and SMTP
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();
@@ -131,9 +153,10 @@
.fi
.SH AVAILABILITY
-As long as HTTP is enabled
+As long as HTTP is enabled. Use in MIME mail added in 7.56.0.
.SH RETURN VALUE
Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
.BR CURLOPT_CUSTOMREQUEST "(3), " CURLOPT_HEADEROPT "(3), "
-.BR CURLOPT_PROXYHEADER "(3), " CURLOPT_HEADER "(3)"
+.BR CURLOPT_PROXYHEADER "(3), " CURLOPT_HEADER "(3), "
+.BR CURLOPT_MIMEPOST "(3), " curl_mime_init "(3)"
diff --git a/docs/libcurl/opts/CURLOPT_HTTPPOST.3 b/docs/libcurl/opts/CURLOPT_HTTPPOST.3
index 4be1316..2c64795 100644
--- a/docs/libcurl/opts/CURLOPT_HTTPPOST.3
+++ b/docs/libcurl/opts/CURLOPT_HTTPPOST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HTTPPOST 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_HTTPPOST 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_HTTPPOST \- multipart formpost content
.SH SYNOPSIS
@@ -32,10 +32,12 @@
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPPOST,
struct curl_httppost *formpost);
.SH DESCRIPTION
-Tells libcurl you want a multipart/formdata HTTP POST to be made and you
+\fBThis option is deprecated.\fP Use \fICURLOPT_MIMEPOST(3)\fP instead.
+
+Tells libcurl you want a \fBmultipart/formdata\fP HTTP POST to be made and you
instruct what data to pass on to the server in the \fIformpost\fP argument.
-Pass a pointer to a linked list of curl_httppost structs as parameter. The
-easiest way to create such a list, is to use \fIcurl_formadd(3)\fP as
+Pass a pointer to a linked list of \fIcurl_httppost\fP structs as parameter.
+The easiest way to create such a list, is to use \fIcurl_formadd(3)\fP as
documented. The data in this list must remain intact as long as the curl
transfer is alive and is using it.
@@ -44,9 +46,6 @@
When setting \fICURLOPT_HTTPPOST(3)\fP, it will automatically set
\fICURLOPT_NOBODY(3)\fP to 0.
-
-This option is deprecated! Do not use it. Use \fICURLOPT_MIMEPOST(3)\fP
-instead after having prepared mime data.
.SH DEFAULT
NULL
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.3 b/docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.3
index cd6dd94..3d9f557 100644
--- a/docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.3
+++ b/docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HTTPPROXYTUNNEL 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_HTTPPROXYTUNNEL 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_HTTPPROXYTUNNEL \- tunnel through HTTP proxy
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.3 b/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.3
index 2d6d742..ddbd4be 100644
--- a/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.3
+++ b/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HTTP_CONTENT_DECODING 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_HTTP_CONTENT_DECODING 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_HTTP_CONTENT_DECODING \- HTTP content decoding control
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.3 b/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.3
index e34169e..899d074 100644
--- a/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.3
+++ b/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HTTP_TRANSFER_DECODING 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_HTTP_TRANSFER_DECODING 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_HTTP_TRANSFER_DECODING \- HTTP transfer decoding control
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3 b/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3
index c0a2a71..0b5be1c 100644
--- a/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3
+++ b/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_HTTP_VERSION 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_HTTP_VERSION 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_HTTP_VERSION \- HTTP protocol version to use
.SH SYNOPSIS
@@ -66,13 +66,12 @@
will still do HTTP/2 the standard way with negotiated protocol version in the
TLS handshake. (Added in 7.49.0)
.IP CURL_HTTP_VERSION_3
-(Added in 7.66.0) Setting this value will make libcurl attempt to use HTTP/3
-directly to server given in the URL. Note that this cannot gracefully
-downgrade to earlier HTTP version if the server does not support HTTP/3.
-
-For more reliably upgrading to HTTP/3, set the preferred version to something
-lower and let the server announce its HTTP/3 support via Alt-Svc:. See
-\fICURLOPT_ALTSVC(3)\fP.
+(Added in 7.66.0) This option makes libcurl attempt to use HTTP/3 to the host
+given in the URL, with fallback to earlier HTTP versions if needed.
+.IP CURL_HTTP_VERSION_3ONLY
+(Added in 7.88.0) Setting this value will make libcurl attempt to use HTTP/3
+directly to server given in the URL but will not downgrade to earlier HTTP
+version if the server does not support HTTP/3.
.SH DEFAULT
Since curl 7.62.0: CURL_HTTP_VERSION_2TLS
@@ -85,7 +84,8 @@
if(curl) {
CURLcode ret;
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
+ curl_easy_setopt(curl, CURLOPT_HTTP_VERSION,
+ (long)CURL_HTTP_VERSION_2TLS);
ret = curl_easy_perform(curl);
if(ret == CURLE_HTTP_RETURNED_ERROR) {
/* an HTTP response error problem */
diff --git a/docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.3 b/docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.3
index 9247ddc..3f9502c 100644
--- a/docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.3
+++ b/docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_IGNORE_CONTENT_LENGTH 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_IGNORE_CONTENT_LENGTH 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_IGNORE_CONTENT_LENGTH \- ignore content length
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_INFILESIZE.3 b/docs/libcurl/opts/CURLOPT_INFILESIZE.3
index 23e3bff..86961de 100644
--- a/docs/libcurl/opts/CURLOPT_INFILESIZE.3
+++ b/docs/libcurl/opts/CURLOPT_INFILESIZE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_INFILESIZE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_INFILESIZE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_INFILESIZE \- size of the input file to send off
.SH SYNOPSIS
@@ -42,6 +42,9 @@
To unset this value again, set it to -1.
+Using \fICURLOPT_UPLOAD(3)\fP to a HTTP/1.1 server and this value set to -1,
+makes libcurl do a chunked transfer-encoded upload.
+
When sending emails using SMTP, this command can be used to specify the
optional SIZE parameter for the MAIL FROM command.
diff --git a/docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.3 b/docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.3
index d96d048..5d62e16 100644
--- a/docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.3
+++ b/docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_INFILESIZE_LARGE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_INFILESIZE_LARGE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_INFILESIZE_LARGE \- size of the input file to send off
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_INTERFACE.3 b/docs/libcurl/opts/CURLOPT_INTERFACE.3
index 9cb4788..e8c9c7a 100644
--- a/docs/libcurl/opts/CURLOPT_INTERFACE.3
+++ b/docs/libcurl/opts/CURLOPT_INTERFACE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_INTERFACE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_INTERFACE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_INTERFACE \- source interface for outgoing traffic
.SH SYNOPSIS
@@ -38,16 +38,21 @@
If the parameter starts with "if!" then it is treated as only as interface
name and no attempt will ever be named to do treat it as an IP address or to
-do name resolution on it. If the parameter starts with \&"host!" it is
-treated as either an IP address or a hostname. Hostnames are resolved
-synchronously. Using the if! format is highly recommended when using the
-multi interfaces to avoid allowing the code to block. If "if!" is specified
-but the parameter does not match an existing interface, CURLE_INTERFACE_FAILED
-is returned from the libcurl function used to perform the transfer.
+do name resolution on it. If the parameter starts with \&"host!" it is treated
+as either an IP address or a hostname.
+
+If "if!" is specified but the parameter does not match an existing interface,
+\fICURLE_INTERFACE_FAILED\fP is returned from the libcurl function used to
+perform the transfer.
libcurl does not support using network interface names for this option on
Windows.
+We strongly advise against specifying the interface with a hostname, as it
+causes libcurl to do a blocking name resolve call to retrieve the IP
+address. That name resolve operation will \fBnot\fP use DNS-over-HTTPS even if
+\fICURLOPT_DOH_URL(3)\fP is set.
+
The application does not have to keep the string around after setting this
option.
.SH DEFAULT
diff --git a/docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.3 b/docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.3
index 7370aa9..be4cb19 100644
--- a/docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.3
+++ b/docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_INTERLEAVEDATA 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_INTERLEAVEDATA 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_INTERLEAVEDATA \- pointer passed to RTSP interleave callback
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.3 b/docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.3
index 8038a2c..fbdf3db 100644
--- a/docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_INTERLEAVEFUNCTION 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_INTERLEAVEFUNCTION 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_INTERLEAVEFUNCTION \- callback for RTSP interleaved data
.SH SYNOPSIS
@@ -44,9 +44,8 @@
writes the interleaved header as well as the included data for each call. The
first byte is always an ASCII dollar sign. The dollar sign is followed by a
one byte channel identifier and then a 2 byte integer length in network byte
-order. See \fIRFC2326 Section 10.12\fP for more information on how RTP
-interleaving behaves. If unset or set to NULL, curl will use the default write
-function.
+order. See RFC 2326 Section 10.12 for more information on how RTP interleaving
+behaves. If unset or set to NULL, curl will use the default write function.
Interleaved RTP poses some challenges for the client application. Since the
stream data is sharing the RTSP control connection, it is critical to service
@@ -59,6 +58,13 @@
The \fICURLOPT_INTERLEAVEDATA(3)\fP is passed in the \fIuserdata\fP argument in
the callback.
+
+Your callback should return the number of bytes actually taken care of. If
+that amount differs from the amount passed to your callback function, it will
+signal an error condition to the library. This will cause the transfer to get
+aborted and the libcurl function used will return \fICURLE_WRITE_ERROR\fP.
+
+You can also abort the transfer by returning CURL_WRITEFUNC_ERROR. (7.87.0)
.SH DEFAULT
NULL, the interleave data is then passed to the regular write function:
\fICURLOPT_WRITEFUNCTION(3)\fP.
diff --git a/docs/libcurl/opts/CURLOPT_IOCTLDATA.3 b/docs/libcurl/opts/CURLOPT_IOCTLDATA.3
index 7029d9c..5d18393 100644
--- a/docs/libcurl/opts/CURLOPT_IOCTLDATA.3
+++ b/docs/libcurl/opts/CURLOPT_IOCTLDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_IOCTLDATA 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_IOCTLDATA 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_IOCTLDATA \- pointer passed to I/O callback
.SH SYNOPSIS
@@ -57,7 +57,7 @@
}
.fi
.SH AVAILABILITY
-Added in 7.12.3
+Added in 7.12.3. Deprecated since 7.18.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.3 b/docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.3
index 49c0987..f2ec3b4 100644
--- a/docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_IOCTLFUNCTION 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_IOCTLFUNCTION 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_IOCTLFUNCTION \- callback for I/O operations
.SH SYNOPSIS
@@ -87,7 +87,7 @@
}
.fi
.SH AVAILABILITY
-Added in 7.12.3
+Added in 7.12.3. Deprecated since 7.18.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLOPT_IPRESOLVE.3 b/docs/libcurl/opts/CURLOPT_IPRESOLVE.3
index 642becd..ec9d6b7 100644
--- a/docs/libcurl/opts/CURLOPT_IPRESOLVE.3
+++ b/docs/libcurl/opts/CURLOPT_IPRESOLVE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_IPRESOLVE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_IPRESOLVE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_IPRESOLVE \- IP protocol version to use
.SH SYNOPSIS
@@ -34,8 +34,13 @@
.SH DESCRIPTION
Allows an application to select what kind of IP addresses to use when
establishing a connection or choosing one from the connection pool. This is
-interesting when using host names that resolve addresses using more than
-one version of IP. The allowed values are:
+interesting when using host names that resolve to more than one version of IP.
+
+If the URL provided for a transfer contains a numerical IP version as a host
+name, this option will not override or prohibit libcurl from using that IP
+version.
+
+Available values for this option are:
.IP CURL_IPRESOLVE_WHATEVER
Default, can use addresses of all IP versions that your system allows.
.IP CURL_IPRESOLVE_V4
diff --git a/docs/libcurl/opts/CURLOPT_ISSUERCERT.3 b/docs/libcurl/opts/CURLOPT_ISSUERCERT.3
index f77e35d..ef03e65 100644
--- a/docs/libcurl/opts/CURLOPT_ISSUERCERT.3
+++ b/docs/libcurl/opts/CURLOPT_ISSUERCERT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_ISSUERCERT 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_ISSUERCERT 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_ISSUERCERT \- issuer SSL certificate filename
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.3 b/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.3
index d9ca824..3e07066 100644
--- a/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.3
+++ b/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_ISSUERCERT_BLOB 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.TH CURLOPT_ISSUERCERT_BLOB 3 "24 Jun 2020" libcurl libcurl
.SH NAME
CURLOPT_ISSUERCERT_BLOB \- issuer SSL certificate from memory blob
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.3 b/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.3
index ef3b52e..816a19f 100644
--- a/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.3
+++ b/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_KEEP_SENDING_ON_ERROR 3 "22 Sep 2016" "libcurl 7.51.0" "curl_easy_setopt options"
+.TH CURLOPT_KEEP_SENDING_ON_ERROR 3 "22 Sep 2016" libcurl libcurl
.SH NAME
CURLOPT_KEEP_SENDING_ON_ERROR \- keep sending on early HTTP response >= 300
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_KEYPASSWD.3 b/docs/libcurl/opts/CURLOPT_KEYPASSWD.3
index d2da329..632525b 100644
--- a/docs/libcurl/opts/CURLOPT_KEYPASSWD.3
+++ b/docs/libcurl/opts/CURLOPT_KEYPASSWD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_KEYPASSWD 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_KEYPASSWD 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_KEYPASSWD \- passphrase to private key
.SH SYNOPSIS
@@ -34,7 +34,7 @@
.SH DESCRIPTION
Pass a pointer to a null-terminated string as parameter. It will be used as
the password required to use the \fICURLOPT_SSLKEY(3)\fP or
-\fICURLOPT_SSH_PRIVATE_KEYFILE(3)\fP private key. You never needed a pass
+\fICURLOPT_SSH_PRIVATE_KEYFILE(3)\fP private key. You never need a pass
phrase to load a certificate but you need one to load your private key.
The application does not have to keep the string around after setting this
diff --git a/docs/libcurl/opts/CURLOPT_KRBLEVEL.3 b/docs/libcurl/opts/CURLOPT_KRBLEVEL.3
index 3005d93..9116380 100644
--- a/docs/libcurl/opts/CURLOPT_KRBLEVEL.3
+++ b/docs/libcurl/opts/CURLOPT_KRBLEVEL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_KRBLEVEL 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_KRBLEVEL 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_KRBLEVEL \- FTP kerberos security level
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_LOCALPORT.3 b/docs/libcurl/opts/CURLOPT_LOCALPORT.3
index f070795..599db39 100644
--- a/docs/libcurl/opts/CURLOPT_LOCALPORT.3
+++ b/docs/libcurl/opts/CURLOPT_LOCALPORT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_LOCALPORT 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_LOCALPORT 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_LOCALPORT \- local port number to use for socket
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.3 b/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.3
index 663124f..9741e01 100644
--- a/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.3
+++ b/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_LOCALPORTRANGE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_LOCALPORTRANGE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_LOCALPORTRANGE \- number of additional local ports to try
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.3
index 403acfb..0fb32a4 100644
--- a/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.3
+++ b/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_LOGIN_OPTIONS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_LOGIN_OPTIONS 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_LOGIN_OPTIONS \- login options
.SH SYNOPSIS
@@ -35,14 +35,20 @@
Pass a char * as parameter, which should be pointing to the null-terminated
\fIoptions\fP string to use for the transfer.
-For more information about the login options please see RFC2384, RFC5092 and
-IETF draft draft-earhart-url-smtp-00.txt
+For more information about the login options please see RFC 2384, RFC 5092 and
+the IETF draft \fBdraft-earhart-url-smtp-00.txt\fP.
\fICURLOPT_LOGIN_OPTIONS(3)\fP can be used to set protocol specific login
options, such as the preferred authentication mechanism via "AUTH=NTLM" or
"AUTH=*", and should be used in conjunction with the \fICURLOPT_USERNAME(3)\fP
option.
+Since 8.2.0, IMAP supports the login option "AUTH=+LOGIN". With this option,
+curl uses the plain (not SASL) LOGIN IMAP command even if the server advertises
+SASL authentication. Care should be taken in using this option, as it will send
+out your password in plain text. This will not work if the IMAP server disables
+the plain LOGIN (e.g. to prevent password snooping).
+
The application does not have to keep the string around after setting this
option.
.SH DEFAULT
diff --git a/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.3 b/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.3
index 424d630..7ac5bf5 100644
--- a/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.3
+++ b/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_LOW_SPEED_LIMIT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_LOW_SPEED_LIMIT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_LOW_SPEED_LIMIT \- low speed limit in bytes per second
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.3 b/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.3
index d57f0cc..9f54ff7 100644
--- a/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.3
+++ b/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_LOW_SPEED_TIME 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_LOW_SPEED_TIME 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_LOW_SPEED_TIME \- low speed limit time period
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_AUTH.3 b/docs/libcurl/opts/CURLOPT_MAIL_AUTH.3
index 05baf7c..d914fc4 100644
--- a/docs/libcurl/opts/CURLOPT_MAIL_AUTH.3
+++ b/docs/libcurl/opts/CURLOPT_MAIL_AUTH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MAIL_AUTH 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_MAIL_AUTH 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_MAIL_AUTH \- SMTP authentication address
.SH SYNOPSIS
@@ -46,7 +46,7 @@
Unlike \fICURLOPT_MAIL_FROM(3)\fP and \fICURLOPT_MAIL_RCPT(3)\fP, the address
should not be specified within a pair of angled brackets (<>). However, if an
empty string is used then a pair of brackets will be sent by libcurl as
-required by RFC2554.
+required by RFC 2554.
The application does not have to keep the string around after setting this
option.
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_FROM.3 b/docs/libcurl/opts/CURLOPT_MAIL_FROM.3
index 360621b..cc0f859 100644
--- a/docs/libcurl/opts/CURLOPT_MAIL_FROM.3
+++ b/docs/libcurl/opts/CURLOPT_MAIL_FROM.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MAIL_FROM 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_MAIL_FROM 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_MAIL_FROM \- SMTP sender address
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_RCPT.3 b/docs/libcurl/opts/CURLOPT_MAIL_RCPT.3
index 98df48a..0f63c04 100644
--- a/docs/libcurl/opts/CURLOPT_MAIL_RCPT.3
+++ b/docs/libcurl/opts/CURLOPT_MAIL_RCPT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MAIL_RCPT 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_MAIL_RCPT 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_MAIL_RCPT \- list of SMTP mail recipients
.SH SYNOPSIS
@@ -43,12 +43,13 @@
the first character libcurl will assume you provided a single email address
and enclose that address within brackets for you.
-When performing an address verification (VRFY command), each recipient should
-be specified as the user name or user name and domain (as per Section 3.5 of
-RFC5321).
+When performing an address verification (\fBVRFY\fP command), each recipient
+should be specified as the user name or user name and domain (as per Section
+3.5 of RFC 5321).
-When performing a mailing list expand (EXPN command), each recipient should be
-specified using the mailing list name, such as "Friends" or "London-Office".
+When performing a mailing list expand (\fBEXPN\fP command), each recipient
+should be specified using the mailing list name, such as "Friends" or
+"London-Office".
.SH DEFAULT
NULL
.SH PROTOCOLS
@@ -68,7 +69,7 @@
}
.fi
.SH AVAILABILITY
-Added in 7.20.0. The VRFY and EXPN logic was added in 7.34.0
+Added in 7.20.0. The \fBVRFY\fP and \fBEXPN\fP logic was added in 7.34.0
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLLOWFAILS.3 b/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.3
similarity index 85%
rename from docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLLOWFAILS.3
rename to docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.3
index c87e363..981e8b2 100644
--- a/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLLOWFAILS.3
+++ b/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,14 +22,14 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MAIL_RCPT_ALLLOWFAILS 3 "16 Jan 2020" "libcurl 7.69.0" "curl_easy_setopt options"
+.TH CURLOPT_MAIL_RCPT_ALLOWFAILS 3 "16 Jan 2020" libcurl libcurl
.SH NAME
-CURLOPT_MAIL_RCPT_ALLLOWFAILS \- allow RCPT TO command to fail for some recipients
+CURLOPT_MAIL_RCPT_ALLOWFAILS \- allow RCPT TO command to fail for some recipients
.SH SYNOPSIS
.nf
#include <curl/curl.h>
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_RCPT_ALLLOWFAILS,
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_RCPT_ALLOWFAILS,
long allow);
.SH DESCRIPTION
If \fIallow\fP is set to 1L, allow RCPT TO command to fail for some recipients.
@@ -59,7 +59,7 @@
list = curl_slist_append(list, "invalidemailaddress");
curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
- curl_easy_setopt(curl, CURLOPT_MAIL_RCPT_ALLLOWFAILS, 1L);
+ curl_easy_setopt(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS, 1L);
ret = curl_easy_perform(curl);
curl_slist_free_all(list);
@@ -67,6 +67,8 @@
}
.fi
.SH AVAILABILITY
+This option was called CURLOPT_MAIL_RCPT_ALLLOWFAILS before 8.2.0
+
Added in 7.69.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_MAXAGE_CONN.3 b/docs/libcurl/opts/CURLOPT_MAXAGE_CONN.3
index d443845..3010c68 100644
--- a/docs/libcurl/opts/CURLOPT_MAXAGE_CONN.3
+++ b/docs/libcurl/opts/CURLOPT_MAXAGE_CONN.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,17 +22,17 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MAXAGE_CONN 3 "18 Apr 2019" "libcurl 7.65.0" "curl_easy_setopt options"
+.TH CURLOPT_MAXAGE_CONN 3 "18 Apr 2019" libcurl libcurl
.SH NAME
CURLOPT_MAXAGE_CONN \- max idle time allowed for reusing a connection
.SH SYNOPSIS
.nf
#include <curl/curl.h>
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXAGE_CONN, long maxage);
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXAGE_CONN, long age);
.fi
.SH DESCRIPTION
-Pass a long as parameter containing \fImaxage\fP - the maximum time in seconds
+Pass a long as parameter containing \fIage\fP - the maximum time in seconds
that you allow an existing connection to have been idle to be considered for
reuse for this request.
@@ -42,10 +42,9 @@
old connections for reuse, since old connections have a high risk of not
working and thus trying them is a performance loss and sometimes service loss
due to the difficulties to figure out the situation. If a connection is found
-in the cache that is older than this set \fImaxage\fP, it will instead be
-closed.
+in the cache that is older than this set \fIage\fP, it will instead be closed.
.SH DEFAULT
-Default maxage is 118 seconds.
+Default maximum age is set to 118 seconds.
.SH PROTOCOLS
All
.SH EXAMPLE
diff --git a/docs/libcurl/opts/CURLOPT_MAXCONNECTS.3 b/docs/libcurl/opts/CURLOPT_MAXCONNECTS.3
index b5f726e..ed0dbca 100644
--- a/docs/libcurl/opts/CURLOPT_MAXCONNECTS.3
+++ b/docs/libcurl/opts/CURLOPT_MAXCONNECTS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MAXCONNECTS 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_MAXCONNECTS 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_MAXCONNECTS \- maximum connection cache size
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_MAXFILESIZE.3 b/docs/libcurl/opts/CURLOPT_MAXFILESIZE.3
index bcd7e9d..8460016 100644
--- a/docs/libcurl/opts/CURLOPT_MAXFILESIZE.3
+++ b/docs/libcurl/opts/CURLOPT_MAXFILESIZE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MAXFILESIZE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_MAXFILESIZE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_MAXFILESIZE \- maximum file size allowed to download
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.3 b/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.3
index f31449b..1ee004c 100644
--- a/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.3
+++ b/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MAXFILESIZE_LARGE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_MAXFILESIZE_LARGE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_MAXFILESIZE_LARGE \- maximum file size allowed to download
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.3 b/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.3
index 80cc4fe..a459c82 100644
--- a/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.3
+++ b/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MAXLIFETIME_CONN 3 "10 Nov 2021" "libcurl 7.80.0" "curl_easy_setopt options"
+.TH CURLOPT_MAXLIFETIME_CONN 3 "10 Nov 2021" libcurl libcurl
.SH NAME
CURLOPT_MAXLIFETIME_CONN \- max lifetime (since creation) allowed for reusing a connection
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_MAXREDIRS.3 b/docs/libcurl/opts/CURLOPT_MAXREDIRS.3
index b69dc66..3aeb074 100644
--- a/docs/libcurl/opts/CURLOPT_MAXREDIRS.3
+++ b/docs/libcurl/opts/CURLOPT_MAXREDIRS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MAXREDIRS 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_MAXREDIRS 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_MAXREDIRS \- maximum number of redirects allowed
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.3 b/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.3
index 996a890..64fd404 100644
--- a/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.3
+++ b/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MAX_RECV_SPEED_LARGE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_MAX_RECV_SPEED_LARGE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_MAX_RECV_SPEED_LARGE \- rate limit data download speed
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.3 b/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.3
index 1e18c7f..ab7c6c2 100644
--- a/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.3
+++ b/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MAX_SEND_SPEED_LARGE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_MAX_SEND_SPEED_LARGE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_MAX_SEND_SPEED_LARGE \- rate limit data upload speed
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_MIMEPOST.3 b/docs/libcurl/opts/CURLOPT_MIMEPOST.3
index 6560e2b..e8e5433 100644
--- a/docs/libcurl/opts/CURLOPT_MIMEPOST.3
+++ b/docs/libcurl/opts/CURLOPT_MIMEPOST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MIMEPOST 3 "22 Aug 2017" "libcurl 7.56.0" "curl_easy_setopt options"
+.TH CURLOPT_MIMEPOST 3 "22 Aug 2017" libcurl libcurl
.SH NAME
CURLOPT_MIMEPOST \- send data from mime structure
.SH SYNOPSIS
@@ -39,13 +39,33 @@
SMTP and IMAP protocols to provide the email data to send/upload.
This option is the preferred way of posting an HTTP form, replacing and
-extending the deprecated \fICURLOPT_HTTPPOST(3)\fP option.
+extending the \fICURLOPT_HTTPPOST(3)\fP option.
+
+When setting \fICURLOPT_MIMEPOST(3)\fP to NULL, libcurl resets the request
+type for HTTP to the default to disable the POST. Typically that would mean it
+is reset to GET. Instead you should set a desired request method explicitly.
.SH PROTOCOLS
HTTP, SMTP, IMAP.
.SH EXAMPLE
-Using this option implies the use of several mime structure building
-functions: see https://curl.se/libcurl/c/smtp-mime.html for a complete
-example.
+.nf
+ curl_mime *multipart = curl_mime_init(handle);
+ curl_mimepart *part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "name");
+ curl_mime_data(part, "daniel", CURL_ZERO_TERMINATED);
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "project");
+ curl_mime_data(part, "curl", CURL_ZERO_TERMINATED);
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "logotype-image");
+ curl_mime_filedata(part, "curl.png");
+
+ /* Set the form info */
+ curl_easy_setopt(handle, CURLOPT_MIMEPOST, multipart);
+
+ curl_easy_perform(handle); /* post away! */
+
+ curl_mime_free(multipart); /* free the post data */
+.fi
.SH AVAILABILITY
Added in 7.56.0
.SH RETURN VALUE
diff --git a/docs/libcurl/opts/CURLOPT_MIME_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_MIME_OPTIONS.3
index 16d0470..ba1ae9a 100644
--- a/docs/libcurl/opts/CURLOPT_MIME_OPTIONS.3
+++ b/docs/libcurl/opts/CURLOPT_MIME_OPTIONS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_MIME_OPTIONS 3 "2 Oct 2021" "libcurl 7.81.0" "curl_easy_setopt options"
+.TH CURLOPT_MIME_OPTIONS 3 "2 Oct 2021" libcurl libcurl
.SH NAME
CURLOPT_MIME_OPTIONS \- set MIME option flags
.SH SYNOPSIS
@@ -47,7 +47,7 @@
Before version 7.81.0, percent-encoding was never applied.
HTTP browsers used to do backslash-escaping in the past but have over time
-transitioned to use percent-encoding. This option allows to address
+transitioned to use percent-encoding. This option allows one to address
server-side applications that have not yet have been converted.
As an example, consider field or file name \fIstrange\\name"kind\fP.
diff --git a/docs/libcurl/opts/CURLOPT_NETRC.3 b/docs/libcurl/opts/CURLOPT_NETRC.3
index 883bccd..672134b 100644
--- a/docs/libcurl/opts/CURLOPT_NETRC.3
+++ b/docs/libcurl/opts/CURLOPT_NETRC.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_NETRC 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_NETRC 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_NETRC \- enable use of .netrc
.SH SYNOPSIS
@@ -74,7 +74,7 @@
newline. Starting in 7.84.0, libcurl also supports quoted strings. They start
and end with double quotes and support the escaped special letters \\\", \\n,
\\r, and \\t. Quoted strings are the only way a space character can be used in
-a user namd or password.
+a user name or password.
.IP "machine <name>"
Provides credentials for a host called \fBname\fP. libcurl searches the .netrc
diff --git a/docs/libcurl/opts/CURLOPT_NETRC_FILE.3 b/docs/libcurl/opts/CURLOPT_NETRC_FILE.3
index 6795ee3..105540c 100644
--- a/docs/libcurl/opts/CURLOPT_NETRC_FILE.3
+++ b/docs/libcurl/opts/CURLOPT_NETRC_FILE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_NETRC_FILE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_NETRC_FILE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_NETRC_FILE \- file name to read .netrc info from
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.3 b/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.3
index 7c4ffc0..e6e8031 100644
--- a/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.3
+++ b/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_NEW_DIRECTORY_PERMS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_NEW_DIRECTORY_PERMS 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_NEW_DIRECTORY_PERMS \- permissions for remotely created directories
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.3 b/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.3
index 0d890fe..ec798e9 100644
--- a/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.3
+++ b/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_NEW_FILE_PERMS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_NEW_FILE_PERMS 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_NEW_FILE_PERMS \- permissions for remotely created files
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_NOBODY.3 b/docs/libcurl/opts/CURLOPT_NOBODY.3
index 6805a37..f190ff6 100644
--- a/docs/libcurl/opts/CURLOPT_NOBODY.3
+++ b/docs/libcurl/opts/CURLOPT_NOBODY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_NOBODY 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_NOBODY 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_NOBODY \- do the download request without getting the body
.SH SYNOPSIS
@@ -37,7 +37,7 @@
libcurl do a HEAD request. For most other protocols it means just not asking
to transfer the body data.
-For HTTP operations when \fICURLOPT_NOBODY(3)\fP has been set, unsetting the
+For HTTP operations when \fICURLOPT_NOBODY(3)\fP has been set, disabling this
option (with 0) will make it a GET again - only if the method is still set to
be HEAD. The proper way to get back to a GET request is to set
\fICURLOPT_HTTPGET(3)\fP and for other methods, use the POST or UPLOAD
diff --git a/docs/libcurl/opts/CURLOPT_NOPROGRESS.3 b/docs/libcurl/opts/CURLOPT_NOPROGRESS.3
index 0d90086..7c3794a 100644
--- a/docs/libcurl/opts/CURLOPT_NOPROGRESS.3
+++ b/docs/libcurl/opts/CURLOPT_NOPROGRESS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_NOPROGRESS 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_NOPROGRESS 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_NOPROGRESS \- switch off the progress meter
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_NOPROXY.3 b/docs/libcurl/opts/CURLOPT_NOPROXY.3
index a006ae4..50157f9 100644
--- a/docs/libcurl/opts/CURLOPT_NOPROXY.3
+++ b/docs/libcurl/opts/CURLOPT_NOPROXY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_NOPROXY 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_NOPROXY 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_NOPROXY \- disable proxy use for specific hosts
.SH SYNOPSIS
@@ -37,25 +37,22 @@
if one is specified. The only wildcard available is a single * character,
which matches all hosts, and effectively disables the proxy. Each name in this
list is matched as either a domain which contains the hostname, or the
-hostname itself. For example, example.com would match example.com,
-example.com:80, and www.example.com, but not www.notanexample.com or
-example.com.othertld.
+hostname itself. For example, "ample.com" would match ample.com, ample.com:80,
+and www.ample.com, but not www.example.com or ample.com.org.
-If the name in the noproxy list has a leading period, it is a domain match
-against the provided host name. This way ".example.com" will switch off proxy
-use for both "www.example.com" as well as for "foo.example.com".
-
-Setting the noproxy string to "" (an empty string) will explicitly enable the
-proxy for all host names, even if there is an environment variable set for it.
+Setting the \fInoproxy\fP string to "" (an empty string) will explicitly
+enable the proxy for all host names, even if there is an environment variable
+set for it.
Enter IPv6 numerical addresses in the list of host names without enclosing
brackets:
"example.com,::1,localhost"
-IPv6 numerical addresses are compared as strings, so they will only match if
-the representations are the same: "::1" is the same as "::0:1" but they do not
-match.
+Since 7.86.0, IP addresses specified to this option can be provided using CIDR
+notation: an appended slash and number specifies the number of "network bits"
+out of the address to use in the comparison. For example "192.168.0.0/16"
+would match all addresses starting with "192.168".
The application does not have to keep the string around after setting this
option.
diff --git a/docs/libcurl/opts/CURLOPT_NOSIGNAL.3 b/docs/libcurl/opts/CURLOPT_NOSIGNAL.3
index fb95c1e..f6c69aa 100644
--- a/docs/libcurl/opts/CURLOPT_NOSIGNAL.3
+++ b/docs/libcurl/opts/CURLOPT_NOSIGNAL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_NOSIGNAL 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_NOSIGNAL 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_NOSIGNAL \- skip all signal handling
.SH SYNOPSIS
@@ -46,10 +46,10 @@
Setting \fICURLOPT_NOSIGNAL(3)\fP to 1 makes libcurl NOT ask the system to
ignore SIGPIPE signals, which otherwise are sent by the system when trying to
send data to a socket which is closed in the other end. libcurl makes an
-effort to never cause such SIGPIPEs to trigger, but some operating systems
-have no way to avoid them and even on those that have there are some corner
-cases when they may still happen, contrary to our desire. In addition, using
-\fICURLAUTH_NTLM_WB\fP authentication could cause a SIGCHLD signal to be
+effort to never cause such SIGPIPE signals to trigger, but some operating
+systems have no way to avoid them and even on those that have there are some
+corner cases when they may still happen, contrary to our desire. In addition,
+using \fICURLAUTH_NTLM_WB\fP authentication could cause a SIGCHLD signal to be
raised.
.SH DEFAULT
0
diff --git a/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.3 b/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.3
index 7426660..a4811f5 100644
--- a/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.3
+++ b/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_OPENSOCKETDATA 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_OPENSOCKETDATA 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_OPENSOCKETDATA \- pointer passed to open socket callback
.SH SYNOPSIS
@@ -33,7 +33,8 @@
.fi
.SH DESCRIPTION
Pass a \fIpointer\fP that will be untouched by libcurl and passed as the first
-argument in the opensocket callback set with \fICURLOPT_OPENSOCKETFUNCTION(3)\fP.
+argument in the open socket callback set with
+\fICURLOPT_OPENSOCKETFUNCTION(3)\fP.
.SH DEFAULT
The default value of this parameter is NULL.
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.3 b/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.3
index 898add7..93ee859 100644
--- a/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_OPENSOCKETFUNCTION 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_OPENSOCKETFUNCTION 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_OPENSOCKETFUNCTION \- callback for opening socket
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PASSWORD.3 b/docs/libcurl/opts/CURLOPT_PASSWORD.3
index 5f29665..db6c862 100644
--- a/docs/libcurl/opts/CURLOPT_PASSWORD.3
+++ b/docs/libcurl/opts/CURLOPT_PASSWORD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PASSWORD 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PASSWORD 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PASSWORD \- password to use in authentication
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PATH_AS_IS.3 b/docs/libcurl/opts/CURLOPT_PATH_AS_IS.3
index 871b20c..e02683b 100644
--- a/docs/libcurl/opts/CURLOPT_PATH_AS_IS.3
+++ b/docs/libcurl/opts/CURLOPT_PATH_AS_IS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PATH_AS_IS 3 "17 Jun 2014" "libcurl 7.42.0" "curl_easy_setopt options"
+.TH CURLOPT_PATH_AS_IS 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PATH_AS_IS \- do not handle dot dot sequences
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3 b/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3
index e5bf581..f754950 100644
--- a/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3
+++ b/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PINNEDPUBLICKEY 3 "27 Aug 2014" "libcurl 7.38.0" "curl_easy_setopt options"
+.TH CURLOPT_PINNEDPUBLICKEY 3 "27 Aug 2014" libcurl libcurl
.SH NAME
CURLOPT_PINNEDPUBLICKEY \- pinned public key
.SH SYNOPSIS
@@ -106,21 +106,21 @@
7.43.0: NSS and wolfSSL
- 7.47.0: mbedtls
+ 7.47.0: mbedTLS
- 7.54.1: SecureTransport on macOS 10.7+/iOS 10+
+ 7.54.1: Secure Transport on macOS 10.7+/iOS 10+
- 7.58.1: SChannel
+ 7.58.1: Schannel
sha256 support:
7.44.0: OpenSSL, GnuTLS, NSS and wolfSSL
- 7.47.0: mbedtls
+ 7.47.0: mbedTLS
- 7.54.1: SecureTransport on macOS 10.7+/iOS 10+
+ 7.54.1: Secure Transport on macOS 10.7+/iOS 10+
- 7.58.1: SChannel Windows XP SP3+
+ 7.58.1: Schannel Windows XP SP3+
Other SSL backends not supported.
.SH RETURN VALUE
diff --git a/docs/libcurl/opts/CURLOPT_PIPEWAIT.3 b/docs/libcurl/opts/CURLOPT_PIPEWAIT.3
index d5f5657..6402e3b 100644
--- a/docs/libcurl/opts/CURLOPT_PIPEWAIT.3
+++ b/docs/libcurl/opts/CURLOPT_PIPEWAIT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PIPEWAIT 3 "12 May 2015" "libcurl 7.43.0" "curl_easy_setopt options"
+.TH CURLOPT_PIPEWAIT 3 "12 May 2015" libcurl libcurl
.SH NAME
CURLOPT_PIPEWAIT \- wait for pipelining/multiplexing
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PORT.3 b/docs/libcurl/opts/CURLOPT_PORT.3
index 1d3b740..320f9ed 100644
--- a/docs/libcurl/opts/CURLOPT_PORT.3
+++ b/docs/libcurl/opts/CURLOPT_PORT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PORT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PORT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PORT \- remote port number to connect to
.SH SYNOPSIS
@@ -42,8 +42,9 @@
Usually, you just let the URL decide which port to use but this allows the
application to override that.
-While this option accepts a 'long', a port number is usually a 16 bit number
-and therefore using a port number over 65535 will cause a runtime error.
+While this option accepts a 'long', a port number is an unsigned 16 bit number
+and therefore using a port number lower than zero or over 65535 will cause a
+\fBCURLE_BAD_FUNCTION_ARGUMENT\fP error.
.SH DEFAULT
By default this is 0 which makes it not used. This also makes port number zero
impossible to set with this API.
diff --git a/docs/libcurl/opts/CURLOPT_POST.3 b/docs/libcurl/opts/CURLOPT_POST.3
index a1a7eae..a6f0acb 100644
--- a/docs/libcurl/opts/CURLOPT_POST.3
+++ b/docs/libcurl/opts/CURLOPT_POST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_POST 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_POST 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_POST \- make an HTTP POST
.SH SYNOPSIS
@@ -68,6 +68,10 @@
If you issue a POST request and then want to make a HEAD or GET using the same
re-used handle, you must explicitly set the new request type using
\fICURLOPT_NOBODY(3)\fP or \fICURLOPT_HTTPGET(3)\fP or similar.
+
+When setting \fICURLOPT_POST(3)\fP to 0, libcurl resets the request type to
+the default to disable the POST. Typically that would mean it's reset to GET.
+Instead you should set a new request type explicitly as described above.
.SH DEFAULT
0, disabled
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDS.3 b/docs/libcurl/opts/CURLOPT_POSTFIELDS.3
index 24988d5..73be852 100644
--- a/docs/libcurl/opts/CURLOPT_POSTFIELDS.3
+++ b/docs/libcurl/opts/CURLOPT_POSTFIELDS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_POSTFIELDS 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_POSTFIELDS 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_POSTFIELDS \- data to POST to server
.SH SYNOPSIS
@@ -35,19 +35,21 @@
Pass a char * as parameter, pointing to the full data to send in an HTTP POST
operation. You must make sure that the data is formatted the way you want the
server to receive it. libcurl will not convert or encode it for you in any
-way. For example, the web server may assume that this data is url-encoded.
+way. For example, the web server may assume that this data is URL encoded.
The data pointed to is NOT copied by the library: as a consequence, it must be
preserved by the calling application until the associated transfer finishes.
This behavior can be changed (so libcurl does copy the data) by setting the
\fICURLOPT_COPYPOSTFIELDS(3)\fP option.
-This POST is a normal application/x-www-form-urlencoded kind (and libcurl will
-set that Content-Type by default when this option is used), which is commonly
-used by HTML forms. Change Content-Type with \fICURLOPT_HTTPHEADER(3)\fP.
+This POST is a normal \fBapplication/x-www-form-urlencoded\fP kind (and
+libcurl will set that Content-Type by default when this option is used), which
+is commonly used by HTML forms. Change Content-Type with
+\fICURLOPT_HTTPHEADER(3)\fP.
-You can use \fIcurl_easy_escape(3)\fP to url-encode your data, if necessary. It
-returns a pointer to an encoded string that can be passed as \fIpostdata\fP.
+You can use \fIcurl_easy_escape(3)\fP to URL encode your data, if
+necessary. It returns a pointer to an encoded string that can be passed as
+\fIpostdata\fP.
Using \fICURLOPT_POSTFIELDS(3)\fP implies setting \fICURLOPT_POST(3)\fP to 1.
@@ -56,9 +58,9 @@
\fICURLOPT_POSTFIELDS(3)\fP to an empty string, or set \fICURLOPT_POST(3)\fP to
1 and \fICURLOPT_POSTFIELDSIZE(3)\fP to 0.
-libcurl will use assume this option points to a nul-terminated string unless
+libcurl will use assume this option points to a null-terminated string unless
you also set \fICURLOPT_POSTFIELDSIZE(3)\fP to specify the length of the
-provided data, which then is strictly required if you want to send off nul
+provided data, which then is strictly required if you want to send off null
bytes included in the data.
Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header,
@@ -66,8 +68,8 @@
be larger than 1MB or if the expected size is unknown. You can disable this
header with \fICURLOPT_HTTPHEADER(3)\fP as usual.
-To make multipart/formdata posts (aka RFC2388-posts), check out the
-\fICURLOPT_HTTPPOST(3)\fP option combined with \fIcurl_formadd(3)\fP.
+To make \fBmultipart/formdata\fP posts, check out the
+\fICURLOPT_MIMEPOST(3)\fP option combined with \fIcurl_mime_init(3)\fP.
.SH DEFAULT
NULL
.SH PROTOCOLS
@@ -95,3 +97,4 @@
Returns CURLE_OK
.SH "SEE ALSO"
.BR CURLOPT_POSTFIELDSIZE "(3), " CURLOPT_READFUNCTION "(3), "
+.BR CURLOPT_MIMEPOST "(3), " CURLOPT_UPLOAD "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.3 b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.3
index aceb320..20adcb5 100644
--- a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.3
+++ b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_POSTFIELDSIZE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_POSTFIELDSIZE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_POSTFIELDSIZE \- size of POST data pointed to
.SH SYNOPSIS
@@ -32,10 +32,11 @@
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDSIZE, long size);
.fi
.SH DESCRIPTION
-If you want to post data to the server without having libcurl do a strlen() to
-measure the data size, this option must be used. When this option is used you
-can post fully binary data, which otherwise is likely to fail. If this size is
-set to -1, the library will use strlen() to get the size.
+If you want to post static data to the server without having libcurl do a
+strlen() to measure the data size, this option must be used. When this option
+is used you can post fully binary data, which otherwise is likely to fail. If
+this size is set to -1, the library will use strlen() to get the size or rely
+on the \fICURLOPT_READFUNCTION\fP (if used) to signal the end of data.
If you post more than 2GB, use \fICURLOPT_POSTFIELDSIZE_LARGE(3)\fP.
.SH DEFAULT
diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.3 b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.3
index 391c49d..6680d74 100644
--- a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.3
+++ b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_POSTFIELDSIZE_LARGE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_POSTFIELDSIZE_LARGE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_POSTFIELDSIZE_LARGE \- size of POST data pointed to
.SH SYNOPSIS
@@ -32,10 +32,11 @@
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDSIZE_LARGE,
curl_off_t size);
.SH DESCRIPTION
-If you want to post data to the server without having libcurl do a strlen() to
-measure the data size, this option must be used. When this option is used you
-can post fully binary data, which otherwise is likely to fail. If this size is
-set to -1, the library will use strlen() to get the size.
+If you want to post static data to the server without having libcurl do a
+strlen() to measure the data size, this option must be used. When this option
+is used you can post fully binary data, which otherwise is likely to fail. If
+this size is set to -1, the library will use strlen() to get the size or rely
+on the \fICURLOPT_READFUNCTION\fP (if used) to signal the end of data.
.SH DEFAULT
-1
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_POSTQUOTE.3 b/docs/libcurl/opts/CURLOPT_POSTQUOTE.3
index a402cff..7dce326 100644
--- a/docs/libcurl/opts/CURLOPT_POSTQUOTE.3
+++ b/docs/libcurl/opts/CURLOPT_POSTQUOTE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_POSTQUOTE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_POSTQUOTE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_POSTQUOTE \- (S)FTP commands to run after the transfer
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_POSTREDIR.3 b/docs/libcurl/opts/CURLOPT_POSTREDIR.3
index 074e9df..c2f773d 100644
--- a/docs/libcurl/opts/CURLOPT_POSTREDIR.3
+++ b/docs/libcurl/opts/CURLOPT_POSTREDIR.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_POSTREDIR 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_POSTREDIR 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_POSTREDIR \- how to act on an HTTP POST redirect
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PREQUOTE.3 b/docs/libcurl/opts/CURLOPT_PREQUOTE.3
index 40d3de1..9b5f815 100644
--- a/docs/libcurl/opts/CURLOPT_PREQUOTE.3
+++ b/docs/libcurl/opts/CURLOPT_PREQUOTE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PREQUOTE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PREQUOTE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PREQUOTE \- commands to run before an FTP transfer
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PREREQDATA.3 b/docs/libcurl/opts/CURLOPT_PREREQDATA.3
index a865a6a..fe8d3e6 100644
--- a/docs/libcurl/opts/CURLOPT_PREREQDATA.3
+++ b/docs/libcurl/opts/CURLOPT_PREREQDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022, Max Dymond, <max.dymond@microsoft.com>, et al.
+.\" * Copyright (C) Max Dymond, <max.dymond@microsoft.com>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PREREQDATA 3 "2 Aug 2021" "libcurl 7.80.0" "curl_easy_setopt options"
+.TH CURLOPT_PREREQDATA 3 "2 Aug 2021" libcurl libcurl
.SH NAME
CURLOPT_PREREQDATA \- pointer passed to the pre-request callback
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.3 b/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.3
index 4f983b8..e67a13a 100644
--- a/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2022 - 2022, Max Dymond, <max.dymond@microsoft.com>, et al.
+.\" * Copyright (C) Max Dymond, <max.dymond@microsoft.com>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PREREQFUNCTION 3 "2 Aug 2021" "libcurl 7.80.0" "curl_easy_setopt options"
+.TH CURLOPT_PREREQFUNCTION 3 "2 Aug 2021" libcurl libcurl
.SH NAME
CURLOPT_PREREQFUNCTION \- user callback called when a connection has been
established, but before a request has been made.
@@ -59,20 +59,20 @@
This function is passed the following arguments:
.IP conn_primary_ip
-A nul-terminated pointer to a C string containing the primary IP of the remote
-server established with this connection. For FTP, this is the IP for the
-control connection. IPv6 addresses are represented without surrounding
+A null-terminated pointer to a C string containing the primary IP of the
+remote server established with this connection. For FTP, this is the IP for
+the control connection. IPv6 addresses are represented without surrounding
brackets.
.IP conn_local_ip
-A nul-terminated pointer to a C string containing the originating IP for this
+A null-terminated pointer to a C string containing the originating IP for this
connection. IPv6 addresses are represented without surrounding brackets.
.IP conn_primary_port
The primary port number on the remote server established with this connection.
For FTP, this is the port for the control connection. This can be a TCP or a
-UDP port number dependending on the protocol.
+UDP port number depending on the protocol.
.IP conn_local_port
The originating port number for this connection. This can be a TCP or a UDP
-port number dependending on the protocol.
+port number depending on the protocol.
.IP clientp
The pointer you set with \fICURLOPT_PREREQDATA(3)\fP.
.SH DEFAULT
diff --git a/docs/libcurl/opts/CURLOPT_PRE_PROXY.3 b/docs/libcurl/opts/CURLOPT_PRE_PROXY.3
index 2f0bac3..3a490de 100644
--- a/docs/libcurl/opts/CURLOPT_PRE_PROXY.3
+++ b/docs/libcurl/opts/CURLOPT_PRE_PROXY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PRE_PROXY 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PRE_PROXY 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PRE_PROXY \- pre-proxy host to use
.SH SYNOPSIS
@@ -69,7 +69,7 @@
CURL *curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/file.txt");
- curl_easy_setopt(curl, CURLOPT_PREPROXY, "socks4://socks-proxy:1080");
+ curl_easy_setopt(curl, CURLOPT_PRE_PROXY, "socks4://socks-proxy:1080");
curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy:80");
curl_easy_perform(curl);
}
diff --git a/docs/libcurl/opts/CURLOPT_PRIVATE.3 b/docs/libcurl/opts/CURLOPT_PRIVATE.3
index a32971a..8f88202 100644
--- a/docs/libcurl/opts/CURLOPT_PRIVATE.3
+++ b/docs/libcurl/opts/CURLOPT_PRIVATE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PRIVATE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PRIVATE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PRIVATE \- store a private pointer
.SH SYNOPSIS
@@ -34,8 +34,8 @@
.SH DESCRIPTION
Pass a void * as parameter, pointing to data that should be associated with
this curl handle. The pointer can subsequently be retrieved using
-\fIcurl_easy_getinfo(3)\fP with the CURLINFO_PRIVATE option. libcurl itself
-never does anything with this data.
+\fIcurl_easy_getinfo(3)\fP with the \fICURLINFO_PRIVATE(3)\fP option. libcurl
+itself never does anything with this data.
.SH DEFAULT
NULL
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_PROGRESSDATA.3 b/docs/libcurl/opts/CURLOPT_PROGRESSDATA.3
index b8e4790..1cfebe6 100644
--- a/docs/libcurl/opts/CURLOPT_PROGRESSDATA.3
+++ b/docs/libcurl/opts/CURLOPT_PROGRESSDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROGRESSDATA 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PROGRESSDATA 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PROGRESSDATA \- pointer passed to the progress callback
.SH SYNOPSIS
@@ -51,7 +51,7 @@
double ultotal,
double ulnow)
{
- struct memory *progress = (struct progress *)userp;
+ struct memory *progress = (struct progress *)clientp;
/* use the values */
diff --git a/docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.3 b/docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.3
index 842a9ff..adae5bd 100644
--- a/docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROGRESSFUNCTION 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PROGRESSFUNCTION 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PROGRESSFUNCTION \- progress meter callback
.SH SYNOPSIS
@@ -42,8 +42,8 @@
Pass a pointer to your callback function, which should match the prototype
shown above.
-We encourage users to use the newer \fICURLOPT_XFERINFOFUNCTION(3)\fP instead,
-if you can.
+This option is deprecated and we encourage users to use the
+newer \fICURLOPT_XFERINFOFUNCTION(3)\fP instead, if you can.
This function gets called by libcurl instead of its internal equivalent with a
frequent interval. While data is being transferred it will be called
@@ -110,8 +110,9 @@
curl_easy_setopt(curl_handle, CURLOPT_PROGRESSFUNCTION, progress_callback);
.fi
.SH AVAILABILITY
-Always
+Deprecated since 7.32.0.
.SH RETURN VALUE
Returns CURLE_OK.
.SH "SEE ALSO"
.BR CURLOPT_VERBOSE "(3), " CURLOPT_NOPROGRESS "(3), "
+.BR CURLOPT_XFERINFOFUNCTION "(3)"
diff --git a/docs/libcurl/opts/CURLOPT_PROTOCOLS.3 b/docs/libcurl/opts/CURLOPT_PROTOCOLS.3
index aeeb475..07d3d44 100644
--- a/docs/libcurl/opts/CURLOPT_PROTOCOLS.3
+++ b/docs/libcurl/opts/CURLOPT_PROTOCOLS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROTOCOLS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PROTOCOLS 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PROTOCOLS \- allowed protocols
.SH SYNOPSIS
@@ -32,6 +32,10 @@
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROTOCOLS, long bitmask);
.fi
.SH DESCRIPTION
+This option is deprecated. We strongly recommend using
+\fICURLOPT_PROTOCOLS_STR(3)\fP instead because this option cannot control all
+available protocols!
+
Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
limits what protocols libcurl may use in the transfer. This allows you to have
a libcurl built to support a wide range of protocols but still limit specific
@@ -71,7 +75,7 @@
CURLPROTO_TFTP
.fi
.SH DEFAULT
-All protocols built-in
+All protocols built-in.
.SH PROTOCOLS
All
.SH EXAMPLE
@@ -90,7 +94,7 @@
}
.fi
.SH AVAILABILITY
-Added in 7.19.4
+Added in 7.19.4. Deprecated since 7.85.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLOPT_PROTOCOLS_STR.3 b/docs/libcurl/opts/CURLOPT_PROTOCOLS_STR.3
new file mode 100644
index 0000000..285db11
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROTOCOLS_STR.3
@@ -0,0 +1,84 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROTOCOLS_STR 3 "11 Jun 2022" libcurl libcurl
+.SH NAME
+CURLOPT_PROTOCOLS_STR \- allowed protocols
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROTOCOLS_STR, char *spec);
+.fi
+.SH DESCRIPTION
+Pass a pointer to a string that holds a comma-separated list of case
+insensitive protocol names (URL schemes) to allow in the transfer. This
+option allows applications to use libcurl built to support a wide range of
+protocols but still limit specific transfers to only be allowed to use a
+subset of them. By default, libcurl accepts all protocols it was built with
+support for. See also \fICURLOPT_REDIR_PROTOCOLS_STR(3)\fP.
+
+If trying to set a non-existing protocol or if no matching protocol at all is
+set, it returns error.
+
+These are the available protocols:
+
+DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS,
+MQTT, POP3, POP3S, RTMP, RTMPE, RTMPS, RTMPT, RTMPTE, RTMPTS, RTSP, SCP, SFTP,
+SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS, WSS
+
+You can set "ALL" as a short-cut to enable all protocols. Note that by setting
+all, you may enable protocols that were not supported the day you write this
+but are introduced in a future libcurl version.
+
+\fIcurl_version_info(3)\fP can be used to get a list of all supported
+protocols in the current libcurl. \fICURLINFO_SCHEME(3)\fP is the recommended
+way to figure out the protocol used in a previous transfer.
+.SH DEFAULT
+All protocols built-in
+.SH PROTOCOLS
+All
+.SH EXAMPLE
+.nf
+curl = curl_easy_init();
+if(curl) {
+ /* pass in the URL from an external source */
+ curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
+
+ /* only allow HTTP, TFTP and SFTP */
+ curl_easy_setopt(curl, CURLOPT_PROTOCOLS_STR, "http,tftp,sftp");
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in 7.85.0
+.SH RETURN VALUE
+Returns CURLE_UNKNOWN_OPTION if the option is not implemented,
+CURLE_UNSUPPORTED_PROTOCOL if a listed protocol is not supported or disabled,
+CURLE_BAD_FUNCTION_ARGUMENT if no protocol is listed else CURLE_OK.
+.SH "SEE ALSO"
+.BR CURLOPT_REDIR_PROTOCOLS_STR "(3), " CURLOPT_URL "(3), "
+.BR curl_version_info "(3), " CURLINFO_SCHEME "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY.3 b/docs/libcurl/opts/CURLOPT_PROXY.3
index 504f1ee..7756581 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PROXY \- proxy to use
.SH SYNOPSIS
@@ -48,7 +48,12 @@
.IP http://
HTTP Proxy. Default when no scheme or proxy type is specified.
.IP https://
-HTTPS Proxy. (Added in 7.52.0 for OpenSSL, GnuTLS and NSS)
+HTTPS Proxy. (Added in 7.52.0 for OpenSSL, GnuTLS and NSS. Since 7.87.0, it
+also works for BearSSL, mbedTLS, rustls, Schannel, Secure Transport and
+wolfSSL.)
+
+This will use HTTP/1 by default. Setting \fICURLOPT_PROXYTYPE(3)\fP to
+\fBCURLPROXY_HTTPS2\fP allows libcurl to negotiate using HTTP/2 with proxy.
.IP socks4://
SOCKS4 Proxy.
.IP socks4a://
@@ -80,6 +85,9 @@
The application does not have to keep the string around after setting this
option.
+
+When a proxy is used, the active FTP mode as set with \fICUROPT_FTPPORT(3)\fP,
+cannot be used.
.SH "Environment variables"
libcurl respects the proxy environment variables named \fBhttp_proxy\fP,
\fBftp_proxy\fP, \fBsftp_proxy\fP etc. If set, libcurl will use the specified
@@ -115,6 +123,9 @@
Since 7.50.2, unsupported schemes in proxy strings cause libcurl to return
error.
+
+curl built to use NSS cannot connect to an HTTPS server over a unix domain
+socket.
.SH RETURN VALUE
Returns CURLE_OK if proxies are supported, CURLE_UNKNOWN_OPTION if not, or
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXYAUTH.3 b/docs/libcurl/opts/CURLOPT_PROXYAUTH.3
index b87c921..96be78a 100644
--- a/docs/libcurl/opts/CURLOPT_PROXYAUTH.3
+++ b/docs/libcurl/opts/CURLOPT_PROXYAUTH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXYAUTH 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXYAUTH 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PROXYAUTH \- HTTP proxy authentication methods
.SH SYNOPSIS
@@ -40,8 +40,8 @@
round-trip. Set the actual name and password with the
\fICURLOPT_PROXYUSERPWD(3)\fP option.
-The bitmask can be constructed by or'ing together the bits fully listed and
-described in the \fICURLOPT_HTTPAUTH(3)\fP man page.
+The bitmask can be constructed by the bits listed and described in the
+\fICURLOPT_HTTPAUTH(3)\fP man page.
.SH DEFAULT
CURLAUTH_BASIC
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_PROXYHEADER.3 b/docs/libcurl/opts/CURLOPT_PROXYHEADER.3
index 374ac93..1320cbc 100644
--- a/docs/libcurl/opts/CURLOPT_PROXYHEADER.3
+++ b/docs/libcurl/opts/CURLOPT_PROXYHEADER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXYHEADER 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXYHEADER 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PROXYHEADER \- set of HTTP headers to pass to proxy
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.3 b/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.3
index b39008f..9a8954f 100644
--- a/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.3
+++ b/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXYPASSWORD 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXYPASSWORD 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PROXYPASSWORD \- password to use with proxy authentication
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXYPORT.3 b/docs/libcurl/opts/CURLOPT_PROXYPORT.3
index e79f24a..458841f 100644
--- a/docs/libcurl/opts/CURLOPT_PROXYPORT.3
+++ b/docs/libcurl/opts/CURLOPT_PROXYPORT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXYPORT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXYPORT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PROXYPORT \- port number the proxy listens on
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXYTYPE.3 b/docs/libcurl/opts/CURLOPT_PROXYTYPE.3
index 1d13a73..89ea880 100644
--- a/docs/libcurl/opts/CURLOPT_PROXYTYPE.3
+++ b/docs/libcurl/opts/CURLOPT_PROXYTYPE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXYTYPE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXYTYPE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PROXYTYPE \- proxy protocol type
.SH SYNOPSIS
@@ -38,10 +38,14 @@
.IP CURLPROXY_HTTP
HTTP Proxy. Default.
.IP CURLPROXY_HTTPS
-HTTPS Proxy. (Added in 7.52.0 for OpenSSL, GnuTLS and NSS)
+HTTPS Proxy using HTTP/1. (Added in 7.52.0 for OpenSSL, GnuTLS and NSS. Since
+7.87.0, it also works for BearSSL, mbedTLS, rustls, Schannel, Secure Transport
+and wolfSSL.)
+.IP CURLPROXY_HTTPS2
+HTTPS Proxy and attempt to speak HTTP/2 over it. (Added in 8.1.0)
.IP CURLPROXY_HTTP_1_0
HTTP 1.0 Proxy. This is similar to CURLPROXY_HTTP except it uses HTTP/1.0 for
-any CONNECT tunnelling. It does not change the HTTP version of the actual HTTP
+any CONNECT tunneling. It does not change the HTTP version of the actual HTTP
requests, controlled by \fICURLOPT_HTTP_VERSION(3)\fP.
.IP CURLPROXY_SOCKS4
SOCKS4 Proxy.
diff --git a/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.3 b/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.3
index bb5808f..5ff3783 100644
--- a/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.3
+++ b/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXYUSERNAME 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXYUSERNAME 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PROXYUSERNAME \- user name to use for proxy authentication
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.3 b/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.3
index 3de4e94..d31721e 100644
--- a/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.3
+++ b/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXYUSERPWD 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXYUSERPWD 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PROXYUSERPWD \- user name and password to use for proxy authentication
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.3 b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.3
index 28b54e1..6d204e2 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_CAINFO 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_CAINFO 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_CAINFO \- path to proxy Certificate Authority (CA) bundle
.SH SYNOPSIS
@@ -41,8 +41,8 @@
server's certificate, \fICURLOPT_PROXY_CAINFO(3)\fP need not even indicate an
accessible file.
-This option is by default set to the system path where libcurl's cacert bundle
-is assumed to be stored, as established at build time.
+This option is by default set to the system path where libcurl's CA
+certificate bundle is assumed to be stored, as established at build time.
If curl is built against the NSS SSL library, the NSS PEM PKCS#11 module
(libnsspem.so) needs to be available for this option to work properly.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.3 b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.3
index c4788eb..0945892 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_CAINFO_BLOB 3 "31 March 2021" "libcurl 7.77.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_CAINFO_BLOB 3 "31 March 2021" libcurl libcurl
.SH NAME
CURLOPT_PROXY_CAINFO_BLOB \- proxy Certificate Authority (CA) bundle in PEM format
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.3 b/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.3
index 25d889c..71448a2 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_CAPATH 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_CAPATH 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_CAPATH \- directory holding HTTPS proxy CA certificates
.SH SYNOPSIS
@@ -34,9 +34,9 @@
.SH DESCRIPTION
Pass a char * to a null-terminated string naming a directory holding multiple
CA certificates to verify the HTTPS proxy with. If libcurl is built against
-OpenSSL, the certificate directory must be prepared using the openssl c_rehash
-utility. This makes sense only when \fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP is
-enabled (which it is by default).
+OpenSSL, the certificate directory must be prepared using the OpenSSL
+\fBc_rehash\fP utility. This makes sense only when
+\fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP is enabled (which it is by default).
The application does not have to keep the string around after setting this
option.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.3 b/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.3
index ae49fd5..c36bda8 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_CRLFILE 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_CRLFILE 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_CRLFILE \- HTTPS proxy Certificate Revocation List file
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.3 b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.3
index d92ab67..5cf5358 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_ISSUERCERT 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_ISSUERCERT 3 "24 Jun 2020" libcurl libcurl
.SH NAME
CURLOPT_PROXY_ISSUERCERT \- proxy issuer SSL certificate filename
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.3 b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.3
index 0c994ff..65d1de2 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_ISSUERCERT_BLOB 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_ISSUERCERT_BLOB 3 "24 Jun 2020" libcurl libcurl
.SH NAME
CURLOPT_PROXY_ISSUERCERT_BLOB \- proxy issuer SSL certificate from memory blob
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.3 b/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.3
index 9846bb6..3f6d85c 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_KEYPASSWD 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_KEYPASSWD 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_KEYPASSWD \- passphrase for the proxy private key
.SH SYNOPSIS
@@ -36,7 +36,7 @@
Pass a pointer to a null-terminated string as parameter. It will be used as
the password required to use the \fICURLOPT_PROXY_SSLKEY(3)\fP private key.
-You never needed a pass phrase to load a certificate but you need one to load
+You never need a pass phrase to load a certificate but you need one to load
your private key.
The application does not have to keep the string around after setting this
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.3 b/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.3
index a81f82b..5527fdd 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_PINNEDPUBLICKEY 3 "24 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_PINNEDPUBLICKEY 3 "24 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_PINNEDPUBLICKEY \- pinned public key for https proxy
.SH SYNOPSIS
@@ -98,11 +98,11 @@
.SH AVAILABILITY
PEM/DER support:
- 7.52.0: GSKit, GnuTLS, NSS, OpenSSL, mbedtls, wolfSSL
+ 7.52.0: GSKit, GnuTLS, NSS, OpenSSL, mbedTLS, wolfSSL
sha256 support:
- 7.52.0: GnuTLS, NSS, OpenSSL, mbedtls, wolfSSL
+ 7.52.0: GnuTLS, NSS, OpenSSL, mbedTLS, wolfSSL
Other SSL backends not supported.
.SH RETURN VALUE
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.3 b/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.3
index 86de34c..664833c 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_SERVICE_NAME 3 "17 Jun 2015" "libcurl 7.43.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_SERVICE_NAME 3 "17 Jun 2015" libcurl libcurl
.SH NAME
CURLOPT_PROXY_SERVICE_NAME \- proxy authentication service name
.SH SYNOPSIS
@@ -34,8 +34,8 @@
.fi
.SH DESCRIPTION
Pass a char * as parameter to a string holding the \fIname\fP of the
-service. The default service name is "HTTP" for HTTP based proxies and "rcmd"
-for SOCKS5. This option allows you to change it.
+service. The default service name is \fB"HTTP"\fP for HTTP based proxies and
+\fB"rcmd"\fP for SOCKS5. This option allows you to change it.
The application does not have to keep the string around after setting this
option.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.3
index 4273710..b08e878 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_SSLCERT 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_SSLCERT 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_SSLCERT \- HTTPS proxy client certificate
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.3
index 7bfc794..502868f 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_SSLCERTTYPE 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_SSLCERTTYPE 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_SSLCERTTYPE \- type of the proxy client SSL certificate
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.3
index 3f758f8..f97bb81 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_SSLCERT_BLOB 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_SSLCERT_BLOB 3 "24 Jun 2020" libcurl libcurl
.SH NAME
CURLOPT_PROXY_SSLCERT_BLOB \- SSL proxy client certificate from memory blob
.SH SYNOPSIS
@@ -48,7 +48,7 @@
.SH DEFAULT
NULL
.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+Used with HTTPS proxy
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.3
index 5e46238..5d1e669 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_SSLKEY 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_SSLKEY 3 "16 Nov 2016" libcurl libcurl
.SH NAME
-CURLOPT_PROXY_SSLKEY \- private keyfile for HTTPS proxy client cert
+CURLOPT_PROXY_SSLKEY \- private key file for HTTPS proxy client cert
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -38,8 +38,8 @@
\fICURLOPT_PROXY_SSLKEYTYPE(3)\fP.
(Windows, iOS and Mac OS X) This option is ignored by Secure Transport and
-Schannel SSL backends because they expect the private key to be already present
-in the keychain or PKCS#12 file containing the certificate.
+Schannel SSL backends because they expect the private key to be already
+present in the key chain or PKCS#12 file containing the certificate.
The application does not have to keep the string around after setting this
option.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.3
index 7214c01..ca1d261 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_SSLKEYTYPE 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_SSLKEYTYPE 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_SSLKEYTYPE \- type of the proxy private key file
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.3
index fa908fb..e6d769e 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_SSLKEY_BLOB 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_SSLKEY_BLOB 3 "24 Jun 2020" libcurl libcurl
.SH NAME
CURLOPT_PROXY_SSLKEY_BLOB \- private key for proxy cert from memory blob
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.3
index 0bb470d..2bbc30a 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_SSLVERSION 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_SSLVERSION 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_SSLVERSION \- preferred HTTPS proxy TLS version
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.3
index 359ee46..d857b6c 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_SSL_CIPHER_LIST 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_SSL_CIPHER_LIST 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_SSL_CIPHER_LIST \- ciphers to use for HTTPS proxy
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3
index 745faa2..eed4794 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_SSL_OPTIONS 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_SSL_OPTIONS 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_SSL_OPTIONS \- HTTPS proxy SSL behavior options
.SH SYNOPSIS
@@ -60,6 +60,12 @@
present. This option is only supported for Schannel (the native Windows SSL
library). If combined with \fICURLSSLOPT_NO_REVOKE\fP, the latter takes
precedence. (Added in 7.70.0)
+.IP CURLSSLOPT_NATIVE_CA
+Tell libcurl to use the operating system's native CA store for certificate
+verification. Works only on Windows when built to use OpenSSL. If you set this
+option and also set a CA certificate file or directory then during verification
+those certificates are searched in addition to the native CA store.
+(Added in 7.71.0)
.IP CURLSSLOPT_AUTO_CLIENT_CERT
Tell libcurl to automatically locate and use a client certificate for
authentication, when requested by the server. This option is only supported
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.3
index 9eec07a..c659dd0 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_SSL_VERIFYHOST 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_SSL_VERIFYHOST 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_SSL_VERIFYHOST \- verify the proxy certificate's name against host
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.3
index 51ed2c4..de445e5 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_SSL_VERIFYPEER 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_SSL_VERIFYPEER 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_SSL_VERIFYPEER \- verify the proxy's SSL certificate
.SH SYNOPSIS
@@ -35,7 +35,7 @@
.SH DESCRIPTION
Pass a long as parameter set to 1L to enable or 0L to disable.
-This option tells curl to verifies the authenticity of the HTTPS proxy's
+This option tells curl to verify the authenticity of the HTTPS proxy's
certificate. A value of 1 means curl verifies; 0 (zero) means it does not.
This is the proxy version of \fICURLOPT_SSL_VERIFYPEER(3)\fP that is used for
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.3 b/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.3
index fc41b0d..1af44c0 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_TLS13_CIPHERS 3 "25 May 2018" "libcurl 7.61.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_TLS13_CIPHERS 3 "25 May 2018" libcurl libcurl
.SH NAME
CURLOPT_PROXY_TLS13_CIPHERS \- ciphers suites for proxy TLS 1.3
.SH SYNOPSIS
@@ -44,7 +44,7 @@
This option is currently used only when curl is built to use OpenSSL 1.1.1 or
later. If you are using a different SSL backend you can try setting TLS 1.3
-cipher suites by using the CURLOPT_PROXY_SSL_CIPHER_LIST option.
+cipher suites by using the \fICURLOPT_PROXY_SSL_CIPHER_LIST(3)\fP option.
The application does not have to keep the string around after setting this
option.
@@ -58,7 +58,7 @@
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
curl_easy_setopt(curl, CURLOPT_PROXY_TLS13_CIPHERS,
- "TLS13-CHACHA20-POLY1305-SHA256");
+ "TLS_CHACHA20_POLY1305_SHA256");
ret = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.3 b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.3
index 8212844..c8750e8 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_TLSAUTH_PASSWORD 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_TLSAUTH_PASSWORD 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_TLSAUTH_PASSWORD \- password to use for proxy TLS authentication
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.3 b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.3
index 0d45be6..f01bf45 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_TLSAUTH_TYPE 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_TLSAUTH_TYPE 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_TLSAUTH_TYPE \- HTTPS proxy TLS authentication methods
.SH SYNOPSIS
@@ -39,7 +39,7 @@
.IP SRP
TLS-SRP authentication. Secure Remote Password authentication for TLS is
-defined in RFC5054 and provides mutual authentication if both sides have a
+defined in RFC 5054 and provides mutual authentication if both sides have a
shared secret. To use TLS-SRP, you must also set the
\fICURLOPT_PROXY_TLSAUTH_USERNAME(3)\fP and
\fICURLOPT_PROXY_TLSAUTH_PASSWORD(3)\fP options.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.3 b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.3
index 5ae5224..5511088 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_TLSAUTH_USERNAME 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_TLSAUTH_USERNAME 3 "16 Nov 2016" libcurl libcurl
.SH NAME
CURLOPT_PROXY_TLSAUTH_USERNAME \- user name to use for proxy TLS authentication
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.3 b/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.3
index b8a7daa..a50c711 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PROXY_TRANSFER_MODE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PROXY_TRANSFER_MODE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PROXY_TRANSFER_MODE \- append FTP transfer mode to URL for proxy
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_PUT.3 b/docs/libcurl/opts/CURLOPT_PUT.3
index ca6f725..1138bb5 100644
--- a/docs/libcurl/opts/CURLOPT_PUT.3
+++ b/docs/libcurl/opts/CURLOPT_PUT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_PUT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_PUT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_PUT \- make an HTTP PUT request
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_QUICK_EXIT.3 b/docs/libcurl/opts/CURLOPT_QUICK_EXIT.3
new file mode 100644
index 0000000..f11b0dd
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_QUICK_EXIT.3
@@ -0,0 +1,59 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_QUICK_EXIT 3 "30 Sep 2022" libcurl libcurl
+.SH NAME
+CURLOPT_QUICK_EXIT \- allow to exit quickly
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_QUICK_EXIT,
+ long value);
+.SH DESCRIPTION
+Pass a long as a parameter, 1L meaning that when recovering from a timeout,
+libcurl should skip lengthy cleanups that are intended to avoid all kinds of
+leaks (threads etc.), as the caller program is about to call exit() anyway.
+This allows for a swift termination after a DNS timeout for example, by
+canceling and/or forgetting about a resolver thread, at the expense of a
+possible (though short-lived) leak of associated resources.
+.SH DEFAULT
+0
+.SH PROTOCOLS
+All
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L);
+ ret = curl_easy_perform(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in 7.87.0
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLOPT_RESOLVE "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_QUOTE.3 b/docs/libcurl/opts/CURLOPT_QUOTE.3
index 99d27cc..f15396b 100644
--- a/docs/libcurl/opts/CURLOPT_QUOTE.3
+++ b/docs/libcurl/opts/CURLOPT_QUOTE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_QUOTE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_QUOTE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_QUOTE \- (S)FTP commands to run before transfer
.SH SYNOPSIS
@@ -46,7 +46,7 @@
make libcurl continue even if the command fails as by default libcurl will
stop at first failure.
-The set of valid FTP commands depends on the server (see RFC959 for a list of
+The set of valid FTP commands depends on the server (see RFC 959 for a list of
mandatory commands).
libcurl does not inspect, parse or "understand" the commands passed to the
@@ -71,8 +71,8 @@
user ID specified by the user operand. The user operand is a decimal
integer user ID.
.IP "ln source_file target_file"
-The ln and symlink commands create a symbolic link at the target_file location
-pointing to the source_file location.
+The \fBln\fP and \fBsymlink\fP commands create a symbolic link at the
+target_file location pointing to the source_file location.
.IP "mkdir directory_name"
The mkdir command creates the directory named by the directory_name operand.
.IP "mtime date file"
@@ -80,7 +80,8 @@
file operand. The <date expression> can be all sorts of date strings, see the
\fIcurl_getdate(3)\fP man page for date expression details. (Added in 7.73.0)
.IP "pwd"
-The pwd command returns the absolute pathname of the current working directory.
+The \fBpwd\fP command returns the absolute path of the current working
+directory.
.IP "rename source target"
The rename command renames the file or directory named by the source
operand to the destination path named by the target operand.
diff --git a/docs/libcurl/opts/CURLOPT_RANDOM_FILE.3 b/docs/libcurl/opts/CURLOPT_RANDOM_FILE.3
index 9fe34f7..0cfc257 100644
--- a/docs/libcurl/opts/CURLOPT_RANDOM_FILE.3
+++ b/docs/libcurl/opts/CURLOPT_RANDOM_FILE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RANDOM_FILE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_RANDOM_FILE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_RANDOM_FILE \- file to read random data from
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_RANGE.3 b/docs/libcurl/opts/CURLOPT_RANGE.3
index 504efc7..fb1f5a9 100644
--- a/docs/libcurl/opts/CURLOPT_RANGE.3
+++ b/docs/libcurl/opts/CURLOPT_RANGE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RANGE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_RANGE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_RANGE \- byte range to request
.SH SYNOPSIS
@@ -43,9 +43,9 @@
servers to ignore range requests so even when you set \fICURLOPT_RANGE(3)\fP
for a request, you may end up getting the full response sent back.
-For RTSP, the formatting of a range should follow RFC2326 Section 12.29. For
+For RTSP, the formatting of a range should follow RFC 2326 Section 12.29. For
RTSP, byte ranges are \fBnot\fP permitted. Instead, ranges should be given in
-npt, utc, or smpte formats.
+\fBnpt\fP, \fButc\fP, or \fBsmpte\fP formats.
For HTTP PUT uploads this option should not be used, since it may conflict with
other options.
diff --git a/docs/libcurl/opts/CURLOPT_READDATA.3 b/docs/libcurl/opts/CURLOPT_READDATA.3
index 79a804b..a4c7cb8 100644
--- a/docs/libcurl/opts/CURLOPT_READDATA.3
+++ b/docs/libcurl/opts/CURLOPT_READDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_READDATA 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_READDATA 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_READDATA \- pointer passed to the read callback
.SH SYNOPSIS
@@ -34,7 +34,7 @@
.SH DESCRIPTION
Data \fIpointer\fP to pass to the file read function. If you use the
\fICURLOPT_READFUNCTION(3)\fP option, this is the pointer you will get as
-input in the 4th argument to the callback.
+input in the fourth argument to the callback.
If you do not specify a read callback but instead rely on the default internal
read function, this data must be a valid readable FILE * (cast to 'void *').
diff --git a/docs/libcurl/opts/CURLOPT_READFUNCTION.3 b/docs/libcurl/opts/CURLOPT_READFUNCTION.3
index 4436683..cb2860a 100644
--- a/docs/libcurl/opts/CURLOPT_READFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_READFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_READFUNCTION 3 "25 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.TH CURLOPT_READFUNCTION 3 "25 Jun 2020" libcurl libcurl
.SH NAME
CURLOPT_READFUNCTION \- read callback for data uploads
.SH SYNOPSIS
@@ -40,7 +40,7 @@
in order to send it to the peer - like if you ask it to upload or post data to
the server. The data area pointed at by the pointer \fIbuffer\fP should be
filled up with at most \fIsize\fP multiplied with \fInitems\fP number of bytes
-by your function.
+by your function. \fIsize\fP is always 1.
Set the \fIuserdata\fP argument with the \fICURLOPT_READDATA(3)\fP option.
diff --git a/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3 b/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3
index 61ee493..3238c4c 100644
--- a/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3
+++ b/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_REDIR_PROTOCOLS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_REDIR_PROTOCOLS 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_REDIR_PROTOCOLS \- protocols allowed to redirect to
.SH SYNOPSIS
@@ -32,6 +32,10 @@
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REDIR_PROTOCOLS, long bitmask);
.fi
.SH DESCRIPTION
+This option is deprecated. We strongly recommend using
+\fICURLOPT_REDIR_PROTOCOLS_STR(3)\fP instead because this option cannot
+control all available protocols!
+
Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
limits what protocols libcurl may use in a transfer that it follows to in a
redirect when \fICURLOPT_FOLLOWLOCATION(3)\fP is enabled. This allows you to
@@ -101,7 +105,8 @@
}
.fi
.SH AVAILABILITY
-Added in 7.19.4, before then it would follow all protocols.
+Added in 7.19.4, before then it would follow all protocols. Deprecated
+since 7.85.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS_STR.3 b/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS_STR.3
new file mode 100644
index 0000000..db41e11
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS_STR.3
@@ -0,0 +1,91 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_REDIR_PROTOCOLS_STR 3 "19 Jun 2014" libcurl libcurl
+.SH NAME
+CURLOPT_REDIR_PROTOCOLS_STR \- protocols allowed to redirect to
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REDIR_PROTOCOLS_STR,
+ char *spec);
+.fi
+.SH DESCRIPTION
+Pass a pointer to a string that holds a comma-separated list of case
+insensitive protocol names (URL schemes). That list limits what protocols
+libcurl may use in a transfer that it follows to in a redirect when
+\fICURLOPT_FOLLOWLOCATION(3)\fP is enabled. This option allows applications to
+limit specific transfers to only be allowed to use a subset of protocols in
+redirections.
+
+Protocols denied by \fICURLOPT_PROTOCOLS_STR(3)\fP are not overridden by this
+option.
+
+By default libcurl will allow HTTP, HTTPS, FTP and FTPS on redirects (since
+7.65.2). Older versions of libcurl allowed all protocols on redirect except
+several disabled for security reasons: Since 7.19.4 FILE and SCP are disabled,
+and since 7.40.0 SMB and SMBS are also disabled.
+
+These are the available protocols:
+
+DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS,
+MQTT, POP3, POP3S, RTMP, RTMPE, RTMPS, RTMPT, RTMPTE, RTMPTS, RTSP, SCP, SFTP,
+SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS, WSS
+
+You can set "ALL" as a short-cut to enable all protocols. Note that by setting
+all, you may enable protocols that were not supported the day you write this
+but are introduced in a future libcurl version.
+
+If trying to set a non-existing protocol or if no matching protocol at all is
+set, it returns error.
+.SH DEFAULT
+HTTP, HTTPS, FTP and FTPS (Added in 7.65.2).
+
+Older versions defaulted to all protocols except FILE, SCP and since 7.40.0
+SMB and SMBS.
+.SH PROTOCOLS
+All
+.SH EXAMPLE
+.nf
+curl = curl_easy_init();
+if(curl) {
+ /* pass in the URL from an external source */
+ curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
+
+ /* only allow redirects to HTTP and HTTPS URLs */
+ curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https");
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in 7.85.0.
+.SH RETURN VALUE
+Returns CURLE_UNKNOWN_OPTION if the option is not implemented,
+CURLE_UNSUPPORTED_PROTOCOL if a listed protocol is not supported or disabled,
+CURLE_BAD_FUNCTION_ARGUMENT if no protocol is listed else CURLE_OK.
+.SH "SEE ALSO"
+.BR CURLOPT_PROTOCOLS_STR "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_REFERER.3 b/docs/libcurl/opts/CURLOPT_REFERER.3
index 907bfc9..5349149 100644
--- a/docs/libcurl/opts/CURLOPT_REFERER.3
+++ b/docs/libcurl/opts/CURLOPT_REFERER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_REFERER 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_REFERER 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_REFERER \- the HTTP referer header
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_REQUEST_TARGET.3 b/docs/libcurl/opts/CURLOPT_REQUEST_TARGET.3
index 5da5961..824209c 100644
--- a/docs/libcurl/opts/CURLOPT_REQUEST_TARGET.3
+++ b/docs/libcurl/opts/CURLOPT_REQUEST_TARGET.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_REQUEST_TARGET 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_REQUEST_TARGET 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_REQUEST_TARGET \- alternative target for this request
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_RESOLVE.3 b/docs/libcurl/opts/CURLOPT_RESOLVE.3
index cf1595d..2c1b202 100644
--- a/docs/libcurl/opts/CURLOPT_RESOLVE.3
+++ b/docs/libcurl/opts/CURLOPT_RESOLVE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RESOLVE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_RESOLVE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_RESOLVE \- provide custom host name to IP address resolves
.SH SYNOPSIS
@@ -46,7 +46,7 @@
\&... where HOST is the name libcurl will try to resolve, PORT is the port
number of the service where libcurl wants to connect to the HOST and ADDRESS
-is one or more numerical IP addresses. If you specify multiple ip addresses
+is one or more numerical IP addresses. If you specify multiple IP addresses
they need to be separated by comma. If libcurl is built to support IPv6, each
of the ADDRESS entries can of course be either IPv4 or IPv6 style addressing.
diff --git a/docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.3 b/docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.3
index 16cd33a..904d8db 100644
--- a/docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.3
+++ b/docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RESOLVER_START_DATA 3 "14 Feb 2018" "libcurl 7.59.0" "curl_easy_setopt options"
+.TH CURLOPT_RESOLVER_START_DATA 3 "14 Feb 2018" libcurl libcurl
.SH NAME
CURLOPT_RESOLVER_START_DATA \- pointer passed to the resolver start callback
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.3
index 59819d7..0b0adde 100644
--- a/docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RESOLVER_START_FUNCTION 3 "14 Feb 2018" "libcurl 7.59.0" "curl_easy_setopt options"
+.TH CURLOPT_RESOLVER_START_FUNCTION 3 "14 Feb 2018" libcurl libcurl
.SH NAME
CURLOPT_RESOLVER_START_FUNCTION \- callback called before a new name resolve is started
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_RESUME_FROM.3 b/docs/libcurl/opts/CURLOPT_RESUME_FROM.3
index 76de70b..9b81448 100644
--- a/docs/libcurl/opts/CURLOPT_RESUME_FROM.3
+++ b/docs/libcurl/opts/CURLOPT_RESUME_FROM.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RESUME_FROM 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_RESUME_FROM 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_RESUME_FROM \- offset to resume transfer from
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.3 b/docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.3
index 3df636e..33f88a9 100644
--- a/docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.3
+++ b/docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RESUME_FROM_LARGE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_RESUME_FROM_LARGE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_RESUME_FROM_LARGE \- offset to resume transfer from
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.3 b/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.3
index 09a9489..fd5272f 100644
--- a/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.3
+++ b/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RTSP_CLIENT_CSEQ 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_RTSP_CLIENT_CSEQ 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_RTSP_CLIENT_CSEQ \- RTSP client CSEQ number
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.3 b/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.3
index 7dcc1e6..3ed1220 100644
--- a/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.3
+++ b/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RTSP_REQUEST 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_RTSP_REQUEST 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_RTSP_REQUEST \- RTSP request
.SH SYNOPSIS
@@ -61,10 +61,11 @@
is not needed for this method.
.IP CURL_RTSPREQ_PLAY
Send a Play command to the server. Use the \fICURLOPT_RANGE(3)\fP option to
-modify the playback time (e.g. 'npt=10-15').
+modify the playback time (e.g. \fInpt=10-15\fP).
.IP CURL_RTSPREQ_PAUSE
Send a Pause command to the server. Use the \fICURLOPT_RANGE(3)\fP option with
-a single value to indicate when the stream should be halted. (e.g. npt='25')
+a single value to indicate when the stream should be
+halted. (e.g. \fInpt=25\fP)
.IP CURL_RTSPREQ_TEARDOWN
This command terminates an RTSP session. Simply closing a connection does not
terminate the RTSP session since it is valid to control an RTSP session over
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.3 b/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.3
index d00bb53..aa153f6 100644
--- a/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.3
+++ b/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RTSP_SERVER_CSEQ 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_RTSP_SERVER_CSEQ 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_RTSP_SERVER_CSEQ \- RTSP server CSEQ number
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.3 b/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.3
index 9d3ed21..aa75b29 100644
--- a/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.3
+++ b/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RTSP_SESSION_ID 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_RTSP_SESSION_ID 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_RTSP_SESSION_ID \- RTSP session ID
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.3 b/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.3
index b770312..95f25ab 100644
--- a/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.3
+++ b/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RTSP_STREAM_URI 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_RTSP_STREAM_URI 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_RTSP_STREAM_URI \- RTSP stream URI
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.3 b/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.3
index 08ed9a4..dd9c399 100644
--- a/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.3
+++ b/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_RTSP_TRANSPORT 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_RTSP_TRANSPORT 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_RTSP_TRANSPORT \- RTSP Transport: header
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.3 b/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.3
index 6d13ddd..aab3ebf 100644
--- a/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.3
+++ b/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SASL_AUTHZID 3 "11 Sep 2019" "libcurl 7.66.0" "curl_easy_setopt options"
+.TH CURLOPT_SASL_AUTHZID 3 "11 Sep 2019" libcurl libcurl
.SH NAME
CURLOPT_SASL_AUTHZID \- authorization identity (identity to act as)
.SH SYNOPSIS
@@ -33,17 +33,17 @@
.fi
.SH DESCRIPTION
Pass a char * as parameter, which should be pointing to the null-terminated
-authorization identity (authzid) for the transfer. Only applicable to the PLAIN
-SASL authentication mechanism where it is optional.
+authorization identity (\fIauthzid\fP) for the transfer. Only applicable to
+the PLAIN SASL authentication mechanism where it is optional.
-When not specified only the authentication identity (authcid) as specified by
-the username will be sent to the server, along with the password. The server
-will derive a authzid from the authcid when not provided, which it will then
-uses internally.
+When not specified only the authentication identity (\fIauthcid\fP) as
+specified by the username will be sent to the server, along with the
+password. The server will derive a \fIauthzid\fP from the \fIauthcid\fP when
+not provided, which it will then uses internally.
-When the authzid is specified, the use of which is server dependent, it can be
-used to access another user's inbox, that the user has been granted access to,
-or a shared mailbox for example.
+When the \fIauthzid\fP is specified, the use of which is server dependent, it
+can be used to access another user's inbox, that the user has been granted
+access to, or a shared mailbox for example.
.SH DEFAULT
blank
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_SASL_IR.3 b/docs/libcurl/opts/CURLOPT_SASL_IR.3
index c6c8afe..e48710a 100644
--- a/docs/libcurl/opts/CURLOPT_SASL_IR.3
+++ b/docs/libcurl/opts/CURLOPT_SASL_IR.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SASL_IR 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SASL_IR 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SASL_IR \- send initial response in first packet
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SEEKDATA.3 b/docs/libcurl/opts/CURLOPT_SEEKDATA.3
index f8c3274..98cdbf3 100644
--- a/docs/libcurl/opts/CURLOPT_SEEKDATA.3
+++ b/docs/libcurl/opts/CURLOPT_SEEKDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SEEKDATA 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SEEKDATA 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SEEKDATA \- pointer passed to the seek callback
.SH SYNOPSIS
@@ -41,9 +41,9 @@
HTTP, FTP, SFTP
.SH EXAMPLE
.nf
-static int seek_cb(void *userp, curl_off_t offset, int origin)
+static int seek_cb(void *clientp, curl_off_t offset, int origin)
{
- struct data *d = (struct data *)userp;
+ struct data *d = (struct data *)clientp;
lseek(d->our_fd, offset, origin);
return CURL_SEEKFUNC_OK;
}
diff --git a/docs/libcurl/opts/CURLOPT_SEEKFUNCTION.3 b/docs/libcurl/opts/CURLOPT_SEEKFUNCTION.3
index ee2a83b..09be6ef 100644
--- a/docs/libcurl/opts/CURLOPT_SEEKFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_SEEKFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SEEKFUNCTION 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SEEKFUNCTION 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SEEKFUNCTION \- user callback for seeking in input stream
.SH SYNOPSIS
@@ -35,7 +35,7 @@
#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking cannot be done, so
libcurl might try other means instead */
-int seek_callback(void *userp, curl_off_t offset, int origin);
+int seek_callback(void *clientp, curl_off_t offset, int origin);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SEEKFUNCTION, seek_callback);
.SH DESCRIPTION
@@ -53,7 +53,7 @@
SEEK_SET, SEEK_CUR or SEEK_END as argument for \fIorigin\fP, although libcurl
currently only passes SEEK_SET.
-\fIuserp\fP is the pointer you set with \fICURLOPT_SEEKDATA(3)\fP.
+\fIclientp\fP is the pointer you set with \fICURLOPT_SEEKDATA(3)\fP.
The callback function must return \fICURL_SEEKFUNC_OK\fP on success,
\fICURL_SEEKFUNC_FAIL\fP to cause the upload operation to fail or
@@ -70,9 +70,9 @@
HTTP, FTP, SFTP
.SH EXAMPLE
.nf
-static int seek_cb(void *userp, curl_off_t offset, int origin)
+static int seek_cb(void *clientp, curl_off_t offset, int origin)
{
- struct data *d = (struct data *)userp;
+ struct data *d = (struct data *)clientp;
lseek(our_fd, offset, origin);
return CURL_SEEKFUNC_OK;
}
diff --git a/docs/libcurl/opts/CURLOPT_FTP_RESPONSE_TIMEOUT.3 b/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.3
similarity index 73%
rename from docs/libcurl/opts/CURLOPT_FTP_RESPONSE_TIMEOUT.3
rename to docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.3
index 3e504ac..46d6fda 100644
--- a/docs/libcurl/opts/CURLOPT_FTP_RESPONSE_TIMEOUT.3
+++ b/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,14 +22,14 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_FTP_RESPONSE_TIMEOUT 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SERVER_RESPONSE_TIMEOUT 3 "19 Jun 2014" libcurl libcurl
.SH NAME
-CURLOPT_FTP_RESPONSE_TIMEOUT \- time allowed to wait for FTP response
+CURLOPT_SERVER_RESPONSE_TIMEOUT \- time allowed to wait for server response
.SH SYNOPSIS
.nf
#include <curl/curl.h>
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_RESPONSE_TIMEOUT,
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SERVER_RESPONSE_TIMEOUT,
long timeout);
.fi
.SH DESCRIPTION
@@ -38,28 +38,33 @@
message for a command before the session is considered dead. While libcurl is
waiting for a response, this value overrides \fICURLOPT_TIMEOUT(3)\fP. It is
recommended that if used in conjunction with \fICURLOPT_TIMEOUT(3)\fP, you set
-\fICURLOPT_FTP_RESPONSE_TIMEOUT(3)\fP to a value smaller than
+\fICURLOPT_SERVER_RESPONSE_TIMEOUT(3)\fP to a value smaller than
\fICURLOPT_TIMEOUT(3)\fP.
+
+This option was formerly known as \fBCURLOPT_FTP_RESPONSE_TIMEOUT\fP.
.SH DEFAULT
None
.SH PROTOCOLS
-FTP
+FTP, IMAP, POP3, SMTP, and SSH
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/slow.txt");
/* wait no more than 23 seconds */
- curl_easy_setopt(curl, CURLOPT_FTP_RESPONSE_TIMEOUT, 23L);
+ curl_easy_setopt(curl, CURLOPT_SERVER_RESPONSE_TIMEOUT, 23L);
ret = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
.fi
.SH AVAILABILITY
-Added in 7.10.8
+Added in 7.10.8. Used under this name since 7.20.0
+
+Support for SSH is predicated on a new enough (1.11.0) version of libssh2
+being available when compiling libcurl.
.SH RETURN VALUE
-Returns CURLE_OK if FTP is supported, and CURLE_UNKNOWN_OPTION if not. Returns
+Returns CURLE_OK if supported, and CURLE_UNKNOWN_OPTION if not. Returns
CURLE_BAD_FUNCTION_ARGUMENT if set to a negative value or a value that when
converted to milliseconds is too large.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLOPT_SERVICE_NAME.3 b/docs/libcurl/opts/CURLOPT_SERVICE_NAME.3
index ff8672b..8046d39 100644
--- a/docs/libcurl/opts/CURLOPT_SERVICE_NAME.3
+++ b/docs/libcurl/opts/CURLOPT_SERVICE_NAME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SERVICE_NAME 3 "17 Jun 2015" "libcurl 7.43.0" "curl_easy_setopt options"
+.TH CURLOPT_SERVICE_NAME 3 "17 Jun 2015" libcurl libcurl
.SH NAME
CURLOPT_SERVICE_NAME \- authentication service name
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SHARE.3 b/docs/libcurl/opts/CURLOPT_SHARE.3
index 95976b9..f26c9f0 100644
--- a/docs/libcurl/opts/CURLOPT_SHARE.3
+++ b/docs/libcurl/opts/CURLOPT_SHARE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SHARE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SHARE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SHARE \- share handle to use
.SH SYNOPSIS
@@ -41,8 +41,8 @@
\fIcurl_share_setopt(3)\fP for details.
If you add a share that is set to share cookies, your easy handle will use
-that cookie cache and get the cookie engine enabled. If you unshare an object
-that was using cookies (or change to another object that does not share
+that cookie cache and get the cookie engine enabled. If you stop sharing an
+object that was using cookies (or change to another object that does not share
cookies), the easy handle will get its cookie engine disabled.
Data that the share object is not set to share will be dealt with the usual
diff --git a/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.3 b/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.3
index 2e02b56..4c33841 100644
--- a/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.3
+++ b/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SOCKOPTDATA 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SOCKOPTDATA 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SOCKOPTDATA \- pointer to pass to sockopt callback
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.3 b/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.3
index c838384..3d65434 100644
--- a/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SOCKOPTFUNCTION 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SOCKOPTFUNCTION 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SOCKOPTFUNCTION \- callback for setting socket options
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.3 b/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.3
index 0164103..3ddc842 100644
--- a/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.3
+++ b/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SOCKS5_AUTH 3 "27 April 2017" "libcurl 7.55.0" "curl_easy_setopt options"
+.TH CURLOPT_SOCKS5_AUTH 3 "27 April 2017" libcurl libcurl
.SH NAME
CURLOPT_SOCKS5_AUTH \- methods for SOCKS5 proxy authentication
.SH SYNOPSIS
@@ -52,7 +52,7 @@
curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://user:pass@myproxy.com");
/* enable username/password authentication only */
- curl_easy_setopt(curl, CURLOPT_SOCKS5_AUTH, CURLAUTH_BASIC);
+ curl_easy_setopt(curl, CURLOPT_SOCKS5_AUTH, (long)CURLAUTH_BASIC);
/* Perform the request */
curl_easy_perform(curl);
diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.3 b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.3
index 44eead9..0f6b584 100644
--- a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.3
+++ b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SOCKS5_GSSAPI_NEC 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SOCKS5_GSSAPI_NEC 3 "19 Jun 2014" libcurl libcurl
.SH NAME
-CURLOPT_SOCKS5_GSSAPI_NEC \- socks proxy gssapi negotiation protection
+CURLOPT_SOCKS5_GSSAPI_NEC \- SOCKS proxy GSSAPI negotiation protection
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -32,8 +32,8 @@
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_GSSAPI_NEC, long nec);
.fi
.SH DESCRIPTION
-Pass a long set to 1 to enable or 0 to disable. As part of the gssapi
-negotiation a protection mode is negotiated. The RFC1961 says in section
+Pass a long set to 1 to enable or 0 to disable. As part of the GSSAPI
+negotiation a protection mode is negotiated. The RFC 1961 says in section
4.3/4.4 it should be protected, but the NEC reference implementation does not.
If enabled, this option allows the unprotected exchange of the protection mode
negotiation.
diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.3 b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.3
index b88581e..995b020 100644
--- a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.3
+++ b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SOCKS5_GSSAPI_SERVICE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SOCKS5_GSSAPI_SERVICE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SOCKS5_GSSAPI_SERVICE \- SOCKS5 proxy authentication service name
.SH SYNOPSIS
@@ -35,9 +35,9 @@
.SH DESCRIPTION
Deprecated since 7.49.0. Use \fICURLOPT_PROXY_SERVICE_NAME(3)\fP instead.
-Pass a char * as parameter to a string holding the \fIname\fP of the service.
-The default service name for a SOCKS5 server is "rcmd". This option allows you
-to change it.
+Pass a \fBchar *\fP as parameter to a string holding the \fIname\fP of the
+service. The default service name for a SOCKS5 server is \fI"rcmd"\fP. This
+option allows you to change it.
The application does not have to keep the string around after setting this
option.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.3 b/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.3
index 563ae57..6d1a856 100644
--- a/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.3
+++ b/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSH_AUTH_TYPES 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSH_AUTH_TYPES 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSH_AUTH_TYPES \- auth types for SFTP and SCP
.SH SYNOPSIS
@@ -41,7 +41,7 @@
attempts to connect to ssh-agent or pageant and let the agent attempt the
authentication.
.SH DEFAULT
-CURLSSH_AUTH_ANY (all availables ones)
+CURLSSH_AUTH_ANY (all available)
.SH PROTOCOLS
SFTP and SCP
.SH EXAMPLE
diff --git a/docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.3 b/docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.3
index c3dd7d8..1f760df 100644
--- a/docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.3
+++ b/docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSH_COMPRESSION 3 "05 Aug 2017" "libcurl 7.56.0" "curl_easy_setopt options"
+.TH CURLOPT_SSH_COMPRESSION 3 "05 Aug 2017" libcurl libcurl
.SH NAME
CURLOPT_SSH_COMPRESSION \- enable SSH compression
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYDATA.3 b/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYDATA.3
index e745738..095a10e 100644
--- a/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYDATA.3
+++ b/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSH_KEYDATA 3 "4 Nov 2021" "libcurl 7.84.0" "curl_easy_setopt options"
+.TH CURLOPT_SSH_KEYDATA 3 "4 Nov 2021" libcurl libcurl
.SH NAME
-CURLOPT_SSH_HOSTKEYDATA \- pointer to pass to the SSH hostkey callback
+CURLOPT_SSH_HOSTKEYDATA \- pointer to pass to the SSH host key callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -42,8 +42,8 @@
.nf
int hostkeycb(void *clientp, /* passed with CURLOPT_SSH_HOSTKEYDATA */
int keytype, /* CURLKHTYPE */
- const char * key, /*hostkey to check*/
- size_t keylen); /*length of the key*/
+ const char * key, /* host key to check */
+ size_t keylen); /* length of the key */
{
/* 'clientp' points to the callback_data struct */
/* investigate the situation and return the correct value */
diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYFUNCTION.3 b/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYFUNCTION.3
index 422392e..024cded 100644
--- a/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSH_HOSTKEYFUNCTION 3 "4 Nov 2021" "libcurl 7.84.0" "curl_easy_setopt options"
+.TH CURLOPT_SSH_HOSTKEYFUNCTION 3 "4 Nov 2021" libcurl libcurl
.SH NAME
-CURLOPT_SSH_HOSTKEYFUNCTION \- callback to check hostkey
+CURLOPT_SSH_HOSTKEYFUNCTION \- callback to check host key
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -41,20 +41,20 @@
Pass a pointer to your callback function, which should match the prototype
shown above. It overrides \fICURLOPT_SSH_KNOWNHOSTS(3)\fP.
-This callback gets called when the verification of the SSH hostkey is needed.
+This callback gets called when the verification of the SSH host key is needed.
\fBkey\fP is \fBkeylen\fP bytes long and is the key to check. \fBkeytype\fP
-says what type it is, from the \fBCURLKHTYPE_*\fP series in the curl_khtype
-enum.
+says what type it is, from the \fBCURLKHTYPE_*\fP series in the
+\fBcurl_khtype\fP enum.
\fBclientp\fP is a custom pointer set with \fICURLOPT_SSH_HOSTKEYDATA(3)\fP.
The callback MUST return one of the following return codes to tell libcurl how
to act:
.IP CURLKHMATCH_OK
-The hostkey is accepted, the connection should continue.
+The host key is accepted, the connection should continue.
.IP CURLKHMATCH_MISMATCH
-the hostkey is rejected, the connection is canceled.
+the host key is rejected, the connection is canceled.
.SH DEFAULT
NULL
.SH PROTOCOLS
@@ -63,8 +63,8 @@
.nf
int hostkeycb(void *clientp, /* passed with CURLOPT_SSH_HOSTKEYDATA */
int keytype, /* CURLKHTYPE */
- const char * key, /*hostkey to check*/
- size_t keylen); /*length of the key*/
+ const char * key, /* host key to check */
+ size_t keylen); /* length of the key */
{
/* 'clientp' points to the callback_data struct */
/* investigate the situation and return the correct value */
diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3 b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3
index 22e158b..60a885c 100644
--- a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3
+++ b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 \- MD5 checksum of SSH server public key
.SH SYNOPSIS
@@ -34,7 +34,7 @@
.SH DESCRIPTION
Pass a char * pointing to a string containing 32 hexadecimal digits. The
string should be the 128 bit MD5 checksum of the remote host's public key, and
-libcurl will reject the connection to the host unless the md5sums match.
+libcurl will reject the connection to the host unless the MD5 checksum match.
The application does not have to keep the string around after setting this
option.
@@ -60,3 +60,4 @@
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
.SH "SEE ALSO"
.BR CURLOPT_SSH_PUBLIC_KEYFILE "(3), " CURLOPT_SSH_AUTH_TYPES "(3), "
+.BR CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.3 b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.3
index 47a87e1..167526c 100644
--- a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.3
+++ b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 3 "27 Aug 2021" "libcurl 7.80.0" "curl_easy_setopt options"
+.TH CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 3 "27 Aug 2021" libcurl libcurl
.SH NAME
CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 \- SHA256 hash of SSH server public key
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSH_KEYDATA.3 b/docs/libcurl/opts/CURLOPT_SSH_KEYDATA.3
index 65e35a8..7d21790 100644
--- a/docs/libcurl/opts/CURLOPT_SSH_KEYDATA.3
+++ b/docs/libcurl/opts/CURLOPT_SSH_KEYDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSH_KEYDATA 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSH_KEYDATA 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSH_KEYDATA \- pointer passed to the SSH key callback
.SH SYNOPSIS
@@ -43,7 +43,7 @@
static int keycb(CURL *easy,
const struct curl_khkey *knownkey,
const struct curl_khkey *foundkey,
- enum curl_khmatch,
+ enum curl_khmatch match,
void *clientp)
{
/* 'clientp' points to the callback_data struct */
diff --git a/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.3 b/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.3
index f8aedf2..53bb88e 100644
--- a/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSH_KEYFUNCTION 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSH_KEYFUNCTION 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSH_KEYFUNCTION \- callback for known host matching logic
.SH SYNOPSIS
@@ -34,9 +34,8 @@
CURLKHSTAT_FINE,
CURLKHSTAT_REJECT, /* reject the connection, return an error */
CURLKHSTAT_DEFER, /* do not accept it, but we cannot answer right
- now so this causes a CURLE_DEFER error but
- otherwise the connection will be left intact
- etc */
+ now. Causes a CURLE_PEER_FAILED_VERIFICATION error but
+ the connection will be left intact */
CURLKHSTAT_FINE_REPLACE
};
@@ -57,7 +56,7 @@
int ssh_keycallback(CURL *easy,
const struct curl_khkey *knownkey,
const struct curl_khkey *foundkey,
- enum curl_khmatch,
+ enum curl_khmatch match,
void *clientp);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KEYFUNCTION,
@@ -109,7 +108,7 @@
static int keycb(CURL *easy,
const struct curl_khkey *knownkey,
const struct curl_khkey *foundkey,
- enum curl_khmatch,
+ enum curl_khmatch match,
void *clientp)
{
/* 'clientp' points to the callback_data struct */
diff --git a/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.3 b/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.3
index 7dc723c..8c4e1a0 100644
--- a/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.3
+++ b/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSH_KNOWNHOSTS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSH_KNOWNHOSTS 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSH_KNOWNHOSTS \- file name holding the SSH known hosts
.SH SYNOPSIS
@@ -37,7 +37,7 @@
format as supported by libssh2. If this file is specified, libcurl will only
accept connections with hosts that are known and present in that file, with a
matching public key. Use \fICURLOPT_SSH_KEYFUNCTION(3)\fP to alter the default
-behavior on host and key (mis)matching.
+behavior on host and key matches and mismatches.
The application does not have to keep the string around after setting this
option.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.3 b/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.3
index db78d81..e23c874 100644
--- a/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.3
+++ b/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSH_PRIVATE_KEYFILE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSH_PRIVATE_KEYFILE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSH_PRIVATE_KEYFILE \- private key file for SSH auth
.SH SYNOPSIS
@@ -33,8 +33,9 @@
char *filename);
.SH DESCRIPTION
Pass a char * pointing to a \fIfilename\fP for your private key. If not used,
-libcurl defaults to \fB$HOME/.ssh/id_dsa\fP if the HOME environment variable
-is set, and just "id_dsa" in the current directory if HOME is not set.
+libcurl defaults to \fB$HOME/.ssh/id_rsa\fP or \fB$HOME/.ssh/id_dsa\fP if the
+HOME environment variable is set, and just \fB"id_rsa"\fP or \fB"id_dsa"\fP in
+the current directory if HOME is not set.
If the file is password-protected, set the password with
\fICURLOPT_KEYPASSWD(3)\fP.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.3 b/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.3
index 5a4b54f..c900974 100644
--- a/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.3
+++ b/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSH_PUBLIC_KEYFILE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSH_PUBLIC_KEYFILE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSH_PUBLIC_KEYFILE \- public key file for SSH auth
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSLCERT.3 b/docs/libcurl/opts/CURLOPT_SSLCERT.3
index 956129a..9603782 100644
--- a/docs/libcurl/opts/CURLOPT_SSLCERT.3
+++ b/docs/libcurl/opts/CURLOPT_SSLCERT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSLCERT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSLCERT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSLCERT \- SSL client certificate
.SH SYNOPSIS
@@ -42,17 +42,17 @@
want to use a file from the current directory, please precede it with "./"
prefix, in order to avoid confusion with a nickname.
-(Schannel only) Client certificates can be specified by a path expression to
-a certificate store. (You can import PFX to a store first). You can use
-"<store location>\\<store name>\\<thumbprint>" to refer to a certificate
-in the system certificates store, for example,
-"CurrentUser\\MY\\934a7ac6f8a5d579285a74fa61e19f23ddfe8d7a". Thumbprint is
-usually a SHA-1 hex string which you can see in certificate details. Following
-store locations are supported: CurrentUser, LocalMachine, CurrentService,
-Services, CurrentUserGroupPolicy, LocalMachineGroupPolicy,
-LocalMachineEnterprise.
-Schannel also support P12 certificate file, with the string "P12" specified
-with \fICURLOPT_SSLCERTTYPE(3)\fP.
+(Schannel only) Client certificates can be specified by a path expression to a
+certificate store. (You can import \fIPFX\fP to a store first). You can use
+"<store location>\\<store name>\\<thumbprint>" to refer to a certificate in
+the system certificates store, for example,
+\fB"CurrentUser\\MY\\934a7ac6f8a5d579285a74fa"\fP. The thumbprint is usually a
+SHA-1 hex string which you can see in certificate details. Following store
+locations are supported: \fBCurrentUser\fP, \fBLocalMachine\fP,
+\fBCurrentService\fP, \fBServices\fP, \fBCurrentUserGroupPolicy\fP,
+\fBLocalMachineGroupPolicy\fP, \fBLocalMachineEnterprise\fP. Schannel also
+support P12 certificate file, with the string "P12" specified with
+\fICURLOPT_SSLCERTTYPE(3)\fP.
When using a client certificate, you most likely also need to provide a
private key with \fICURLOPT_SSLKEY(3)\fP.
diff --git a/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.3 b/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.3
index d5b82e9..52d442c 100644
--- a/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.3
+++ b/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSLCERTTYPE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSLCERTTYPE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSLCERTTYPE \- type of client SSL certificate
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.3 b/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.3
index 9f4e246..d9d4730 100644
--- a/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.3
+++ b/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSLCERT_BLOB 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.TH CURLOPT_SSLCERT_BLOB 3 "24 Jun 2020" libcurl libcurl
.SH NAME
CURLOPT_SSLCERT_BLOB \- SSL client certificate from memory blob
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSLENGINE.3 b/docs/libcurl/opts/CURLOPT_SSLENGINE.3
index 5106e95..56565bb 100644
--- a/docs/libcurl/opts/CURLOPT_SSLENGINE.3
+++ b/docs/libcurl/opts/CURLOPT_SSLENGINE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSLENGINE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSLENGINE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSLENGINE \- SSL engine identifier
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.3 b/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.3
index 826868c..5e53f6a 100644
--- a/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.3
+++ b/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSLENGINE_DEFAULT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSLENGINE_DEFAULT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSLENGINE_DEFAULT \- make SSL engine default
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSLKEY.3 b/docs/libcurl/opts/CURLOPT_SSLKEY.3
index 91c4c26..7df27bb 100644
--- a/docs/libcurl/opts/CURLOPT_SSLKEY.3
+++ b/docs/libcurl/opts/CURLOPT_SSLKEY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSLKEY 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSLKEY 3 "17 Jun 2014" libcurl libcurl
.SH NAME
-CURLOPT_SSLKEY \- private keyfile for TLS and SSL client cert
+CURLOPT_SSLKEY \- private key file for TLS and SSL client cert
.SH SYNOPSIS
.nf
#include <curl/curl.h>
@@ -38,7 +38,7 @@
(Windows, iOS and Mac OS X) This option is ignored by Secure Transport and
Schannel SSL backends because they expect the private key to be already present
-in the keychain or PKCS#12 file containing the certificate.
+in the key-chain or PKCS#12 file containing the certificate.
The application does not have to keep the string around after setting this
option.
diff --git a/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.3 b/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.3
index 0fddc02..78d1744 100644
--- a/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.3
+++ b/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSLKEYTYPE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSLKEYTYPE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSLKEYTYPE \- type of the private key file
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.3 b/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.3
index 609d7a4..27cd9b9 100644
--- a/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.3
+++ b/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSLKEY_BLOB 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.TH CURLOPT_SSLKEY_BLOB 3 "24 Jun 2020" libcurl libcurl
.SH NAME
CURLOPT_SSLKEY_BLOB \- private key for client cert from memory blob
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSLVERSION.3 b/docs/libcurl/opts/CURLOPT_SSLVERSION.3
index 960e54b..0288dd7 100644
--- a/docs/libcurl/opts/CURLOPT_SSLVERSION.3
+++ b/docs/libcurl/opts/CURLOPT_SSLVERSION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSLVERSION 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSLVERSION 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSLVERSION \- preferred TLS/SSL version
.SH SYNOPSIS
@@ -99,7 +99,7 @@
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
/* ask libcurl to use TLS version 1.0 or later */
- curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
+ curl_easy_setopt(curl, CURLOPT_SSLVERSION, (long)CURL_SSLVERSION_TLSv1);
/* Perform the request */
curl_easy_perform(curl);
diff --git a/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.3 b/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.3
index 5815272..f8e0e7e 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSL_CIPHER_LIST 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSL_CIPHER_LIST 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSL_CIPHER_LIST \- ciphers to use for TLS
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.3 b/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.3
index f6d6eac..aa49751 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSL_CTX_DATA 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSL_CTX_DATA 3 "19 Jun 2014" libcurl libcurl
.SH NAME
-CURLOPT_SSL_CTX_DATA \- pointer passed to ssl_ctx callback
+CURLOPT_SSL_CTX_DATA \- pointer passed to SSL context callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>
diff --git a/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.3
index 407dd4b..7d4e688 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,14 +22,14 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSL_CTX_FUNCTION 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSL_CTX_FUNCTION 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSL_CTX_FUNCTION \- SSL context callback for OpenSSL, wolfSSL or mbedTLS
.SH SYNOPSIS
.nf
#include <curl/curl.h>
-CURLcode ssl_ctx_callback(CURL *curl, void *ssl_ctx, void *userptr);
+CURLcode ssl_ctx_callback(CURL *curl, void *ssl_ctx, void *clientp);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CTX_FUNCTION,
ssl_ctx_callback);
@@ -49,7 +49,7 @@
\fImbedtls_ssl_config\fP for mbedTLS or a pointer to
\fIbr_ssl_client_context\fP for BearSSL. If an error is returned from the
callback no attempt to establish a connection is made and the perform
-operation will return the callback's error code. Set the \fIuserptr\fP
+operation will return the callback's error code. Set the \fIclientp\fP
argument with the \fICURLOPT_SSL_CTX_DATA(3)\fP option.
This function will get called on all new connections made to a server, during
@@ -68,12 +68,12 @@
you may set \fICURLOPT_FORBID_REUSE(3)\fP from the callback function.
WARNING: If you are using DNS-over-HTTPS (DoH) via \fICURLOPT_DOH_URL(3)\fP
-then the CTX callback will also be called for those transfers and the curl
-handle is set to an internal handle. \fBThis behavior is subject to change.\fP
-We recommend before performing your transfer set \fICURLOPT_PRIVATE(3)\fP on
-your curl handle so you can identify it in the CTX callback. If you have a
-reason to modify DoH SSL context please let us know on the curl-library mailing
-list because we are considering removing this capability.
+then this callback will also be called for those transfers and the curl handle
+is set to an internal handle. \fBThis behavior is subject to change.\fP We
+recommend before performing your transfer set \fICURLOPT_PRIVATE(3)\fP on your
+curl handle so you can identify it in the context callback. If you have a
+reason to modify DoH SSL context please let us know on the curl-library
+mailing list because we are considering removing this capability.
.SH DEFAULT
NULL
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.3 b/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.3
index 0fea2da..4d91437 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSL_EC_CURVES 3 "29 Aug 2020" "libcurl 7.73.0" "curl_easy_setopt options"
+.TH CURLOPT_SSL_EC_CURVES 3 "29 Aug 2020" libcurl libcurl
.SH NAME
CURLOPT_SSL_EC_CURVES \- key exchange curves
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.3 b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.3
index a294aa6..973306e 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSL_ENABLE_ALPN 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSL_ENABLE_ALPN 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSL_ENABLE_ALPN \- Application Layer Protocol Negotiation
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.3 b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.3
index 1d0ccb6..c3a995a 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSL_ENABLE_NPN 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSL_ENABLE_NPN 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSL_ENABLE_NPN \- use NPN
.SH SYNOPSIS
@@ -32,6 +32,8 @@
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_ENABLE_NPN, long npn);
.fi
.SH DESCRIPTION
+Deprecated in 7.86.0. Setting this option has no function.
+
Pass a long as parameter, 0 or 1 where 1 is for enable and 0 for disable. This
option enables/disables NPN in the SSL handshake (if the SSL backend libcurl
is built to use supports it), which can be used to negotiate http2.
@@ -50,7 +52,7 @@
}
.fi
.SH AVAILABILITY
-Added in 7.36.0
+Added in 7.36.0. Deprecated in 7.86.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3 b/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3
index daf826c..a7df43c 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSL_FALSESTART 3 "14 Feb 2015" "libcurl 7.41.0" "curl_easy_setopt options"
+.TH CURLOPT_SSL_FALSESTART 3 "14 Feb 2015" libcurl libcurl
.SH NAME
CURLOPT_SSL_FALSESTART \- TLS false start
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3
index 3d773ae..c81eecc 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSL_OPTIONS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSL_OPTIONS 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSL_OPTIONS \- SSL behavior options
.SH SYNOPSIS
@@ -61,8 +61,9 @@
precedence. (Added in 7.70.0)
.IP CURLSSLOPT_NATIVE_CA
Tell libcurl to use the operating system's native CA store for certificate
-verification. Works only on Windows when built to use OpenSSL. This option is
-experimental and behavior is subject to change.
+verification. Works only on Windows when built to use OpenSSL. If you set this
+option and also set a CA certificate file or directory then during verification
+those certificates are searched in addition to the native CA store.
(Added in 7.71.0)
.IP CURLSSLOPT_AUTO_CLIENT_CERT
Tell libcurl to automatically locate and use a client certificate for
@@ -82,7 +83,7 @@
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
/* weaken TLS only for use with silly servers */
- curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_ALLOW_BEAST |
+ curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_ALLOW_BEAST |
CURLSSLOPT_NO_REVOKE);
ret = curl_easy_perform(curl);
curl_easy_cleanup(curl);
diff --git a/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.3 b/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.3
index 6e0048f..7651d3c 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSL_SESSIONID_CACHE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSL_SESSIONID_CACHE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSL_SESSIONID_CACHE \- use the SSL session-ID cache
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.3 b/docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.3
index 024661b..0ef75ba 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSL_VERIFYHOST 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSL_VERIFYHOST 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSL_VERIFYHOST \- verify the certificate's name against host
.SH SYNOPSIS
@@ -67,6 +67,17 @@
This option controls checking the server's certificate's claimed identity.
The server could be lying. To control lying, see
\fICURLOPT_SSL_VERIFYPEER(3)\fP.
+
+WARNING: disabling verification of the certificate allows bad guys to
+man-in-the-middle the communication without you knowing it. Disabling
+verification makes the communication insecure. Just having encryption on a
+transfer is not enough as you cannot be sure that you are communicating with
+the correct end-point.
+
+When libcurl uses secure protocols it trusts responses and allows for example
+HSTS and Alt-Svc information to be stored and used subsequently. Disabling
+certificate verification can make libcurl trust and use such information from
+malicious servers.
.SH LIMITATIONS
Secure Transport: If \fIverify\fP value is 0, then SNI is also disabled. SNI is
a TLS extension that sends the hostname to the server. The server may use that
diff --git a/docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.3 b/docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.3
index 1a0c1b5..56d0950 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSL_VERIFYPEER 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_SSL_VERIFYPEER 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_SSL_VERIFYPEER \- verify the peer's SSL certificate
.SH SYNOPSIS
@@ -62,14 +62,10 @@
transfer is not enough as you cannot be sure that you are communicating with
the correct end-point.
-NOTE: even when this option is disabled, depending on the used TLS backend,
-curl may still load the certificate file specified in
-\fICURLOPT_CAINFO(3)\fP. curl default settings in some distributions might use
-quite a large file as a default setting for \fICURLOPT_CAINFO(3)\fP, so
-loading the file can be quite expensive, especially when dealing with many
-connections. Thus, in some situations, you might want to disable verification
-fully to save resources by setting \fICURLOPT_CAINFO(3)\fP to NULL - but
-please also consider the warning above!
+When libcurl uses secure protocols it trusts responses and allows for example
+HSTS and Alt-Svc information to be stored and used subsequently. Disabling
+certificate verification can make libcurl trust and use such information from
+malicious servers.
.SH DEFAULT
By default, curl assumes a value of 1.
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.3 b/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.3
index b19b1a2..da80e6b 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SSL_VERIFYSTATUS 3 "04 Dec 2014" "libcurl 7.40.0" "curl_easy_setopt options"
+.TH CURLOPT_SSL_VERIFYSTATUS 3 "04 Dec 2014" libcurl libcurl
.SH NAME
CURLOPT_SSL_VERIFYSTATUS \- verify the certificate's status
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_STDERR.3 b/docs/libcurl/opts/CURLOPT_STDERR.3
index 51031a5..2c2071c 100644
--- a/docs/libcurl/opts/CURLOPT_STDERR.3
+++ b/docs/libcurl/opts/CURLOPT_STDERR.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_STDERR 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_STDERR 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_STDERR \- redirect stderr to another stream
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.3 b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.3
index 792c289..d292904 100644
--- a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.3
+++ b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_STREAM_DEPENDS 3 "13 Sep 2015" "libcurl 7.46.0" "curl_easy_setopt options"
+.TH CURLOPT_STREAM_DEPENDS 3 "13 Sep 2015" libcurl libcurl
.SH NAME
CURLOPT_STREAM_DEPENDS \- stream this transfer depends on
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.3 b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.3
index 19d2caa..f9b2776 100644
--- a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.3
+++ b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_STREAM_DEPENDS_E 3 "13 Sep 2015" "libcurl 7.46.0" "curl_easy_setopt options"
+.TH CURLOPT_STREAM_DEPENDS_E 3 "13 Sep 2015" libcurl libcurl
.SH NAME
CURLOPT_STREAM_DEPENDS_E \- stream this transfer depends on exclusively
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.3 b/docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.3
index 7bf5d2a..a91588f 100644
--- a/docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.3
+++ b/docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_STREAM_WEIGHT 3 "13 Sep 2015" "libcurl 7.46.0" "curl_easy_setopt options"
+.TH CURLOPT_STREAM_WEIGHT 3 "13 Sep 2015" libcurl libcurl
.SH NAME
CURLOPT_STREAM_WEIGHT \- numerical stream weight
.SH SYNOPSIS
@@ -43,8 +43,7 @@
info get sent to the server the next time an HTTP/2 frame is sent to the
server.
-See section 5.3 of RFC 7540 for protocol details:
-https://httpwg.github.io/specs/rfc7540.html#StreamPriority
+See section 5.3 of RFC 7540 for protocol details.
Streams with the same parent should be allocated resources proportionally
based on their weight. So if you have two streams going, stream A with weight
diff --git a/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.3 b/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.3
index 197d316..f67a87d 100644
--- a/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.3
+++ b/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_SUPPRESS_CONNECT_HEADERS 3 "13 February 2017" "libcurl 7.54.0" "curl_easy_setopt options"
+.TH CURLOPT_SUPPRESS_CONNECT_HEADERS 3 "13 February 2017" libcurl libcurl
.SH NAME
CURLOPT_SUPPRESS_CONNECT_HEADERS \- suppress proxy CONNECT response headers from user callbacks
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.3 b/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.3
index da05ed9..06da3bf 100644
--- a/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.3
+++ b/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TCP_FASTOPEN 3 "16 Feb 2016" "libcurl 7.49.0" "curl_easy_setopt options"
+.TH CURLOPT_TCP_FASTOPEN 3 "16 Feb 2016" libcurl libcurl
.SH NAME
CURLOPT_TCP_FASTOPEN \- TCP Fast Open
.SH SYNOPSIS
@@ -34,9 +34,12 @@
.SH DESCRIPTION
Pass a long as parameter set to 1L to enable or 0 to disable.
-TCP Fast Open (RFC7413) is a mechanism that allows data to be carried in the
+TCP Fast Open (RFC 7413) is a mechanism that allows data to be carried in the
SYN and SYN-ACK packets and consumed by the receiving end during the initial
connection handshake, saving up to one full round-trip time (RTT).
+
+Beware: the TLS session cache does not work when TCP Fast Open is enabled. TCP
+Fast Open is also known to be problematic on or across certain networks.
.SH DEFAULT
0
.SH PROTOCOLS
@@ -51,8 +54,8 @@
}
.fi
.SH AVAILABILITY
-Added in 7.49.0. This option is currently only supported on Linux and OS X
-El Capitan.
+Added in 7.49.0. This option is currently only supported on Linux and macOS
+10.11 or later.
.SH RETURN VALUE
Returns CURLE_OK if fast open is supported by the operating system, otherwise
returns CURLE_NOT_BUILT_IN.
diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.3 b/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.3
index 56ddae7..ef65421 100644
--- a/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.3
+++ b/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TCP_KEEPALIVE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TCP_KEEPALIVE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TCP_KEEPALIVE \- TCP keep-alive probing
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.3 b/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.3
index 18538dc..20100b0 100644
--- a/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.3
+++ b/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TCP_KEEPIDLE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TCP_KEEPIDLE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TCP_KEEPIDLE \- TCP keep-alive idle time wait
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.3 b/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.3
index ec3a384..5a845c6 100644
--- a/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.3
+++ b/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TCP_KEEPINTVL 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TCP_KEEPINTVL 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TCP_KEEPINTVL \- TCP keep-alive interval
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_TCP_NODELAY.3 b/docs/libcurl/opts/CURLOPT_TCP_NODELAY.3
index b6c1d21..2d30ad4 100644
--- a/docs/libcurl/opts/CURLOPT_TCP_NODELAY.3
+++ b/docs/libcurl/opts/CURLOPT_TCP_NODELAY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TCP_NODELAY 3 "30 Jun 2016" "libcurl 7.50.0" "curl_easy_setopt options"
+.TH CURLOPT_TCP_NODELAY 3 "30 Jun 2016" libcurl libcurl
.SH NAME
CURLOPT_TCP_NODELAY \- the TCP_NODELAY option
.SH SYNOPSIS
@@ -32,14 +32,14 @@
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_NODELAY, long nodelay);
.fi
.SH DESCRIPTION
-Pass a long specifying whether the TCP_NODELAY option is to be set or cleared
-(1L = set, 0 = clear). The option is set by default. This will have no effect
-after the connection has been established.
+Pass a long specifying whether the \fITCP_NODELAY\fP option is to be set or
+cleared (1L = set, 0 = clear). The option is set by default. This will have no
+effect after the connection has been established.
Setting this option to 1L will disable TCP's Nagle algorithm on this
connection. The purpose of this algorithm is to try to minimize the number of
small packets on the network (where "small packets" means TCP segments less
-than the Maximum Segment Size (MSS) for the network).
+than the Maximum Segment Size for the network).
Maximizing the amount of data sent per TCP segment is good because it
amortizes the overhead of the send. However, in some cases small segments may
diff --git a/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.3 b/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.3
index f8e17a0..c2c1065 100644
--- a/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.3
+++ b/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TELNETOPTIONS 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TELNETOPTIONS 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TELNETOPTIONS \- set of telnet options
.SH SYNOPSIS
@@ -35,8 +35,8 @@
.SH DESCRIPTION
Provide a pointer to a curl_slist with variables to pass to the telnet
negotiations. The variables should be in the format <option=value>. libcurl
-supports the options 'TTYPE', 'XDISPLOC' and 'NEW_ENV'. See the TELNET
-standard for details.
+supports the options \fBTTYPE\fP, \fBXDISPLOC\fP and \fBNEW_ENV\fP. See the
+TELNET standard for details.
.SH DEFAULT
NULL
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.3 b/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.3
index 4fe3a61..fd79db9 100644
--- a/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.3
+++ b/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TFTP_BLKSIZE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TFTP_BLKSIZE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TFTP_BLKSIZE \- TFTP block size
.SH SYNOPSIS
@@ -33,11 +33,11 @@
.fi
.SH DESCRIPTION
Specify \fIblocksize\fP to use for TFTP data transmission. Valid range as per
-RFC2348 is 8-65464 bytes. The default of 512 bytes will be used if this option
+RFC 2348 is 8-65464 bytes. The default of 512 bytes will be used if this option
is not specified. The specified block size will only be used pending support
-by the remote server. If the server does not return an option acknowledgement
-or returns an option acknowledgement with no blksize, the default of 512 bytes
-will be used.
+by the remote server. If the server does not return an option acknowledgment
+or returns an option acknowledgment with no block size, the default of 512
+bytes will be used.
.SH DEFAULT
512
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.3
index c467872..fc3b3b3 100644
--- a/docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.3
+++ b/docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TFTP_NO_OPTIONS 3 "23 Feb 2016" "libcurl 7.48.0" "curl_easy_setopt options"
+.TH CURLOPT_TFTP_NO_OPTIONS 3 "23 Feb 2016" libcurl libcurl
.SH NAME
CURLOPT_TFTP_NO_OPTIONS \- send no TFTP options requests
.SH SYNOPSIS
@@ -32,11 +32,11 @@
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TFTP_NO_OPTIONS, long onoff);
.fi
.SH DESCRIPTION
-Set \fIonoff\fP to 1L to exclude all TFTP options defined in RFC2347, RFC2348
-and RFC2349 from read and write requests (RRQs/WRQs).
+Set \fIonoff\fP to 1L to exclude all TFTP options defined in RFC 2347,
+RFC 2348 and RFC 2349 from read and write requests.
-This option improves interop with some legacy servers that do not acknowledge
-or properly implement TFTP options. When this option is used
+This option improves interoperability with legacy servers that do not
+acknowledge or properly implement TFTP options. When this option is used
\fICURLOPT_TFTP_BLKSIZE(3)\fP is ignored.
.SH DEFAULT
0
diff --git a/docs/libcurl/opts/CURLOPT_TIMECONDITION.3 b/docs/libcurl/opts/CURLOPT_TIMECONDITION.3
index dc7c836..84d0516 100644
--- a/docs/libcurl/opts/CURLOPT_TIMECONDITION.3
+++ b/docs/libcurl/opts/CURLOPT_TIMECONDITION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TIMECONDITION 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TIMECONDITION 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TIMECONDITION \- select condition for a time request
.SH SYNOPSIS
@@ -55,7 +55,8 @@
curl_easy_setopt(curl, CURLOPT_TIMEVALUE, 1577833200L);
/* If-Modified-Since the above time stamp */
- curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
+ curl_easy_setopt(curl, CURLOPT_TIMECONDITION,
+ (long)CURL_TIMECOND_IFMODSINCE);
/* Perform the request */
curl_easy_perform(curl);
diff --git a/docs/libcurl/opts/CURLOPT_TIMEOUT.3 b/docs/libcurl/opts/CURLOPT_TIMEOUT.3
index ae9dcda..ab1dd27 100644
--- a/docs/libcurl/opts/CURLOPT_TIMEOUT.3
+++ b/docs/libcurl/opts/CURLOPT_TIMEOUT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TIMEOUT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TIMEOUT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TIMEOUT \- maximum time the transfer is allowed to complete
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_TIMEOUT_MS.3 b/docs/libcurl/opts/CURLOPT_TIMEOUT_MS.3
index 6ea80a6..d208769 100644
--- a/docs/libcurl/opts/CURLOPT_TIMEOUT_MS.3
+++ b/docs/libcurl/opts/CURLOPT_TIMEOUT_MS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TIMEOUT_MS 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TIMEOUT_MS 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TIMEOUT_MS \- maximum time the transfer is allowed to complete
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_TIMEVALUE.3 b/docs/libcurl/opts/CURLOPT_TIMEVALUE.3
index 6ae67ee..5d4f530 100644
--- a/docs/libcurl/opts/CURLOPT_TIMEVALUE.3
+++ b/docs/libcurl/opts/CURLOPT_TIMEVALUE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TIMEVALUE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TIMEVALUE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TIMEVALUE \- time value for conditional
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.3 b/docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.3
index 18f3a8c..0d0f575 100644
--- a/docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.3
+++ b/docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TIMEVALUE_LARGE 3 "25 Jan 2018" "libcurl 7.59.0" "curl_easy_setopt options"
+.TH CURLOPT_TIMEVALUE_LARGE 3 "25 Jan 2018" libcurl libcurl
.SH NAME
CURLOPT_TIMEVALUE_LARGE \- time value for conditional
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.3 b/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.3
index 2349d4e..37ebd76 100644
--- a/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.3
+++ b/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TLS13_CIPHERS 3 "25 May 2018" "libcurl 7.61.0" "curl_easy_setopt options"
+.TH CURLOPT_TLS13_CIPHERS 3 "25 May 2018" libcurl libcurl
.SH NAME
CURLOPT_TLS13_CIPHERS \- ciphers suites to use for TLS 1.3
.SH SYNOPSIS
@@ -41,8 +41,9 @@
https://curl.se/docs/ssl-ciphers.html
This option is currently used only when curl is built to use OpenSSL 1.1.1 or
-later. If you are using a different SSL backend you can try setting TLS 1.3
-cipher suites by using the CURLOPT_SSL_CIPHER_LIST option.
+later or Schannel. If you are using a different SSL backend you can try
+setting TLS 1.3 cipher suites by using the \fICURLOPT_SSL_CIPHER_LIST(3)\fP
+option.
The application does not have to keep the string around after setting this
option.
@@ -56,14 +57,15 @@
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
curl_easy_setopt(curl, CURLOPT_TLS13_CIPHERS,
- "TLS13-CHACHA20-POLY1305-SHA256");
+ "TLS_CHACHA20_POLY1305_SHA256");
ret = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
.fi
.SH AVAILABILITY
-Added in 7.61.0.
-Available when built with OpenSSL >= 1.1.1.
+Added in 7.61.0 for OpenSSL. Available when built with OpenSSL >= 1.1.1.
+
+Added in 7.85.0 for Schannel.
.SH RETURN VALUE
Returns CURLE_OK if supported, CURLE_NOT_BUILT_IN otherwise.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.3 b/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.3
index 5b01b84..df9e378 100644
--- a/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.3
+++ b/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TLSAUTH_PASSWORD 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TLSAUTH_PASSWORD 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TLSAUTH_PASSWORD \- password to use for TLS authentication
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.3 b/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.3
index f580861..6f87657 100644
--- a/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.3
+++ b/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TLSAUTH_TYPE 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TLSAUTH_TYPE 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TLSAUTH_TYPE \- TLS authentication methods
.SH SYNOPSIS
@@ -37,7 +37,7 @@
.IP SRP
TLS-SRP authentication. Secure Remote Password authentication for TLS is
-defined in RFC5054 and provides mutual authentication if both sides have a
+defined in RFC 5054 and provides mutual authentication if both sides have a
shared secret. To use TLS-SRP, you must also set the
\fICURLOPT_TLSAUTH_USERNAME(3)\fP and \fICURLOPT_TLSAUTH_PASSWORD(3)\fP
options.
diff --git a/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.3 b/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.3
index 5ba093a..d7868e0 100644
--- a/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.3
+++ b/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TLSAUTH_USERNAME 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TLSAUTH_USERNAME 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TLSAUTH_USERNAME \- user name to use for TLS authentication
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_TRAILERDATA.3 b/docs/libcurl/opts/CURLOPT_TRAILERDATA.3
index f59d3c4..ef2ea56 100644
--- a/docs/libcurl/opts/CURLOPT_TRAILERDATA.3
+++ b/docs/libcurl/opts/CURLOPT_TRAILERDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TRAILERDATA 3 "14 Aug 2018" "libcurl 7.64.0" "curl_easy_setopt options"
+.TH CURLOPT_TRAILERDATA 3 "14 Aug 2018" libcurl libcurl
.SH NAME
CURLOPT_TRAILERDATA \- pointer passed to trailing headers callback
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.3 b/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.3
index efa3e90..00783e4 100644
--- a/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TRAILERFUNCTION 3 "14 Aug 2018" "libcurl 7.64.0" "curl_easy_setopt options"
+.TH CURLOPT_TRAILERFUNCTION 3 "14 Aug 2018" libcurl libcurl
.SH NAME
CURLOPT_TRAILERFUNCTION \- callback for sending trailing headers
.SH SYNOPSIS
@@ -41,7 +41,8 @@
CR LF in an HTTP chunked transfer to fill a list of trailing headers to be
sent before finishing the HTTP transfer.
-You can set the userdata argument with the CURLOPT_TRAILERDATA option.
+You can set the userdata argument with the \fICURLOPT_TRAILERDATA(3)\fP
+option.
The trailing headers included in the linked list must not be CRLF-terminated,
because libcurl will add the appropriate line termination characters after
@@ -51,13 +52,12 @@
libcurl will duplicate the strings, and will free the curl_slist and the
duplicates once the trailers have been sent.
-If one of the trailing headers is not formatted correctly
-(i.e. HeaderName: headerdata) it will be ignored and an info message
-will be emitted.
+If one of the trailing header fields is not formatted correctly it will be
+ignored and an info message will be emitted.
-The return value can either be CURL_TRAILERFUNC_OK or CURL_TRAILERFUNC_ABORT
-which would respectively instruct libcurl to either continue with sending the
-trailers or to abort the request.
+The return value can either be \fBCURL_TRAILERFUNC_OK\fP or
+\fBCURL_TRAILERFUNC_ABORT\fP which would respectively instruct libcurl to
+either continue with sending the trailers or to abort the request.
If you set this option to NULL, then the transfer proceeds as usual
without any interruptions.
diff --git a/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.3 b/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.3
index 88d342c..b572ce4 100644
--- a/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.3
+++ b/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TRANSFERTEXT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TRANSFERTEXT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TRANSFERTEXT \- request a text based transfer for FTP
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.3 b/docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.3
index 8ca96b0..2a64d86 100644
--- a/docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.3
+++ b/docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TRANSFER_ENCODING 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TRANSFER_ENCODING 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_TRANSFER_ENCODING \- ask for HTTP Transfer Encoding
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3 b/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3
index c7467b8..0836610 100644
--- a/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3
+++ b/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_UNIX_SOCKET_PATH 3 "09 Oct 2014" "libcurl 7.40.0" "curl_easy_setopt options"
+.TH CURLOPT_UNIX_SOCKET_PATH 3 "09 Oct 2014" libcurl libcurl
.SH NAME
CURLOPT_UNIX_SOCKET_PATH \- Unix domain socket
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.3 b/docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.3
index 6247b58..9813437 100644
--- a/docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.3
+++ b/docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_UNRESTRICTED_AUTH 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_UNRESTRICTED_AUTH 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_UNRESTRICTED_AUTH \- send credentials to other hosts too
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.3 b/docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.3
index 511e65f..5066000 100644
--- a/docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.3
+++ b/docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_UPKEEP_INTERVAL_MS 3 "31 Oct 2018" "libcurl 7.62.0" "curl_easy_setopt options"
+.TH CURLOPT_UPKEEP_INTERVAL_MS 3 "31 Oct 2018" libcurl libcurl
.SH NAME
CURLOPT_UPKEEP_INTERVAL_MS \- connection upkeep interval
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_UPLOAD.3 b/docs/libcurl/opts/CURLOPT_UPLOAD.3
index 4184e95..190e6ae 100644
--- a/docs/libcurl/opts/CURLOPT_UPLOAD.3
+++ b/docs/libcurl/opts/CURLOPT_UPLOAD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_UPLOAD 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_UPLOAD 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_UPLOAD \- data upload
.SH SYNOPSIS
@@ -42,10 +42,10 @@
You can disable this header with \fICURLOPT_HTTPHEADER(3)\fP as usual.
If you use PUT to an HTTP 1.1 server, you can upload data without knowing the
-size before starting the transfer if you use chunked encoding. You enable this
-by adding a header like "Transfer-Encoding: chunked" with
-\fICURLOPT_HTTPHEADER(3)\fP. With HTTP 1.0 or without chunked transfer, you
-must specify the size.
+size before starting the transfer. The library enables this by adding a header
+"Transfer-Encoding: chunked". With HTTP 1.0 or if you prefer not to use chunked
+transfer, you must specify the size of the data with
+\fICURLOPT_INFILESIZE(3)\fP or \fICURLOPT_INFILESIZE_LARGE(3)\fP.
.SH DEFAULT
0, default is download
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.3 b/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.3
index ed7e006..380e2ac 100644
--- a/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.3
+++ b/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_UPLOAD_BUFFERSIZE 3 "18 Aug 2018" "libcurl 7.62.0" "curl_easy_setopt options"
+.TH CURLOPT_UPLOAD_BUFFERSIZE 3 "18 Aug 2018" libcurl libcurl
.SH NAME
CURLOPT_UPLOAD_BUFFERSIZE \- upload buffer size
.SH SYNOPSIS
@@ -51,7 +51,7 @@
DO NOT set this option on a handle that is currently used for an active
transfer as that may lead to unintended consequences.
.SH DEFAULT
-64 kB
+65536 bytes
.SH PROTOCOLS
All
.SH EXAMPLE
diff --git a/docs/libcurl/opts/CURLOPT_URL.3 b/docs/libcurl/opts/CURLOPT_URL.3
index 31ce660..3083786 100644
--- a/docs/libcurl/opts/CURLOPT_URL.3
+++ b/docs/libcurl/opts/CURLOPT_URL.3
@@ -1,3 +1,4 @@
+
.\" **************************************************************************
.\" * _ _ ____ _
.\" * Project ___| | | | _ \| |
@@ -5,7 +6,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +23,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_URL 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_URL 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_URL \- URL for this transfer
.SH SYNOPSIS
@@ -38,7 +39,7 @@
scheme://host:port/path
-For a greater explanation of the format please see RFC3986.
+For a greater explanation of the format please see RFC 3986.
libcurl does not validate the syntax or use this variable until the transfer is
issued. Even if you set a crazy value here, \fIcurl_easy_setopt(3)\fP will
diff --git a/docs/libcurl/opts/CURLOPT_USERAGENT.3 b/docs/libcurl/opts/CURLOPT_USERAGENT.3
index 012e0b0..5b4365c 100644
--- a/docs/libcurl/opts/CURLOPT_USERAGENT.3
+++ b/docs/libcurl/opts/CURLOPT_USERAGENT.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_USERAGENT 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_USERAGENT 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_USERAGENT \- HTTP user-agent header
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_USERNAME.3 b/docs/libcurl/opts/CURLOPT_USERNAME.3
index 1e2295f..0c32762 100644
--- a/docs/libcurl/opts/CURLOPT_USERNAME.3
+++ b/docs/libcurl/opts/CURLOPT_USERNAME.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_USERNAME 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_USERNAME 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_USERNAME \- user name to use in authentication
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_USERPWD.3 b/docs/libcurl/opts/CURLOPT_USERPWD.3
index 419f131..c5c551a 100644
--- a/docs/libcurl/opts/CURLOPT_USERPWD.3
+++ b/docs/libcurl/opts/CURLOPT_USERPWD.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_USERPWD 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_USERPWD 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_USERPWD \- user name and password to use in authentication
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_USE_SSL.3 b/docs/libcurl/opts/CURLOPT_USE_SSL.3
index 1f3e0a8..3e6f630 100644
--- a/docs/libcurl/opts/CURLOPT_USE_SSL.3
+++ b/docs/libcurl/opts/CURLOPT_USE_SSL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_USE_SSL 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_USE_SSL 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_USE_SSL \- request using SSL / TLS for the transfer
.SH SYNOPSIS
@@ -59,7 +59,7 @@
curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/dir/file.ext");
/* require use of SSL for this, or fail */
- curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
+ curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
/* Perform the request */
curl_easy_perform(curl);
@@ -68,7 +68,7 @@
.SH AVAILABILITY
Added in 7.11.0. This option was known as CURLOPT_FTP_SSL up to 7.16.4, and
the constants were known as CURLFTPSSL_*
-Handled by LDAP since 7.81.0. Fully supported by the openldap backend only.
+Handled by LDAP since 7.81.0. Fully supported by the OpenLDAP backend only.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLOPT_VERBOSE.3 b/docs/libcurl/opts/CURLOPT_VERBOSE.3
index 278aa47..6a99dff 100644
--- a/docs/libcurl/opts/CURLOPT_VERBOSE.3
+++ b/docs/libcurl/opts/CURLOPT_VERBOSE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_VERBOSE 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_VERBOSE 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_VERBOSE \- verbose mode
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_WILDCARDMATCH.3 b/docs/libcurl/opts/CURLOPT_WILDCARDMATCH.3
index 24f3863..a74df70 100644
--- a/docs/libcurl/opts/CURLOPT_WILDCARDMATCH.3
+++ b/docs/libcurl/opts/CURLOPT_WILDCARDMATCH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_WILDCARDMATCH 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_WILDCARDMATCH 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_WILDCARDMATCH \- directory wildcard transfers
.SH SYNOPSIS
@@ -34,8 +34,8 @@
.SH DESCRIPTION
Set \fIonoff\fP to 1 if you want to transfer multiple files according to a
file name pattern. The pattern can be specified as part of the
-\fICURLOPT_URL(3)\fP option, using an fnmatch-like pattern (Shell Pattern
-Matching) in the last part of URL (file name).
+\fICURLOPT_URL(3)\fP option, using an \fBfnmatch\fP-like pattern (Shell
+Pattern Matching) in the last part of URL (file name).
By default, libcurl uses its internal wildcard matching implementation. You
can provide your own matching function by the
@@ -44,14 +44,18 @@
A brief introduction of its syntax follows:
.RS
.IP "* - ASTERISK"
-\&ftp://example.com/some/path/\fB*.txt\fP (for all txt's from the root
-directory). Only two asterisks are allowed within the same pattern string.
+.nf
+ ftp://example.com/some/path/*.txt
+.fi
+for all txt's from the root directory. Only two asterisks are allowed within
+the same pattern string.
.RE
.RS
.IP "? - QUESTION MARK"
Question mark matches any (exactly one) character.
-
-\&ftp://example.com/some/path/\fBphoto?.jpeg\fP
+.nf
+ ftp://example.com/some/path/photo?.jpg
+.fi
.RE
.RS
.IP "[ - BRACKET EXPRESSION"
@@ -65,18 +69,19 @@
\fB[^abc]\fP or \fB[!abc]\fP - negation
-\fB[[:\fP\fIname\fP\fB:]]\fP class expression. Supported classes are
+\fB[[:name:]]\fP class expression. Supported classes are
\fBalnum\fP,\fBlower\fP, \fBspace\fP, \fBalpha\fP, \fBdigit\fP, \fBprint\fP,
\fBupper\fP, \fBblank\fP, \fBgraph\fP, \fBxdigit\fP.
\fB[][-!^]\fP - special case \- matches only '\-', ']', '[', '!' or '^'. These
characters have no special purpose.
-\fB[\\[\\]\\\\]\fP - escape syntax. Matches '[', ']' or '\\'.
+\fB[\\[\\]\\\\]\fP - escape syntax. Matches '[', ']' or '\e'.
Using the rules above, a file name pattern can be constructed:
-
-\&ftp://example.com/some/path/\fB[a-z[:upper:]\\\\].jpeg\fP
+.nf
+ ftp://example.com/some/path/[a-z[:upper:]\\\\].jpg
+.fi
.SH PROTOCOLS
This feature is only supported for FTP download.
.SH EXAMPLE
diff --git a/docs/libcurl/opts/CURLOPT_WRITEDATA.3 b/docs/libcurl/opts/CURLOPT_WRITEDATA.3
index c954e41..0cef315 100644
--- a/docs/libcurl/opts/CURLOPT_WRITEDATA.3
+++ b/docs/libcurl/opts/CURLOPT_WRITEDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_WRITEDATA 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_WRITEDATA 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_WRITEDATA \- pointer passed to the write callback
.SH SYNOPSIS
@@ -33,10 +33,10 @@
.fi
.SH DESCRIPTION
A data \fIpointer\fP to pass to the write callback. If you use the
-\fICURLOPT_WRITEFUNCTION(3)\fP option, this is the pointer you will get in that
-callback's 4th argument. If you do not use a write callback, you must make
-\fIpointer\fP a 'FILE *' (cast to 'void *') as libcurl will pass this to
-\fIfwrite(3)\fP when writing data.
+\fICURLOPT_WRITEFUNCTION(3)\fP option, this is the pointer you will get in
+that callback's fourth and last argument. If you do not use a write callback,
+you must make \fIpointer\fP a 'FILE *' (cast to 'void *') as libcurl will pass
+this to \fIfwrite(3)\fP when writing data.
The internal \fICURLOPT_WRITEFUNCTION(3)\fP will write the data to the FILE *
given with this option, or to stdout if this option has not been set.
diff --git a/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.3 b/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.3
index 027984c..e443234 100644
--- a/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_WRITEFUNCTION 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_WRITEFUNCTION 3 "16 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_WRITEFUNCTION \- callback for writing received data
.SH SYNOPSIS
@@ -63,6 +63,8 @@
signal an error condition to the library. This will cause the transfer to get
aborted and the libcurl function used will return \fICURLE_WRITE_ERROR\fP.
+You can also abort the transfer by returning CURL_WRITEFUNC_ERROR. (7.87.0)
+
If your callback function returns CURL_WRITEFUNC_PAUSE it will cause this
transfer to become paused. See \fIcurl_easy_pause(3)\fP for further details.
@@ -78,35 +80,48 @@
For all protocols
.SH EXAMPLE
.nf
- struct memory {
- char *response;
- size_t size;
- };
+struct memory {
+ char *response;
+ size_t size;
+};
- static size_t cb(void *data, size_t size, size_t nmemb, void *userp)
- {
- size_t realsize = size * nmemb;
- struct memory *mem = (struct memory *)userp;
+static size_t cb(void *data, size_t size, size_t nmemb, void *clientp)
+{
+ size_t realsize = size * nmemb;
+ struct memory *mem = (struct memory *)clientp;
- char *ptr = realloc(mem->response, mem->size + realsize + 1);
- if(ptr == NULL)
- return 0; /* out of memory! */
+ char *ptr = realloc(mem->response, mem->size + realsize + 1);
+ if(ptr == NULL)
+ return 0; /* out of memory! */
- mem->response = ptr;
- memcpy(&(mem->response[mem->size]), data, realsize);
- mem->size += realsize;
- mem->response[mem->size] = 0;
+ mem->response = ptr;
+ memcpy(&(mem->response[mem->size]), data, realsize);
+ mem->size += realsize;
+ mem->response[mem->size] = 0;
- return realsize;
- }
+ return realsize;
+}
- struct memory chunk = {0};
+struct memory chunk = {0};
+CURLcode res;
+CURL *curl_handle = curl_easy_init();
- /* send all data to this function */
- curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, cb);
+if (curl_handle)
+{
+ /* send all data to this function */
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, cb);
- /* we pass our 'chunk' struct to the callback function */
- curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
+ /* we pass our 'chunk' struct to the callback function */
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
+
+ /* send a request */
+ res = curl_easy_perform(curl_handle);
+
+ /* remember to free the buffer */
+ free(chunk.response);
+
+ curl_easy_cleanup(curl_handle);
+}
.fi
.SH AVAILABILITY
Support for the CURL_WRITEFUNC_PAUSE return code was added in version 7.18.0.
diff --git a/docs/libcurl/opts/CURLOPT_WS_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_WS_OPTIONS.3
new file mode 100644
index 0000000..a575fc3
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_WS_OPTIONS.3
@@ -0,0 +1,69 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" * SPDX-License-Identifier: curl
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_WS_OPTIONS 3 "10 Jun 2022" libcurl libcurl
+.SH NAME
+CURLOPT_WS_OPTIONS \- WebSocket behavior options
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WS_OPTIONS, long bitmask);
+.fi
+.SH DESCRIPTION
+Pass a long with a bitmask to tell libcurl about specific WebSocket
+behaviors.
+
+To detach a WebSocket connection and use the \fIcurl_ws_send(3)\fP and
+\fIcurl_ws_recv(3)\fP functions after the HTTP upgrade procedure, set the
+\fICURLOPT_CONNECT_ONLY(3)\fP option to 2L.
+
+Available bits in the bitmask
+.IP "CURLWS_RAW_MODE (1)"
+Deliver "raw" WebSocket traffic to the \fICURLOPT_WRITEFUNCTION(3)\fP
+callback.
+
+In raw mode, libcurl does not handle pings or any other frame for the
+application.
+.SH DEFAULT
+0
+.SH PROTOCOLS
+WebSocket
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "ws://example.com/");
+ /* tell curl we deal with all the WebSocket magic ourselves */
+ curl_easy_setopt(curl, CURLOPT_WS_OPTIONS, (long)CURLWS_RAW_MODE);
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in 7.86.0
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR curl_ws_recv "(3), " curl_ws_send "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_XFERINFODATA.3 b/docs/libcurl/opts/CURLOPT_XFERINFODATA.3
index fa70048..e3d31bf 100644
--- a/docs/libcurl/opts/CURLOPT_XFERINFODATA.3
+++ b/docs/libcurl/opts/CURLOPT_XFERINFODATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_XFERINFODATA 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_XFERINFODATA 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_XFERINFODATA \- pointer passed to the progress callback
.SH SYNOPSIS
@@ -53,7 +53,7 @@
curl_off_t ultotal,
curl_off_t ulnow)
{
- struct memory *progress = (struct progress *)userp;
+ struct memory *progress = (struct progress *)clientp;
/* use the values */
diff --git a/docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.3 b/docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.3
index 4711f2e..5f7105f 100644
--- a/docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_XFERINFOFUNCTION 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_XFERINFOFUNCTION 3 "17 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_XFERINFOFUNCTION \- progress meter callback
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3 b/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3
index 549d9cb..04dc7b6 100644
--- a/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3
+++ b/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_XOAUTH2_BEARER 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_XOAUTH2_BEARER 3 "19 Jun 2014" libcurl libcurl
.SH NAME
CURLOPT_XOAUTH2_BEARER \- OAuth 2.0 access token
.SH SYNOPSIS
@@ -56,7 +56,7 @@
}
.fi
.SH AVAILABILITY
-Added in 7.33.0. Support for OpenLAP added in 7.82.0.
+Added in 7.33.0. Support for OpenLDAP added in 7.82.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLSHOPT_LOCKFUNC.3 b/docs/libcurl/opts/CURLSHOPT_LOCKFUNC.3
index ed265fc..4fcff53 100644
--- a/docs/libcurl/opts/CURLSHOPT_LOCKFUNC.3
+++ b/docs/libcurl/opts/CURLSHOPT_LOCKFUNC.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH CURLSHOPT_LOCKFUNC 3 "8 Aug 2003" "libcurl 7.10.7" "libcurl Manual"
+.TH CURLSHOPT_LOCKFUNC 3 "8 Aug 2003" libcurl libcurl
.SH NAME
CURLSHOPT_LOCKFUNC - mutex lock callback
.SH SYNOPSIS
@@ -29,7 +29,7 @@
#include <curl/curl.h>
void lockcb(CURL *handle, curl_lock_data data, curl_lock_access access,
- void *userptr);
+ void *clientp);
CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_LOCKFUNC, lockcb);
.fi
@@ -49,7 +49,7 @@
\fIaccess\fP defines what access type libcurl wants, shared or single.
-\fIuserptr\fP is the private pointer you set with \fICURLSHOPT_USERDATA\fP.
+\fIclientp\fP is the private pointer you set with \fICURLSHOPT_USERDATA\fP.
This pointer is not used by libcurl itself.
.SH PROTOCOLS
All
diff --git a/docs/libcurl/opts/CURLSHOPT_SHARE.3 b/docs/libcurl/opts/CURLSHOPT_SHARE.3
index 72079d8..78c051d 100644
--- a/docs/libcurl/opts/CURLSHOPT_SHARE.3
+++ b/docs/libcurl/opts/CURLSHOPT_SHARE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH CURLSHOPT_SHARE 3 "8 Aug 2003" "libcurl 7.10.7" "libcurl Manual"
+.TH CURLSHOPT_SHARE 3 "8 Aug 2003" libcurl libcurl
.SH NAME
CURLSHOPT_SHARE - add data to share
.SH SYNOPSIS
@@ -56,8 +56,7 @@
Put the connection cache in the share object and make all easy handles using
this share object share the connection cache.
-Note that due to a known bug, it is not safe to share connections this way
-between multiple concurrent threads.
+It is not supported to share connections between multiple concurrent threads.
Connections that are used for HTTP/1.1 Pipelining or HTTP/2 multiplexing only
get additional transfers added to them if the existing connection is held by
@@ -78,6 +77,12 @@
Note that when you use the multi interface, all easy handles added to the same
multi handle will share PSL cache by default without using this option.
+.IP CURL_LOCK_DATA_HSTS
+The in-memory HSTS cache.
+
+It is not supported to share the HSTS between multiple concurrent threads.
+
+Added in 7.88.0
.SH PROTOCOLS
All
.SH EXAMPLE
diff --git a/docs/libcurl/opts/CURLSHOPT_UNLOCKFUNC.3 b/docs/libcurl/opts/CURLSHOPT_UNLOCKFUNC.3
index 0a8a7ae..13f0258 100644
--- a/docs/libcurl/opts/CURLSHOPT_UNLOCKFUNC.3
+++ b/docs/libcurl/opts/CURLSHOPT_UNLOCKFUNC.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,14 +21,14 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH CURLSHOPT_UNLOCKFUNC 3 "8 Aug 2003" "libcurl 7.10.7" "libcurl Manual"
+.TH CURLSHOPT_UNLOCKFUNC 3 "8 Aug 2003" libcurl libcurl
.SH NAME
CURLSHOPT_UNLOCKFUNC - mutex unlock callback
.SH SYNOPSIS
.nf
#include <curl/curl.h>
-void unlockcb(CURL *handle, curl_lock_data data, void *userptr);
+void unlockcb(CURL *handle, curl_lock_data data, void *clientp);
CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_UNLOCKFUNC, unlockcb);
.fi
@@ -45,9 +45,7 @@
The \fIdata\fP argument tells what kind of data libcurl wants to unlock. Make
sure that the callback uses a different lock for each kind of data.
-\fIaccess\fP defines what access type libcurl wants, shared or single.
-
-\fIuserptr\fP is the private pointer you set with \fICURLSHOPT_USERDATA\fP.
+\fIclientp\fP is the private pointer you set with \fICURLSHOPT_USERDATA\fP.
This pointer is not used by libcurl itself.
.SH PROTOCOLS
All
diff --git a/docs/libcurl/opts/CURLSHOPT_UNSHARE.3 b/docs/libcurl/opts/CURLSHOPT_UNSHARE.3
index f712f9c..f1b6d02 100644
--- a/docs/libcurl/opts/CURLSHOPT_UNSHARE.3
+++ b/docs/libcurl/opts/CURLSHOPT_UNSHARE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH CURLSHOPT_UNSHARE 3 "8 Aug 2003" "libcurl 7.10.7" "libcurl Manual"
+.TH CURLSHOPT_UNSHARE 3 "8 Aug 2003" libcurl libcurl
.SH NAME
CURLSHOPT_UNSHARE - remove data to share
.SH SYNOPSIS
diff --git a/docs/libcurl/opts/CURLSHOPT_USERDATA.3 b/docs/libcurl/opts/CURLSHOPT_USERDATA.3
index f5958a9..f4ed32f 100644
--- a/docs/libcurl/opts/CURLSHOPT_USERDATA.3
+++ b/docs/libcurl/opts/CURLSHOPT_USERDATA.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -21,19 +21,19 @@
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
-.TH CURLSHOPT_USERDATA 3 "8 Aug 2003" "libcurl 7.10.7" "libcurl Manual"
+.TH CURLSHOPT_USERDATA 3 "8 Aug 2003" libcurl libcurl
.SH NAME
-CURLSHOPT_USERDATA - pointer passed to the (un)lock mutex callbacks
+CURLSHOPT_USERDATA - pointer passed to the lock and unlock mutex callbacks
.SH SYNOPSIS
.nf
#include <curl/curl.h>
-CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_USERDATA, void *ptr);
+CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_USERDATA, void *clientp);
.fi
.SH DESCRIPTION
-The \fIptr\fP parameter is held verbatim by libcurl and is passed on as the
-\fIuserptr\fP argument to the callbacks set with \fICURLSHOPT_LOCKFUNC(3)\fP
-and \fICURLSHOPT_UNLOCKFUNC(3)\fP.
+The \fIclientp\fP parameter is held verbatim by libcurl and is passed on as
+the \fIclientp\fP argument to the callbacks set with
+\fICURLSHOPT_LOCKFUNC(3)\fP and \fICURLSHOPT_UNLOCKFUNC(3)\fP.
.SH PROTOCOLS
All
.SH EXAMPLE
diff --git a/docs/libcurl/opts/Makefile.am b/docs/libcurl/opts/Makefile.am
index e952cd9..21193e0 100644
--- a/docs/libcurl/opts/Makefile.am
+++ b/docs/libcurl/opts/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc
index 95aec8b..8577b03 100644
--- a/docs/libcurl/opts/Makefile.inc
+++ b/docs/libcurl/opts/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -45,9 +45,9 @@
CURLINFO_FILETIME_T.3 \
CURLINFO_FTP_ENTRY_PATH.3 \
CURLINFO_HEADER_SIZE.3 \
- CURLINFO_HTTPAUTH_AVAIL.3 \
CURLINFO_HTTP_CONNECTCODE.3 \
CURLINFO_HTTP_VERSION.3 \
+ CURLINFO_HTTPAUTH_AVAIL.3 \
CURLINFO_LASTSOCKET.3 \
CURLINFO_LOCAL_IP.3 \
CURLINFO_LOCAL_PORT.3 \
@@ -95,11 +95,11 @@
CURLINFO_TOTAL_TIME_T.3 \
CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3 \
CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3 \
- CURLMOPT_MAXCONNECTS.3 \
CURLMOPT_MAX_CONCURRENT_STREAMS.3 \
CURLMOPT_MAX_HOST_CONNECTIONS.3 \
CURLMOPT_MAX_PIPELINE_LENGTH.3 \
CURLMOPT_MAX_TOTAL_CONNECTIONS.3 \
+ CURLMOPT_MAXCONNECTS.3 \
CURLMOPT_PIPELINING.3 \
CURLMOPT_PIPELINING_SERVER_BL.3 \
CURLMOPT_PIPELINING_SITE_BL.3 \
@@ -110,27 +110,29 @@
CURLMOPT_TIMERDATA.3 \
CURLMOPT_TIMERFUNCTION.3 \
CURLOPT_ABSTRACT_UNIX_SOCKET.3 \
- CURLOPT_ACCEPTTIMEOUT_MS.3 \
CURLOPT_ACCEPT_ENCODING.3 \
+ CURLOPT_ACCEPTTIMEOUT_MS.3 \
CURLOPT_ADDRESS_SCOPE.3 \
CURLOPT_ALTSVC.3 \
CURLOPT_ALTSVC_CTRL.3 \
CURLOPT_APPEND.3 \
CURLOPT_AUTOREFERER.3 \
+ CURLOPT_AWS_SIGV4.3 \
CURLOPT_BUFFERSIZE.3 \
CURLOPT_CAINFO.3 \
CURLOPT_CAINFO_BLOB.3 \
CURLOPT_CAPATH.3 \
+ CURLOPT_CA_CACHE_TIMEOUT.3 \
CURLOPT_CERTINFO.3 \
CURLOPT_CHUNK_BGN_FUNCTION.3 \
CURLOPT_CHUNK_DATA.3 \
CURLOPT_CHUNK_END_FUNCTION.3 \
CURLOPT_CLOSESOCKETDATA.3 \
CURLOPT_CLOSESOCKETFUNCTION.3 \
- CURLOPT_CONNECTTIMEOUT.3 \
- CURLOPT_CONNECTTIMEOUT_MS.3 \
CURLOPT_CONNECT_ONLY.3 \
CURLOPT_CONNECT_TO.3 \
+ CURLOPT_CONNECTTIMEOUT.3 \
+ CURLOPT_CONNECTTIMEOUT_MS.3 \
CURLOPT_CONV_FROM_NETWORK_FUNCTION.3 \
CURLOPT_CONV_FROM_UTF8_FUNCTION.3 \
CURLOPT_CONV_TO_NETWORK_FUNCTION.3 \
@@ -170,41 +172,41 @@
CURLOPT_FOLLOWLOCATION.3 \
CURLOPT_FORBID_REUSE.3 \
CURLOPT_FRESH_CONNECT.3 \
- CURLOPT_FTPPORT.3 \
- CURLOPT_FTPSSLAUTH.3 \
CURLOPT_FTP_ACCOUNT.3 \
CURLOPT_FTP_ALTERNATIVE_TO_USER.3 \
CURLOPT_FTP_CREATE_MISSING_DIRS.3 \
CURLOPT_FTP_FILEMETHOD.3 \
- CURLOPT_FTP_RESPONSE_TIMEOUT.3 \
CURLOPT_FTP_SKIP_PASV_IP.3 \
CURLOPT_FTP_SSL_CCC.3 \
CURLOPT_FTP_USE_EPRT.3 \
CURLOPT_FTP_USE_EPSV.3 \
CURLOPT_FTP_USE_PRET.3 \
+ CURLOPT_FTPPORT.3 \
+ CURLOPT_FTPSSLAUTH.3 \
CURLOPT_GSSAPI_DELEGATION.3 \
CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 \
CURLOPT_HAPROXYPROTOCOL.3 \
+ CURLOPT_HAPROXY_CLIENT_IP.3 \
CURLOPT_HEADER.3 \
CURLOPT_HEADERDATA.3 \
CURLOPT_HEADERFUNCTION.3 \
CURLOPT_HEADEROPT.3 \
CURLOPT_HSTS.3 \
+ CURLOPT_HSTS_CTRL.3 \
CURLOPT_HSTSREADDATA.3 \
CURLOPT_HSTSREADFUNCTION.3 \
CURLOPT_HSTSWRITEDATA.3 \
CURLOPT_HSTSWRITEFUNCTION.3 \
- CURLOPT_HSTS_CTRL.3 \
CURLOPT_HTTP09_ALLOWED.3 \
CURLOPT_HTTP200ALIASES.3 \
+ CURLOPT_HTTP_CONTENT_DECODING.3 \
+ CURLOPT_HTTP_TRANSFER_DECODING.3 \
+ CURLOPT_HTTP_VERSION.3 \
CURLOPT_HTTPAUTH.3 \
CURLOPT_HTTPGET.3 \
CURLOPT_HTTPHEADER.3 \
CURLOPT_HTTPPOST.3 \
CURLOPT_HTTPPROXYTUNNEL.3 \
- CURLOPT_HTTP_CONTENT_DECODING.3 \
- CURLOPT_HTTP_TRANSFER_DECODING.3 \
- CURLOPT_HTTP_VERSION.3 \
CURLOPT_IGNORE_CONTENT_LENGTH.3 \
CURLOPT_INFILESIZE.3 \
CURLOPT_INFILESIZE_LARGE.3 \
@@ -227,17 +229,17 @@
CURLOPT_MAIL_AUTH.3 \
CURLOPT_MAIL_FROM.3 \
CURLOPT_MAIL_RCPT.3 \
- CURLOPT_MAIL_RCPT_ALLLOWFAILS.3 \
+ CURLOPT_MAIL_RCPT_ALLOWFAILS.3 \
+ CURLOPT_MAX_RECV_SPEED_LARGE.3 \
+ CURLOPT_MAX_SEND_SPEED_LARGE.3 \
CURLOPT_MAXAGE_CONN.3 \
CURLOPT_MAXCONNECTS.3 \
CURLOPT_MAXFILESIZE.3 \
CURLOPT_MAXFILESIZE_LARGE.3 \
CURLOPT_MAXLIFETIME_CONN.3 \
CURLOPT_MAXREDIRS.3 \
- CURLOPT_MAX_RECV_SPEED_LARGE.3 \
- CURLOPT_MAX_SEND_SPEED_LARGE.3 \
- CURLOPT_MIMEPOST.3 \
CURLOPT_MIME_OPTIONS.3 \
+ CURLOPT_MIMEPOST.3 \
CURLOPT_NETRC.3 \
CURLOPT_NETRC_FILE.3 \
CURLOPT_NEW_DIRECTORY_PERMS.3 \
@@ -259,31 +261,29 @@
CURLOPT_POSTFIELDSIZE_LARGE.3 \
CURLOPT_POSTQUOTE.3 \
CURLOPT_POSTREDIR.3 \
+ CURLOPT_PRE_PROXY.3 \
CURLOPT_PREQUOTE.3 \
CURLOPT_PREREQDATA.3 \
CURLOPT_PREREQFUNCTION.3 \
- CURLOPT_PRE_PROXY.3 \
CURLOPT_PRIVATE.3 \
CURLOPT_PROGRESSDATA.3 \
CURLOPT_PROGRESSFUNCTION.3 \
CURLOPT_PROTOCOLS.3 \
+ CURLOPT_PROTOCOLS_STR.3 \
CURLOPT_PROXY.3 \
- CURLOPT_PROXYAUTH.3 \
- CURLOPT_PROXYHEADER.3 \
- CURLOPT_PROXYPASSWORD.3 \
- CURLOPT_PROXYPORT.3 \
- CURLOPT_PROXYTYPE.3 \
- CURLOPT_PROXYUSERNAME.3 \
- CURLOPT_PROXYUSERPWD.3 \
CURLOPT_PROXY_CAINFO.3 \
CURLOPT_PROXY_CAINFO_BLOB.3 \
CURLOPT_PROXY_CAPATH.3 \
CURLOPT_PROXY_CRLFILE.3 \
- CURLOPT_PROXY_KEYPASSWD.3 \
CURLOPT_PROXY_ISSUERCERT.3 \
CURLOPT_PROXY_ISSUERCERT_BLOB.3 \
+ CURLOPT_PROXY_KEYPASSWD.3 \
CURLOPT_PROXY_PINNEDPUBLICKEY.3 \
CURLOPT_PROXY_SERVICE_NAME.3 \
+ CURLOPT_PROXY_SSL_CIPHER_LIST.3 \
+ CURLOPT_PROXY_SSL_OPTIONS.3 \
+ CURLOPT_PROXY_SSL_VERIFYHOST.3 \
+ CURLOPT_PROXY_SSL_VERIFYPEER.3 \
CURLOPT_PROXY_SSLCERT.3 \
CURLOPT_PROXY_SSLCERT_BLOB.3 \
CURLOPT_PROXY_SSLCERTTYPE.3 \
@@ -291,15 +291,18 @@
CURLOPT_PROXY_SSLKEY_BLOB.3 \
CURLOPT_PROXY_SSLKEYTYPE.3 \
CURLOPT_PROXY_SSLVERSION.3 \
- CURLOPT_PROXY_SSL_CIPHER_LIST.3 \
- CURLOPT_PROXY_SSL_OPTIONS.3 \
- CURLOPT_PROXY_SSL_VERIFYHOST.3 \
- CURLOPT_PROXY_SSL_VERIFYPEER.3 \
CURLOPT_PROXY_TLS13_CIPHERS.3 \
CURLOPT_PROXY_TLSAUTH_PASSWORD.3 \
CURLOPT_PROXY_TLSAUTH_TYPE.3 \
CURLOPT_PROXY_TLSAUTH_USERNAME.3 \
CURLOPT_PROXY_TRANSFER_MODE.3 \
+ CURLOPT_PROXYAUTH.3 \
+ CURLOPT_PROXYHEADER.3 \
+ CURLOPT_PROXYPASSWORD.3 \
+ CURLOPT_PROXYPORT.3 \
+ CURLOPT_PROXYTYPE.3 \
+ CURLOPT_PROXYUSERNAME.3 \
+ CURLOPT_PROXYUSERPWD.3 \
CURLOPT_PUT.3 \
CURLOPT_QUOTE.3 \
CURLOPT_RANDOM_FILE.3 \
@@ -307,6 +310,7 @@
CURLOPT_READDATA.3 \
CURLOPT_READFUNCTION.3 \
CURLOPT_REDIR_PROTOCOLS.3 \
+ CURLOPT_REDIR_PROTOCOLS_STR.3 \
CURLOPT_REFERER.3 \
CURLOPT_REQUEST_TARGET.3 \
CURLOPT_RESOLVE.3 \
@@ -324,6 +328,7 @@
CURLOPT_SASL_IR.3 \
CURLOPT_SEEKDATA.3 \
CURLOPT_SEEKFUNCTION.3 \
+ CURLOPT_SERVER_RESPONSE_TIMEOUT.3 \
CURLOPT_SERVICE_NAME.3 \
CURLOPT_SHARE.3 \
CURLOPT_SOCKOPTDATA.3 \
@@ -340,15 +345,6 @@
CURLOPT_SSH_KNOWNHOSTS.3 \
CURLOPT_SSH_PRIVATE_KEYFILE.3 \
CURLOPT_SSH_PUBLIC_KEYFILE.3 \
- CURLOPT_SSLCERT.3 \
- CURLOPT_SSLCERT_BLOB.3 \
- CURLOPT_SSLCERTTYPE.3 \
- CURLOPT_SSLENGINE.3 \
- CURLOPT_SSLENGINE_DEFAULT.3 \
- CURLOPT_SSLKEY.3 \
- CURLOPT_SSLKEY_BLOB.3 \
- CURLOPT_SSLKEYTYPE.3 \
- CURLOPT_SSLVERSION.3 \
CURLOPT_SSL_CIPHER_LIST.3 \
CURLOPT_SSL_CTX_DATA.3 \
CURLOPT_SSL_CTX_FUNCTION.3 \
@@ -361,6 +357,15 @@
CURLOPT_SSL_VERIFYHOST.3 \
CURLOPT_SSL_VERIFYPEER.3 \
CURLOPT_SSL_VERIFYSTATUS.3 \
+ CURLOPT_SSLCERT.3 \
+ CURLOPT_SSLCERT_BLOB.3 \
+ CURLOPT_SSLCERTTYPE.3 \
+ CURLOPT_SSLENGINE.3 \
+ CURLOPT_SSLENGINE_DEFAULT.3 \
+ CURLOPT_SSLKEY.3 \
+ CURLOPT_SSLKEY_BLOB.3 \
+ CURLOPT_SSLKEYTYPE.3 \
+ CURLOPT_SSLVERSION.3 \
CURLOPT_STDERR.3 \
CURLOPT_STREAM_DEPENDS.3 \
CURLOPT_STREAM_DEPENDS_E.3 \
@@ -385,23 +390,23 @@
CURLOPT_TLSAUTH_USERNAME.3 \
CURLOPT_TRAILERDATA.3 \
CURLOPT_TRAILERFUNCTION.3 \
- CURLOPT_TRANSFERTEXT.3 \
CURLOPT_TRANSFER_ENCODING.3 \
+ CURLOPT_TRANSFERTEXT.3 \
CURLOPT_UNIX_SOCKET_PATH.3 \
CURLOPT_UNRESTRICTED_AUTH.3 \
CURLOPT_UPKEEP_INTERVAL_MS.3 \
CURLOPT_UPLOAD.3 \
CURLOPT_UPLOAD_BUFFERSIZE.3 \
CURLOPT_URL.3 \
+ CURLOPT_USE_SSL.3 \
CURLOPT_USERAGENT.3 \
CURLOPT_USERNAME.3 \
CURLOPT_USERPWD.3 \
- CURLOPT_USE_SSL.3 \
- CURLOPT_AWS_SIGV4.3 \
CURLOPT_VERBOSE.3 \
CURLOPT_WILDCARDMATCH.3 \
CURLOPT_WRITEDATA.3 \
CURLOPT_WRITEFUNCTION.3 \
+ CURLOPT_WS_OPTIONS.3 \
CURLOPT_XFERINFODATA.3 \
CURLOPT_XFERINFOFUNCTION.3 \
CURLOPT_XOAUTH2_BEARER.3 \
diff --git a/docs/libcurl/opts/template.3 b/docs/libcurl/opts/template.3
index 9b4e3ef..93f51c4 100644
--- a/docs/libcurl/opts/template.3
+++ b/docs/libcurl/opts/template.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,9 +22,9 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TEMPLATE 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TEMPLATE 3 "17 Jun 2014" libcurl libcurl
.SH NAME
-CURLOPT_TEMPLATE \- [short desc]
+CURLOPT_TEMPLATE \- [short description]
.SH SYNOPSIS
#include <curl/curl.h>
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index c590d08..6f88bf5 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -12,6 +12,9 @@
Name Introduced Deprecated Last
+CURL_AT_LEAST_VERSION 7.43.0
+CURL_BLOB_COPY 7.71.0
+CURL_BLOB_NOCOPY 7.71.0
CURL_CHUNK_BGN_FUNC_FAIL 7.21.0
CURL_CHUNK_BGN_FUNC_OK 7.21.0
CURL_CHUNK_BGN_FUNC_SKIP 7.21.0
@@ -20,6 +23,7 @@
CURL_CSELECT_ERR 7.16.3
CURL_CSELECT_IN 7.16.3
CURL_CSELECT_OUT 7.16.3
+CURL_DEPRECATED 7.87.0
CURL_DID_MEMORY_FUNC_TYPEDEFS 7.49.0
CURL_EASY_NONE 7.14.0 - 7.15.4
CURL_EASY_TIMEOUT 7.14.0 - 7.15.4
@@ -49,6 +53,7 @@
CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE 7.49.0
CURL_HTTP_VERSION_2TLS 7.47.0
CURL_HTTP_VERSION_3 7.66.0
+CURL_HTTP_VERSION_3ONLY 7.88.0
CURL_HTTP_VERSION_NONE 7.9.1
CURL_HTTPPOST_BUFFER 7.46.0
CURL_HTTPPOST_CALLBACK 7.46.0
@@ -58,15 +63,18 @@
CURL_HTTPPOST_PTRCONTENTS 7.46.0
CURL_HTTPPOST_PTRNAME 7.46.0
CURL_HTTPPOST_READFILE 7.46.0
+CURL_IGNORE_DEPRECATION 7.87.0
CURL_IPRESOLVE_V4 7.10.8
CURL_IPRESOLVE_V6 7.10.8
CURL_IPRESOLVE_WHATEVER 7.10.8
+CURL_ISOCPP 7.10.2
CURL_LOCK_ACCESS_NONE 7.10.3
CURL_LOCK_ACCESS_SHARED 7.10.3
CURL_LOCK_ACCESS_SINGLE 7.10.3
CURL_LOCK_DATA_CONNECT 7.10.3
CURL_LOCK_DATA_COOKIE 7.10.3
CURL_LOCK_DATA_DNS 7.10.3
+CURL_LOCK_DATA_HSTS 7.88.0
CURL_LOCK_DATA_NONE 7.10.3
CURL_LOCK_DATA_PSL 7.61.0
CURL_LOCK_DATA_SHARE 7.10.4
@@ -92,6 +100,7 @@
CURL_PROGRESS_BAR 7.1.1 - 7.4.1
CURL_PROGRESS_STATS 7.1.1 - 7.4.1
CURL_PROGRESSFUNC_CONTINUE 7.68.0
+CURL_PULL_SYS_POLL_H 7.56.0
CURL_PUSH_DENY 7.44.0
CURL_PUSH_ERROROUT 7.72.0
CURL_PUSH_OK 7.44.0
@@ -148,6 +157,7 @@
CURL_UPKEEP_INTERVAL_DEFAULT 7.62.0
CURL_VERSION_ALTSVC 7.64.1
CURL_VERSION_ASYNCHDNS 7.10.7
+CURL_VERSION_BITS 7.43.0
CURL_VERSION_BROTLI 7.57.0
CURL_VERSION_CONV 7.15.4
CURL_VERSION_CURLDEBUG 7.19.6
@@ -181,6 +191,7 @@
CURL_WAIT_POLLOUT 7.28.0
CURL_WAIT_POLLPRI 7.28.0
CURL_WIN32 7.69.0
+CURL_WRITEFUNC_ERROR 7.87.0
CURL_WRITEFUNC_PAUSE 7.18.0
CURL_ZERO_TERMINATED 7.56.0
CURLALTSVC_H1 7.64.1
@@ -217,7 +228,7 @@
CURLE_BAD_FUNCTION_ARGUMENT 7.1
CURLE_BAD_PASSWORD_ENTERED 7.4.2 7.17.0
CURLE_CHUNK_FAILED 7.21.0
-CURLE_CONV_FAILED 7.15.4
+CURLE_CONV_FAILED 7.15.4 7.82.0
CURLE_CONV_REQD 7.15.4 7.82.0
CURLE_COULDNT_CONNECT 7.1
CURLE_COULDNT_RESOLVE_HOST 7.1
@@ -406,15 +417,16 @@
CURLINFO_ACTIVESOCKET 7.45.0
CURLINFO_APPCONNECT_TIME 7.19.0
CURLINFO_APPCONNECT_TIME_T 7.61.0
-CURLINFO_CAPATH 7.84.0
CURLINFO_CAINFO 7.84.0
+CURLINFO_CAPATH 7.84.0
CURLINFO_CERTINFO 7.19.1
CURLINFO_CONDITION_UNMET 7.19.4
+CURLINFO_CONN_ID 8.2.0
CURLINFO_CONNECT_TIME 7.4.1
CURLINFO_CONNECT_TIME_T 7.61.0
-CURLINFO_CONTENT_LENGTH_DOWNLOAD 7.6.1
+CURLINFO_CONTENT_LENGTH_DOWNLOAD 7.6.1 7.55.0
CURLINFO_CONTENT_LENGTH_DOWNLOAD_T 7.55.0
-CURLINFO_CONTENT_LENGTH_UPLOAD 7.6.1
+CURLINFO_CONTENT_LENGTH_UPLOAD 7.6.1 7.55.0
CURLINFO_CONTENT_LENGTH_UPLOAD_T 7.55.0
CURLINFO_CONTENT_TYPE 7.9.4
CURLINFO_COOKIELIST 7.14.1
@@ -435,7 +447,7 @@
CURLINFO_HTTP_VERSION 7.50.0
CURLINFO_HTTPAUTH_AVAIL 7.10.8
CURLINFO_LASTONE 7.4.1
-CURLINFO_LASTSOCKET 7.15.2
+CURLINFO_LASTSOCKET 7.15.2 7.45.0
CURLINFO_LOCAL_IP 7.21.0
CURLINFO_LOCAL_PORT 7.21.0
CURLINFO_LONG 7.4.1
@@ -451,7 +463,7 @@
CURLINFO_PRIMARY_IP 7.19.0
CURLINFO_PRIMARY_PORT 7.21.0
CURLINFO_PRIVATE 7.10.3
-CURLINFO_PROTOCOL 7.52.0
+CURLINFO_PROTOCOL 7.52.0 7.85.0
CURLINFO_PROXY_ERROR 7.73.0
CURLINFO_PROXY_SSL_VERIFYRESULT 7.52.0
CURLINFO_PROXYAUTH_AVAIL 7.10.8
@@ -469,15 +481,15 @@
CURLINFO_RTSP_SERVER_CSEQ 7.20.0
CURLINFO_RTSP_SESSION_ID 7.20.0
CURLINFO_SCHEME 7.52.0
-CURLINFO_SIZE_DOWNLOAD 7.4.1
+CURLINFO_SIZE_DOWNLOAD 7.4.1 7.55.0
CURLINFO_SIZE_DOWNLOAD_T 7.55.0
-CURLINFO_SIZE_UPLOAD 7.4.1
+CURLINFO_SIZE_UPLOAD 7.4.1 7.55.0
CURLINFO_SIZE_UPLOAD_T 7.55.0
CURLINFO_SLIST 7.12.3
CURLINFO_SOCKET 7.45.0
-CURLINFO_SPEED_DOWNLOAD 7.4.1
+CURLINFO_SPEED_DOWNLOAD 7.4.1 7.55.0
CURLINFO_SPEED_DOWNLOAD_T 7.55.0
-CURLINFO_SPEED_UPLOAD 7.4.1
+CURLINFO_SPEED_UPLOAD 7.4.1 7.55.0
CURLINFO_SPEED_UPLOAD_T 7.55.0
CURLINFO_SSL_DATA_IN 7.12.1
CURLINFO_SSL_DATA_OUT 7.12.1
@@ -492,6 +504,7 @@
CURLINFO_TOTAL_TIME 7.4.1
CURLINFO_TOTAL_TIME_T 7.61.0
CURLINFO_TYPEMASK 7.4.1
+CURLINFO_XFER_ID 8.2.0
CURLIOCMD_NOP 7.12.3
CURLIOCMD_RESTARTREAD 7.12.3
CURLIOE_FAILRESTART 7.12.3
@@ -559,6 +572,7 @@
CURLOPT_CAINFO 7.4.2
CURLOPT_CAINFO_BLOB 7.77.0
CURLOPT_CAPATH 7.9.8
+CURLOPT_CA_CACHE_TIMEOUT 7.87.0
CURLOPT_CERTINFO 7.19.1
CURLOPT_CHUNK_BGN_FUNCTION 7.21.0
CURLOPT_CHUNK_DATA 7.21.0
@@ -600,8 +614,8 @@
CURLOPT_DOH_SSL_VERIFYPEER 7.76.0
CURLOPT_DOH_SSL_VERIFYSTATUS 7.76.0
CURLOPT_DOH_URL 7.62.0
-CURLOPT_EGDSOCKET 7.7
-CURLOPT_ENCODING 7.10
+CURLOPT_EGDSOCKET 7.7 7.84.0
+CURLOPT_ENCODING 7.10 7.21.6
CURLOPT_ERRORBUFFER 7.1
CURLOPT_EXPECT_100_TIMEOUT_MS 7.36.0
CURLOPT_FAILONERROR 7.1
@@ -616,7 +630,7 @@
CURLOPT_FTP_ALTERNATIVE_TO_USER 7.15.5
CURLOPT_FTP_CREATE_MISSING_DIRS 7.10.7
CURLOPT_FTP_FILEMETHOD 7.15.1
-CURLOPT_FTP_RESPONSE_TIMEOUT 7.10.8
+CURLOPT_FTP_RESPONSE_TIMEOUT 7.10.8 7.85.0
CURLOPT_FTP_SKIP_PASV_IP 7.15.0
CURLOPT_FTP_SSL 7.11.0 7.16.4
CURLOPT_FTP_SSL_CCC 7.16.1
@@ -631,6 +645,7 @@
CURLOPT_GSSAPI_DELEGATION 7.22.0
CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS 7.59.0
CURLOPT_HAPROXYPROTOCOL 7.60.0
+CURLOPT_HAPROXY_CLIENT_IP 8.2.0
CURLOPT_HEADER 7.1
CURLOPT_HEADERDATA 7.10
CURLOPT_HEADERFUNCTION 7.7.2
@@ -659,8 +674,8 @@
CURLOPT_INTERFACE 7.3
CURLOPT_INTERLEAVEDATA 7.20.0
CURLOPT_INTERLEAVEFUNCTION 7.20.0
-CURLOPT_IOCTLDATA 7.12.3
-CURLOPT_IOCTLFUNCTION 7.12.3
+CURLOPT_IOCTLDATA 7.12.3 7.18.0
+CURLOPT_IOCTLFUNCTION 7.12.3 7.18.0
CURLOPT_IPRESOLVE 7.10.8
CURLOPT_ISSUERCERT 7.19.0
CURLOPT_ISSUERCERT_BLOB 7.71.0
@@ -676,7 +691,9 @@
CURLOPT_MAIL_AUTH 7.25.0
CURLOPT_MAIL_FROM 7.20.0
CURLOPT_MAIL_RCPT 7.20.0
-CURLOPT_MAIL_RCPT_ALLLOWFAILS 7.69.0
+CURLOPT_MAIL_RCPT_ALLLOWFAILS 7.69.0 8.2.0
+CURLOPT_MAIL_RCPT_ALLOWFAILS 8.2.0
+CURLOPT_QUICK_EXIT 7.87.0
CURLOPT_MAX_RECV_SPEED_LARGE 7.15.5
CURLOPT_MAX_SEND_SPEED_LARGE 7.15.5
CURLOPT_MAXAGE_CONN 7.65.0
@@ -721,7 +738,8 @@
CURLOPT_PRIVATE 7.10.3
CURLOPT_PROGRESSDATA 7.1
CURLOPT_PROGRESSFUNCTION 7.1 7.32.0
-CURLOPT_PROTOCOLS 7.19.4
+CURLOPT_PROTOCOLS 7.19.4 7.85.0
+CURLOPT_PROTOCOLS_STR 7.85.0
CURLOPT_PROXY 7.1
CURLOPT_PROXY_CAINFO 7.52.0
CURLOPT_PROXY_CAINFO_BLOB 7.77.0
@@ -755,13 +773,14 @@
CURLOPT_PROXYTYPE 7.10
CURLOPT_PROXYUSERNAME 7.19.1
CURLOPT_PROXYUSERPWD 7.1
-CURLOPT_PUT 7.1
+CURLOPT_PUT 7.1 7.12.1
CURLOPT_QUOTE 7.1
-CURLOPT_RANDOM_FILE 7.7
+CURLOPT_RANDOM_FILE 7.7 7.84.0
CURLOPT_RANGE 7.1
CURLOPT_READDATA 7.9.7
CURLOPT_READFUNCTION 7.1
-CURLOPT_REDIR_PROTOCOLS 7.19.4
+CURLOPT_REDIR_PROTOCOLS 7.19.4 7.85.0
+CURLOPT_REDIR_PROTOCOLS_STR 7.85.0
CURLOPT_REFERER 7.1
CURLOPT_REQUEST_TARGET 7.55.0
CURLOPT_RESOLVE 7.21.3
@@ -800,10 +819,10 @@
CURLOPT_SSH_COMPRESSION 7.56.0
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 7.17.1
CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 7.80.0
+CURLOPT_SSH_HOSTKEYDATA 7.84.0
+CURLOPT_SSH_HOSTKEYFUNCTION 7.84.0
CURLOPT_SSH_KEYDATA 7.19.6
CURLOPT_SSH_KEYFUNCTION 7.19.6
-CURLOPT_SSH_HOSTKEYFUNCTION 7.84.0
-CURLOPT_SSH_HOSTKEYDATA 7.84.0
CURLOPT_SSH_KNOWNHOSTS 7.19.6
CURLOPT_SSH_PRIVATE_KEYFILE 7.16.1
CURLOPT_SSH_PUBLIC_KEYFILE 7.16.1
@@ -812,7 +831,7 @@
CURLOPT_SSL_CTX_FUNCTION 7.10.6
CURLOPT_SSL_EC_CURVES 7.73.0
CURLOPT_SSL_ENABLE_ALPN 7.36.0
-CURLOPT_SSL_ENABLE_NPN 7.36.0
+CURLOPT_SSL_ENABLE_NPN 7.36.0 7.86.0
CURLOPT_SSL_FALSESTART 7.42.0
CURLOPT_SSL_OPTIONS 7.25.0
CURLOPT_SSL_SESSIONID_CACHE 7.16.0
@@ -872,9 +891,11 @@
CURLOPT_WRITEFUNCTION 7.1
CURLOPT_WRITEHEADER 7.1
CURLOPT_WRITEINFO 7.1
+CURLOPT_WS_OPTIONS 7.86.0
CURLOPT_XFERINFODATA 7.32.0
CURLOPT_XFERINFOFUNCTION 7.32.0
CURLOPT_XOAUTH2_BEARER 7.33.0
+CURLOPTDEPRECATED 7.87.0
CURLOPTTYPE_BLOB 7.71.0
CURLOPTTYPE_CBPOINT 7.73.0
CURLOPTTYPE_FUNCTIONPOINT 7.1
@@ -886,6 +907,7 @@
CURLOPTTYPE_VALUES 7.73.0
CURLOT_BLOB 7.73.0
CURLOT_CBPTR 7.73.0
+CURLOT_FLAG_ALIAS 7.73.0
CURLOT_FUNCTION 7.73.0
CURLOT_LONG 7.73.0
CURLOT_OBJECT 7.73.0
@@ -936,6 +958,7 @@
CURLPROXY_HTTP 7.10
CURLPROXY_HTTP_1_0 7.19.4
CURLPROXY_HTTPS 7.52.0
+CURLPROXY_HTTPS2 8.1.0
CURLPROXY_SOCKS4 7.10
CURLPROXY_SOCKS4A 7.18.0
CURLPROXY_SOCKS5 7.10
@@ -997,6 +1020,7 @@
CURLSSH_AUTH_NONE 7.16.1
CURLSSH_AUTH_PASSWORD 7.16.1
CURLSSH_AUTH_PUBLICKEY 7.16.1
+CURLSSLBACKEND_AWSLC 8.1.0
CURLSSLBACKEND_AXTLS 7.38.0 7.61.0
CURLSSLBACKEND_BEARSSL 7.68.0
CURLSSLBACKEND_BORINGSSL 7.49.0
@@ -1039,6 +1063,7 @@
CURLU_NO_DEFAULT_PORT 7.62.0
CURLU_NON_SUPPORT_SCHEME 7.62.0
CURLU_PATH_AS_IS 7.62.0
+CURLU_PUNYCODE 7.88.0
CURLU_URLDECODE 7.62.0
CURLU_URLENCODE 7.62.0
CURLUE_BAD_FILE_URL 7.81.0
@@ -1055,6 +1080,7 @@
CURLUE_BAD_SCHEME 7.81.0
CURLUE_BAD_SLASHES 7.81.0
CURLUE_BAD_USER 7.81.0
+CURLUE_LACKS_IDN 7.88.0
CURLUE_MALFORMED_INPUT 7.62.0
CURLUE_NO_FRAGMENT 7.62.0
CURLUE_NO_HOST 7.62.0
@@ -1087,6 +1113,7 @@
CURLUSESSL_NONE 7.17.0
CURLUSESSL_TRY 7.17.0
CURLVERSION_EIGHTH 7.72.0
+CURLVERSION_ELEVENTH 7.87.0
CURLVERSION_FIFTH 7.57.0
CURLVERSION_FIRST 7.10
CURLVERSION_FOURTH 7.16.1
@@ -1097,3 +1124,19 @@
CURLVERSION_SIXTH 7.66.0
CURLVERSION_TENTH 7.77.0
CURLVERSION_THIRD 7.12.0
+CURLWARNING 7.66.0
+CURLWS_BINARY 7.86.0
+CURLWS_CLOSE 7.86.0
+CURLWS_CONT 7.86.0
+CURLWS_OFFSET 7.86.0
+CURLWS_PING 7.86.0
+CURLWS_PONG 7.86.0
+CURLWS_RAW_MODE 7.86.0
+CURLWS_TEXT 7.86.0
+LIBCURL_COPYRIGHT 7.18.0
+LIBCURL_TIMESTAMP 7.16.2
+LIBCURL_VERSION 7.11.0
+LIBCURL_VERSION_MAJOR 7.11.0
+LIBCURL_VERSION_MINOR 7.11.0
+LIBCURL_VERSION_NUM 7.11.0
+LIBCURL_VERSION_PATCH 7.11.0
diff --git a/docs/libcurl/symbols.pl b/docs/libcurl/symbols.pl
index 8087d0f..a92d4ec 100755
--- a/docs/libcurl/symbols.pl
+++ b/docs/libcurl/symbols.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2011 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/docs/mk-ca-bundle.1 b/docs/mk-ca-bundle.1
index f4ee20d..e6db050 100644
--- a/docs/mk-ca-bundle.1
+++ b/docs/mk-ca-bundle.1
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2008 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,35 +22,37 @@
.\" *
.\" **************************************************************************
.\"
-.TH mk-ca-bundle 1 "24 Oct 2016" "version 1.27" "mk-ca-bundle manual"
+.TH mk-ca-bundle 1 "24 Oct 2016" mk-ca-bundle mk-ca-bundle
.SH NAME
-mk-ca-bundle \- convert mozilla's certdata.txt to PEM format
+mk-ca-bundle \- convert Mozilla's certificate bundle to PEM format
.SH SYNOPSIS
mk-ca-bundle [options]
.I [outputfile]
.SH DESCRIPTION
-The mk-ca-bundle tool downloads the certdata.txt file from Mozilla's source
-tree over HTTPS, then parses certdata.txt and extracts certificates into PEM
-format. By default, only CA root certificates trusted to issue SSL server
-authentication certificates are extracted. These are then processed with the
-OpenSSL commandline tool to produce the final ca-bundle file.
+The mk-ca-bundle tool downloads the \fIcertdata.txt\fP file from Mozilla's
+source tree over HTTPS, then parses \fIcertdata.txt\fP and extracts
+certificates into PEM format. By default, only CA root certificates trusted to
+issue SSL server authentication certificates are extracted. These are then
+processed with the OpenSSL command line tool to produce the final ca-bundle
+file.
The default \fIoutputfile\fP name is \fBca-bundle.crt\fP. By setting it to '-'
(a single dash) you will get the output sent to STDOUT instead of a file.
The PEM format this scripts uses for output makes the result readily available
-for use by just about all OpenSSL or GnuTLS powered applications, such as
-curl, wget and more.
+for use by just about all OpenSSL or GnuTLS powered applications, such as curl
+and others.
.SH OPTIONS
The following options are supported:
.IP -b
backup an existing version of \fIoutputfilename\fP
.IP "-d [name]"
-specify which Mozilla tree to pull certdata.txt from (or a custom URL). Valid
-names are: aurora, beta, central, mozilla, nss, release (default). They are
-shortcuts for which source tree to get the cert data from.
+specify which Mozilla tree to pull \fIcertdata.txt\fP from (or a custom
+URL). Valid names are: aurora, beta, central, Mozilla, nss, release
+(default). They are shortcuts for which source tree to get the certificates
+data from.
.IP -f
-force rebuild even if certdata.txt is current (Added in version 1.17)
+force rebuild even if \fIcertdata.txt\fP is current (Added in version 1.17)
.IP -i
print version info about used modules
.IP -k
@@ -58,33 +60,36 @@
if the HTTPS transfer fails. This overrides that decision (and opens for
man-in-the-middle attacks).
.IP -l
-print license info about certdata.txt
+print license info about \fIcertdata.txt\fP
.IP -m
(Added in 1.26) Include meta data comments in the output. The meta data is
specific information about each certificate that is stored in the original
file as comments and using this option will make those comments get passed on
to the output file. The meta data is not parsed in any way by mk-ca-bundle.
.IP -n
-no download of certdata.txt (to use existing)
+no download of \fIcertdata.txt\fP (to use existing)
.IP "-p [purposes]:[levels]"
-list of Mozilla trust purposes and levels for certificates to include in output.
-Takes the form of a comma separated list of purposes, a colon, and a comma
-separated list of levels. The default is to include all certificates trusted
-to issue SSL Server certificates (SERVER_AUTH:TRUSTED_DELEGATOR).
+list of Mozilla trust purposes and levels for certificates to include in
+output. Takes the form of a comma separated list of purposes, a colon, and a
+comma separated list of levels. The default is to include all certificates
+trusted to issue SSL Server certificates
+(\fISERVER_AUTH:TRUSTED_DELEGATOR\fP).
(Added in version 1.21, Perl only)
Valid purposes are:
.RS
-ALL, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT,
-DATA_ENCIPHERMENT, KEY_AGREEMENT, KEY_CERT_SIGN, CRL_SIGN,
-SERVER_AUTH (default), CLIENT_AUTH, CODE_SIGNING, EMAIL_PROTECTION,
-IPSEC_END_SYSTEM, IPSEC_TUNNEL, IPSEC_USER, TIME_STAMPING, STEP_UP_APPROVED
+\fIALL\fP, \fIDIGITAL_SIGNATURE\fP, \fINON_REPUDIATION\fP,
+\fIKEY_ENCIPHERMENT\fP, \fIDATA_ENCIPHERMENT\fP, \fIKEY_AGREEMENT\fP,
+\fIKEY_CERT_SIGN\fP, \fICRL_SIGN\fP, \fISERVER_AUTH\fP (default),
+\fICLIENT_AUTH\fP, \fICODE_SIGNING\fP, \fIEMAIL_PROTECTION\fP,
+\fIIPSEC_END_SYSTEM\fP, \fIIPSEC_TUNNEL\fP, \fIIPSEC_USER\fP,
+\fITIME_STAMPING\fP, \fISTEP_UP_APPROVED\fP
.RE
.IP
Valid trust levels are:
.RS
-ALL, TRUSTED_DELEGATOR (default), NOT_TRUSTED, MUST_VERIFY_TRUST, TRUSTED
+\fIALL\fP, \fITRUSTED_DELEGATOR\fP (default), \fINOT_TRUSTED\fP, \fIMUST_VERIFY_TRUST\fP, \fITRUSTED\fP
.RE
.IP -q
be really quiet (no progress output at all)
@@ -101,21 +106,15 @@
ALL, NONE, MD5 (default), SHA1, SHA256, SHA384, SHA512
.RE
.IP -u
-unlink (remove) certdata.txt after processing
+unlink (remove) \fIcertdata.txt\fP after processing
.IP -v
-be verbose and print out processed CAs
+be verbose and print out processed certificate authorities
.SH EXIT STATUS
Returns 0 on success. Returns 1 if it fails to download data.
-.SH CERTDATA FORMAT
-The file format used by Mozilla for this trust information seems to be documented here:
+.SH FILE FORMAT
+The file format used by Mozilla for this trust information is documented here:
.nf
https://p11-glue.freedesktop.org/doc/storing-trust-policy/storing-trust-existing.html
.fi
.SH SEE ALSO
.BR curl (1)
-.SH HISTORY
-\fBmk-ca-bundle\fP is a command line tool that is shipped as part of every
-curl and libcurl release (see https://curl.se/). It was originally based
-on the parse-certs script written by Roland Krikava and was later much
-improved by Guenter Knauf. This manual page was initially written by Jan
-Schaumann \&<jschauma@netmeister.org>.
diff --git a/docs/options-in-versions b/docs/options-in-versions
index a6c75cf..885d4c0 100644
--- a/docs/options-in-versions
+++ b/docs/options-in-versions
@@ -16,6 +16,7 @@
--append (-a) 4.8
--aws-sigv4 7.75.0
--basic 7.10.6
+--ca-native 8.2.0
--cacert 7.5
--capath 7.9.8
--cert (-E) 5.0
@@ -81,6 +82,7 @@
--globoff (-g) 7.6
--happy-eyeballs-timeout-ms 7.59.0
--haproxy-protocol 7.60.0
+--haproxy-clientip 8.2.0
--head (-I) 4.0
--header (-H) 5.0
--help (-h) 4.0
@@ -93,6 +95,7 @@
--http2 7.33.0
--http2-prior-knowledge 7.49.0
--http3 7.66.0
+--http3-only 7.88.0
--ignore-content-length 7.14.1
--include (-i) 4.8
--insecure (-k) 7.10
@@ -156,6 +159,7 @@
--proxy (-x) 4.0
--proxy-anyauth 7.13.2
--proxy-basic 7.12.0
+--proxy-ca-native 8.2.0
--proxy-cacert 7.52.0
--proxy-capath 7.52.0
--proxy-cert 7.52.0
@@ -164,6 +168,7 @@
--proxy-crlfile 7.52.0
--proxy-digest 7.12.0
--proxy-header 7.37.0
+--proxy-http2 8.1.0
--proxy-insecure 7.52.0
--proxy-key 7.52.0
--proxy-key-type 7.52.0
@@ -247,10 +252,12 @@
--tr-encoding 7.21.6
--trace 7.9.7
--trace-ascii 7.9.7
+--trace-ids 8.2.0
--trace-time 7.14.0
--unix-socket 7.40.0
--upload-file (-T) 4.0
--url 7.5
+--url-query 7.87.0
--use-ascii (-B) 5.0
--user (-u) 4.0
--user-agent (-A) 4.5.1
diff --git a/include/Makefile.am b/include/Makefile.am
index 32d7b33..d65bfea 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/include/README.md b/include/README.md
index 8fdbe0e..c965932 100644
--- a/include/README.md
+++ b/include/README.md
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
diff --git a/include/curl/.gitignore b/include/curl/.gitignore
index a856a0f..2467938 100644
--- a/include/curl/.gitignore
+++ b/include/curl/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/include/curl/Makefile.am b/include/curl/Makefile.am
index 60e2652..a655aff 100644
--- a/include/curl/Makefile.am
+++ b/include/curl/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
###########################################################################
pkginclude_HEADERS = \
curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \
- typecheck-gcc.h system.h urlapi.h options.h header.h
+ typecheck-gcc.h system.h urlapi.h options.h header.h websockets.h
pkgincludedir= $(includedir)/curl
diff --git a/include/curl/curl.h b/include/curl/curl.h
index b00648e..ea6fcb6 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,6 +33,23 @@
#define CURL_STRICTER
#endif
+/* Compile-time deprecation macros. */
+#if defined(__GNUC__) && \
+ ((__GNUC__ > 12) || ((__GNUC__ == 12) && (__GNUC_MINOR__ >= 1 ))) && \
+ !defined(__INTEL_COMPILER) && \
+ !defined(CURL_DISABLE_DEPRECATION) && !defined(BUILDING_LIBCURL)
+#define CURL_DEPRECATED(version, message) \
+ __attribute__((deprecated("since " # version ". " message)))
+#define CURL_IGNORE_DEPRECATION(statements) \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \
+ statements \
+ _Pragma("GCC diagnostic pop")
+#else
+#define CURL_DEPRECATED(version, message)
+#define CURL_IGNORE_DEPRECATION(statements) statements
+#endif
+
#include "curlver.h" /* libcurl version defines */
#include "system.h" /* determine things run-time */
@@ -75,7 +92,8 @@
defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \
- (defined(__MidnightBSD_version) && (__MidnightBSD_version < 100000))
+ (defined(__MidnightBSD_version) && (__MidnightBSD_version < 100000)) || \
+ defined(__sun__) || defined(__serenity__) || defined(__vxworks__)
#include <sys/select.h>
#endif
@@ -144,20 +162,21 @@
CURLSSLBACKEND_NSS = 3,
CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */
CURLSSLBACKEND_GSKIT = 5,
- CURLSSLBACKEND_POLARSSL = 6,
+ CURLSSLBACKEND_POLARSSL CURL_DEPRECATED(7.69.0, "") = 6,
CURLSSLBACKEND_WOLFSSL = 7,
CURLSSLBACKEND_SCHANNEL = 8,
CURLSSLBACKEND_SECURETRANSPORT = 9,
- CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */
+ CURLSSLBACKEND_AXTLS CURL_DEPRECATED(7.61.0, "") = 10,
CURLSSLBACKEND_MBEDTLS = 11,
- CURLSSLBACKEND_MESALINK = 12,
+ CURLSSLBACKEND_MESALINK CURL_DEPRECATED(7.82.0, "") = 12,
CURLSSLBACKEND_BEARSSL = 13,
CURLSSLBACKEND_RUSTLS = 14
} curl_sslbackend;
/* aliases for library clones and renames */
-#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
+#define CURLSSLBACKEND_AWSLC CURLSSLBACKEND_OPENSSL
#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL
+#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
/* deprecated names: */
#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
@@ -231,7 +250,7 @@
#ifndef CURL_MAX_READ_SIZE
/* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */
-#define CURL_MAX_READ_SIZE 524288
+#define CURL_MAX_READ_SIZE (10*1024*1024)
#endif
#ifndef CURL_MAX_WRITE_SIZE
@@ -255,6 +274,10 @@
will signal libcurl to pause receiving on the current transfer. */
#define CURL_WRITEFUNC_PAUSE 0x10000001
+/* This is a magic return code for the write callback that, when returned,
+ will signal an error from the callback. */
+#define CURL_WRITEFUNC_ERROR 0xFFFFFFFF
+
typedef size_t (*curl_write_callback)(char *buffer,
size_t size,
size_t nitems,
@@ -309,7 +332,8 @@
unsigned int flags;
- /* used internally */
+ /* These are libcurl private struct fields. Previously used by libcurl, so
+ they must never be interfered with. */
char *b_data;
size_t b_size;
size_t b_used;
@@ -367,7 +391,7 @@
#define CURL_READFUNC_PAUSE 0x10000001
/* Return code for when the trailing headers' callback has terminated
- without any errors*/
+ without any errors */
#define CURL_TRAILERFUNC_OK 0
/* Return code for when was an error in the trailing header's list and we
want to abort the request */
@@ -449,7 +473,7 @@
#define CURL_DID_MEMORY_FUNC_TYPEDEFS
#endif
-/* the kind of data that is passed to information_callback*/
+/* the kind of data that is passed to information_callback */
typedef enum {
CURLINFO_TEXT = 0,
CURLINFO_HEADER_IN, /* 1 */
@@ -577,7 +601,7 @@
CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */
CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
- CURLE_CONV_FAILED, /* 75 - conversion failed */
+ CURLE_OBSOLETE75, /* 75 - NOT IN USE since 7.82.0 */
CURLE_OBSOLETE76, /* 76 - NOT IN USE since 7.82.0 */
CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing
or wrong format */
@@ -680,6 +704,7 @@
#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
#define CURLE_LDAP_INVALID_URL CURLE_OBSOLETE62
#define CURLE_CONV_REQD CURLE_OBSOLETE76
+#define CURLE_CONV_FAILED CURLE_OBSOLETE75
/* This was the error code 50 in 7.7.3 and a few earlier versions, this
is no longer used by libcurl but is instead #defined here only to not
@@ -696,7 +721,7 @@
#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
-#endif /*!CURL_NO_OLDIES*/
+#endif /* !CURL_NO_OLDIES */
/*
* Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was
@@ -755,7 +780,8 @@
CONNECT HTTP/1.1 */
CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
HTTP/1.0 */
- CURLPROXY_HTTPS = 2, /* added in 7.52.0 */
+ CURLPROXY_HTTPS = 2, /* HTTPS but stick to HTTP/1 added in 7.52.0 */
+ CURLPROXY_HTTPS2 = 3, /* HTTPS and attempt HTTP/2 added in 8.2.0 */
CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
in 7.10 */
CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
@@ -838,10 +864,10 @@
CURLKHSTAT_FINE_ADD_TO_FILE,
CURLKHSTAT_FINE,
CURLKHSTAT_REJECT, /* reject the connection, return an error */
- CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so
- this causes a CURLE_DEFER error but otherwise the
+ CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now.
+ Causes a CURLE_PEER_FAILED_VERIFICATION error but the
connection will be left intact etc */
- CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key*/
+ CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key */
CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */
};
@@ -862,13 +888,13 @@
/* CURLOPT_SSH_KEYDATA */
typedef int
- (*curl_sshhostkeycallback) (void *clientp,/* custom pointer passed*/
+ (*curl_sshhostkeycallback) (void *clientp,/* custom pointer passed */
/* with CURLOPT_SSH_HOSTKEYDATA */
int keytype, /* CURLKHTYPE */
- const char *key, /*hostkey to check*/
- size_t keylen); /*length of the key*/
- /*return CURLE_OK to accept*/
- /*or something else to refuse*/
+ const char *key, /* hostkey to check */
+ size_t keylen); /* length of the key */
+ /* return CURLE_OK to accept */
+ /* or something else to refuse */
/* parameter for the CURLOPT_USE_SSL option */
@@ -930,7 +956,7 @@
#define CURLFTPSSL_ALL CURLUSESSL_ALL
#define CURLFTPSSL_LAST CURLUSESSL_LAST
#define curl_ftpssl curl_usessl
-#endif /*!CURL_NO_OLDIES*/
+#endif /* !CURL_NO_OLDIES */
/* parameter for the CURLOPT_FTP_SSL_CCC option */
typedef enum {
@@ -1009,7 +1035,8 @@
#define CURLHSTS_ENABLE (long)(1<<0)
#define CURLHSTS_READONLYFILE (long)(1<<1)
-/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
+/* The CURLPROTO_ defines below are for the **deprecated** CURLOPT_*PROTOCOLS
+ options. Do not use. */
#define CURLPROTO_HTTP (1<<0)
#define CURLPROTO_HTTPS (1<<1)
#define CURLPROTO_FTP (1<<2)
@@ -1055,6 +1082,7 @@
#define CURLOPT(na,t,nu) na = t + nu
+#define CURLOPTDEPRECATED(na,t,nu,v,m) na CURL_DEPRECATED(v,m) = t + nu
/* CURLOPT aliases that make no run-time difference */
@@ -1116,7 +1144,7 @@
/* Time-out the read operation after this amount of seconds */
CURLOPT(CURLOPT_TIMEOUT, CURLOPTTYPE_LONG, 13),
- /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
+ /* If CURLOPT_READDATA is used, this can be used to inform libcurl about
* how large the file being sent really is. That allows better error
* checking and better verifies that the upload was successful. -1 means
* unknown size.
@@ -1168,7 +1196,8 @@
CURLOPT(CURLOPT_HTTPHEADER, CURLOPTTYPE_SLISTPOINT, 23),
/* This points to a linked list of post entries, struct curl_httppost */
- CURLOPT(CURLOPT_HTTPPOST, CURLOPTTYPE_OBJECTPOINT, 24),
+ CURLOPTDEPRECATED(CURLOPT_HTTPPOST, CURLOPTTYPE_OBJECTPOINT, 24,
+ 7.56.0, "Use CURLOPT_MIMEPOST"),
/* name of the file keeping your private SSL-certificate */
CURLOPT(CURLOPT_SSLCERT, CURLOPTTYPE_STRINGPOINT, 25),
@@ -1258,7 +1287,8 @@
CURLOPT(CURLOPT_TRANSFERTEXT, CURLOPTTYPE_LONG, 53),
/* HTTP PUT */
- CURLOPT(CURLOPT_PUT, CURLOPTTYPE_LONG, 54),
+ CURLOPTDEPRECATED(CURLOPT_PUT, CURLOPTTYPE_LONG, 54,
+ 7.12.1, "Use CURLOPT_UPLOAD"),
/* 55 = OBSOLETE */
@@ -1266,7 +1296,8 @@
* Function that will be called instead of the internal progress display
* function. This function should be defined as the curl_progress_callback
* prototype defines. */
- CURLOPT(CURLOPT_PROGRESSFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 56),
+ CURLOPTDEPRECATED(CURLOPT_PROGRESSFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 56,
+ 7.32.0, "Use CURLOPT_XFERINFOFUNCTION"),
/* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
callbacks */
@@ -1283,7 +1314,7 @@
/* size of the POST input data, if strlen() is not good to use */
CURLOPT(CURLOPT_POSTFIELDSIZE, CURLOPTTYPE_LONG, 60),
- /* tunnel non-http operations through a HTTP proxy */
+ /* tunnel non-http operations through an HTTP proxy */
CURLOPT(CURLOPT_HTTPPROXYTUNNEL, CURLOPTTYPE_LONG, 61),
/* Set the interface string to use as outgoing network interface */
@@ -1334,10 +1365,12 @@
/* Set to a file name that contains random data for libcurl to use to
seed the random engine when doing SSL connects. */
- CURLOPT(CURLOPT_RANDOM_FILE, CURLOPTTYPE_STRINGPOINT, 76),
+ CURLOPTDEPRECATED(CURLOPT_RANDOM_FILE, CURLOPTTYPE_STRINGPOINT, 76,
+ 7.84.0, "Serves no purpose anymore"),
/* Set to the Entropy Gathering Daemon socket pathname */
- CURLOPT(CURLOPT_EGDSOCKET, CURLOPTTYPE_STRINGPOINT, 77),
+ CURLOPTDEPRECATED(CURLOPT_EGDSOCKET, CURLOPTTYPE_STRINGPOINT, 77,
+ 7.84.0, "Serves no purpose anymore"),
/* Time-out connect operations after this amount of seconds, if connects are
OK within this time, then fine... This only aborts the connect phase. */
@@ -1392,7 +1425,8 @@
/* Non-zero value means to use the global dns cache */
/* DEPRECATED, do not use! */
- CURLOPT(CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOPTTYPE_LONG, 91),
+ CURLOPTDEPRECATED(CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOPTTYPE_LONG, 91,
+ 7.11.1, "Use CURLOPT_SHARE"),
/* DNS cache timeout */
CURLOPT(CURLOPT_DNS_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 92),
@@ -1475,12 +1509,11 @@
Note that setting multiple bits may cause extra network round-trips. */
CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_VALUES, 111),
- /* FTP option that changes the timeout, in seconds, associated with
- getting a response. This is different from transfer timeout time and
- essentially places a demand on the FTP server to acknowledge commands
- in a timely manner. */
- CURLOPT(CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOPTTYPE_LONG, 112),
-#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
+ /* Option that changes the timeout, in seconds, associated with getting a
+ response. This is different from transfer timeout time and essentially
+ places a demand on the server to acknowledge commands in a timely
+ manner. For FTP, SMTP, IMAP and POP3. */
+ CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT, CURLOPTTYPE_LONG, 112),
/* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
tell libcurl to use those IP versions only. This only has effect on
@@ -1548,8 +1581,10 @@
*/
CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_VALUES, 129),
- CURLOPT(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130),
- CURLOPT(CURLOPT_IOCTLDATA, CURLOPTTYPE_CBPOINT, 131),
+ CURLOPTDEPRECATED(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130,
+ 7.18.0, "Use CURLOPT_SEEKFUNCTION"),
+ CURLOPTDEPRECATED(CURLOPT_IOCTLDATA, CURLOPTTYPE_CBPOINT, 131,
+ 7.18.0, "Use CURLOPT_SEEKDATA"),
/* 132 OBSOLETE. Gone in 7.16.0 */
/* 133 OBSOLETE. Gone in 7.16.0 */
@@ -1588,16 +1623,22 @@
/* Function that will be called to convert from the
network encoding (instead of using the iconv calls in libcurl) */
- CURLOPT(CURLOPT_CONV_FROM_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 142),
+ CURLOPTDEPRECATED(CURLOPT_CONV_FROM_NETWORK_FUNCTION,
+ CURLOPTTYPE_FUNCTIONPOINT, 142,
+ 7.82.0, "Serves no purpose anymore"),
/* Function that will be called to convert to the
network encoding (instead of using the iconv calls in libcurl) */
- CURLOPT(CURLOPT_CONV_TO_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 143),
+ CURLOPTDEPRECATED(CURLOPT_CONV_TO_NETWORK_FUNCTION,
+ CURLOPTTYPE_FUNCTIONPOINT, 143,
+ 7.82.0, "Serves no purpose anymore"),
/* Function that will be called to convert from UTF8
(instead of using the iconv calls in libcurl)
Note that this is used only for SSL certificate processing */
- CURLOPT(CURLOPT_CONV_FROM_UTF8_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 144),
+ CURLOPTDEPRECATED(CURLOPT_CONV_FROM_UTF8_FUNCTION,
+ CURLOPTTYPE_FUNCTIONPOINT, 144,
+ 7.82.0, "Serves no purpose anymore"),
/* if the connection proceeds too quickly then need to slow it down */
/* limit-rate: maximum number of bytes per second to send or receive */
@@ -1698,7 +1739,9 @@
/* Socks Service */
/* DEPRECATED, do not use! */
- CURLOPT(CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOPTTYPE_STRINGPOINT, 179),
+ CURLOPTDEPRECATED(CURLOPT_SOCKS5_GSSAPI_SERVICE,
+ CURLOPTTYPE_STRINGPOINT, 179,
+ 7.49.0, "Use CURLOPT_PROXY_SERVICE_NAME"),
/* Socks Service */
CURLOPT(CURLOPT_SOCKS5_GSSAPI_NEC, CURLOPTTYPE_LONG, 180),
@@ -1707,12 +1750,14 @@
transfer, which thus helps the app which takes URLs from users or other
external inputs and want to restrict what protocol(s) to deal
with. Defaults to CURLPROTO_ALL. */
- CURLOPT(CURLOPT_PROTOCOLS, CURLOPTTYPE_LONG, 181),
+ CURLOPTDEPRECATED(CURLOPT_PROTOCOLS, CURLOPTTYPE_LONG, 181,
+ 7.85.0, "Use CURLOPT_PROTOCOLS_STR"),
/* set the bitmask for the protocols that libcurl is allowed to follow to,
as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
to be set in both bitmasks to be allowed to get redirected to. */
- CURLOPT(CURLOPT_REDIR_PROTOCOLS, CURLOPTTYPE_LONG, 182),
+ CURLOPTDEPRECATED(CURLOPT_REDIR_PROTOCOLS, CURLOPTTYPE_LONG, 182,
+ 7.85.0, "Use CURLOPT_REDIR_PROTOCOLS_STR"),
/* set the SSH knownhost file name to use */
CURLOPT(CURLOPT_SSH_KNOWNHOSTS, CURLOPTTYPE_STRINGPOINT, 183),
@@ -1857,12 +1902,13 @@
CURLOPT(CURLOPT_LOGIN_OPTIONS, CURLOPTTYPE_STRINGPOINT, 224),
/* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
- CURLOPT(CURLOPT_SSL_ENABLE_NPN, CURLOPTTYPE_LONG, 225),
+ CURLOPTDEPRECATED(CURLOPT_SSL_ENABLE_NPN, CURLOPTTYPE_LONG, 225,
+ 7.86.0, "Has no function"),
/* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
CURLOPT(CURLOPT_SSL_ENABLE_ALPN, CURLOPTTYPE_LONG, 226),
- /* Time to wait for a response to a HTTP request containing an
+ /* Time to wait for a response to an HTTP request containing an
* Expect: 100-continue header before sending the data anyway. */
CURLOPT(CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOPTTYPE_LONG, 227),
@@ -2067,7 +2113,7 @@
CURLOPT(CURLOPT_SASL_AUTHZID, CURLOPTTYPE_STRINGPOINT, 289),
/* allow RCPT TO command to fail for some recipients */
- CURLOPT(CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOPTTYPE_LONG, 290),
+ CURLOPT(CURLOPT_MAIL_RCPT_ALLOWFAILS, CURLOPTTYPE_LONG, 290),
/* the private SSL-certificate as a "blob" */
CURLOPT(CURLOPT_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 291),
@@ -2143,6 +2189,27 @@
/* set the SSH host key callback custom pointer */
CURLOPT(CURLOPT_SSH_HOSTKEYDATA, CURLOPTTYPE_CBPOINT, 317),
+ /* specify which protocols that are allowed to be used for the transfer,
+ which thus helps the app which takes URLs from users or other external
+ inputs and want to restrict what protocol(s) to deal with. Defaults to
+ all built-in protocols. */
+ CURLOPT(CURLOPT_PROTOCOLS_STR, CURLOPTTYPE_STRINGPOINT, 318),
+
+ /* specify which protocols that libcurl is allowed to follow directs to */
+ CURLOPT(CURLOPT_REDIR_PROTOCOLS_STR, CURLOPTTYPE_STRINGPOINT, 319),
+
+ /* websockets options */
+ CURLOPT(CURLOPT_WS_OPTIONS, CURLOPTTYPE_LONG, 320),
+
+ /* CA cache timeout */
+ CURLOPT(CURLOPT_CA_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 321),
+
+ /* Can leak things, gonna exit() soon */
+ CURLOPT(CURLOPT_QUICK_EXIT, CURLOPTTYPE_LONG, 322),
+
+ /* set a specific client IP for HAProxy PROXY protocol header? */
+ CURLOPT(CURLOPT_HAPROXY_CLIENT_IP, CURLOPTTYPE_STRINGPOINT, 323),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2168,6 +2235,12 @@
#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD
#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
+/* */
+#define CURLOPT_FTP_RESPONSE_TIMEOUT CURLOPT_SERVER_RESPONSE_TIMEOUT
+
+/* Added in 8.2.0 */
+#define CURLOPT_MAIL_RCPT_ALLLOWFAILS CURLOPT_MAIL_RCPT_ALLOWFAILS
+
#else
/* This is set if CURL_NO_OLDIES is defined at compile-time */
#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
@@ -2182,7 +2255,7 @@
#define CURL_IPRESOLVE_V4 1 /* uses only IPv4 addresses/connections */
#define CURL_IPRESOLVE_V6 2 /* uses only IPv6 addresses/connections */
- /* three convenient "aliases" that follow the name scheme better */
+ /* Convenient "aliases" */
#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
/* These enums are for use with the CURLOPT_HTTP_VERSION option. */
@@ -2196,8 +2269,13 @@
CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */
CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1
Upgrade */
- CURL_HTTP_VERSION_3 = 30, /* Makes use of explicit HTTP/3 without fallback.
- Use CURLOPT_ALTSVC to enable HTTP/3 upgrade */
+ CURL_HTTP_VERSION_3 = 30, /* Use HTTP/3, fallback to HTTP/2 or HTTP/1 if
+ needed. For HTTPS only. For HTTP, this option
+ makes libcurl return error. */
+ CURL_HTTP_VERSION_3ONLY = 31, /* Use HTTP/3 without fallback. For HTTPS
+ only. For HTTP, this makes libcurl
+ return error. */
+
CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
};
@@ -2427,30 +2505,32 @@
int take_ownership);
typedef enum {
- CURLFORM_NOTHING, /********* the first one is unused ************/
- CURLFORM_COPYNAME,
- CURLFORM_PTRNAME,
- CURLFORM_NAMELENGTH,
- CURLFORM_COPYCONTENTS,
- CURLFORM_PTRCONTENTS,
- CURLFORM_CONTENTSLENGTH,
- CURLFORM_FILECONTENT,
- CURLFORM_ARRAY,
+ /********* the first one is unused ************/
+ CURLFORM_NOTHING CURL_DEPRECATED(7.56.0, ""),
+ CURLFORM_COPYNAME CURL_DEPRECATED(7.56.0, "Use curl_mime_name()"),
+ CURLFORM_PTRNAME CURL_DEPRECATED(7.56.0, "Use curl_mime_name()"),
+ CURLFORM_NAMELENGTH CURL_DEPRECATED(7.56.0, ""),
+ CURLFORM_COPYCONTENTS CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"),
+ CURLFORM_PTRCONTENTS CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"),
+ CURLFORM_CONTENTSLENGTH CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"),
+ CURLFORM_FILECONTENT CURL_DEPRECATED(7.56.0, "Use curl_mime_data_cb()"),
+ CURLFORM_ARRAY CURL_DEPRECATED(7.56.0, ""),
CURLFORM_OBSOLETE,
- CURLFORM_FILE,
+ CURLFORM_FILE CURL_DEPRECATED(7.56.0, "Use curl_mime_filedata()"),
- CURLFORM_BUFFER,
- CURLFORM_BUFFERPTR,
- CURLFORM_BUFFERLENGTH,
+ CURLFORM_BUFFER CURL_DEPRECATED(7.56.0, "Use curl_mime_filename()"),
+ CURLFORM_BUFFERPTR CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"),
+ CURLFORM_BUFFERLENGTH CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"),
- CURLFORM_CONTENTTYPE,
- CURLFORM_CONTENTHEADER,
- CURLFORM_FILENAME,
+ CURLFORM_CONTENTTYPE CURL_DEPRECATED(7.56.0, "Use curl_mime_type()"),
+ CURLFORM_CONTENTHEADER CURL_DEPRECATED(7.56.0, "Use curl_mime_headers()"),
+ CURLFORM_FILENAME CURL_DEPRECATED(7.56.0, "Use curl_mime_filename()"),
CURLFORM_END,
CURLFORM_OBSOLETE2,
- CURLFORM_STREAM,
- CURLFORM_CONTENTLEN, /* added in 7.46.0, provide a curl_off_t length */
+ CURLFORM_STREAM CURL_DEPRECATED(7.56.0, "Use curl_mime_data_cb()"),
+ CURLFORM_CONTENTLEN /* added in 7.46.0, provide a curl_off_t length */
+ CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"),
CURLFORM_LASTENTRY /* the last unused */
} CURLformoption;
@@ -2478,15 +2558,16 @@
*
***************************************************************************/
typedef enum {
- CURL_FORMADD_OK, /* first, no error */
+ CURL_FORMADD_OK CURL_DEPRECATED(7.56.0, ""), /* 1st, no error */
- CURL_FORMADD_MEMORY,
- CURL_FORMADD_OPTION_TWICE,
- CURL_FORMADD_NULL,
- CURL_FORMADD_UNKNOWN_OPTION,
- CURL_FORMADD_INCOMPLETE,
- CURL_FORMADD_ILLEGAL_ARRAY,
- CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */
+ CURL_FORMADD_MEMORY CURL_DEPRECATED(7.56.0, ""),
+ CURL_FORMADD_OPTION_TWICE CURL_DEPRECATED(7.56.0, ""),
+ CURL_FORMADD_NULL CURL_DEPRECATED(7.56.0, ""),
+ CURL_FORMADD_UNKNOWN_OPTION CURL_DEPRECATED(7.56.0, ""),
+ CURL_FORMADD_INCOMPLETE CURL_DEPRECATED(7.56.0, ""),
+ CURL_FORMADD_ILLEGAL_ARRAY CURL_DEPRECATED(7.56.0, ""),
+ /* libcurl was built with form api disabled */
+ CURL_FORMADD_DISABLED CURL_DEPRECATED(7.56.0, ""),
CURL_FORMADD_LAST /* last */
} CURLFORMcode;
@@ -2500,9 +2581,10 @@
* adds one part that together construct a full post. Then use
* CURLOPT_HTTPPOST to send it off to libcurl.
*/
-CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
- struct curl_httppost **last_post,
- ...);
+CURL_EXTERN CURLFORMcode CURL_DEPRECATED(7.56.0, "Use curl_mime_init()")
+curl_formadd(struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ ...);
/*
* callback function for curl_formget()
@@ -2525,8 +2607,9 @@
* the curl_formget_callback function.
* Returns 0 on success.
*/
-CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
- curl_formget_callback append);
+CURL_EXTERN int CURL_DEPRECATED(7.56.0, "")
+curl_formget(struct curl_httppost *form, void *arg,
+ curl_formget_callback append);
/*
* NAME curl_formfree()
*
@@ -2534,7 +2617,8 @@
*
* Free a multipart formpost previously built with curl_formadd().
*/
-CURL_EXTERN void curl_formfree(struct curl_httppost *form);
+CURL_EXTERN void CURL_DEPRECATED(7.56.0, "Use curl_mime_free()")
+curl_formfree(struct curl_httppost *form);
/*
* NAME curl_getenv()
@@ -2703,8 +2787,8 @@
* Appends a string to a linked list. If no list exists, it will be created
* first. Returns the new list, after appending.
*/
-CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
- const char *);
+CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *list,
+ const char *data);
/*
* NAME curl_slist_free_all()
@@ -2713,7 +2797,7 @@
*
* free a previously built curl_slist.
*/
-CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
+CURL_EXTERN void curl_slist_free_all(struct curl_slist *list);
/*
* NAME curl_getdate()
@@ -2761,22 +2845,35 @@
CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4,
CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5,
CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
- CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7,
+ CURLINFO_SIZE_UPLOAD CURL_DEPRECATED(7.55.0, "Use CURLINFO_SIZE_UPLOAD_T")
+ = CURLINFO_DOUBLE + 7,
CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7,
- CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8,
+ CURLINFO_SIZE_DOWNLOAD
+ CURL_DEPRECATED(7.55.0, "Use CURLINFO_SIZE_DOWNLOAD_T")
+ = CURLINFO_DOUBLE + 8,
CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8,
- CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9,
+ CURLINFO_SPEED_DOWNLOAD
+ CURL_DEPRECATED(7.55.0, "Use CURLINFO_SPEED_DOWNLOAD_T")
+ = CURLINFO_DOUBLE + 9,
CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9,
- CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10,
+ CURLINFO_SPEED_UPLOAD
+ CURL_DEPRECATED(7.55.0, "Use CURLINFO_SPEED_UPLOAD_T")
+ = CURLINFO_DOUBLE + 10,
CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10,
CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11,
CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
CURLINFO_FILETIME = CURLINFO_LONG + 14,
CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14,
- CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD
+ CURL_DEPRECATED(7.55.0,
+ "Use CURLINFO_CONTENT_LENGTH_DOWNLOAD_T")
+ = CURLINFO_DOUBLE + 15,
CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15,
- CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
+ CURLINFO_CONTENT_LENGTH_UPLOAD
+ CURL_DEPRECATED(7.55.0,
+ "Use CURLINFO_CONTENT_LENGTH_UPLOAD_T")
+ = CURLINFO_DOUBLE + 16,
CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16,
CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18,
@@ -2790,7 +2887,8 @@
CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26,
CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27,
CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
- CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
+ CURLINFO_LASTSOCKET CURL_DEPRECATED(7.45.0, "Use CURLINFO_ACTIVESOCKET")
+ = CURLINFO_LONG + 29,
CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30,
CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31,
CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
@@ -2804,12 +2902,14 @@
CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
- CURLINFO_TLS_SESSION = CURLINFO_PTR + 43,
+ CURLINFO_TLS_SESSION CURL_DEPRECATED(7.48.0, "Use CURLINFO_TLS_SSL_PTR")
+ = CURLINFO_PTR + 43,
CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44,
CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45,
CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46,
CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
- CURLINFO_PROTOCOL = CURLINFO_LONG + 48,
+ CURLINFO_PROTOCOL CURL_DEPRECATED(7.85.0, "Use CURLINFO_SCHEME")
+ = CURLINFO_LONG + 48,
CURLINFO_SCHEME = CURLINFO_STRING + 49,
CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50,
CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51,
@@ -2824,7 +2924,9 @@
CURLINFO_REFERER = CURLINFO_STRING + 60,
CURLINFO_CAINFO = CURLINFO_STRING + 61,
CURLINFO_CAPATH = CURLINFO_STRING + 62,
- CURLINFO_LASTONE = 62
+ CURLINFO_XFER_ID = CURLINFO_OFF_T + 63,
+ CURLINFO_CONN_ID = CURLINFO_OFF_T + 64,
+ CURLINFO_LASTONE = 64
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -2868,6 +2970,7 @@
CURL_LOCK_DATA_SSL_SESSION,
CURL_LOCK_DATA_CONNECT,
CURL_LOCK_DATA_PSL,
+ CURL_LOCK_DATA_HSTS,
CURL_LOCK_DATA_LAST
} curl_lock_data;
@@ -2910,8 +3013,9 @@
} CURLSHoption;
CURL_EXTERN CURLSH *curl_share_init(void);
-CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
-CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
+CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *share, CURLSHoption option,
+ ...);
+CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *share);
/****************************************************************************
* Structures for querying information about the curl library at runtime.
@@ -2928,6 +3032,7 @@
CURLVERSION_EIGHTH,
CURLVERSION_NINTH,
CURLVERSION_TENTH,
+ CURLVERSION_ELEVENTH,
CURLVERSION_LAST /* never actually use this */
} CURLversion;
@@ -2936,7 +3041,7 @@
meant to be a built-in version number for what kind of struct the caller
expects. If the struct ever changes, we redefine the NOW to another enum
from above. */
-#define CURLVERSION_NOW CURLVERSION_TENTH
+#define CURLVERSION_NOW CURLVERSION_ELEVENTH
struct curl_version_info_data {
CURLversion age; /* age of the returned struct */
@@ -2992,6 +3097,10 @@
/* These fields were added in CURLVERSION_TENTH */
const char *gsasl_version; /* human readable string. */
+
+ /* These fields were added in CURLVERSION_ELEVENTH */
+ /* feature_names is terminated by an entry with a NULL feature name */
+ const char * const *feature_names;
};
typedef struct curl_version_info_data curl_version_info_data;
@@ -3085,7 +3194,7 @@
#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
#ifdef __cplusplus
-}
+} /* end of extern "C" */
#endif
/* unfortunately, the easy.h and multi.h include files need options and info
@@ -3095,6 +3204,7 @@
#include "urlapi.h"
#include "options.h"
#include "header.h"
+#include "websockets.h"
/* the typechecker doesn't work in C++ (yet) */
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
@@ -3111,6 +3221,6 @@
#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
#endif /* __STDC__ >= 1 */
-#endif /* gcc >= 4.3 && !__cplusplus */
+#endif /* gcc >= 4.3 && !__cplusplus && !CURL_DISABLE_TYPECHECK */
#endif /* CURLINC_CURL_H */
diff --git a/include/curl/curlver.h b/include/curl/curlver.h
index a936eb4..c3b7f2b 100644
--- a/include/curl/curlver.h
+++ b/include/curl/curlver.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,17 +28,17 @@
a script at release-time. This was made its own header file in 7.11.2 */
/* This is the global package copyright */
-#define LIBCURL_COPYRIGHT "1996 - 2022 Daniel Stenberg, <daniel@haxx.se>."
+#define LIBCURL_COPYRIGHT "Daniel Stenberg, <daniel@haxx.se>."
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.84.0-DEV"
+#define LIBCURL_VERSION "8.2.1-DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
-#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 84
-#define LIBCURL_VERSION_PATCH 0
+#define LIBCURL_VERSION_MAJOR 8
+#define LIBCURL_VERSION_MINOR 2
+#define LIBCURL_VERSION_PATCH 1
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
@@ -59,7 +59,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
-#define LIBCURL_VERSION_NUM 0x075400
+#define LIBCURL_VERSION_NUM 0x080201
/*
* 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 9c7e63a..1285101 100644
--- a/include/curl/easy.h
+++ b/include/curl/easy.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,13 +48,13 @@
*
* DESCRIPTION
*
- * Request internal information from the curl session with this function. The
- * third argument MUST be a pointer to a long, a pointer to a char * or a
- * pointer to a double (as the documentation describes elsewhere). 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 is completed.
+ * 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 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
+ * is completed.
*/
CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
@@ -119,7 +119,7 @@
CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
#ifdef __cplusplus
-}
+} /* end of extern "C" */
#endif
#endif
diff --git a/include/curl/header.h b/include/curl/header.h
index 6af29c0..8df11e1 100644
--- a/include/curl/header.h
+++ b/include/curl/header.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,6 +24,10 @@
*
***************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct curl_header {
char *name; /* this might not use the same case */
char *value;
@@ -63,4 +67,8 @@
int request,
struct curl_header *prev);
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
#endif /* CURLINC_HEADER_H */
diff --git a/include/curl/mprintf.h b/include/curl/mprintf.h
index cb948dc..e652a65 100644
--- a/include/curl/mprintf.h
+++ b/include/curl/mprintf.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -46,7 +46,7 @@
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
#ifdef __cplusplus
-}
+} /* end of extern "C" */
#endif
#endif /* CURLINC_MPRINTF_H */
diff --git a/include/curl/multi.h b/include/curl/multi.h
index 3010492..30a3d93 100644
--- a/include/curl/multi.h
+++ b/include/curl/multi.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -124,7 +124,7 @@
/*
* Name: curl_multi_init()
*
- * Desc: inititalize multi-style curl usage
+ * Desc: initialize multi-style curl usage
*
* Returns: a new CURLM handle to use in all 'curl_multi' functions.
*/
@@ -318,16 +318,16 @@
void *userp); /* private callback
pointer */
-CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
- int *running_handles);
+CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()")
+curl_multi_socket(CURLM *multi_handle, curl_socket_t s, int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
curl_socket_t s,
int ev_bitmask,
int *running_handles);
-CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
- int *running_handles);
+CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()")
+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
diff --git a/include/curl/options.h b/include/curl/options.h
index c8ac827..1ed76a9 100644
--- a/include/curl/options.h
+++ b/include/curl/options.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,7 +33,7 @@
CURLOT_VALUES, /* (a defined set or bitmask) */
CURLOT_OFF_T, /* curl_off_t (a range of values) */
CURLOT_OBJECT, /* pointer (void *) */
- CURLOT_STRING, /* (char * to zero terminated buffer) */
+ CURLOT_STRING, /* (char * to null-terminated buffer) */
CURLOT_SLIST, /* (struct curl_slist *) */
CURLOT_CBPTR, /* (void * passed as-is to a callback) */
CURLOT_BLOB, /* blob (struct curl_blob *) */
diff --git a/include/curl/stdcheaders.h b/include/curl/stdcheaders.h
index 82e1b5f..7451aa3 100644
--- a/include/curl/stdcheaders.h
+++ b/include/curl/stdcheaders.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/include/curl/system.h b/include/curl/system.h
index 8d56b8a..b2640c8 100644
--- a/include/curl/system.h
+++ b/include/curl/system.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -164,13 +164,33 @@
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
-#elif defined(__MWERKS__)
+#elif defined(macintosh)
+# include <ConditionalMacros.h>
+# if TYPE_LONGLONG
+# 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
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
+
+#elif defined(__TANDEM)
+# if ! defined(__LP64)
+ /* Required for 32-bit NonStop builds only. */
# 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
+# endif
#elif defined(_WIN32_WCE)
# define CURL_TYPEOF_CURL_OFF_T __int64
@@ -207,45 +227,38 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__OS400__)
-# if defined(__ILEC400__)
+# 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 socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+
+#elif defined(__MVS__)
+# if defined(_LONG_LONG)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
-# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-# define CURL_PULL_SYS_TYPES_H 1
-# define CURL_PULL_SYS_SOCKET_H 1
+# elif defined(_LP64)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
-
-#elif defined(__MVS__)
-# if defined(__IBMC__) || defined(__IBMCPP__)
-# if defined(_ILP32)
-# elif defined(_LP64)
-# endif
-# if defined(_LONG_LONG)
-# define CURL_TYPEOF_CURL_OFF_T long long
-# define CURL_FORMAT_CURL_OFF_T "lld"
-# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SUFFIX_CURL_OFF_T LL
-# define CURL_SUFFIX_CURL_OFF_TU ULL
-# elif defined(_LP64)
-# define CURL_TYPEOF_CURL_OFF_T long
-# define CURL_FORMAT_CURL_OFF_T "ld"
-# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SUFFIX_CURL_OFF_T L
-# define CURL_SUFFIX_CURL_OFF_TU UL
-# else
-# define CURL_TYPEOF_CURL_OFF_T long
-# define CURL_FORMAT_CURL_OFF_T "ld"
-# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SUFFIX_CURL_OFF_T L
-# define CURL_SUFFIX_CURL_OFF_TU UL
-# endif
-# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-# define CURL_PULL_SYS_TYPES_H 1
-# define CURL_PULL_SYS_SOCKET_H 1
-# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__370__)
# if defined(__IBMC__) || defined(__IBMCPP__)
diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h
index d7c7a9a..b880f3d 100644
--- a/include/curl/typecheck-gcc.h
+++ b/include/curl/typecheck-gcc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,107 +42,111 @@
*/
#define curl_easy_setopt(handle, option, value) \
__extension__({ \
- __typeof__(option) _curl_opt = option; \
+ CURLoption _curl_opt = (option); \
if(__builtin_constant_p(_curl_opt)) { \
- if(curlcheck_long_option(_curl_opt)) \
- if(!curlcheck_long(value)) \
- _curl_easy_setopt_err_long(); \
- if(curlcheck_off_t_option(_curl_opt)) \
- if(!curlcheck_off_t(value)) \
- _curl_easy_setopt_err_curl_off_t(); \
- if(curlcheck_string_option(_curl_opt)) \
- if(!curlcheck_string(value)) \
- _curl_easy_setopt_err_string(); \
- if(curlcheck_write_cb_option(_curl_opt)) \
- if(!curlcheck_write_cb(value)) \
- _curl_easy_setopt_err_write_callback(); \
- if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
- if(!curlcheck_resolver_start_callback(value)) \
- _curl_easy_setopt_err_resolver_start_callback(); \
- if((_curl_opt) == CURLOPT_READFUNCTION) \
- if(!curlcheck_read_cb(value)) \
- _curl_easy_setopt_err_read_cb(); \
- if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
- if(!curlcheck_ioctl_cb(value)) \
- _curl_easy_setopt_err_ioctl_cb(); \
- if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
- if(!curlcheck_sockopt_cb(value)) \
- _curl_easy_setopt_err_sockopt_cb(); \
- if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
- if(!curlcheck_opensocket_cb(value)) \
- _curl_easy_setopt_err_opensocket_cb(); \
- if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
- if(!curlcheck_progress_cb(value)) \
- _curl_easy_setopt_err_progress_cb(); \
- if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
- if(!curlcheck_debug_cb(value)) \
- _curl_easy_setopt_err_debug_cb(); \
- if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
- if(!curlcheck_ssl_ctx_cb(value)) \
- _curl_easy_setopt_err_ssl_ctx_cb(); \
- if(curlcheck_conv_cb_option(_curl_opt)) \
- if(!curlcheck_conv_cb(value)) \
- _curl_easy_setopt_err_conv_cb(); \
- if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
- if(!curlcheck_seek_cb(value)) \
- _curl_easy_setopt_err_seek_cb(); \
- if(curlcheck_cb_data_option(_curl_opt)) \
- if(!curlcheck_cb_data(value)) \
- _curl_easy_setopt_err_cb_data(); \
- if((_curl_opt) == CURLOPT_ERRORBUFFER) \
- if(!curlcheck_error_buffer(value)) \
- _curl_easy_setopt_err_error_buffer(); \
- if((_curl_opt) == CURLOPT_STDERR) \
- if(!curlcheck_FILE(value)) \
- _curl_easy_setopt_err_FILE(); \
- if(curlcheck_postfields_option(_curl_opt)) \
- if(!curlcheck_postfields(value)) \
- _curl_easy_setopt_err_postfields(); \
- if((_curl_opt) == CURLOPT_HTTPPOST) \
- if(!curlcheck_arr((value), struct curl_httppost)) \
- _curl_easy_setopt_err_curl_httpost(); \
- if((_curl_opt) == CURLOPT_MIMEPOST) \
- if(!curlcheck_ptr((value), curl_mime)) \
- _curl_easy_setopt_err_curl_mimepost(); \
- if(curlcheck_slist_option(_curl_opt)) \
- if(!curlcheck_arr((value), struct curl_slist)) \
- _curl_easy_setopt_err_curl_slist(); \
- if((_curl_opt) == CURLOPT_SHARE) \
- if(!curlcheck_ptr((value), CURLSH)) \
- _curl_easy_setopt_err_CURLSH(); \
+ CURL_IGNORE_DEPRECATION( \
+ if(curlcheck_long_option(_curl_opt)) \
+ if(!curlcheck_long(value)) \
+ _curl_easy_setopt_err_long(); \
+ if(curlcheck_off_t_option(_curl_opt)) \
+ if(!curlcheck_off_t(value)) \
+ _curl_easy_setopt_err_curl_off_t(); \
+ if(curlcheck_string_option(_curl_opt)) \
+ if(!curlcheck_string(value)) \
+ _curl_easy_setopt_err_string(); \
+ if(curlcheck_write_cb_option(_curl_opt)) \
+ if(!curlcheck_write_cb(value)) \
+ _curl_easy_setopt_err_write_callback(); \
+ if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
+ if(!curlcheck_resolver_start_callback(value)) \
+ _curl_easy_setopt_err_resolver_start_callback(); \
+ if((_curl_opt) == CURLOPT_READFUNCTION) \
+ if(!curlcheck_read_cb(value)) \
+ _curl_easy_setopt_err_read_cb(); \
+ if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
+ if(!curlcheck_ioctl_cb(value)) \
+ _curl_easy_setopt_err_ioctl_cb(); \
+ if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
+ if(!curlcheck_sockopt_cb(value)) \
+ _curl_easy_setopt_err_sockopt_cb(); \
+ if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
+ if(!curlcheck_opensocket_cb(value)) \
+ _curl_easy_setopt_err_opensocket_cb(); \
+ if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
+ if(!curlcheck_progress_cb(value)) \
+ _curl_easy_setopt_err_progress_cb(); \
+ if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
+ if(!curlcheck_debug_cb(value)) \
+ _curl_easy_setopt_err_debug_cb(); \
+ if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
+ if(!curlcheck_ssl_ctx_cb(value)) \
+ _curl_easy_setopt_err_ssl_ctx_cb(); \
+ if(curlcheck_conv_cb_option(_curl_opt)) \
+ if(!curlcheck_conv_cb(value)) \
+ _curl_easy_setopt_err_conv_cb(); \
+ if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
+ if(!curlcheck_seek_cb(value)) \
+ _curl_easy_setopt_err_seek_cb(); \
+ if(curlcheck_cb_data_option(_curl_opt)) \
+ if(!curlcheck_cb_data(value)) \
+ _curl_easy_setopt_err_cb_data(); \
+ if((_curl_opt) == CURLOPT_ERRORBUFFER) \
+ if(!curlcheck_error_buffer(value)) \
+ _curl_easy_setopt_err_error_buffer(); \
+ if((_curl_opt) == CURLOPT_STDERR) \
+ if(!curlcheck_FILE(value)) \
+ _curl_easy_setopt_err_FILE(); \
+ if(curlcheck_postfields_option(_curl_opt)) \
+ if(!curlcheck_postfields(value)) \
+ _curl_easy_setopt_err_postfields(); \
+ if((_curl_opt) == CURLOPT_HTTPPOST) \
+ if(!curlcheck_arr((value), struct curl_httppost)) \
+ _curl_easy_setopt_err_curl_httpost(); \
+ if((_curl_opt) == CURLOPT_MIMEPOST) \
+ if(!curlcheck_ptr((value), curl_mime)) \
+ _curl_easy_setopt_err_curl_mimepost(); \
+ if(curlcheck_slist_option(_curl_opt)) \
+ if(!curlcheck_arr((value), struct curl_slist)) \
+ _curl_easy_setopt_err_curl_slist(); \
+ if((_curl_opt) == CURLOPT_SHARE) \
+ if(!curlcheck_ptr((value), CURLSH)) \
+ _curl_easy_setopt_err_CURLSH(); \
+ ) \
} \
curl_easy_setopt(handle, _curl_opt, value); \
})
/* wraps curl_easy_getinfo() with typechecking */
#define curl_easy_getinfo(handle, info, arg) \
- __extension__({ \
- __typeof__(info) _curl_info = info; \
+ __extension__({ \
+ CURLINFO _curl_info = (info); \
if(__builtin_constant_p(_curl_info)) { \
- if(curlcheck_string_info(_curl_info)) \
- if(!curlcheck_arr((arg), char *)) \
- _curl_easy_getinfo_err_string(); \
- if(curlcheck_long_info(_curl_info)) \
- if(!curlcheck_arr((arg), long)) \
- _curl_easy_getinfo_err_long(); \
- if(curlcheck_double_info(_curl_info)) \
- if(!curlcheck_arr((arg), double)) \
- _curl_easy_getinfo_err_double(); \
- if(curlcheck_slist_info(_curl_info)) \
- if(!curlcheck_arr((arg), struct curl_slist *)) \
- _curl_easy_getinfo_err_curl_slist(); \
- if(curlcheck_tlssessioninfo_info(_curl_info)) \
- if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
- _curl_easy_getinfo_err_curl_tlssesssioninfo(); \
- if(curlcheck_certinfo_info(_curl_info)) \
- if(!curlcheck_arr((arg), struct curl_certinfo *)) \
- _curl_easy_getinfo_err_curl_certinfo(); \
- if(curlcheck_socket_info(_curl_info)) \
- if(!curlcheck_arr((arg), curl_socket_t)) \
- _curl_easy_getinfo_err_curl_socket(); \
- if(curlcheck_off_t_info(_curl_info)) \
- if(!curlcheck_arr((arg), curl_off_t)) \
- _curl_easy_getinfo_err_curl_off_t(); \
+ CURL_IGNORE_DEPRECATION( \
+ if(curlcheck_string_info(_curl_info)) \
+ if(!curlcheck_arr((arg), char *)) \
+ _curl_easy_getinfo_err_string(); \
+ if(curlcheck_long_info(_curl_info)) \
+ if(!curlcheck_arr((arg), long)) \
+ _curl_easy_getinfo_err_long(); \
+ if(curlcheck_double_info(_curl_info)) \
+ if(!curlcheck_arr((arg), double)) \
+ _curl_easy_getinfo_err_double(); \
+ if(curlcheck_slist_info(_curl_info)) \
+ if(!curlcheck_arr((arg), struct curl_slist *)) \
+ _curl_easy_getinfo_err_curl_slist(); \
+ if(curlcheck_tlssessioninfo_info(_curl_info)) \
+ if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
+ _curl_easy_getinfo_err_curl_tlssesssioninfo(); \
+ if(curlcheck_certinfo_info(_curl_info)) \
+ if(!curlcheck_arr((arg), struct curl_certinfo *)) \
+ _curl_easy_getinfo_err_curl_certinfo(); \
+ if(curlcheck_socket_info(_curl_info)) \
+ if(!curlcheck_arr((arg), curl_socket_t)) \
+ _curl_easy_getinfo_err_curl_socket(); \
+ if(curlcheck_off_t_info(_curl_info)) \
+ if(!curlcheck_arr((arg), curl_off_t)) \
+ _curl_easy_getinfo_err_curl_off_t(); \
+ ) \
} \
curl_easy_getinfo(handle, _curl_info, arg); \
})
@@ -272,10 +276,11 @@
(option) == CURLOPT_DNS_SERVERS || \
(option) == CURLOPT_DOH_URL || \
(option) == CURLOPT_EGDSOCKET || \
- (option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ACCOUNT || \
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
+ (option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_HSTS || \
+ (option) == CURLOPT_HAPROXY_CLIENT_IP || \
(option) == CURLOPT_INTERFACE || \
(option) == CURLOPT_ISSUERCERT || \
(option) == CURLOPT_KEYPASSWD || \
@@ -288,10 +293,8 @@
(option) == CURLOPT_PASSWORD || \
(option) == CURLOPT_PINNEDPUBLICKEY || \
(option) == CURLOPT_PRE_PROXY || \
+ (option) == CURLOPT_PROTOCOLS_STR || \
(option) == CURLOPT_PROXY || \
- (option) == CURLOPT_PROXYPASSWORD || \
- (option) == CURLOPT_PROXYUSERNAME || \
- (option) == CURLOPT_PROXYUSERPWD || \
(option) == CURLOPT_PROXY_CAINFO || \
(option) == CURLOPT_PROXY_CAPATH || \
(option) == CURLOPT_PROXY_CRLFILE || \
@@ -299,17 +302,21 @@
(option) == CURLOPT_PROXY_KEYPASSWD || \
(option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
(option) == CURLOPT_PROXY_SERVICE_NAME || \
+ (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
(option) == CURLOPT_PROXY_SSLCERT || \
(option) == CURLOPT_PROXY_SSLCERTTYPE || \
(option) == CURLOPT_PROXY_SSLKEY || \
(option) == CURLOPT_PROXY_SSLKEYTYPE || \
- (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
(option) == CURLOPT_PROXY_TLS13_CIPHERS || \
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
+ (option) == CURLOPT_PROXYPASSWORD || \
+ (option) == CURLOPT_PROXYUSERNAME || \
+ (option) == CURLOPT_PROXYUSERPWD || \
(option) == CURLOPT_RANDOM_FILE || \
(option) == CURLOPT_RANGE || \
+ (option) == CURLOPT_REDIR_PROTOCOLS_STR || \
(option) == CURLOPT_REFERER || \
(option) == CURLOPT_REQUEST_TARGET || \
(option) == CURLOPT_RTSP_SESSION_ID || \
@@ -434,7 +441,7 @@
(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
diff --git a/include/curl/urlapi.h b/include/curl/urlapi.h
index e15c213..b3504b6 100644
--- a/include/curl/urlapi.h
+++ b/include/curl/urlapi.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -62,6 +62,7 @@
CURLUE_BAD_SCHEME, /* 27 */
CURLUE_BAD_SLASHES, /* 28 */
CURLUE_BAD_USER, /* 29 */
+ CURLUE_LACKS_IDN, /* 30 */
CURLUE_LAST
} CURLUcode;
@@ -95,6 +96,7 @@
#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the
scheme is unknown. */
#define CURLU_ALLOW_SPACE (1<<11) /* Allow spaces in the URL */
+#define CURLU_PUNYCODE (1<<12) /* get the host name in pynycode */
typedef struct Curl_URL CURLU;
@@ -115,14 +117,14 @@
* curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
* handle must also be freed with curl_url_cleanup().
*/
-CURL_EXTERN CURLU *curl_url_dup(CURLU *in);
+CURL_EXTERN CURLU *curl_url_dup(const CURLU *in);
/*
* curl_url_get() extracts a specific part of the URL from a CURLU
* handle. Returns error code. The returned pointer MUST be freed with
* curl_free() afterwards.
*/
-CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what,
+CURL_EXTERN CURLUcode curl_url_get(const CURLU *handle, CURLUPart what,
char **part, unsigned int flags);
/*
diff --git a/include/curl/websockets.h b/include/curl/websockets.h
new file mode 100644
index 0000000..6ef6a2b
--- /dev/null
+++ b/include/curl/websockets.h
@@ -0,0 +1,84 @@
+#ifndef CURLINC_WEBSOCKETS_H
+#define CURLINC_WEBSOCKETS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct curl_ws_frame {
+ int age; /* zero */
+ int flags; /* See the CURLWS_* defines */
+ curl_off_t offset; /* the offset of this data into the frame */
+ curl_off_t bytesleft; /* number of pending bytes left of the payload */
+ size_t len; /* size of the current data chunk */
+};
+
+/* flag bits */
+#define CURLWS_TEXT (1<<0)
+#define CURLWS_BINARY (1<<1)
+#define CURLWS_CONT (1<<2)
+#define CURLWS_CLOSE (1<<3)
+#define CURLWS_PING (1<<4)
+#define CURLWS_OFFSET (1<<5)
+
+/*
+ * NAME curl_ws_recv()
+ *
+ * DESCRIPTION
+ *
+ * Receives data from the websocket connection. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
+ size_t *recv,
+ const struct curl_ws_frame **metap);
+
+/* flags for curl_ws_send() */
+#define CURLWS_PONG (1<<6)
+
+/*
+ * NAME curl_ws_send()
+ *
+ * DESCRIPTION
+ *
+ * Sends data over the websocket connection. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_ws_send(CURL *curl, const void *buffer,
+ size_t buflen, size_t *sent,
+ curl_off_t fragsize,
+ unsigned int flags);
+
+/* bits for the CURLOPT_WS_OPTIONS bitmask: */
+#define CURLWS_RAW_MODE (1<<0)
+
+CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(CURL *curl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CURLINC_WEBSOCKETS_H */
diff --git a/lib/.gitattributes b/lib/.gitattributes
index 3131209..7e1eea5 100644
--- a/lib/.gitattributes
+++ b/lib/.gitattributes
@@ -1,3 +1,3 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/lib/.gitignore b/lib/.gitignore
index ef15643..7528196 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index f998751..712d7c7 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,6 +23,7 @@
###########################################################################
set(LIB_NAME libcurl)
set(LIBCURL_OUTPUT_NAME libcurl CACHE STRING "Basename of the curl library")
+add_definitions(-DBUILDING_LIBCURL)
if(BUILD_SHARED_LIBS)
set(CURL_STATICLIB NO)
@@ -46,29 +47,6 @@
list(APPEND CSOURCES libcurl.rc)
endif()
-# SET(CSOURCES
-# # memdebug.c -not used
-# # nwlib.c - Not used
-# # strtok.c - specify later
-# # strtoofft.c - specify later
-# )
-
-# #OPTION(CURL_MALLOC_DEBUG "Debug mallocs in Curl" OFF)
-# MARK_AS_ADVANCED(CURL_MALLOC_DEBUG)
-# IF(CURL_MALLOC_DEBUG)
-# SET(CSOURCES ${CSOURCES}
-# memdebug.c
-# )
-# ENDIF(CURL_MALLOC_DEBUG)
-
-# # only build compat strtoofft if we need to
-# IF(NOT HAVE_STRTOLL AND NOT HAVE__STRTOI64)
-# SET(CSOURCES ${CSOURCES}
-# strtoofft.c
-# )
-# ENDIF(NOT HAVE_STRTOLL AND NOT HAVE__STRTOI64)
-
-
# The rest of the build
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include)
@@ -87,21 +65,64 @@
)
add_library(
+ curlu # special libcurlu library just for unittests
+ STATIC
+ EXCLUDE_FROM_ALL
+ ${HHEADERS} ${CSOURCES}
+)
+target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
+
+add_library(
${PROJECT_NAME}::${LIB_NAME}
ALIAS ${LIB_NAME}
)
+if(ENABLE_CURLDEBUG)
+ # We must compile memdebug.c separately to avoid memdebug.h redefinitions
+ # being applied to memdebug.c itself.
+ set_source_files_properties(memdebug.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
+endif()
+
if(NOT BUILD_SHARED_LIBS)
set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB)
endif()
-target_link_libraries(${LIB_NAME} ${CURL_LIBS})
+target_link_libraries(${LIB_NAME} PRIVATE ${CURL_LIBS})
+target_link_libraries(curlu PRIVATE ${CURL_LIBS})
+
+transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
+include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake)
set_target_properties(${LIB_NAME} PROPERTIES
COMPILE_DEFINITIONS BUILDING_LIBCURL
OUTPUT_NAME ${LIBCURL_OUTPUT_NAME}
)
+if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
+ CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
+ CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
+ CMAKE_SYSTEM_NAME STREQUAL "SunOS" OR
+ CMAKE_SYSTEM_NAME STREQUAL "GNU/kFreeBSD" OR
+
+ # FreeBSD comes with the a.out and elf flavours
+ # but a.out was supported up to version 3.x and
+ # elf from 3.x. I cannot imagine someone running
+ # CMake on those ancient systems
+ CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
+
+ CMAKE_SYSTEM_NAME STREQUAL "Haiku")
+
+ math(EXPR CMAKESONAME "${VERSIONCHANGE} - ${VERSIONDEL}")
+ set(CMAKEVERSION "${CMAKESONAME}.${VERSIONDEL}.${VERSIONADD}")
+
+ set_target_properties(${LIB_NAME} PROPERTIES
+ VERSION ${CMAKEVERSION}
+ SOVERSION ${CMAKESONAME}
+ )
+
+endif()
+
+
if(HIDES_CURL_PRIVATE_SYMBOLS)
set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE})
@@ -119,27 +140,39 @@
if(WIN32)
if(BUILD_SHARED_LIBS)
- set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "_USRDLL")
if(MSVC)
# Add "_imp" as a suffix before the extension to avoid conflicting with
# the statically linked "libcurl.lib"
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
endif()
endif()
+elseif(NOT CMAKE_CROSSCOMPILING)
+ # on not-Windows and not-crosscompiling, check for writable argv[]
+ include(CheckCSourceRuns)
+ check_c_source_runs("
+int main(int argc, char **argv)
+{
+ (void)argc;
+ argv[0][0] = ' ';
+ return (argv[0][0] == ' ')?0:1;
+}"
+ HAVE_WRITABLE_ARGV)
endif()
target_include_directories(${LIB_NAME} INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
-install(TARGETS ${LIB_NAME}
- EXPORT ${TARGETS_EXPORT_NAME}
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-)
+if(CURL_ENABLE_EXPORT_TARGET)
+ install(TARGETS ${LIB_NAME}
+ EXPORT ${TARGETS_EXPORT_NAME}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ )
-export(TARGETS ${LIB_NAME}
- APPEND FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
- NAMESPACE ${PROJECT_NAME}::
-)
+ export(TARGETS ${LIB_NAME}
+ FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
+ NAMESPACE ${PROJECT_NAME}::
+ )
+endif()
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 18ce47e..3c0a709 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -25,10 +25,11 @@
CMAKE_DIST = CMakeLists.txt curl_config.h.cmake
-EXTRA_DIST = Makefile.m32 config-win32.h config-win32ce.h config-plan9.h \
- config-riscos.h config-mac.h curl_config.h.in makefile.dj config-dos.h \
- libcurl.plist libcurl.rc config-amigaos.h makefile.amiga config-win32ce.h \
- config-os400.h setup-os400.h $(CMAKE_DIST) setup-win32.h .checksrc
+EXTRA_DIST = Makefile.mk config-win32.h config-win32ce.h config-plan9.h \
+ config-riscos.h config-mac.h curl_config.h.in config-dos.h \
+ libcurl.plist libcurl.rc config-amigaos.h config-win32ce.h \
+ config-os400.h setup-os400.h $(CMAKE_DIST) setup-win32.h .checksrc \
+ Makefile.soname
lib_LTLIBRARIES = libcurl.la
@@ -57,24 +58,18 @@
# Prevent LIBS from being used for all link targets
LIBS = $(BLANK_AT_MAKETIME)
-VERSIONINFO=-version-info 12:0:8
-# This flag accepts an argument of the form current[:revision[:age]]. So,
-# passing -version-info 3:12:1 sets current to 3, revision to 12, and age to
-# 1.
-#
-# Here's the simplified rule guide on how to change -version-info:
-# (current version is C:R:A)
-#
-# 1. if there are only source changes, use C:R+1:A
-# 2. if interfaces were added use C+1:0:A+1
-# 3. if interfaces were removed, then use C+1:0:0
-#
-# For the full guide on libcurl ABI rules, see docs/libcurl/ABI
+include Makefile.soname
AM_CPPFLAGS += -DBUILDING_LIBCURL
AM_LDFLAGS =
AM_CFLAGS =
+# Makefile.inc provides the CSOURCES and HHEADERS defines
+include Makefile.inc
+
+libcurl_la_SOURCES = $(CSOURCES) $(HHEADERS)
+libcurlu_la_SOURCES = $(CSOURCES) $(HHEADERS)
+
libcurl_la_CPPFLAGS_EXTRA =
libcurl_la_LDFLAGS_EXTRA =
libcurl_la_CFLAGS_EXTRA =
@@ -102,6 +97,11 @@
if USE_CPPFLAG_CURL_STATICLIB
libcurl_la_CPPFLAGS_EXTRA += -DCURL_STATICLIB
+else
+if HAVE_WINDRES
+libcurl_la_SOURCES += $(LIB_RCFILES)
+$(LIB_RCFILES): $(top_srcdir)/include/curl/curlver.h
+endif
endif
if DOING_CURL_SYMBOL_HIDING
@@ -117,12 +117,6 @@
libcurlu_la_LDFLAGS = $(AM_LDFLAGS) -static $(LIBCURL_LIBS)
libcurlu_la_CFLAGS = $(AM_CFLAGS)
-# Makefile.inc provides the CSOURCES and HHEADERS defines
-include Makefile.inc
-
-libcurl_la_SOURCES = $(CSOURCES) $(HHEADERS)
-libcurlu_la_SOURCES = $(CSOURCES) $(HHEADERS)
-
CHECKSRC = $(CS_$(V))
CS_0 = @echo " RUN " $@;
CS_1 =
@@ -148,3 +142,8 @@
optiontable:
perl optiontable.pl < $(top_srcdir)/include/curl/curl.h > easyoptions.c
+
+if HAVE_WINDRES
+.rc.lo:
+ $(LIBTOOL) --tag=RC --mode=compile $(RC) -I$(top_srcdir)/include $(RCFLAGS) -i $< -o $@
+endif
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 9bd8e32..cc7d287 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -72,22 +72,25 @@
vtls/openssl.h \
vtls/rustls.h \
vtls/schannel.h \
+ vtls/schannel_int.h \
vtls/sectransp.h \
vtls/vtls.h \
+ vtls/vtls_int.h \
vtls/wolfssl.h \
vtls/x509asn1.h
LIB_VQUIC_CFILES = \
- vquic/msh3.c \
- vquic/ngtcp2.c \
- vquic/quiche.c \
+ vquic/curl_msh3.c \
+ vquic/curl_ngtcp2.c \
+ vquic/curl_quiche.c \
vquic/vquic.c
LIB_VQUIC_HFILES = \
- vquic/msh3.h \
- vquic/ngtcp2.h \
- vquic/quiche.h \
- vquic/vquic.h
+ vquic/curl_msh3.h \
+ vquic/curl_ngtcp2.h \
+ vquic/curl_quiche.h \
+ vquic/vquic.h \
+ vquic/vquic_int.h
LIB_VSSH_CFILES = \
vssh/libssh.c \
@@ -103,20 +106,27 @@
asyn-ares.c \
asyn-thread.c \
base64.c \
+ bufq.c \
bufref.c \
c-hyper.c \
+ cf-h1-proxy.c \
+ cf-h2-proxy.c \
+ cf-haproxy.c \
+ cf-https-connect.c \
+ cf-socket.c \
+ cfilters.c \
conncache.c \
connect.c \
content_encoding.c \
cookie.c \
curl_addrinfo.c \
- curl_ctype.c \
curl_des.c \
curl_endian.c \
curl_fnmatch.c \
curl_get_line.c \
curl_gethostname.c \
curl_gssapi.c \
+ curl_log.c \
curl_memrchr.c \
curl_multibyte.c \
curl_ntlm_core.c \
@@ -129,8 +139,8 @@
curl_threads.c \
dict.c \
doh.c \
- dotdot.c \
dynbuf.c \
+ dynhds.c \
easy.c \
easygetopt.c \
easyoptions.c \
@@ -144,7 +154,6 @@
getenv.c \
getinfo.c \
gopher.c \
- h2h3.c \
hash.c \
headers.c \
hmac.c \
@@ -155,6 +164,7 @@
hostsyn.c \
hsts.c \
http.c \
+ http1.c \
http2.c \
http_chunks.c \
http_digest.c \
@@ -162,7 +172,7 @@
http_ntlm.c \
http_proxy.c \
http_aws_sigv4.c \
- idn_win32.c \
+ idn.c \
if2ip.c \
imap.c \
inet_ntop.c \
@@ -170,6 +180,7 @@
krb5.c \
ldap.c \
llist.c \
+ macos.c \
md4.c \
md5.c \
memdebug.c \
@@ -179,6 +190,7 @@
multi.c \
netrc.c \
nonblock.c \
+ noproxy.c \
openldap.c \
parsedate.c \
pingpong.c \
@@ -218,15 +230,22 @@
version.c \
version_win32.c \
warnless.c \
- wildcard.c
+ ws.c
LIB_HFILES = \
altsvc.h \
amigaos.h \
arpa_telnet.h \
asyn.h \
+ bufq.h \
bufref.h \
c-hyper.h \
+ cf-h1-proxy.h \
+ cf-h2-proxy.h \
+ cf-haproxy.h \
+ cf-https-connect.h \
+ cf-socket.h \
+ cfilters.h \
conncache.h \
connect.h \
content_encoding.h \
@@ -243,6 +262,7 @@
curl_hmac.h \
curl_krb5.h \
curl_ldap.h \
+ curl_log.h \
curl_md4.h \
curl_md5.h \
curl_memory.h \
@@ -263,8 +283,8 @@
curlx.h \
dict.h \
doh.h \
- dotdot.h \
dynbuf.h \
+ dynhds.h \
easy_lock.h \
easyif.h \
easyoptions.h \
@@ -273,16 +293,17 @@
fileinfo.h \
fopen.h \
formdata.h \
+ functypes.h \
ftp.h \
ftplistparser.h \
getinfo.h \
gopher.h \
- h2h3.h \
hash.h \
headers.h \
hostip.h \
hsts.h \
http.h \
+ http1.h \
http2.h \
http_chunks.h \
http_digest.h \
@@ -290,11 +311,13 @@
http_ntlm.h \
http_proxy.h \
http_aws_sigv4.h \
+ idn.h \
if2ip.h \
imap.h \
inet_ntop.h \
inet_pton.h \
llist.h \
+ macos.h \
memdebug.h \
mime.h \
mqtt.h \
@@ -302,12 +325,12 @@
multiif.h \
netrc.h \
nonblock.h \
+ noproxy.h \
parsedate.h \
pingpong.h \
pop3.h \
progress.h \
psl.h \
- quic.h \
rand.h \
rename.h \
rtsp.h \
@@ -341,7 +364,7 @@
urldata.h \
version_win32.h \
warnless.h \
- wildcard.h
+ ws.h
LIB_RCFILES = libcurl.rc
diff --git a/lib/Makefile.m32 b/lib/Makefile.m32
deleted file mode 100644
index 1987b23..0000000
--- a/lib/Makefile.m32
+++ /dev/null
@@ -1,451 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1999 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-#***************************************************************************
-
-###########################################################################
-#
-## Makefile for building libcurl.a with MingW (GCC-3.2 or later or LLVM/Clang)
-## and optionally OpenSSL (1.0.2a), libssh2 (1.5), zlib (1.2.8), librtmp (2.4),
-## brotli (1.0.1), zstd (1.4.5)
-##
-## Usage: mingw32-make -f Makefile.m32 CFG=-feature1[-feature2][-feature3][...]
-## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-sspi-winidn
-##
-## Hint: you can also set environment vars to control the build, f.e.:
-## set ZLIB_PATH=c:/zlib-1.2.8
-## set ZLIB=1
-#
-###########################################################################
-
-# Edit the path below to point to the base of your Zlib sources.
-ifndef ZLIB_PATH
-ZLIB_PATH = ../../zlib-1.2.8
-endif
-# Edit the path below to point to the base of your Zstandard sources.
-ifndef ZSTD_PATH
-ZSTD_PATH = ../../zstd-1.4.5
-endif
-# Edit the path below to point to the base of your Brotli sources.
-ifndef BROTLI_PATH
-BROTLI_PATH = ../../brotli-1.0.1
-endif
-# Edit the path below to point to the base of your OpenSSL package.
-ifndef OPENSSL_PATH
-OPENSSL_PATH = ../../openssl-1.0.2a
-endif
-# Edit the path below to point to the base of your LibSSH2 package.
-ifndef LIBSSH2_PATH
-LIBSSH2_PATH = ../../libssh2-1.5.0
-endif
-# Edit the path below to point to the base of your librtmp package.
-ifndef LIBRTMP_PATH
-LIBRTMP_PATH = ../../librtmp-2.4
-endif
-# Edit the path below to point to the base of your libgsasl package.
-ifndef LIBGSASL_PATH
-LIBGSASL_PATH = ../../libgsasl-1.10.0
-endif
-# Edit the path below to point to the base of your libidn2 package.
-ifndef LIBIDN2_PATH
-LIBIDN2_PATH = ../../libidn2-2.0.3
-endif
-# Edit the path below to point to the base of your MS IDN package.
-# Microsoft Internationalized Domain Names (IDN) Mitigation APIs 1.1
-# https://www.microsoft.com/en-us/download/details.aspx?id=734
-ifndef WINIDN_PATH
-WINIDN_PATH = ../../Microsoft IDN Mitigation APIs
-endif
-# Edit the path below to point to the base of your Novell LDAP NDK.
-ifndef LDAP_SDK
-LDAP_SDK = c:/novell/ndk/cldapsdk/win32
-endif
-# Edit the path below to point to the base of your nghttp2 package.
-ifndef NGHTTP2_PATH
-NGHTTP2_PATH = ../../nghttp2-1.0.0
-endif
-# Edit the path below to point to the base of your nghttp3 package.
-ifndef NGHTTP3_PATH
-NGHTTP3_PATH = ../../nghttp3-1.0.0
-endif
-# Edit the path below to point to the base of your ngtcp2 package.
-ifndef NGTCP2_PATH
-NGTCP2_PATH = ../../ngtcp2-1.0.0
-endif
-
-PROOT = ..
-
-# Edit the path below to point to the base of your c-ares package.
-ifndef LIBCARES_PATH
-LIBCARES_PATH = $(PROOT)/ares
-endif
-
-ifeq ($(CURL_CC),)
-CURL_CC := $(CROSSPREFIX)gcc
-endif
-ifeq ($(CURL_AR),)
-CURL_AR := $(CROSSPREFIX)ar
-endif
-ifeq ($(CURL_RANLIB),)
-CURL_RANLIB := $(CROSSPREFIX)ranlib
-endif
-
-CC = $(CURL_CC)
-CFLAGS = -O3 $(CURL_CFLAG_EXTRAS) -W -Wall
-LDFLAGS = $(CURL_LDFLAG_EXTRAS) $(CURL_LDFLAG_EXTRAS_DLL)
-AR = $(CURL_AR)
-RANLIB = $(CURL_RANLIB)
-RC = $(CROSSPREFIX)windres
-RCFLAGS = --include-dir=$(PROOT)/include -DDEBUGBUILD=0 -O coff
-STRIP = $(CROSSPREFIX)strip -g
-
-# Set environment var ARCH to your architecture to override autodetection.
-ifndef ARCH
-ifeq ($(findstring x86_64,$(shell $(CC) -dumpmachine)),x86_64)
-ARCH = w64
-else
-ARCH = w32
-endif
-endif
-
-ifeq ($(ARCH),w64)
-CFLAGS += -m64
-LDFLAGS += -m64
-RCFLAGS += -F pe-x86-64
-else
-CFLAGS += -m32
-LDFLAGS += -m32
-RCFLAGS += -F pe-i386
-endif
-
-# Platform-dependent helper tool macros
-ifeq ($(findstring /sh,$(SHELL)),/sh)
-DEL = rm -f $1
-RMDIR = rm -fr $1
-MKDIR = mkdir -p $1
-COPY = -cp -afv $1 $2
-#COPYR = -cp -afr $1/* $2
-COPYR = -rsync -aC $1/* $2
-TOUCH = touch $1
-CAT = cat
-ECHONL = echo ""
-DL = '
-else
-ifeq "$(OS)" "Windows_NT"
-DEL = -del 2>NUL /q /f $(subst /,\,$1)
-RMDIR = -rd 2>NUL /q /s $(subst /,\,$1)
-else
-DEL = -del 2>NUL $(subst /,\,$1)
-RMDIR = -deltree 2>NUL /y $(subst /,\,$1)
-endif
-MKDIR = -md 2>NUL $(subst /,\,$1)
-COPY = -copy 2>NUL /y $(subst /,\,$1) $(subst /,\,$2)
-COPYR = -xcopy 2>NUL /q /y /e $(subst /,\,$1) $(subst /,\,$2)
-TOUCH = copy 2>&1>NUL /b $(subst /,\,$1) +,,
-CAT = type
-ECHONL = $(ComSpec) /c echo.
-endif
-
-########################################################
-## Nothing more to do below this line!
-
-ifneq ($(findstring -dyn,$(CFG)),)
-DYN = 1
-endif
-ifneq ($(findstring -ares,$(CFG)),)
-ARES = 1
-endif
-ifneq ($(findstring -sync,$(CFG)),)
-SYNC = 1
-endif
-ifneq ($(findstring -rtmp,$(CFG)),)
-RTMP = 1
-ZLIB = 1
-endif
-ifneq ($(findstring -ssh2,$(CFG)),)
-SSH2 = 1
-ZLIB = 1
-endif
-ifneq ($(findstring -ssl,$(CFG)),)
-SSL = 1
-endif
-ifneq ($(findstring -srp,$(CFG)),)
-SRP = 1
-endif
-ifneq ($(findstring -zlib,$(CFG)),)
-ZLIB = 1
-endif
-ifneq ($(findstring -zstd,$(CFG)),)
-ZSTD = 1
-endif
-ifneq ($(findstring -brotli,$(CFG)),)
-BROTLI = 1
-endif
-ifneq ($(findstring -gsasl,$(CFG)),)
-GSASL = 1
-endif
-ifneq ($(findstring -idn2,$(CFG)),)
-IDN2 = 1
-endif
-ifneq ($(findstring -winidn,$(CFG)),)
-WINIDN = 1
-endif
-ifneq ($(findstring -sspi,$(CFG)),)
-SSPI = 1
-endif
-ifneq ($(findstring -ldaps,$(CFG)),)
-LDAPS = 1
-endif
-ifneq ($(findstring -ipv6,$(CFG)),)
-IPV6 = 1
-endif
-ifneq ($(findstring -schannel,$(CFG))$(findstring -winssl,$(CFG)),)
-SCHANNEL = 1
-SSPI = 1
-endif
-ifneq ($(findstring -nghttp2,$(CFG)),)
-NGHTTP2 = 1
-endif
-ifneq ($(findstring -nghttp3,$(CFG)),)
-NGHTTP3 = 1
-endif
-ifneq ($(findstring -ngtcp2,$(CFG)),)
-NGTCP2 = 1
-endif
-ifneq ($(findstring -unicode,$(CFG)),)
-UNICODE = 1
-endif
-
-# SSH2 and RTMP require an SSL library; assume OpenSSL if none specified
-ifneq ($(SSH2)$(RTMP),)
- ifeq ($(SSL)$(SCHANNEL),)
- SSL = 1
- endif
-endif
-
-INCLUDES = -I. -I../include
-CFLAGS += -DBUILDING_LIBCURL
-ifdef SSL
- ifdef SCHANNEL
- CFLAGS += -DCURL_WITH_MULTI_SSL
- endif
-endif
-ifdef UNICODE
- CFLAGS += -DUNICODE -D_UNICODE
-endif
-
-ifdef SYNC
- CFLAGS += -DUSE_SYNC_DNS
-else
- ifdef ARES
- INCLUDES += -I"$(LIBCARES_PATH)"
- CFLAGS += -DUSE_ARES -DCARES_STATICLIB
- DLL_LIBS += -L"$(LIBCARES_PATH)" -lcares
- libcurl_dll_DEPENDENCIES = $(LIBCARES_PATH)/libcares.a
- endif
-endif
-ifdef RTMP
- INCLUDES += -I"$(LIBRTMP_PATH)"
- CFLAGS += -DUSE_LIBRTMP
- DLL_LIBS += -L"$(LIBRTMP_PATH)/librtmp" -lrtmp -lwinmm
-endif
-ifdef NGHTTP2
- INCLUDES += -I"$(NGHTTP2_PATH)/include"
- CFLAGS += -DUSE_NGHTTP2
- DLL_LIBS += -L"$(NGHTTP2_PATH)/lib" -lnghttp2
-endif
-ifdef SSH2
- INCLUDES += -I"$(LIBSSH2_PATH)/include" -I"$(LIBSSH2_PATH)/win32"
- CFLAGS += -DUSE_LIBSSH2 -DHAVE_LIBSSH2_H
- DLL_LIBS += -L"$(LIBSSH2_PATH)/win32" -lssh2
- ifdef SCHANNEL
- ifndef DYN
- DLL_LIBS += -lbcrypt -lcrypt32
- endif
- endif
-endif
-ifdef SSL
- ifdef NGHTTP3
- INCLUDES += -I"$(NGHTTP3_PATH)/include"
- CFLAGS += -DUSE_NGHTTP3
- DLL_LIBS += -L"$(NGHTTP3_PATH)/lib" -lnghttp3
- ifdef NGTCP2
- INCLUDES += -I"$(NGTCP2_PATH)/include"
- CFLAGS += -DUSE_NGTCP2
- DLL_LIBS += -L"$(NGTCP2_PATH)/lib" -lngtcp2 -lngtcp2_crypto_openssl
- endif
- endif
-
- ifndef OPENSSL_INCLUDE
- ifeq "$(wildcard $(OPENSSL_PATH)/outinc)" "$(OPENSSL_PATH)/outinc"
- OPENSSL_INCLUDE = $(OPENSSL_PATH)/outinc
- endif
- ifeq "$(wildcard $(OPENSSL_PATH)/include)" "$(OPENSSL_PATH)/include"
- OPENSSL_INCLUDE = $(OPENSSL_PATH)/include
- endif
- endif
- ifneq "$(wildcard $(OPENSSL_INCLUDE)/openssl/opensslv.h)" "$(OPENSSL_INCLUDE)/openssl/opensslv.h"
- $(error Invalid path to OpenSSL package: $(OPENSSL_PATH))
- endif
- ifndef OPENSSL_LIBPATH
- ifeq "$(wildcard $(OPENSSL_PATH)/out)" "$(OPENSSL_PATH)/out"
- OPENSSL_LIBPATH = $(OPENSSL_PATH)/out
- OPENSSL_LIBS = -leay32 -lssl32
- endif
- ifeq "$(wildcard $(OPENSSL_PATH)/lib)" "$(OPENSSL_PATH)/lib"
- OPENSSL_LIBPATH = $(OPENSSL_PATH)/lib
- OPENSSL_LIBS = -lcrypto -lssl
- endif
- endif
- ifndef DYN
- OPENSSL_LIBS += -lgdi32 -lcrypt32
- endif
- INCLUDES += -I"$(OPENSSL_INCLUDE)"
- CFLAGS += -DUSE_OPENSSL
- DLL_LIBS += -L"$(OPENSSL_LIBPATH)" $(OPENSSL_LIBS)
- ifdef SRP
- ifeq "$(wildcard $(OPENSSL_INCLUDE)/openssl/srp.h)" "$(OPENSSL_INCLUDE)/openssl/srp.h"
- CFLAGS += -DHAVE_OPENSSL_SRP -DUSE_TLS_SRP
- endif
- endif
-endif
-ifdef SCHANNEL
- CFLAGS += -DUSE_SCHANNEL
- DLL_LIBS += -lcrypt32
-endif
-ifdef ZLIB
- INCLUDES += -I"$(ZLIB_PATH)"
- CFLAGS += -DHAVE_LIBZ -DHAVE_ZLIB_H
- DLL_LIBS += -L"$(ZLIB_PATH)" -lz
-endif
-ifdef ZSTD
- INCLUDES += -I"$(ZSTD_PATH)/include"
- CFLAGS += -DHAVE_ZSTD
- DLL_LIBS += -L"$(ZSTD_PATH)/lib"
- ifdef ZSTD_LIBS
- DLL_LIBS += $(ZSTD_LIBS)
- else
- DLL_LIBS += -lzstd
- endif
-endif
-ifdef BROTLI
- INCLUDES += -I"$(BROTLI_PATH)/include"
- CFLAGS += -DHAVE_BROTLI
- DLL_LIBS += -L"$(BROTLI_PATH)/lib"
- ifdef BROTLI_LIBS
- DLL_LIBS += $(BROTLI_LIBS)
- else
- DLL_LIBS += -lbrotlidec
- endif
-endif
-ifdef GSASL
- INCLUDES += -I"$(LIBGSASL_PATH)/include"
- CFLAGS += -DUSE_GSASL
- DLL_LIBS += -L"$(LIBGSASL_PATH)/lib" -lgsasl
-endif
-ifdef IDN2
- INCLUDES += -I"$(LIBIDN2_PATH)/include"
- CFLAGS += -DUSE_LIBIDN2
- DLL_LIBS += -L"$(LIBIDN2_PATH)/lib" -lidn2
-else
-ifdef WINIDN
- CFLAGS += -DUSE_WIN32_IDN
- CFLAGS += -DWANT_IDN_PROTOTYPES
- DLL_LIBS += -L"$(WINIDN_PATH)" -lnormaliz
-endif
-endif
-ifdef SSPI
- CFLAGS += -DUSE_WINDOWS_SSPI
-endif
-ifdef SPNEGO
- CFLAGS += -DHAVE_SPNEGO
-endif
-ifdef IPV6
- CFLAGS += -DENABLE_IPV6
-endif
-ifdef LDAPS
- CFLAGS += -DHAVE_LDAP_SSL
-endif
-ifdef USE_LDAP_NOVELL
- INCLUDES += -I"$(LDAP_SDK)/inc"
- CFLAGS += -DCURL_HAS_NOVELL_LDAPSDK
- DLL_LIBS += -L"$(LDAP_SDK)/lib/mscvc" -lldapsdk -lldapssl -lldapx
-endif
-ifdef USE_LDAP_OPENLDAP
- INCLUDES += -I"$(LDAP_SDK)/include"
- CFLAGS += -DCURL_HAS_OPENLDAP_LDAPSDK
- DLL_LIBS += -L"$(LDAP_SDK)/lib" -lldap -llber
-endif
-ifndef USE_LDAP_NOVELL
-ifndef USE_LDAP_OPENLDAP
- DLL_LIBS += -lwldap32
-endif
-endif
-DLL_LIBS += -lws2_32
-
-# Makefile.inc provides the CSOURCES and HHEADERS defines
-include Makefile.inc
-
-ifeq ($(CURL_DLL_A_SUFFIX),)
-CURL_DLL_A_SUFFIX := dll
-endif
-
-libcurl_dll_LIBRARY = libcurl$(CURL_DLL_SUFFIX).dll
-libcurl_dll_a_LIBRARY = libcurl$(CURL_DLL_A_SUFFIX).a
-libcurl_a_LIBRARY = libcurl.a
-
-libcurl_a_OBJECTS := $(patsubst %.c,%.o,$(strip $(CSOURCES)))
-libcurl_a_DEPENDENCIES := $(strip $(CSOURCES) $(HHEADERS))
-
-RESOURCE = libcurl.res
-
-
-all: $(libcurl_a_LIBRARY) $(libcurl_dll_LIBRARY)
-
-$(libcurl_a_LIBRARY): $(libcurl_a_OBJECTS) $(libcurl_a_DEPENDENCIES)
- @$(call DEL, $@)
- $(AR) cru $@ $(libcurl_a_OBJECTS)
- $(RANLIB) $@
- $(STRIP) $@
-
-# remove the last line above to keep debug info
-
-$(libcurl_dll_LIBRARY): $(libcurl_a_OBJECTS) $(RESOURCE) $(libcurl_dll_DEPENDENCIES)
- @$(call DEL, $@)
- $(CC) $(LDFLAGS) -shared -o $@ \
- -Wl,--output-def,$(@:.dll=.def),--out-implib,$(libcurl_dll_a_LIBRARY) \
- $(libcurl_a_OBJECTS) $(RESOURCE) $(DLL_LIBS)
-
-%.o: %.c
- $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@
-
-%.res: %.rc
- $(RC) $(RCFLAGS) -i $< -o $@
-
-clean:
- @$(call DEL, $(libcurl_a_OBJECTS) $(RESOURCE))
-
-distclean vclean: clean
- @$(call DEL, $(libcurl_a_LIBRARY) $(libcurl_dll_LIBRARY) $(libcurl_dll_LIBRARY:.dll=.def) $(libcurl_dll_a_LIBRARY))
-
-$(LIBCARES_PATH)/libcares.a:
- $(MAKE) -C $(LIBCARES_PATH) -f Makefile.m32
diff --git a/lib/Makefile.mk b/lib/Makefile.mk
new file mode 100644
index 0000000..b298ac0
--- /dev/null
+++ b/lib/Makefile.mk
@@ -0,0 +1,420 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+#***************************************************************************
+
+# Makefile to build curl parts with GCC-like toolchains and optional features.
+#
+# Usage: [mingw32-]make -f Makefile.mk CFG=-feat1[-feat2][-feat3][...]
+# Example: [mingw32-]make -f Makefile.mk CFG=-zlib-ssl-libssh2-ipv6
+#
+# Look for ' ?=' to find all accepted customization variables.
+
+# This script is reused by 'src' and 'docs/examples' Makefile.mk scripts.
+
+ifndef PROOT
+ PROOT := ..
+ LOCAL := 1
+endif
+
+### Common
+
+CFLAGS ?=
+CPPFLAGS ?=
+RCFLAGS ?=
+LDFLAGS ?=
+CURL_LDFLAGS_BIN ?=
+CURL_LDFLAGS_LIB ?=
+LIBS ?=
+
+CROSSPREFIX ?=
+
+ifeq ($(CC),cc)
+ CC := gcc
+endif
+CC := $(CROSSPREFIX)$(CC)
+AR := $(CROSSPREFIX)$(AR)
+RC ?= $(CROSSPREFIX)windres
+
+# For compatibility
+ARCH ?=
+ifeq ($(ARCH),w64)
+ TRIPLET := x86_64-w64-mingw32
+ CFLAGS += -m64
+ LDFLAGS += -m64
+ RCFLAGS += --target=pe-x86-64
+else ifdef ARCH
+ TRIPLET := i686-w64-mingw32
+ CFLAGS += -m32
+ LDFLAGS += -m32
+ RCFLAGS += --target=pe-i386
+else
+ TRIPLET ?= $(shell $(CC) -dumpmachine)
+endif
+
+BIN_EXT := .exe
+
+ifneq ($(findstring -w,$(TRIPLET)),)
+ WIN32 := 1
+else ifneq ($(findstring msdos,$(TRIPLET)),)
+ # Cross-tools: https://github.com/andrewwutw/build-djgpp
+ MSDOS := 1
+else ifneq ($(findstring amigaos,$(TRIPLET)),)
+ # Cross-tools: https://github.com/bebbo/amiga-gcc
+ AMIGA := 1
+endif
+
+CPPFLAGS += -I. -I$(PROOT)/include
+RCFLAGS += -I$(PROOT)/include
+
+ifndef WIN32
+ DYN :=
+endif
+
+ifdef AMIGA
+ BIN_EXT :=
+endif
+
+### Deprecated settings. For compatibility.
+
+ifdef WATT_ROOT
+ WATT_PATH := $(realpath $(WATT_ROOT))
+endif
+
+### Optional features
+
+ifneq ($(findstring -debug,$(CFG)),)
+ CFLAGS += -g
+ CPPFLAGS += -DDEBUGBUILD
+else
+ CPPFLAGS += -DNDEBUG
+endif
+ifneq ($(findstring -trackmem,$(CFG)),)
+ CPPFLAGS += -DCURLDEBUG
+endif
+ifneq ($(findstring -map,$(CFG)),)
+ MAP := 1
+endif
+
+ifdef WIN32
+ ifneq ($(findstring -unicode,$(CFG)),)
+ CPPFLAGS += -DUNICODE -D_UNICODE
+ CURL_LDFLAGS_BIN += -municode
+ endif
+endif
+
+# CPPFLAGS below are only necessary when building libcurl via 'lib' (see
+# comments below about exceptions). Always include them anyway to match
+# behavior of other build systems.
+
+# Linker options to exclude for shared mode executables.
+_LDFLAGS :=
+_LIBS :=
+
+ifneq ($(findstring -sync,$(CFG)),)
+ CPPFLAGS += -DUSE_SYNC_DNS
+else ifneq ($(findstring -ares,$(CFG)),)
+ LIBCARES_PATH ?= $(PROOT)/../c-ares
+ CPPFLAGS += -DUSE_ARES
+ CPPFLAGS += -I"$(LIBCARES_PATH)/include"
+ _LDFLAGS += -L"$(LIBCARES_PATH)/lib"
+ _LIBS += -lcares
+endif
+
+ifneq ($(findstring -rtmp,$(CFG)),)
+ LIBRTMP_PATH ?= $(PROOT)/../librtmp
+ CPPFLAGS += -DUSE_LIBRTMP
+ CPPFLAGS += -I"$(LIBRTMP_PATH)"
+ _LDFLAGS += -L"$(LIBRTMP_PATH)/librtmp"
+ _LIBS += -lrtmp -lwinmm
+ ZLIB := 1
+endif
+
+ifneq ($(findstring -ssh2,$(CFG)),)
+ LIBSSH2_PATH ?= $(PROOT)/../libssh2
+ CPPFLAGS += -DUSE_LIBSSH2
+ CPPFLAGS += -I"$(LIBSSH2_PATH)/include"
+ _LDFLAGS += -L"$(LIBSSH2_PATH)/lib"
+ ifdef WIN32
+ _LDFLAGS += -L"$(LIBSSH2_PATH)/win32"
+ endif
+ _LIBS += -lssh2
+else ifneq ($(findstring -libssh,$(CFG)),)
+ LIBSSH_PATH ?= $(PROOT)/../libssh
+ CPPFLAGS += -DUSE_LIBSSH
+ CPPFLAGS += -I"$(LIBSSH_PATH)/include"
+ _LDFLAGS += -L"$(LIBSSH_PATH)/lib"
+ _LIBS += -lssh
+else ifneq ($(findstring -wolfssh,$(CFG)),)
+ WOLFSSH_PATH ?= $(PROOT)/../wolfssh
+ CPPFLAGS += -DUSE_WOLFSSH
+ CPPFLAGS += -I"$(WOLFSSH_PATH)/include"
+ _LDFLAGS += -L"$(WOLFSSH_PATH)/lib"
+ _LIBS += -lwolfssh
+endif
+
+ifneq ($(findstring -ssl,$(CFG)),)
+ OPENSSL_PATH ?= $(PROOT)/../openssl
+ CPPFLAGS += -DUSE_OPENSSL
+ CPPFLAGS += -DCURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
+ OPENSSL_INCLUDE ?= $(OPENSSL_PATH)/include
+ OPENSSL_LIBPATH ?= $(OPENSSL_PATH)/lib
+ CPPFLAGS += -I"$(OPENSSL_INCLUDE)"
+ _LDFLAGS += -L"$(OPENSSL_LIBPATH)"
+ OPENSSL_LIBS ?= -lssl -lcrypto
+ _LIBS += $(OPENSSL_LIBS)
+
+ ifneq ($(findstring -srp,$(CFG)),)
+ ifneq ($(wildcard $(OPENSSL_INCLUDE)/openssl/srp.h),)
+ # OpenSSL 1.0.1 and later.
+ CPPFLAGS += -DHAVE_OPENSSL_SRP -DUSE_TLS_SRP
+ endif
+ endif
+ SSLLIBS += 1
+endif
+ifneq ($(findstring -wolfssl,$(CFG)),)
+ WOLFSSL_PATH ?= $(PROOT)/../wolfssl
+ CPPFLAGS += -DUSE_WOLFSSL
+ CPPFLAGS += -DSIZEOF_LONG_LONG=8
+ CPPFLAGS += -I"$(WOLFSSL_PATH)/include"
+ _LDFLAGS += -L"$(WOLFSSL_PATH)/lib"
+ _LIBS += -lwolfssl
+ SSLLIBS += 1
+endif
+ifneq ($(findstring -mbedtls,$(CFG)),)
+ MBEDTLS_PATH ?= $(PROOT)/../mbedtls
+ CPPFLAGS += -DUSE_MBEDTLS
+ CPPFLAGS += -I"$(MBEDTLS_PATH)/include"
+ _LDFLAGS += -L"$(MBEDTLS_PATH)/lib"
+ _LIBS += -lmbedtls -lmbedx509 -lmbedcrypto
+ SSLLIBS += 1
+endif
+ifneq ($(findstring -schannel,$(CFG)),)
+ CPPFLAGS += -DUSE_SCHANNEL
+ SSLLIBS += 1
+endif
+
+ifneq ($(findstring -nghttp2,$(CFG)),)
+ NGHTTP2_PATH ?= $(PROOT)/../nghttp2
+ CPPFLAGS += -DUSE_NGHTTP2
+ CPPFLAGS += -I"$(NGHTTP2_PATH)/include"
+ _LDFLAGS += -L"$(NGHTTP2_PATH)/lib"
+ _LIBS += -lnghttp2
+endif
+
+ifeq ($(findstring -nghttp3,$(CFG))$(findstring -ngtcp2,$(CFG)),-nghttp3-ngtcp2)
+ NGHTTP3_PATH ?= $(PROOT)/../nghttp3
+ CPPFLAGS += -DUSE_NGHTTP3
+ CPPFLAGS += -I"$(NGHTTP3_PATH)/include"
+ _LDFLAGS += -L"$(NGHTTP3_PATH)/lib"
+ _LIBS += -lnghttp3
+
+ NGTCP2_PATH ?= $(PROOT)/../ngtcp2
+ CPPFLAGS += -DUSE_NGTCP2
+ CPPFLAGS += -I"$(NGTCP2_PATH)/include"
+ _LDFLAGS += -L"$(NGTCP2_PATH)/lib"
+
+ NGTCP2_LIBS ?=
+ ifeq ($(NGTCP2_LIBS),)
+ ifneq ($(findstring -ssl,$(CFG)),)
+ ifneq ($(wildcard $(OPENSSL_INCLUDE)/openssl/aead.h),)
+ NGTCP2_LIBS := -lngtcp2_crypto_boringssl
+ else # including libressl
+ NGTCP2_LIBS := -lngtcp2_crypto_quictls
+ endif
+ else ifneq ($(findstring -wolfssl,$(CFG)),)
+ NGTCP2_LIBS := -lngtcp2_crypto_wolfssl
+ endif
+ endif
+
+ _LIBS += -lngtcp2 $(NGTCP2_LIBS)
+endif
+
+ifneq ($(findstring -zlib,$(CFG))$(ZLIB),)
+ ZLIB_PATH ?= $(PROOT)/../zlib
+ # These CPPFLAGS are also required when compiling the curl tool via 'src'.
+ CPPFLAGS += -DHAVE_LIBZ
+ CPPFLAGS += -I"$(ZLIB_PATH)/include"
+ _LDFLAGS += -L"$(ZLIB_PATH)/lib"
+ ZLIB_LIBS ?= -lz
+ _LIBS += $(ZLIB_LIBS)
+ ZLIB := 1
+endif
+ifneq ($(findstring -zstd,$(CFG)),)
+ ZSTD_PATH ?= $(PROOT)/../zstd
+ CPPFLAGS += -DHAVE_ZSTD
+ CPPFLAGS += -I"$(ZSTD_PATH)/include"
+ _LDFLAGS += -L"$(ZSTD_PATH)/lib"
+ ZSTD_LIBS ?= -lzstd
+ _LIBS += $(ZSTD_LIBS)
+endif
+ifneq ($(findstring -brotli,$(CFG)),)
+ BROTLI_PATH ?= $(PROOT)/../brotli
+ CPPFLAGS += -DHAVE_BROTLI
+ CPPFLAGS += -I"$(BROTLI_PATH)/include"
+ _LDFLAGS += -L"$(BROTLI_PATH)/lib"
+ BROTLI_LIBS ?= -lbrotlidec -lbrotlicommon
+ _LIBS += $(BROTLI_LIBS)
+endif
+ifneq ($(findstring -gsasl,$(CFG)),)
+ LIBGSASL_PATH ?= $(PROOT)/../gsasl
+ CPPFLAGS += -DUSE_GSASL
+ CPPFLAGS += -I"$(LIBGSASL_PATH)/include"
+ _LDFLAGS += -L"$(LIBGSASL_PATH)/lib"
+ _LIBS += -lgsasl
+endif
+
+ifneq ($(findstring -idn2,$(CFG)),)
+ LIBIDN2_PATH ?= $(PROOT)/../libidn2
+ CPPFLAGS += -DUSE_LIBIDN2
+ CPPFLAGS += -I"$(LIBIDN2_PATH)/include"
+ _LDFLAGS += -L"$(LIBIDN2_PATH)/lib"
+ _LIBS += -lidn2
+
+ifneq ($(findstring -psl,$(CFG)),)
+ LIBPSL_PATH ?= $(PROOT)/../libpsl
+ CPPFLAGS += -DUSE_LIBPSL
+ CPPFLAGS += -I"$(LIBPSL_PATH)/include"
+ _LDFLAGS += -L"$(LIBPSL_PATH)/lib"
+ _LIBS += -lpsl
+endif
+else ifneq ($(findstring -winidn,$(CFG)),)
+ CPPFLAGS += -DUSE_WIN32_IDN
+ _LIBS += -lnormaliz
+endif
+
+ifneq ($(findstring -sspi,$(CFG)),)
+ ifdef WIN32
+ CPPFLAGS += -DUSE_WINDOWS_SSPI
+ endif
+endif
+ifneq ($(findstring -ipv6,$(CFG)),)
+ CPPFLAGS += -DENABLE_IPV6
+endif
+
+ifneq ($(findstring -watt,$(CFG))$(MSDOS),)
+ WATT_PATH ?= $(PROOT)/../watt
+ CPPFLAGS += -I"$(WATT_PATH)/inc"
+ _LDFLAGS += -L"$(WATT_PATH)/lib"
+ _LIBS += -lwatt
+endif
+
+ifdef WIN32
+ ifeq ($(findstring -lldap,$(LIBS)),)
+ _LIBS += -lwldap32
+ endif
+ _LIBS += -lws2_32 -lcrypt32 -lbcrypt
+endif
+
+ifneq ($(findstring 11,$(subst $(subst ,, ),,$(SSLLIBS))),)
+ CPPFLAGS += -DCURL_WITH_MULTI_SSL
+endif
+
+ifndef DYN
+ LDFLAGS += $(_LDFLAGS)
+ LIBS += $(_LIBS)
+endif
+
+### Common rules
+
+OBJ_DIR := $(TRIPLET)
+
+ifneq ($(findstring /sh,$(SHELL)),)
+DEL = rm -f $1
+COPY = -cp -afv $1 $2
+MKDIR = mkdir -p $1
+RMDIR = rm -fr $1
+WHICH = $(SHELL) -c "command -v $1"
+else
+DEL = -del 2>NUL /q /f $(subst /,\,$1)
+COPY = -copy 2>NUL /y $(subst /,\,$1) $(subst /,\,$2)
+MKDIR = -md 2>NUL $(subst /,\,$1)
+RMDIR = -rd 2>NUL /q /s $(subst /,\,$1)
+WHICH = where $1
+endif
+
+all: $(TARGETS)
+
+$(OBJ_DIR):
+ -$(call MKDIR, $(OBJ_DIR))
+
+$(OBJ_DIR)/%.o: %.c
+ $(CC) -W -Wall $(CFLAGS) $(CPPFLAGS) -c $< -o $@
+
+$(OBJ_DIR)/%.res: %.rc
+ $(RC) -O coff $(RCFLAGS) -i $< -o $@
+
+clean:
+ @$(call DEL, $(TOCLEAN))
+ @$(RMDIR) $(OBJ_DIR)
+
+distclean vclean: clean
+ @$(call DEL, $(TARGETS) $(TOVCLEAN))
+
+### Local
+
+ifdef LOCAL
+
+CPPFLAGS += -DBUILDING_LIBCURL
+
+### Sources and targets
+
+# Provides CSOURCES, HHEADERS, LIB_RCFILES
+include Makefile.inc
+
+vpath %.c vauth vquic vssh vtls
+
+libcurl_a_LIBRARY := libcurl.a
+ifdef WIN32
+CURL_DLL_SUFFIX ?=
+libcurl_dll_LIBRARY := libcurl$(CURL_DLL_SUFFIX).dll
+libcurl_dll_a_LIBRARY := libcurl.dll.a
+ifdef MAP
+libcurl_map_LIBRARY := libcurl$(CURL_DLL_SUFFIX).map
+CURL_LDFLAGS_LIB += -Wl,-Map,$(libcurl_map_LIBRARY)
+endif
+endif
+
+TARGETS := $(libcurl_a_LIBRARY) $(libcurl_dll_LIBRARY)
+
+libcurl_a_OBJECTS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(notdir $(strip $(CSOURCES))))
+libcurl_a_DEPENDENCIES := $(strip $(CSOURCES) $(HHEADERS))
+ifdef WIN32
+libcurl_dll_OBJECTS := $(libcurl_a_OBJECTS)
+libcurl_dll_OBJECTS += $(patsubst %.rc,$(OBJ_DIR)/%.res,$(strip $(LIB_RCFILES)))
+endif
+
+TOCLEAN := $(libcurl_dll_OBJECTS)
+TOVCLEAN := $(libcurl_dll_LIBRARY:.dll=.def) $(libcurl_dll_a_LIBRARY) $(libcurl_map_LIBRARY)
+
+### Rules
+
+$(libcurl_a_LIBRARY): $(libcurl_a_OBJECTS) $(libcurl_a_DEPENDENCIES)
+ @$(call DEL, $@)
+ $(AR) rcs $@ $(libcurl_a_OBJECTS)
+
+$(libcurl_dll_LIBRARY): $(libcurl_dll_OBJECTS)
+ $(CC) $(LDFLAGS) -shared $(CURL_LDFLAGS_LIB) -o $@ $(libcurl_dll_OBJECTS) $(LIBS) \
+ -Wl,--output-def,$(@:.dll=.def),--out-implib,$(libcurl_dll_a_LIBRARY)
+
+all: $(OBJ_DIR) $(TARGETS)
+endif
diff --git a/lib/Makefile.soname b/lib/Makefile.soname
new file mode 100644
index 0000000..02e003a
--- /dev/null
+++ b/lib/Makefile.soname
@@ -0,0 +1,42 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+VERSIONCHANGE=12
+VERSIONADD=0
+VERSIONDEL=8
+
+# libtool version:
+VERSIONINFO=-version-info $(VERSIONCHANGE):$(VERSIONADD):$(VERSIONDEL)
+# This flag accepts an argument of the form current[:revision[:age]]. So,
+# passing -version-info 3:12:1 sets current to 3, revision to 12, and age to
+# 1.
+#
+# Here's the simplified rule guide on how to change -version-info:
+# (current version is C:R:A)
+#
+# 1. if there are only source changes, use C:R+1:A
+# 2. if interfaces were added use C+1:0:A+1
+# 3. if interfaces were removed, then use C+1:0:0
+#
+# For the full guide on libcurl ABI rules, see docs/libcurl/ABI
diff --git a/lib/altsvc.c b/lib/altsvc.c
index 2c0b3bd..11009d5 100644
--- a/lib/altsvc.c
+++ b/lib/altsvc.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -52,15 +52,7 @@
#define MAX_ALTSVC_ALPNLENSTR "10"
#define MAX_ALTSVC_ALPNLEN 10
-#if defined(USE_QUICHE) && !defined(UNITTESTS)
-#define H3VERSION "h3-29"
-#elif defined(USE_NGTCP2) && !defined(UNITTESTS)
-#define H3VERSION "h3-29"
-#elif defined(USE_MSH3) && !defined(UNITTESTS)
-#define H3VERSION "h3-29"
-#else
#define H3VERSION "h3"
-#endif
static enum alpnid alpn2alpnid(char *name)
{
@@ -125,7 +117,7 @@
as->dst.port = curlx_ultous(dstport);
return as;
- error:
+error:
altsvc_free(as);
return NULL;
}
@@ -225,7 +217,7 @@
}
return result;
- fail:
+fail:
Curl_safefree(asi->filename);
free(line);
fclose(fp);
@@ -432,7 +424,7 @@
#ifdef DEBUGBUILD
/* to play well with debug builds, we can *set* a fixed time this will
return */
-static time_t debugtime(void *unused)
+static time_t altsvc_debugtime(void *unused)
{
char *timestr = getenv("CURL_TIME");
(void)unused;
@@ -442,7 +434,8 @@
}
return time(NULL);
}
-#define time(x) debugtime(x)
+#undef time
+#define time(x) altsvc_debugtime(x)
#endif
#define ISNEWLINE(x) (((x) == '\n') || (x) == '\r')
@@ -470,6 +463,7 @@
struct altsvc *as;
unsigned short dstport = srcport; /* the same by default */
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
+ size_t entries = 0;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
@@ -480,11 +474,10 @@
DEBUGASSERT(asi);
- /* Flush all cached alternatives for this source origin, if any */
- altsvc_flush(asi, srcalpnid, srchost, srcport);
-
/* "clear" is a magic keyword */
if(strcasecompare(alpnbuf, "clear")) {
+ /* Flush cached alternatives for this source origin */
+ altsvc_flush(asi, srcalpnid, srchost, srcport);
return CURLE_OK;
}
@@ -502,6 +495,7 @@
bool quoted = FALSE;
time_t maxage = 24 * 3600; /* default is 24 hours */
bool persist = FALSE;
+ bool valid = TRUE;
p++;
if(*p != ':') {
/* host name starts here */
@@ -511,7 +505,7 @@
len = p - hostp;
if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
infof(data, "Excessive alt-svc host name, ignoring.");
- dstalpnid = ALPN_none;
+ valid = FALSE;
}
else {
memcpy(namebuf, hostp, len);
@@ -524,14 +518,21 @@
dsthost = srchost;
}
if(*p == ':') {
- /* a port number */
- unsigned long port = strtoul(++p, &end_ptr, 10);
- if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
+ unsigned long port = 0;
+ p++;
+ if(ISDIGIT(*p))
+ /* a port number */
+ port = strtoul(p, &end_ptr, 10);
+ else
+ end_ptr = (char *)p; /* not left uninitialized */
+ if(!port || port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
infof(data, "Unknown alt-svc port number, ignoring.");
- dstalpnid = ALPN_none;
+ valid = FALSE;
}
- p = end_ptr;
- dstport = curlx_ultous(port);
+ else {
+ dstport = curlx_ultous(port);
+ p = end_ptr;
+ }
}
if(*p++ != '\"')
break;
@@ -583,7 +584,12 @@
persist = TRUE;
}
}
- if(dstalpnid) {
+ if(dstalpnid && valid) {
+ if(!entries++)
+ /* Flush cached alternatives for this source origin, if any - when
+ this is the first entry of the line. */
+ altsvc_flush(asi, srcalpnid, srchost, srcport);
+
as = altsvc_createid(srchost, dsthost,
srcalpnid, dstalpnid,
srcport, dstport);
@@ -597,10 +603,6 @@
Curl_alpnid2str(dstalpnid));
}
}
- else {
- infof(data, "Unknown alt-svc protocol \"%s\", skipping.",
- alpnbuf);
- }
}
else
break;
diff --git a/lib/altsvc.h b/lib/altsvc.h
index 2751d27..7fea143 100644
--- a/lib/altsvc.h
+++ b/lib/altsvc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/amigaos.c b/lib/amigaos.c
index 6c14409..139309b 100644
--- a/lib/amigaos.c
+++ b/lib/amigaos.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,8 +25,16 @@
#include "curl_setup.h"
#ifdef __AMIGA__
-# include "amigaos.h"
-# if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
+
+#include <curl/curl.h>
+
+#include "hostip.h"
+#include "amigaos.h"
+
+#ifdef HAVE_PROTO_BSDSOCKET_H
+# if defined(__amigaos4__)
+# include <bsdsocket/socketbasetags.h>
+# elif !defined(USE_AMISSL)
# include <amitcp/socketbasetags.h>
# endif
# ifdef __libnix__
@@ -38,8 +46,155 @@
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef __AMIGA__
-#if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
+#ifdef HAVE_PROTO_BSDSOCKET_H
+
+#ifdef __amigaos4__
+/*
+ * AmigaOS 4.x specific code
+ */
+
+/*
+ * hostip4.c - Curl_ipv4_resolve_r() replacement code
+ *
+ * Logic that needs to be considered are the following build cases:
+ * - newlib networking
+ * - clib2 networking
+ * - direct bsdsocket.library networking (usually AmiSSL builds)
+ * Each with the threaded resolver enabled or not.
+ *
+ * With the threaded resolver enabled, try to use gethostbyname_r() where
+ * available, otherwise (re)open bsdsocket.library and fallback to
+ * gethostbyname().
+ */
+
+#include <proto/bsdsocket.h>
+
+static struct SocketIFace *__CurlISocket = NULL;
+static uint32 SocketFeatures = 0;
+
+#define HAVE_BSDSOCKET_GETHOSTBYNAME_R 0x01
+#define HAVE_BSDSOCKET_GETADDRINFO 0x02
+
+CURLcode Curl_amiga_init(void)
+{
+ struct SocketIFace *ISocket;
+ struct Library *base = OpenLibrary("bsdsocket.library", 4);
+
+ if(base) {
+ ISocket = (struct SocketIFace *)GetInterface(base, "main", 1, NULL);
+ if(ISocket) {
+ ULONG enabled = 0;
+
+ SocketBaseTags(SBTM_SETVAL(SBTC_CAN_SHARE_LIBRARY_BASES), TRUE,
+ SBTM_GETREF(SBTC_HAVE_GETHOSTADDR_R_API), (ULONG)&enabled,
+ TAG_DONE);
+
+ if(enabled) {
+ SocketFeatures |= HAVE_BSDSOCKET_GETHOSTBYNAME_R;
+ }
+
+ __CurlISocket = ISocket;
+
+ atexit(Curl_amiga_cleanup);
+
+ return CURLE_OK;
+ }
+ CloseLibrary(base);
+ }
+
+ return CURLE_FAILED_INIT;
+}
+
+void Curl_amiga_cleanup(void)
+{
+ if(__CurlISocket) {
+ struct Library *base = __CurlISocket->Data.LibBase;
+ DropInterface((struct Interface *)__CurlISocket);
+ CloseLibrary(base);
+ __CurlISocket = NULL;
+ }
+}
+
+#ifdef CURLRES_AMIGA
+/*
+ * Because we need to handle the different cases in hostip4.c at run-time,
+ * 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()
+ * allocates memory also.
+ */
+
+struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
+ int port)
+{
+ struct Curl_addrinfo *ai = NULL;
+ struct hostent *h;
+ struct SocketIFace *ISocket = __CurlISocket;
+
+ if(SocketFeatures & HAVE_BSDSOCKET_GETHOSTBYNAME_R) {
+ LONG h_errnop = 0;
+ struct hostent *buf;
+
+ buf = calloc(1, CURL_HOSTENT_SIZE);
+ if(buf) {
+ h = gethostbyname_r((STRPTR)hostname, buf,
+ (char *)buf + sizeof(struct hostent),
+ CURL_HOSTENT_SIZE - sizeof(struct hostent),
+ &h_errnop);
+ if(h) {
+ ai = Curl_he2ai(h, port);
+ }
+ free(buf);
+ }
+ }
+ else {
+ #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);
+ if(base) {
+ ISocket = (struct SocketIFace *)GetInterface(base, "main", 1, NULL);
+ if(ISocket) {
+ h = gethostbyname((STRPTR)hostname);
+ if(h) {
+ ai = Curl_he2ai(h, port);
+ }
+ DropInterface((struct Interface *)ISocket);
+ }
+ CloseLibrary(base);
+ }
+ #else
+ /* not using threaded resolver - safe to use this as-is */
+ h = gethostbyname(hostname);
+ if(h) {
+ ai = Curl_he2ai(h, port);
+ }
+ #endif
+ }
+
+ return ai;
+}
+#endif /* CURLRES_AMIGA */
+
+#ifdef USE_AMISSL
+#include <signal.h>
+int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *errorfds, struct timeval *timeout)
+{
+ int r = WaitSelect(nfds, readfds, writefds, errorfds, timeout, 0);
+ /* Ensure Ctrl-C signal is actioned */
+ if((r == -1) && (SOCKERRNO == EINTR))
+ raise(SIGINT);
+ return r;
+}
+#endif /* USE_AMISSL */
+
+#elif !defined(USE_AMISSL) /* __amigaos4__ */
+/*
+ * Amiga OS3 specific code
+ */
+
struct Library *SocketBase = NULL;
extern int errno, h_errno;
@@ -49,7 +204,7 @@
# define __request(msg) Printf(msg "\n\a")
#endif
-void Curl_amiga_cleanup()
+void Curl_amiga_cleanup(void)
{
if(SocketBase) {
CloseLibrary(SocketBase);
@@ -57,68 +212,36 @@
}
}
-bool Curl_amiga_init()
+CURLcode Curl_amiga_init(void)
{
if(!SocketBase)
SocketBase = OpenLibrary("bsdsocket.library", 4);
if(!SocketBase) {
__request("No TCP/IP Stack running!");
- return FALSE;
+ return CURLE_FAILED_INIT;
}
if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "curl",
TAG_DONE)) {
__request("SocketBaseTags ERROR");
- return FALSE;
+ return CURLE_FAILED_INIT;
}
#ifndef __libnix__
atexit(Curl_amiga_cleanup);
#endif
- return TRUE;
+ return CURLE_OK;
}
#ifdef __libnix__
ADD2EXIT(Curl_amiga_cleanup, -50);
#endif
+#endif /* !USE_AMISSL */
+
#endif /* HAVE_PROTO_BSDSOCKET_H */
-#ifdef USE_AMISSL
-void Curl_amiga_X509_free(X509 *a)
-{
- X509_free(a);
-}
-
-/* AmiSSL replaces many functions with macros. Curl requires pointer
- * to some of these functions. Thus, we have to encapsulate these macros.
- */
-
-#include "warnless.h"
-
-int (SHA256_Init)(SHA256_CTX *c)
-{
- return SHA256_Init(c);
-};
-
-int (SHA256_Update)(SHA256_CTX *c, const void *data, size_t len)
-{
- return SHA256_Update(c, data, curlx_uztoui(len));
-};
-
-int (SHA256_Final)(unsigned char *md, SHA256_CTX *c)
-{
- return SHA256_Final(md, c);
-};
-
-void (X509_INFO_free)(X509_INFO *a)
-{
- X509_INFO_free(a);
-};
-
-#endif /* USE_AMISSL */
#endif /* __AMIGA__ */
-
diff --git a/lib/amigaos.h b/lib/amigaos.h
index 8757aa8..7997ede 100644
--- a/lib/amigaos.h
+++ b/lib/amigaos.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,22 +25,18 @@
***************************************************************************/
#include "curl_setup.h"
-#if defined(__AMIGA__) && defined(HAVE_BSDSOCKET_H) && !defined(USE_AMISSL)
+#if defined(__AMIGA__) && defined(HAVE_PROTO_BSDSOCKET_H) && \
+ (!defined(USE_AMISSL) || defined(__amigaos4__))
-bool Curl_amiga_init();
-void Curl_amiga_cleanup();
+CURLcode Curl_amiga_init(void);
+void Curl_amiga_cleanup(void);
#else
-#define Curl_amiga_init() 1
+#define Curl_amiga_init() CURLE_OK
#define Curl_amiga_cleanup() Curl_nop_stmt
#endif
-#ifdef USE_AMISSL
-#include <openssl/x509v3.h>
-void Curl_amiga_X509_free(X509 *a);
-#endif /* USE_AMISSL */
-
#endif /* HEADER_CURL_AMIGAOS_H */
diff --git a/lib/arpa_telnet.h b/lib/arpa_telnet.h
index 523f7f5..de13738 100644
--- a/lib/arpa_telnet.h
+++ b/lib/arpa_telnet.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index 8b620a1..19fe853 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,15 +47,6 @@
#include <inet.h>
#endif
-#ifdef HAVE_PROCESS_H
-#include <process.h>
-#endif
-
-#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
-#undef in_addr_t
-#define in_addr_t unsigned long
-#endif
-
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
@@ -115,6 +106,7 @@
#ifndef HAVE_CARES_GETADDRINFO
struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
#endif
+ char hostname[1];
};
/* How long we are willing to wait for additional parallel responses after
@@ -252,8 +244,6 @@
*/
static void destroy_async_data(struct Curl_async *async)
{
- free(async->hostname);
-
if(async->tdata) {
struct thread_data *res = async->tdata;
if(res) {
@@ -265,8 +255,6 @@
}
async->tdata = NULL;
}
-
- async->hostname = NULL;
}
/*
@@ -749,7 +737,7 @@
* Curl_resolver_getaddrinfo() - when using ares
*
* Returns name information about the given hostname and port number. If
- * successful, the 'hostent' is returned and the forth argument will point to
+ * 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.
*/
@@ -758,25 +746,18 @@
int port,
int *waitp)
{
- char *bufp;
-
+ struct thread_data *res = NULL;
+ size_t namelen = strlen(hostname);
*waitp = 0; /* default to synchronous response */
- bufp = strdup(hostname);
- if(bufp) {
- struct thread_data *res = NULL;
- free(data->state.async.hostname);
- data->state.async.hostname = bufp;
+ res = calloc(sizeof(struct thread_data) + namelen, 1);
+ if(res) {
+ strcpy(res->hostname, hostname);
+ data->state.async.hostname = res->hostname;
data->state.async.port = port;
data->state.async.done = FALSE; /* not done */
data->state.async.status = 0; /* clear */
data->state.async.dns = NULL; /* clear */
- res = calloc(sizeof(struct thread_data), 1);
- if(!res) {
- free(data->state.async.hostname);
- data->state.async.hostname = NULL;
- return NULL;
- }
data->state.async.tdata = res;
/* initial status - failed */
@@ -789,13 +770,17 @@
int pf = PF_INET;
memset(&hints, 0, sizeof(hints));
#ifdef CURLRES_IPV6
- if(Curl_ipv6works(data))
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
#endif /* CURLRES_IPV6 */
hints.ai_family = pf;
hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
SOCK_STREAM : SOCK_DGRAM;
+ /* Since the service is a numerical one, set the hint flags
+ * accordingly to save a call to getservbyname in inside C-Ares
+ */
+ hints.ai_flags = ARES_AI_NUMERICSERV;
msnprintf(service, sizeof(service), "%d", port);
res->num_pending = 1;
ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname,
@@ -804,7 +789,7 @@
#else
#ifdef HAVE_CARES_IPV6
- if(Curl_ipv6works(data)) {
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
res->num_pending = 2;
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index d0edc32..6f0a212 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,19 +44,8 @@
#include <inet.h>
#endif
-#if defined(USE_THREADS_POSIX)
-# ifdef HAVE_PTHREAD_H
-# include <pthread.h>
-# endif
-#elif defined(USE_THREADS_WIN32)
-# ifdef HAVE_PROCESS_H
-# include <process.h>
-# endif
-#endif
-
-#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
-#undef in_addr_t
-#define in_addr_t unsigned long
+#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
+# include <pthread.h>
#endif
#ifdef HAVE_GETADDRINFO
@@ -75,7 +64,6 @@
#include "inet_ntop.h"
#include "curl_threads.h"
#include "connect.h"
-#include "socketpair.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -263,24 +251,29 @@
return 1;
- err_exit:
- /* Memory allocation failed */
+err_exit:
+#ifndef CURL_DISABLE_SOCKETPAIR
+ if(tsd->sock_pair[0] != CURL_SOCKET_BAD) {
+ sclose(tsd->sock_pair[0]);
+ tsd->sock_pair[0] = CURL_SOCKET_BAD;
+ }
+#endif
destroy_thread_sync_data(tsd);
return 0;
}
-static int getaddrinfo_complete(struct Curl_easy *data)
+static CURLcode getaddrinfo_complete(struct Curl_easy *data)
{
struct thread_sync_data *tsd = conn_thread_sync_data(data);
- int rc;
+ CURLcode result;
- rc = Curl_addrinfo_callback(data, tsd->sock_error, tsd->res);
+ result = Curl_addrinfo_callback(data, tsd->sock_error, tsd->res);
/* The tsd->res structure has been copied to async.dns and perhaps the DNS
cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it.
*/
tsd->res = NULL;
- return rc;
+ return result;
}
@@ -476,10 +469,10 @@
return TRUE;
- err_exit:
+err_exit:
destroy_async_data(asp);
- errno_exit:
+errno_exit:
errno = err;
return FALSE;
}
@@ -536,7 +529,8 @@
/* If we're still resolving, we must wait for the threads to fully clean up,
unfortunately. Otherwise, we can simply cancel to clean up any resolver
data. */
- if(td && td->thread_hnd != curl_thread_t_null)
+ if(td && td->thread_hnd != curl_thread_t_null
+ && (data->set.quick_exit != 1L))
(void)thread_wait_resolv(data, NULL, FALSE);
else
Curl_resolver_cancel(data);
@@ -702,7 +696,7 @@
*waitp = 0; /* default to synchronous response */
#ifdef CURLRES_IPV6
- if(Curl_ipv6works(data))
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
#endif /* CURLRES_IPV6 */
diff --git a/lib/asyn.h b/lib/asyn.h
index 80ca54d..7e207c4 100644
--- a/lib/asyn.h
+++ b/lib/asyn.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -148,7 +148,7 @@
* Curl_resolver_getaddrinfo() - when using this resolver
*
* Returns name information about the given hostname and port number. If
- * successful, the 'hostent' is returned and the forth argument will point to
+ * 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.
*
diff --git a/lib/base64.c b/lib/base64.c
index d5d79cf..9d495d4 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,60 +37,26 @@
#include "warnless.h"
#include "curl_base64.h"
-/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
+/* The last 2 #include files should be in this order */
#include "curl_memory.h"
#include "memdebug.h"
/* ---- Base64 Encoding/Decoding Table --- */
-static const char base64[]=
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+/* Padding character string starts at offset 64. */
+static const char base64encdec[]=
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-/* The Base 64 encoding with an URL and filename safe alphabet, RFC 4648
+/* The Base 64 encoding with a URL and filename safe alphabet, RFC 4648
section 5 */
static const char base64url[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
-static size_t decodeQuantum(unsigned char *dest, const char *src)
-{
- size_t padding = 0;
- const char *s, *p;
- unsigned long i, x = 0;
-
- for(i = 0, s = src; i < 4; i++, s++) {
- if(*s == '=') {
- x = (x << 6);
- padding++;
- }
- else {
- unsigned long v = 0;
- p = base64;
-
- while(*p && (*p != *s)) {
- v++;
- p++;
- }
-
- if(*p == *s)
- x = (x << 6) + v;
- else
- return 0;
- }
- }
-
- if(padding < 1)
- dest[2] = curlx_ultouc(x & 0xFFUL);
-
- x >>= 8;
- if(padding < 2)
- dest[1] = curlx_ultouc(x & 0xFFUL);
-
- x >>= 8;
- dest[0] = curlx_ultouc(x & 0xFFUL);
-
- return 3 - padding;
-}
-
+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 };
/*
* Curl_base64_decode()
*
@@ -109,13 +75,14 @@
unsigned char **outptr, size_t *outlen)
{
size_t srclen = 0;
- size_t length = 0;
size_t padding = 0;
size_t i;
size_t numQuantums;
+ size_t fullQuantums;
size_t rawlen = 0;
unsigned char *pos;
unsigned char *newstr;
+ unsigned char lookup[256];
*outptr = NULL;
*outlen = 0;
@@ -125,45 +92,82 @@
if(!srclen || srclen % 4)
return CURLE_BAD_CONTENT_ENCODING;
- /* Find the position of any = padding characters */
- while((src[length] != '=') && src[length])
- length++;
-
- /* A maximum of two = padding characters is allowed */
- if(src[length] == '=') {
+ /* srclen is at least 4 here */
+ while(src[srclen - 1 - padding] == '=') {
+ /* count padding characters */
padding++;
- if(src[length + 1] == '=')
- padding++;
+ /* A maximum of two = padding characters is allowed */
+ if(padding > 2)
+ return CURLE_BAD_CONTENT_ENCODING;
}
- /* Check the = padding characters weren't part way through the input */
- if(length + padding != srclen)
- return CURLE_BAD_CONTENT_ENCODING;
-
/* Calculate the number of quantums */
numQuantums = srclen / 4;
+ fullQuantums = numQuantums - (padding ? 1 : 0);
/* Calculate the size of the decoded string */
rawlen = (numQuantums * 3) - padding;
- /* Allocate our buffer including room for a zero terminator */
+ /* Allocate our buffer including room for a null-terminator */
newstr = malloc(rawlen + 1);
if(!newstr)
return CURLE_OUT_OF_MEMORY;
pos = newstr;
- /* Decode the quantums */
- for(i = 0; i < numQuantums; i++) {
- size_t result = decodeQuantum(pos, src);
- if(!result) {
- free(newstr);
+ memset(lookup, 0xff, sizeof(lookup));
+ memcpy(&lookup['+'], decodetable, sizeof(decodetable));
+ /* replaces
+ {
+ unsigned char c;
+ const unsigned char *p = (const unsigned char *)base64encdec;
+ for(c = 0; *p; c++, p++)
+ lookup[*p] = c;
+ }
+ */
- return CURLE_BAD_CONTENT_ENCODING;
+ /* Decode the complete quantums first */
+ for(i = 0; i < fullQuantums; i++) {
+ unsigned char val;
+ unsigned int x = 0;
+ int j;
+
+ for(j = 0; j < 4; j++) {
+ val = lookup[(unsigned char)*src++];
+ if(val == 0xff) /* bad symbol */
+ goto bad;
+ x = (x << 6) | val;
}
-
- pos += result;
- src += 4;
+ pos[2] = x & 0xff;
+ pos[1] = (x >> 8) & 0xff;
+ pos[0] = (x >> 16) & 0xff;
+ pos += 3;
+ }
+ if(padding) {
+ /* this means either 8 or 16 bits output */
+ unsigned char val;
+ unsigned int x = 0;
+ int j;
+ size_t padc = 0;
+ for(j = 0; j < 4; j++) {
+ if(*src == '=') {
+ x <<= 6;
+ src++;
+ if(++padc > padding)
+ /* this is a badly placed '=' symbol! */
+ goto bad;
+ }
+ else {
+ val = lookup[(unsigned char)*src++];
+ if(val == 0xff) /* bad symbol */
+ goto bad;
+ x = (x << 6) | val;
+ }
+ }
+ if(padding == 1)
+ pos[1] = (x >> 8) & 0xff;
+ pos[0] = (x >> 16) & 0xff;
+ pos += 3 - padding;
}
/* Zero terminate */
@@ -174,77 +178,60 @@
*outlen = rawlen;
return CURLE_OK;
+bad:
+ free(newstr);
+ return CURLE_BAD_CONTENT_ENCODING;
}
static CURLcode base64_encode(const char *table64,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen)
{
- unsigned char ibuf[3];
- unsigned char obuf[4];
- int i;
- int inputparts;
char *output;
char *base64data;
- const char *indata = inputbuff;
+ const unsigned char *in = (unsigned char *)inputbuff;
+ const char *padstr = &table64[64]; /* Point to padding string. */
*outptr = NULL;
*outlen = 0;
if(!insize)
- insize = strlen(indata);
+ insize = strlen(inputbuff);
#if SIZEOF_SIZE_T == 4
if(insize > UINT_MAX/4)
return CURLE_OUT_OF_MEMORY;
#endif
- base64data = output = malloc(insize * 4 / 3 + 4);
+ base64data = output = malloc((insize + 2) / 3 * 4 + 1);
if(!output)
return CURLE_OUT_OF_MEMORY;
- while(insize > 0) {
- for(i = inputparts = 0; i < 3; i++) {
- if(insize > 0) {
- inputparts++;
- ibuf[i] = (unsigned char) *indata;
- indata++;
- insize--;
+ 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 ];
+ insize -= 3;
+ in += 3;
+ }
+ if(insize) {
+ /* this is only one or two bytes now */
+ *output++ = table64[ in[0] >> 2 ];
+ if(insize == 1) {
+ *output++ = table64[ ((in[0] & 0x03) << 4) ];
+ if(*padstr) {
+ *output++ = *padstr;
+ *output++ = *padstr;
}
- else
- ibuf[i] = 0;
}
-
- obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
- obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
- ((ibuf[1] & 0xF0) >> 4));
- obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
- ((ibuf[2] & 0xC0) >> 6));
- obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
-
- switch(inputparts) {
- case 1: /* only one byte read */
- msnprintf(output, 5, "%c%c==",
- table64[obuf[0]],
- table64[obuf[1]]);
- break;
-
- case 2: /* two bytes read */
- msnprintf(output, 5, "%c%c%c=",
- table64[obuf[0]],
- table64[obuf[1]],
- table64[obuf[2]]);
- break;
-
- default:
- msnprintf(output, 5, "%c%c%c%c",
- table64[obuf[0]],
- table64[obuf[1]],
- table64[obuf[2]],
- table64[obuf[3]]);
- break;
+ else {
+ /* insize == 2 */
+ *output++ = table64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xF0) >> 4) ];
+ *output++ = table64[ ((in[1] & 0x0F) << 2) ];
+ if(*padstr)
+ *output++ = *padstr;
}
- output += 4;
}
/* Zero terminate */
@@ -272,14 +259,12 @@
* Returns CURLE_OK on success, otherwise specific error code. Function
* output shall not be considered valid unless CURLE_OK is returned.
*
- * When encoded data length is 0, returns NULL in *outptr.
- *
* @unittest: 1302
*/
CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
char **outptr, size_t *outlen)
{
- return base64_encode(base64, inputbuff, insize, outptr, outlen);
+ return base64_encode(base64encdec, inputbuff, insize, outptr, outlen);
}
/*
@@ -295,8 +280,6 @@
* Returns CURLE_OK on success, otherwise specific error code. Function
* output shall not be considered valid unless CURLE_OK is returned.
*
- * When encoded data length is 0, returns NULL in *outptr.
- *
* @unittest: 1302
*/
CURLcode Curl_base64url_encode(const char *inputbuff, size_t insize,
diff --git a/lib/bufq.c b/lib/bufq.c
new file mode 100644
index 0000000..1555449
--- /dev/null
+++ b/lib/bufq.c
@@ -0,0 +1,678 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "bufq.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+static bool chunk_is_empty(const struct buf_chunk *chunk)
+{
+ return chunk->r_offset >= chunk->w_offset;
+}
+
+static bool chunk_is_full(const struct buf_chunk *chunk)
+{
+ return chunk->w_offset >= chunk->dlen;
+}
+
+static size_t chunk_len(const struct buf_chunk *chunk)
+{
+ return chunk->w_offset - chunk->r_offset;
+}
+
+static size_t chunk_space(const struct buf_chunk *chunk)
+{
+ return chunk->dlen - chunk->w_offset;
+}
+
+static void chunk_reset(struct buf_chunk *chunk)
+{
+ chunk->next = NULL;
+ chunk->r_offset = chunk->w_offset = 0;
+}
+
+static size_t chunk_append(struct buf_chunk *chunk,
+ const unsigned char *buf, size_t len)
+{
+ unsigned char *p = &chunk->x.data[chunk->w_offset];
+ size_t n = chunk->dlen - chunk->w_offset;
+ DEBUGASSERT(chunk->dlen >= chunk->w_offset);
+ if(n) {
+ n = CURLMIN(n, len);
+ memcpy(p, buf, n);
+ chunk->w_offset += n;
+ }
+ return n;
+}
+
+static size_t chunk_read(struct buf_chunk *chunk,
+ unsigned char *buf, size_t len)
+{
+ unsigned char *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) {
+ return 0;
+ }
+ else if(n <= len) {
+ memcpy(buf, p, n);
+ chunk->r_offset = chunk->w_offset = 0;
+ return n;
+ }
+ else {
+ memcpy(buf, p, len);
+ chunk->r_offset += len;
+ return len;
+ }
+}
+
+static ssize_t chunk_slurpn(struct buf_chunk *chunk, size_t max_len,
+ Curl_bufq_reader *reader,
+ void *reader_ctx, CURLcode *err)
+{
+ unsigned char *p = &chunk->x.data[chunk->w_offset];
+ size_t n = chunk->dlen - chunk->w_offset; /* free amount */
+ ssize_t nread;
+
+ DEBUGASSERT(chunk->dlen >= chunk->w_offset);
+ if(!n) {
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+ if(max_len && n > max_len)
+ n = max_len;
+ nread = reader(reader_ctx, p, n, err);
+ if(nread > 0) {
+ DEBUGASSERT((size_t)nread <= n);
+ chunk->w_offset += nread;
+ }
+ return nread;
+}
+
+static void chunk_peek(const struct buf_chunk *chunk,
+ const unsigned char **pbuf, size_t *plen)
+{
+ DEBUGASSERT(chunk->w_offset >= chunk->r_offset);
+ *pbuf = &chunk->x.data[chunk->r_offset];
+ *plen = chunk->w_offset - chunk->r_offset;
+}
+
+static void chunk_peek_at(const struct buf_chunk *chunk, size_t offset,
+ const unsigned char **pbuf, size_t *plen)
+{
+ offset += chunk->r_offset;
+ DEBUGASSERT(chunk->w_offset >= offset);
+ *pbuf = &chunk->x.data[offset];
+ *plen = chunk->w_offset - offset;
+}
+
+static size_t chunk_skip(struct buf_chunk *chunk, size_t amount)
+{
+ size_t n = chunk->w_offset - chunk->r_offset;
+ DEBUGASSERT(chunk->w_offset >= chunk->r_offset);
+ if(n) {
+ n = CURLMIN(n, amount);
+ chunk->r_offset += n;
+ if(chunk->r_offset == chunk->w_offset)
+ chunk->r_offset = chunk->w_offset = 0;
+ }
+ return n;
+}
+
+static void chunk_shift(struct buf_chunk *chunk)
+{
+ if(chunk->r_offset) {
+ if(!chunk_is_empty(chunk)) {
+ size_t n = chunk->w_offset - chunk->r_offset;
+ memmove(chunk->x.data, chunk->x.data + chunk->r_offset, n);
+ chunk->w_offset -= chunk->r_offset;
+ chunk->r_offset = 0;
+ }
+ else {
+ chunk->r_offset = chunk->w_offset = 0;
+ }
+ }
+}
+
+static void chunk_list_free(struct buf_chunk **anchor)
+{
+ struct buf_chunk *chunk;
+ while(*anchor) {
+ chunk = *anchor;
+ *anchor = chunk->next;
+ free(chunk);
+ }
+}
+
+
+
+void Curl_bufcp_init(struct bufc_pool *pool,
+ size_t chunk_size, size_t spare_max)
+{
+ DEBUGASSERT(chunk_size > 0);
+ DEBUGASSERT(spare_max > 0);
+ memset(pool, 0, sizeof(*pool));
+ pool->chunk_size = chunk_size;
+ pool->spare_max = spare_max;
+}
+
+static CURLcode bufcp_take(struct bufc_pool *pool,
+ struct buf_chunk **pchunk)
+{
+ struct buf_chunk *chunk = NULL;
+
+ if(pool->spare) {
+ chunk = pool->spare;
+ pool->spare = chunk->next;
+ --pool->spare_count;
+ chunk_reset(chunk);
+ *pchunk = chunk;
+ return CURLE_OK;
+ }
+
+ chunk = calloc(1, sizeof(*chunk) + pool->chunk_size);
+ if(!chunk) {
+ *pchunk = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ chunk->dlen = pool->chunk_size;
+ *pchunk = chunk;
+ return CURLE_OK;
+}
+
+static void bufcp_put(struct bufc_pool *pool,
+ struct buf_chunk *chunk)
+{
+ if(pool->spare_count >= pool->spare_max) {
+ free(chunk);
+ }
+ else {
+ chunk_reset(chunk);
+ chunk->next = pool->spare;
+ pool->spare = chunk;
+ ++pool->spare_count;
+ }
+}
+
+void Curl_bufcp_free(struct bufc_pool *pool)
+{
+ chunk_list_free(&pool->spare);
+ pool->spare_count = 0;
+}
+
+static void bufq_init(struct bufq *q, struct bufc_pool *pool,
+ size_t chunk_size, size_t max_chunks, int opts)
+{
+ DEBUGASSERT(chunk_size > 0);
+ DEBUGASSERT(max_chunks > 0);
+ memset(q, 0, sizeof(*q));
+ q->chunk_size = chunk_size;
+ q->max_chunks = max_chunks;
+ q->pool = pool;
+ q->opts = opts;
+}
+
+void Curl_bufq_init2(struct bufq *q, size_t chunk_size, size_t max_chunks,
+ int opts)
+{
+ bufq_init(q, NULL, chunk_size, max_chunks, opts);
+}
+
+void Curl_bufq_init(struct bufq *q, size_t chunk_size, size_t max_chunks)
+{
+ bufq_init(q, NULL, chunk_size, max_chunks, BUFQ_OPT_NONE);
+}
+
+void Curl_bufq_initp(struct bufq *q, struct bufc_pool *pool,
+ size_t max_chunks, int opts)
+{
+ bufq_init(q, pool, pool->chunk_size, max_chunks, opts);
+}
+
+void Curl_bufq_free(struct bufq *q)
+{
+ chunk_list_free(&q->head);
+ chunk_list_free(&q->spare);
+ q->tail = NULL;
+ q->chunk_count = 0;
+}
+
+void Curl_bufq_reset(struct bufq *q)
+{
+ struct buf_chunk *chunk;
+ while(q->head) {
+ chunk = q->head;
+ q->head = chunk->next;
+ chunk->next = q->spare;
+ q->spare = chunk;
+ }
+ q->tail = NULL;
+}
+
+size_t Curl_bufq_len(const struct bufq *q)
+{
+ const struct buf_chunk *chunk = q->head;
+ size_t len = 0;
+ while(chunk) {
+ len += chunk_len(chunk);
+ chunk = chunk->next;
+ }
+ return len;
+}
+
+size_t Curl_bufq_space(const struct bufq *q)
+{
+ size_t space = 0;
+ if(q->tail)
+ space += chunk_space(q->tail);
+ if(q->spare) {
+ struct buf_chunk *chunk = q->spare;
+ while(chunk) {
+ space += chunk->dlen;
+ chunk = chunk->next;
+ }
+ }
+ if(q->chunk_count < q->max_chunks) {
+ space += (q->max_chunks - q->chunk_count) * q->chunk_size;
+ }
+ return space;
+}
+
+bool Curl_bufq_is_empty(const struct bufq *q)
+{
+ return !q->head || chunk_is_empty(q->head);
+}
+
+bool Curl_bufq_is_full(const struct bufq *q)
+{
+ if(!q->tail || q->spare)
+ return FALSE;
+ if(q->chunk_count < q->max_chunks)
+ return FALSE;
+ if(q->chunk_count > q->max_chunks)
+ return TRUE;
+ /* we have no spares and cannot make more, is the tail full? */
+ return chunk_is_full(q->tail);
+}
+
+static struct buf_chunk *get_spare(struct bufq *q)
+{
+ struct buf_chunk *chunk = NULL;
+
+ if(q->spare) {
+ chunk = q->spare;
+ q->spare = chunk->next;
+ chunk_reset(chunk);
+ return chunk;
+ }
+
+ if(q->chunk_count >= q->max_chunks && (!(q->opts & BUFQ_OPT_SOFT_LIMIT)))
+ return NULL;
+
+ if(q->pool) {
+ if(bufcp_take(q->pool, &chunk))
+ return NULL;
+ ++q->chunk_count;
+ return chunk;
+ }
+ else {
+ chunk = calloc(1, sizeof(*chunk) + q->chunk_size);
+ if(!chunk)
+ return NULL;
+ chunk->dlen = q->chunk_size;
+ ++q->chunk_count;
+ return chunk;
+ }
+}
+
+static void prune_head(struct bufq *q)
+{
+ struct buf_chunk *chunk;
+
+ while(q->head && chunk_is_empty(q->head)) {
+ chunk = q->head;
+ q->head = chunk->next;
+ if(q->tail == chunk)
+ q->tail = q->head;
+ if(q->pool) {
+ bufcp_put(q->pool, chunk);
+ --q->chunk_count;
+ }
+ else if((q->chunk_count > q->max_chunks) ||
+ (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);
+ --q->chunk_count;
+ }
+ else {
+ chunk->next = q->spare;
+ q->spare = chunk;
+ }
+ }
+}
+
+static struct buf_chunk *get_non_full_tail(struct bufq *q)
+{
+ struct buf_chunk *chunk;
+
+ if(q->tail && !chunk_is_full(q->tail))
+ return q->tail;
+ chunk = get_spare(q);
+ if(chunk) {
+ /* new tail, and possibly new head */
+ if(q->tail) {
+ q->tail->next = chunk;
+ q->tail = chunk;
+ }
+ else {
+ DEBUGASSERT(!q->head);
+ q->head = q->tail = chunk;
+ }
+ }
+ return chunk;
+}
+
+ssize_t Curl_bufq_write(struct bufq *q,
+ const unsigned char *buf, size_t len,
+ CURLcode *err)
+{
+ struct buf_chunk *tail;
+ ssize_t nwritten = 0;
+ size_t n;
+
+ DEBUGASSERT(q->max_chunks > 0);
+ while(len) {
+ tail = get_non_full_tail(q);
+ if(!tail) {
+ if(q->chunk_count < q->max_chunks) {
+ *err = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
+ break;
+ }
+ n = chunk_append(tail, buf, len);
+ if(!n)
+ break;
+ nwritten += n;
+ buf += n;
+ len -= n;
+ }
+ if(nwritten == 0 && len) {
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+ *err = CURLE_OK;
+ return nwritten;
+}
+
+ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len,
+ CURLcode *err)
+{
+ ssize_t nread = 0;
+ size_t n;
+
+ *err = CURLE_OK;
+ while(len && q->head) {
+ n = chunk_read(q->head, buf, len);
+ if(n) {
+ nread += n;
+ buf += n;
+ len -= n;
+ }
+ prune_head(q);
+ }
+ if(nread == 0) {
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+ return nread;
+}
+
+bool Curl_bufq_peek(struct bufq *q,
+ const unsigned char **pbuf, size_t *plen)
+{
+ if(q->head && chunk_is_empty(q->head)) {
+ prune_head(q);
+ }
+ if(q->head && !chunk_is_empty(q->head)) {
+ chunk_peek(q->head, pbuf, plen);
+ return TRUE;
+ }
+ *pbuf = NULL;
+ *plen = 0;
+ return FALSE;
+}
+
+bool Curl_bufq_peek_at(struct bufq *q, size_t offset,
+ const unsigned char **pbuf, size_t *plen)
+{
+ struct buf_chunk *c = q->head;
+ size_t clen;
+
+ while(c) {
+ clen = chunk_len(c);
+ if(!clen)
+ break;
+ if(offset >= clen) {
+ offset -= clen;
+ c = c->next;
+ continue;
+ }
+ chunk_peek_at(c, offset, pbuf, plen);
+ return TRUE;
+ }
+ *pbuf = NULL;
+ *plen = 0;
+ return FALSE;
+}
+
+void Curl_bufq_skip(struct bufq *q, size_t amount)
+{
+ size_t n;
+
+ while(amount && q->head) {
+ n = chunk_skip(q->head, amount);
+ amount -= n;
+ prune_head(q);
+ }
+}
+
+void Curl_bufq_skip_and_shift(struct bufq *q, size_t amount)
+{
+ Curl_bufq_skip(q, amount);
+ if(q->tail)
+ chunk_shift(q->tail);
+}
+
+ssize_t Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer,
+ void *writer_ctx, CURLcode *err)
+{
+ const unsigned char *buf;
+ size_t blen;
+ ssize_t nwritten = 0;
+
+ while(Curl_bufq_peek(q, &buf, &blen)) {
+ ssize_t chunk_written;
+
+ chunk_written = writer(writer_ctx, buf, blen, err);
+ if(chunk_written < 0) {
+ if(!nwritten || *err != CURLE_AGAIN) {
+ /* blocked on first write or real error, fail */
+ nwritten = -1;
+ }
+ break;
+ }
+ if(!chunk_written) {
+ if(!nwritten) {
+ /* treat as blocked */
+ *err = CURLE_AGAIN;
+ nwritten = -1;
+ }
+ break;
+ }
+ Curl_bufq_skip(q, (size_t)chunk_written);
+ nwritten += chunk_written;
+ }
+ return nwritten;
+}
+
+ssize_t Curl_bufq_write_pass(struct bufq *q,
+ const unsigned char *buf, size_t len,
+ Curl_bufq_writer *writer, void *writer_ctx,
+ CURLcode *err)
+{
+ ssize_t nwritten = 0, n;
+
+ *err = CURLE_OK;
+ while(len) {
+ if(Curl_bufq_is_full(q)) {
+ /* try to make room in case we are full */
+ n = Curl_bufq_pass(q, writer, writer_ctx, err);
+ if(n < 0) {
+ if(*err != CURLE_AGAIN) {
+ /* real error, fail */
+ return -1;
+ }
+ /* would block, bufq is full, give up */
+ break;
+ }
+ }
+
+ /* Add whatever is remaining now to bufq */
+ n = Curl_bufq_write(q, buf, len, err);
+ if(n < 0) {
+ if(*err != CURLE_AGAIN) {
+ /* real error, fail */
+ return -1;
+ }
+ /* no room in bufq */
+ break;
+ }
+ /* edge case of writer returning 0 (and len is >0)
+ * break or we might enter an infinite loop here */
+ if(n == 0)
+ break;
+
+ /* Maybe only part of `data` has been added, continue to loop */
+ buf += (size_t)n;
+ len -= (size_t)n;
+ nwritten += (size_t)n;
+ }
+
+ if(!nwritten && len) {
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+ *err = CURLE_OK;
+ return nwritten;
+}
+
+ssize_t Curl_bufq_sipn(struct bufq *q, size_t max_len,
+ Curl_bufq_reader *reader, void *reader_ctx,
+ CURLcode *err)
+{
+ struct buf_chunk *tail = NULL;
+ ssize_t nread;
+
+ *err = CURLE_AGAIN;
+ tail = get_non_full_tail(q);
+ if(!tail) {
+ if(q->chunk_count < q->max_chunks) {
+ *err = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
+ /* full, blocked */
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+
+ nread = chunk_slurpn(tail, max_len, reader, reader_ctx, err);
+ if(nread < 0) {
+ return -1;
+ }
+ else if(nread == 0) {
+ /* eof */
+ *err = CURLE_OK;
+ }
+ return nread;
+}
+
+/**
+ * Read up to `max_len` bytes and append it to the end of the buffer queue.
+ * if `max_len` is 0, no limit is imposed and the call behaves exactly
+ * the same as `Curl_bufq_slurp()`.
+ * Returns the total amount of buf read (may be 0) or -1 on other
+ * reader errors.
+ * Note that even in case of a -1 chunks may have been read and
+ * the buffer queue will have different length than before.
+ */
+static ssize_t bufq_slurpn(struct bufq *q, size_t max_len,
+ Curl_bufq_reader *reader, void *reader_ctx,
+ CURLcode *err)
+{
+ ssize_t nread = 0, n;
+
+ *err = CURLE_AGAIN;
+ while(1) {
+
+ n = Curl_bufq_sipn(q, max_len, reader, reader_ctx, err);
+ if(n < 0) {
+ if(!nread || *err != CURLE_AGAIN) {
+ /* blocked on first read or real error, fail */
+ nread = -1;
+ }
+ else
+ *err = CURLE_OK;
+ break;
+ }
+ else if(n == 0) {
+ /* eof */
+ *err = CURLE_OK;
+ break;
+ }
+ nread += (size_t)n;
+ if(max_len) {
+ DEBUGASSERT((size_t)n <= max_len);
+ max_len -= (size_t)n;
+ if(!max_len)
+ break;
+ }
+ /* give up slurping when we get less bytes than we asked for */
+ if(q->tail && !chunk_is_full(q->tail))
+ break;
+ }
+ return nread;
+}
+
+ssize_t Curl_bufq_slurp(struct bufq *q, Curl_bufq_reader *reader,
+ void *reader_ctx, CURLcode *err)
+{
+ return bufq_slurpn(q, 0, reader, reader_ctx, err);
+}
diff --git a/lib/bufq.h b/lib/bufq.h
new file mode 100644
index 0000000..89b5c84
--- /dev/null
+++ b/lib/bufq.h
@@ -0,0 +1,271 @@
+#ifndef HEADER_CURL_BUFQ_H
+#define HEADER_CURL_BUFQ_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+/**
+ * A chunk of bytes for reading and writing.
+ * The size is fixed a creation with read and write offset
+ * for where unread content is.
+ */
+struct buf_chunk {
+ struct buf_chunk *next; /* to keep it in a list */
+ size_t dlen; /* the amount of allocated x.data[] */
+ 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 */
+ void *dummy; /* alignment */
+ } x;
+};
+
+/**
+ * A pool for providing/keeping a number of chunks of the same size
+ *
+ * The same pool can be shared by many `bufq` instances. However, a pool
+ * is not thread safe. All bufqs using it are supposed to operate in the
+ * same thread.
+ */
+struct bufc_pool {
+ struct buf_chunk *spare; /* list of available spare chunks */
+ size_t chunk_size; /* the size of chunks in this pool */
+ size_t spare_count; /* current number of spare chunks in list */
+ size_t spare_max; /* max number of spares to keep */
+};
+
+void Curl_bufcp_init(struct bufc_pool *pool,
+ size_t chunk_size, size_t spare_max);
+
+void Curl_bufcp_free(struct bufc_pool *pool);
+
+/**
+ * A queue of byte chunks for reading and writing.
+ * Reading is done from `head`, writing is done to `tail`.
+ *
+ * `bufq`s can be empty or full or neither. Its `len` is the number
+ * of bytes that can be read. For an empty bufq, `len` will be 0.
+ *
+ * By default, a bufq can hold up to `max_chunks * chunk_size` number
+ * of bytes. When `max_chunks` are used (in the `head` list) and the
+ * `tail` chunk is full, the bufq will report that it is full.
+ *
+ * On a full bufq, `len` may be less than the maximum number of bytes,
+ * e.g. when the head chunk is partially read. `len` may also become
+ * larger than the max when option `BUFQ_OPT_SOFT_LIMIT` is used.
+ *
+ * By default, writing to a full bufq will return (-1, CURLE_AGAIN). Same
+ * as reading from an empty bufq.
+ * With `BUFQ_OPT_SOFT_LIMIT` set, a bufq will allow writing becond this
+ * limit and use more than `max_chunks`. However it will report that it
+ * is full nevertheless. This is provided for situation where writes
+ * preferably never fail (except for memory exhaustion).
+ *
+ * By default and without a pool, a bufq will keep chunks that read
+ * read empty in its `spare` list. Option `BUFQ_OPT_NO_SPARES` will
+ * disable that and free chunks once they become empty.
+ *
+ * When providing a pool to a bufq, all chunk creation and spare handling
+ * will be delegated to that pool.
+ */
+struct bufq {
+ struct buf_chunk *head; /* chunk with bytes to read from */
+ struct buf_chunk *tail; /* chunk to write to */
+ struct buf_chunk *spare; /* list of free chunks, unless `pool` */
+ struct bufc_pool *pool; /* optional pool for free chunks */
+ size_t chunk_count; /* current number of chunks in `head+spare` */
+ size_t max_chunks; /* max `head` chunks to use */
+ size_t chunk_size; /* size of chunks to manage */
+ int opts; /* options for handling queue, see below */
+};
+
+/**
+ * Default behaviour: chunk limit is "hard", meaning attempts to write
+ * more bytes than can be hold in `max_chunks` is refused and will return
+ * -1, CURLE_AGAIN. */
+#define BUFQ_OPT_NONE (0)
+/**
+ * Make `max_chunks` a "soft" limit. A bufq will report that it is "full"
+ * when `max_chunks` are used, but allows writing beyond this limit.
+ */
+#define BUFQ_OPT_SOFT_LIMIT (1 << 0)
+/**
+ * Do not keep spare chunks.
+ */
+#define BUFQ_OPT_NO_SPARES (1 << 1)
+
+/**
+ * Initialize a buffer queue that can hold up to `max_chunks` buffers
+ * each of size `chunk_size`. The bufq will not allow writing of
+ * more bytes than can be held in `max_chunks`.
+ */
+void Curl_bufq_init(struct bufq *q, size_t chunk_size, size_t max_chunks);
+
+/**
+ * Initialize a buffer queue that can hold up to `max_chunks` buffers
+ * each of size `chunk_size` with the given options. See `BUFQ_OPT_*`.
+ */
+void Curl_bufq_init2(struct bufq *q, size_t chunk_size,
+ size_t max_chunks, int opts);
+
+void Curl_bufq_initp(struct bufq *q, struct bufc_pool *pool,
+ size_t max_chunks, int opts);
+
+/**
+ * Reset the buffer queue to be empty. Will keep any allocated buffer
+ * chunks around.
+ */
+void Curl_bufq_reset(struct bufq *q);
+
+/**
+ * Free all resources held by the buffer queue.
+ */
+void Curl_bufq_free(struct bufq *q);
+
+/**
+ * Return the total amount of data in the queue.
+ */
+size_t Curl_bufq_len(const struct bufq *q);
+
+/**
+ * Return the total amount of free space in the queue.
+ * The returned length is the number of bytes that can
+ * be expected to be written successfully to the bufq,
+ * providing no memory allocations fail.
+ */
+size_t Curl_bufq_space(const struct bufq *q);
+
+/**
+ * Returns TRUE iff there is no data in the buffer queue.
+ */
+bool Curl_bufq_is_empty(const struct bufq *q);
+
+/**
+ * Returns TRUE iff there is no space left in the buffer queue.
+ */
+bool Curl_bufq_is_full(const struct bufq *q);
+
+/**
+ * Write buf to the end of the buffer queue. The buf is copied
+ * and the amount of copied bytes is returned.
+ * A return code of -1 indicates an error, setting `err` to the
+ * cause. An err of CURLE_AGAIN is returned if the buffer queue is full.
+ */
+ssize_t Curl_bufq_write(struct bufq *q,
+ const unsigned char *buf, size_t len,
+ CURLcode *err);
+
+/**
+ * Read buf from the start of the buffer queue. The buf is copied
+ * and the amount of copied bytes is returned.
+ * A return code of -1 indicates an error, setting `err` to the
+ * cause. An err of CURLE_AGAIN is returned if the buffer queue is empty.
+ */
+ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len,
+ CURLcode *err);
+
+/**
+ * Peek at the head chunk in the buffer queue. Returns a pointer to
+ * the chunk buf (at the current offset) and its length. Does not
+ * modify the buffer queue.
+ * Returns TRUE iff bytes are available. Sets `pbuf` to NULL and `plen`
+ * to 0 when no bytes are available.
+ * Repeated calls return the same information until the buffer queue
+ * is modified, see `Curl_bufq_skip()``
+ */
+bool Curl_bufq_peek(struct bufq *q,
+ const unsigned char **pbuf, size_t *plen);
+
+bool Curl_bufq_peek_at(struct bufq *q, size_t offset,
+ const unsigned char **pbuf, size_t *plen);
+
+/**
+ * Tell the buffer queue to discard `amount` buf bytes at the head
+ * of the queue. Skipping more buf than is currently buffered will
+ * just empty the queue.
+ */
+void Curl_bufq_skip(struct bufq *q, size_t amount);
+
+/**
+ * Same as `skip` but shift tail data to the start afterwards,
+ * so that further writes will find room in tail.
+ */
+void Curl_bufq_skip_and_shift(struct bufq *q, size_t amount);
+
+typedef ssize_t Curl_bufq_writer(void *writer_ctx,
+ const unsigned char *buf, size_t len,
+ CURLcode *err);
+/**
+ * Passes the chunks in the buffer queue to the writer and returns
+ * the amount of buf written. A writer may return -1 and CURLE_AGAIN
+ * to indicate blocking at which point the queue will stop and return
+ * the amount of buf passed so far.
+ * -1 is returned on any other errors reported by the writer.
+ * Note that in case of a -1 chunks may have been written and
+ * the buffer queue will have different length than before.
+ */
+ssize_t Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer,
+ void *writer_ctx, CURLcode *err);
+
+typedef ssize_t Curl_bufq_reader(void *reader_ctx,
+ unsigned char *buf, size_t len,
+ CURLcode *err);
+
+/**
+ * Read date and append it to the end of the buffer queue until the
+ * reader returns blocking or the queue is full. A reader returns
+ * -1 and CURLE_AGAIN to indicate blocking.
+ * Returns the total amount of buf read (may be 0) or -1 on other
+ * reader errors.
+ * Note that in case of a -1 chunks may have been read and
+ * the buffer queue will have different length than before.
+ */
+ssize_t Curl_bufq_slurp(struct bufq *q, Curl_bufq_reader *reader,
+ void *reader_ctx, CURLcode *err);
+
+/**
+ * Read *once* up to `max_len` bytes and append it to the buffer.
+ * if `max_len` is 0, no limit is imposed besides the chunk space.
+ * Returns the total amount of buf read (may be 0) or -1 on other
+ * reader errors.
+ */
+ssize_t Curl_bufq_sipn(struct bufq *q, size_t max_len,
+ Curl_bufq_reader *reader, void *reader_ctx,
+ CURLcode *err);
+
+/**
+ * Write buf to the end of the buffer queue.
+ * Will write bufq content or passed `buf` directly using the `writer`
+ * callback when it sees fit. 'buf' might get passed directly
+ * on or is placed into the buffer, depending on `len` and current
+ * amount buffered, chunk size, etc.
+ */
+ssize_t Curl_bufq_write_pass(struct bufq *q,
+ const unsigned char *buf, size_t len,
+ Curl_bufq_writer *writer, void *writer_ctx,
+ CURLcode *err);
+
+#endif /* HEADER_CURL_BUFQ_H */
diff --git a/lib/bufref.c b/lib/bufref.c
index 91b0374..ce686b6 100644
--- a/lib/bufref.c
+++ b/lib/bufref.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2021 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/bufref.h b/lib/bufref.h
index 96b818b..dd424f1 100644
--- a/lib/bufref.h
+++ b/lib/bufref.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2021 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/c-hyper.c b/lib/c-hyper.c
index 69b904e..c29983c 100644
--- a/lib/c-hyper.c
+++ b/lib/c-hyper.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -54,6 +54,7 @@
#include "multiif.h"
#include "progress.h"
#include "content_encoding.h"
+#include "ws.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -70,9 +71,11 @@
DEBUGASSERT(conn);
(void)ctx;
+ DEBUGF(infof(data, "Curl_hyper_recv(%zu)", buflen));
result = Curl_read(data, conn->sockfd, (char *)buf, buflen, &nread);
if(result == CURLE_AGAIN) {
/* would block, register interest */
+ DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> EAGAIN", buflen));
if(data->hyp.read_waker)
hyper_waker_free(data->hyp.read_waker);
data->hyp.read_waker = hyper_context_waker(ctx);
@@ -86,6 +89,7 @@
failf(data, "Curl_read failed");
return HYPER_IO_ERROR;
}
+ DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> %zd", buflen, nread));
return (size_t)nread;
}
@@ -97,8 +101,12 @@
CURLcode result;
ssize_t nwrote;
+ DEBUGF(infof(data, "Curl_hyper_send(%zu)", buflen));
result = Curl_write(data, conn->sockfd, (void *)buf, buflen, &nwrote);
+ if(!result && !nwrote)
+ result = CURLE_AGAIN;
if(result == CURLE_AGAIN) {
+ DEBUGF(infof(data, "Curl_hyper_send(%zu) -> EAGAIN", buflen));
/* would block, register interest */
if(data->hyp.write_waker)
hyper_waker_free(data->hyp.write_waker);
@@ -113,6 +121,7 @@
failf(data, "Curl_write failed");
return HYPER_IO_ERROR;
}
+ DEBUGF(infof(data, "Curl_hyper_send(%zu) -> %zd", buflen, nwrote));
return (size_t)nwrote;
}
@@ -162,6 +171,10 @@
writetype = CLIENTWRITE_HEADER;
if(data->set.include_header)
writetype |= CLIENTWRITE_BODY;
+ if(data->state.hconnect)
+ writetype |= CLIENTWRITE_CONNECT;
+ if(data->req.httpcode/100 == 1)
+ writetype |= CLIENTWRITE_1XX;
result = Curl_client_write(data, writetype, headp, len);
if(result) {
data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
@@ -169,8 +182,8 @@
}
}
- data->info.header_size += (long)len;
- data->req.headerbytecount += (long)len;
+ data->info.header_size += (curl_off_t)len;
+ data->req.headerbytecount += (curl_off_t)len;
return HYPER_ITER_CONTINUE;
}
@@ -244,7 +257,7 @@
}
/*
- * Hyper does not consider the status line, the first line in a HTTP/1
+ * Hyper does not consider the status line, the first line in an HTTP/1
* response, to be a header. The libcurl API does. This function sends the
* status line in the header callback. */
static CURLcode status_line(struct Curl_easy *data,
@@ -259,23 +272,25 @@
int writetype;
vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" :
(http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0");
- conn->httpversion =
- http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
- (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
- if(http_version == HYPER_HTTP_VERSION_1_0)
- data->state.httpwant = CURL_HTTP_VERSION_1_0;
-
- if(data->state.hconnect)
- /* CONNECT */
- data->info.httpproxycode = http_status;
/* We need to set 'httpcodeq' for functions that check the response code in
a single place. */
data->req.httpcode = http_status;
- result = Curl_http_statusline(data, conn);
- if(result)
- return result;
+ if(data->state.hconnect)
+ /* CONNECT */
+ data->info.httpproxycode = http_status;
+ else {
+ conn->httpversion =
+ http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
+ (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
+ if(http_version == HYPER_HTTP_VERSION_1_0)
+ data->state.httpwant = CURL_HTTP_VERSION_1_0;
+
+ result = Curl_http_statusline(data, conn);
+ if(result)
+ return result;
+ }
Curl_dyn_reset(&data->state.headerb);
@@ -298,9 +313,8 @@
if(result)
return result;
}
- data->info.header_size += (long)len;
- data->req.headerbytecount += (long)len;
- data->req.httpcode = http_status;
+ data->info.header_size += (curl_off_t)len;
+ data->req.headerbytecount += (curl_off_t)len;
return CURLE_OK;
}
@@ -414,8 +428,10 @@
break;
}
else if(h->endtask == task) {
- /* end of transfer */
+ /* end of transfer, forget the task handled, we might get a
+ * new one with the same address in the future. */
*done = TRUE;
+ h->endtask = NULL;
infof(data, "hyperstream is done");
if(!k->bodywrites) {
/* hyper doesn't always call the body write callback */
@@ -425,8 +441,7 @@
break;
}
else if(t != HYPER_TASK_RESPONSE) {
- *didwhat = KEEP_RECV;
- break;
+ continue;
}
/* HYPER_TASK_RESPONSE */
@@ -471,6 +486,24 @@
if(result)
break;
+ k->deductheadercount =
+ (100 <= http_status && 199 >= http_status)?k->headerbytecount:0;
+#ifdef USE_WEBSOCKETS
+ if(k->upgr101 == UPGR101_WS) {
+ if(http_status == 101) {
+ /* verify the response */
+ result = Curl_ws_accept(data, NULL, 0);
+ if(result)
+ return result;
+ }
+ else {
+ failf(data, "Expected 101, got %u", k->httpcode);
+ result = CURLE_HTTP_RETURNED_ERROR;
+ break;
+ }
+ }
+#endif
+
/* Curl_http_auth_act() checks what authentication methods that are
* available and decides which one (if any) to use. It will set 'newurl'
* if an auth method was picked. */
@@ -660,7 +693,7 @@
return HYPER_POLL_ERROR;
}
/* increasing the writebytecount here is a little premature but we
- don't know exactly when the body is sent*/
+ don't know exactly when the body is sent */
data->req.writebytecount += (size_t)data->req.p.http->postsize;
Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
data->req.upload_done = TRUE;
@@ -673,6 +706,7 @@
{
size_t fillcount;
struct Curl_easy *data = (struct Curl_easy *)userdata;
+ struct connectdata *conn = (struct connectdata *)data->conn;
CURLcode result;
(void)ctx;
@@ -687,14 +721,31 @@
return HYPER_POLL_PENDING;
}
- result = Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount);
+ if(data->req.upload_chunky && conn->bits.authneg) {
+ fillcount = 0;
+ data->req.upload_chunky = FALSE;
+ result = CURLE_OK;
+ }
+ else {
+ result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
+ &fillcount);
+ }
if(result) {
data->state.hresult = result;
return HYPER_POLL_ERROR;
}
- if(!fillcount)
- /* done! */
- *chunk = NULL;
+ if(!fillcount) {
+ if((data->req.keepon & KEEP_SEND_PAUSE) != KEEP_SEND_PAUSE)
+ /* done! */
+ *chunk = NULL;
+ else {
+ /* paused, save a waker */
+ if(data->hyp.send_body_waker)
+ hyper_waker_free(data->hyp.send_body_waker);
+ data->hyp.send_body_waker = hyper_context_waker(ctx);
+ return HYPER_POLL_PENDING;
+ }
+ }
else {
hyper_buf *copy = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount);
if(copy)
@@ -704,7 +755,7 @@
return HYPER_POLL_ERROR;
}
/* increasing the writebytecount here is a little premature but we
- don't know exactly when the body is sent*/
+ don't know exactly when the body is sent */
data->req.writebytecount += fillcount;
Curl_pgrsSetUploadCounter(data, fillcount);
}
@@ -712,7 +763,7 @@
}
/*
- * bodysend() sets up headers in the outgoing request for a HTTP transfer that
+ * bodysend() sets up headers in the outgoing request for an HTTP transfer that
* sends a body
*/
@@ -817,7 +868,7 @@
}
/*
- * Curl_http() gets called from the generic multi_do() function when a HTTP
+ * Curl_http() gets called from the generic multi_do() function when an HTTP
* request is to be performed. This creates and sends a properly constructed
* HTTP request.
*/
@@ -909,12 +960,13 @@
result = CURLE_OUT_OF_MEMORY;
goto error;
}
- if(conn->negnpn == CURL_HTTP_VERSION_2) {
+ if(conn->alpn == CURL_HTTP_VERSION_2) {
hyper_clientconn_options_http2(options, 1);
h2 = TRUE;
}
hyper_clientconn_options_set_preserve_header_case(options, 1);
hyper_clientconn_options_set_preserve_header_order(options, 1);
+ hyper_clientconn_options_http1_allow_multiline_headers(options, 1);
hyper_clientconn_options_exec(options, h->exec);
@@ -1004,10 +1056,8 @@
/* For HTTP/2, we show the Host: header as if we sent it, to make it look
like for HTTP/1 but it isn't actually sent since :authority is then
used. */
- result = Curl_debug(data, CURLINFO_HEADER_OUT, data->state.aptr.host,
- strlen(data->state.aptr.host));
- if(result)
- goto error;
+ Curl_debug(data, CURLINFO_HEADER_OUT, data->state.aptr.host,
+ strlen(data->state.aptr.host));
}
if(data->state.aptr.proxyuserpwd) {
@@ -1085,6 +1135,16 @@
goto error;
}
+#ifdef HAVE_LIBZ
+ /* we only consider transfer-encoding magic if libz support is built-in */
+ result = Curl_transferencode(data);
+ if(result)
+ goto error;
+ result = Curl_hyper_header(data, headers, data->state.aptr.te);
+ if(result)
+ goto error;
+#endif
+
if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(data->state.aptr.accept_encoding);
@@ -1101,20 +1161,13 @@
else
Curl_safefree(data->state.aptr.accept_encoding);
-#ifdef HAVE_LIBZ
- /* we only consider transfer-encoding magic if libz support is built-in */
- result = Curl_transferencode(data);
- if(result)
- goto error;
- result = Curl_hyper_header(data, headers, data->state.aptr.te);
- if(result)
- goto error;
-#endif
-
result = cookies(data, conn, headers);
if(result)
goto error;
+ if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
+ result = Curl_ws_request(data, headers);
+
result = Curl_add_timecondition(data, headers);
if(result)
goto error;
@@ -1127,11 +1180,14 @@
if(result)
goto error;
- result = Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
- if(result)
- goto error;
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
- data->req.upload_chunky = FALSE;
+ if(data->req.upload_chunky && conn->bits.authneg) {
+ data->req.upload_chunky = TRUE;
+ }
+ else {
+ data->req.upload_chunky = FALSE;
+ }
sendtask = hyper_clientconn_send(client, req);
if(!sendtask) {
failf(data, "hyper_clientconn_send");
@@ -1163,7 +1219,7 @@
Curl_safefree(data->state.aptr.userpwd);
Curl_safefree(data->state.aptr.proxyuserpwd);
return CURLE_OK;
- error:
+error:
DEBUGASSERT(result);
if(io)
hyper_io_free(io);
diff --git a/lib/c-hyper.h b/lib/c-hyper.h
index 91a6261..4218cda 100644
--- a/lib/c-hyper.h
+++ b/lib/c-hyper.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,6 +36,7 @@
const hyper_executor *exec;
hyper_task *endtask;
hyper_waker *exp100_waker;
+ hyper_waker *send_body_waker;
};
size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
diff --git a/lib/cf-h1-proxy.c b/lib/cf-h1-proxy.c
new file mode 100644
index 0000000..c9b157c
--- /dev/null
+++ b/lib/cf-h1-proxy.c
@@ -0,0 +1,1184 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
+
+#include <curl/curl.h>
+#ifdef USE_HYPER
+#include <hyper.h>
+#endif
+#include "urldata.h"
+#include "dynbuf.h"
+#include "sendf.h"
+#include "http.h"
+#include "http_proxy.h"
+#include "url.h"
+#include "select.h"
+#include "progress.h"
+#include "cfilters.h"
+#include "cf-h1-proxy.h"
+#include "connect.h"
+#include "curl_log.h"
+#include "curlx.h"
+#include "vtls/vtls.h"
+#include "transfer.h"
+#include "multiif.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#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_state;
+
+/* struct for HTTP CONNECT tunneling */
+struct h1_tunnel_state {
+ int sockindex;
+ const char *hostname;
+ int remote_port;
+ struct HTTP CONNECT;
+ struct dynbuf rcvbuf;
+ struct dynbuf req;
+ size_t nsend;
+ size_t headerlines;
+ enum keeponval {
+ KEEPON_DONE,
+ KEEPON_CONNECT,
+ KEEPON_IGNORE
+ } keepon;
+ curl_off_t cl; /* size of content to read and ignore */
+ h1_tunnel_state tunnel_state;
+ BIT(chunked_encoding);
+ BIT(close_connection);
+};
+
+
+static bool tunnel_is_established(struct h1_tunnel_state *ts)
+{
+ return ts && (ts->tunnel_state == H1_TUNNEL_ESTABLISHED);
+}
+
+static bool tunnel_is_failed(struct h1_tunnel_state *ts)
+{
+ return ts && (ts->tunnel_state == H1_TUNNEL_FAILED);
+}
+
+static CURLcode tunnel_reinit(struct h1_tunnel_state *ts,
+ struct connectdata *conn,
+ struct Curl_easy *data)
+{
+ (void)data;
+ DEBUGASSERT(ts);
+ Curl_dyn_reset(&ts->rcvbuf);
+ Curl_dyn_reset(&ts->req);
+ ts->tunnel_state = H1_TUNNEL_INIT;
+ ts->keepon = KEEPON_CONNECT;
+ ts->cl = 0;
+ ts->close_connection = FALSE;
+
+ if(conn->bits.conn_to_host)
+ ts->hostname = conn->conn_to_host.name;
+ else if(ts->sockindex == SECONDARYSOCKET)
+ ts->hostname = conn->secondaryhostname;
+ else
+ ts->hostname = conn->host.name;
+
+ if(ts->sockindex == SECONDARYSOCKET)
+ ts->remote_port = conn->secondary_port;
+ else if(conn->bits.conn_to_port)
+ ts->remote_port = conn->conn_to_port;
+ else
+ ts->remote_port = conn->remote_port;
+
+ return CURLE_OK;
+}
+
+static CURLcode tunnel_init(struct h1_tunnel_state **pts,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
+{
+ struct h1_tunnel_state *ts;
+ CURLcode result;
+
+ if(conn->handler->flags & PROTOPT_NOTCPPROXY) {
+ failf(data, "%s cannot be done over CONNECT", conn->handler->scheme);
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+
+ /* we might need the upload buffer for streaming a partial request */
+ result = Curl_get_upload_buffer(data);
+ if(result)
+ return result;
+
+ ts = calloc(1, sizeof(*ts));
+ if(!ts)
+ return CURLE_OUT_OF_MEMORY;
+
+ ts->sockindex = sockindex;
+ infof(data, "allocate connect buffer");
+
+ Curl_dyn_init(&ts->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
+ Curl_dyn_init(&ts->req, DYN_HTTP_REQUEST);
+
+ *pts = ts;
+ connkeep(conn, "HTTP proxy CONNECT");
+ return tunnel_reinit(ts, conn, data);
+}
+
+static void h1_tunnel_go_state(struct Curl_cfilter *cf,
+ struct h1_tunnel_state *ts,
+ h1_tunnel_state new_state,
+ struct Curl_easy *data)
+{
+ if(ts->tunnel_state == new_state)
+ return;
+ /* leaving this one */
+ switch(ts->tunnel_state) {
+ case H1_TUNNEL_CONNECT:
+ data->req.ignorebody = FALSE;
+ break;
+ default:
+ break;
+ }
+ /* entering this one */
+ switch(new_state) {
+ case H1_TUNNEL_INIT:
+ DEBUGF(LOG_CF(data, cf, "new tunnel state 'init'"));
+ tunnel_reinit(ts, cf->conn, data);
+ break;
+
+ case H1_TUNNEL_CONNECT:
+ DEBUGF(LOG_CF(data, cf, "new tunnel state 'connect'"));
+ ts->tunnel_state = H1_TUNNEL_CONNECT;
+ ts->keepon = KEEPON_CONNECT;
+ Curl_dyn_reset(&ts->rcvbuf);
+ break;
+
+ case H1_TUNNEL_RECEIVE:
+ DEBUGF(LOG_CF(data, cf, "new tunnel state 'receive'"));
+ ts->tunnel_state = H1_TUNNEL_RECEIVE;
+ break;
+
+ case H1_TUNNEL_RESPONSE:
+ DEBUGF(LOG_CF(data, cf, "new tunnel state 'response'"));
+ ts->tunnel_state = H1_TUNNEL_RESPONSE;
+ break;
+
+ case H1_TUNNEL_ESTABLISHED:
+ DEBUGF(LOG_CF(data, cf, "new tunnel state 'established'"));
+ infof(data, "CONNECT phase completed");
+ data->state.authproxy.done = TRUE;
+ data->state.authproxy.multipass = FALSE;
+ /* FALLTHROUGH */
+ case H1_TUNNEL_FAILED:
+ if(new_state == H1_TUNNEL_FAILED)
+ DEBUGF(LOG_CF(data, cf, "new tunnel state 'failed'"));
+ ts->tunnel_state = new_state;
+ Curl_dyn_reset(&ts->rcvbuf);
+ Curl_dyn_reset(&ts->req);
+ /* restore the protocol pointer */
+ data->info.httpcode = 0; /* clear it as it might've been used for the
+ proxy */
+ /* If a proxy-authorization header was used for the proxy, then we should
+ make sure that it isn't accidentally used for the document request
+ after we've connected. So let's free and clear it here. */
+ Curl_safefree(data->state.aptr.proxyuserpwd);
+#ifdef USE_HYPER
+ data->state.hconnect = FALSE;
+#endif
+ break;
+ }
+}
+
+static void tunnel_free(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct h1_tunnel_state *ts = cf->ctx;
+ if(ts) {
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
+ Curl_dyn_free(&ts->rcvbuf);
+ Curl_dyn_free(&ts->req);
+ free(ts);
+ cf->ctx = NULL;
+ }
+}
+
+static CURLcode CONNECT_host(struct Curl_easy *data,
+ struct connectdata *conn,
+ const char *hostname,
+ int remote_port,
+ char **connecthostp,
+ char **hostp)
+{
+ char *hostheader; /* for CONNECT */
+ char *host = NULL; /* Host: */
+ bool ipv6_ip = conn->bits.ipv6_ip;
+
+ /* the hostname may be different */
+ if(hostname != conn->host.name)
+ ipv6_ip = (strchr(hostname, ':') != NULL);
+ hostheader = /* host:port with IPv6 support */
+ aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
+ remote_port);
+ if(!hostheader)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(!Curl_checkProxyheaders(data, conn, STRCONST("Host"))) {
+ host = aprintf("Host: %s\r\n", hostheader);
+ if(!host) {
+ free(hostheader);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ *connecthostp = hostheader;
+ *hostp = host;
+ return CURLE_OK;
+}
+
+#ifndef USE_HYPER
+static CURLcode start_CONNECT(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h1_tunnel_state *ts)
+{
+ struct connectdata *conn = cf->conn;
+ char *hostheader = NULL;
+ char *host = NULL;
+ const char *httpv;
+ CURLcode result;
+
+ infof(data, "Establish HTTP proxy tunnel to %s:%d",
+ ts->hostname, ts->remote_port);
+
+ /* This only happens if we've looped here due to authentication
+ reasons, and we don't really use the newly cloned URL here
+ then. Just free() it. */
+ Curl_safefree(data->req.newurl);
+
+ result = CONNECT_host(data, conn,
+ ts->hostname, ts->remote_port,
+ &hostheader, &host);
+ if(result)
+ goto out;
+
+ /* Setup the proxy-authorization header, if any */
+ result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
+ hostheader, TRUE);
+ if(result)
+ goto out;
+
+ httpv = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";
+
+ result =
+ Curl_dyn_addf(&ts->req,
+ "CONNECT %s HTTP/%s\r\n"
+ "%s" /* Host: */
+ "%s", /* Proxy-Authorization */
+ hostheader,
+ httpv,
+ host?host:"",
+ data->state.aptr.proxyuserpwd?
+ data->state.aptr.proxyuserpwd:"");
+ if(result)
+ goto out;
+
+ if(!Curl_checkProxyheaders(data, conn, STRCONST("User-Agent"))
+ && data->set.str[STRING_USERAGENT])
+ result = Curl_dyn_addf(&ts->req, "User-Agent: %s\r\n",
+ data->set.str[STRING_USERAGENT]);
+ if(result)
+ goto out;
+
+ if(!Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection")))
+ result = Curl_dyn_addn(&ts->req,
+ STRCONST("Proxy-Connection: Keep-Alive\r\n"));
+ if(result)
+ goto out;
+
+ result = Curl_add_custom_headers(data, TRUE, &ts->req);
+ if(result)
+ goto out;
+
+ /* CRLF terminate the request */
+ result = Curl_dyn_addn(&ts->req, STRCONST("\r\n"));
+ if(result)
+ goto out;
+
+ /* Send the connect request to the proxy */
+ result = Curl_buffer_send(&ts->req, data, &ts->CONNECT,
+ &data->info.request_size, 0,
+ ts->sockindex);
+ ts->headerlines = 0;
+
+out:
+ if(result)
+ failf(data, "Failed sending CONNECT to proxy");
+ free(host);
+ free(hostheader);
+ return result;
+}
+
+static CURLcode send_CONNECT(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct h1_tunnel_state *ts,
+ bool *done)
+{
+ struct SingleRequest *k = &data->req;
+ struct HTTP *http = &ts->CONNECT;
+ CURLcode result = CURLE_OK;
+
+ if(http->sending != HTTPSEND_REQUEST)
+ goto out;
+
+ if(!ts->nsend) {
+ size_t fillcount;
+ k->upload_fromhere = data->state.ulbuf;
+ result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
+ &fillcount);
+ if(result)
+ goto out;
+ ts->nsend = fillcount;
+ }
+ if(ts->nsend) {
+ ssize_t bytes_written;
+ /* write to socket (send away data) */
+ result = Curl_write(data,
+ conn->writesockfd, /* socket to send to */
+ k->upload_fromhere, /* buffer pointer */
+ ts->nsend, /* buffer size */
+ &bytes_written); /* actually sent */
+ if(result)
+ goto out;
+ /* send to debug callback! */
+ Curl_debug(data, CURLINFO_HEADER_OUT,
+ k->upload_fromhere, bytes_written);
+
+ ts->nsend -= bytes_written;
+ k->upload_fromhere += bytes_written;
+ }
+ if(!ts->nsend)
+ http->sending = HTTPSEND_NADA;
+
+out:
+ if(result)
+ failf(data, "Failed sending CONNECT to proxy");
+ *done = (http->sending != HTTPSEND_REQUEST);
+ return result;
+}
+
+static CURLcode on_resp_header(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h1_tunnel_state *ts,
+ const char *header)
+{
+ CURLcode result = CURLE_OK;
+ struct SingleRequest *k = &data->req;
+ (void)cf;
+
+ if((checkprefix("WWW-Authenticate:", header) &&
+ (401 == k->httpcode)) ||
+ (checkprefix("Proxy-authenticate:", header) &&
+ (407 == k->httpcode))) {
+
+ bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
+ char *auth = Curl_copy_header_value(header);
+ if(!auth)
+ return CURLE_OUT_OF_MEMORY;
+
+ DEBUGF(LOG_CF(data, cf, "CONNECT: fwd auth header '%s'", header));
+ result = Curl_http_input_auth(data, proxy, auth);
+
+ free(auth);
+
+ if(result)
+ return result;
+ }
+ else if(checkprefix("Content-Length:", header)) {
+ 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 */
+ infof(data, "Ignoring Content-Length in CONNECT %03d response",
+ k->httpcode);
+ }
+ else {
+ (void)curlx_strtoofft(header + strlen("Content-Length:"),
+ NULL, 10, &ts->cl);
+ }
+ }
+ else if(Curl_compareheader(header,
+ STRCONST("Connection:"), STRCONST("close")))
+ ts->close_connection = TRUE;
+ else if(checkprefix("Transfer-Encoding:", header)) {
+ 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 */
+ infof(data, "Ignoring Transfer-Encoding in "
+ "CONNECT %03d response", k->httpcode);
+ }
+ else if(Curl_compareheader(header,
+ STRCONST("Transfer-Encoding:"),
+ STRCONST("chunked"))) {
+ infof(data, "CONNECT responded chunked");
+ ts->chunked_encoding = TRUE;
+ /* init our chunky engine */
+ Curl_httpchunk_init(data);
+ }
+ }
+ else if(Curl_compareheader(header,
+ STRCONST("Proxy-Connection:"),
+ STRCONST("close")))
+ ts->close_connection = TRUE;
+ else if(!strncmp(header, "HTTP/1.", 7) &&
+ ((header[7] == '0') || (header[7] == '1')) &&
+ (header[8] == ' ') &&
+ 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 +
+ (header[10] - '0') * 10 + (header[11] - '0');
+ }
+ return result;
+}
+
+static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h1_tunnel_state *ts,
+ bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct SingleRequest *k = &data->req;
+ curl_socket_t tunnelsocket = Curl_conn_cf_get_socket(cf, data);
+ char *linep;
+ size_t perline;
+ int error;
+
+#define SELECT_OK 0
+#define SELECT_ERROR 1
+
+ error = SELECT_OK;
+ *done = FALSE;
+
+ if(!Curl_conn_data_pending(data, ts->sockindex))
+ return CURLE_OK;
+
+ while(ts->keepon) {
+ ssize_t gotbytes;
+ char byte;
+
+ /* Read one byte at a time to avoid a race condition. Wait at most one
+ second before looping to ensure continuous pgrsUpdates. */
+ result = Curl_read(data, tunnelsocket, &byte, 1, &gotbytes);
+ if(result == CURLE_AGAIN)
+ /* socket buffer drained, return */
+ return CURLE_OK;
+
+ if(Curl_pgrsUpdate(data))
+ return CURLE_ABORTED_BY_CALLBACK;
+
+ if(result) {
+ ts->keepon = KEEPON_DONE;
+ break;
+ }
+
+ if(gotbytes <= 0) {
+ if(data->set.proxyauth && data->state.authproxy.avail &&
+ data->state.aptr.proxyuserpwd) {
+ /* proxy auth was requested and there was proxy auth available,
+ then deem this as "mere" proxy disconnect */
+ ts->close_connection = TRUE;
+ infof(data, "Proxy CONNECT connection closed");
+ }
+ else {
+ error = SELECT_ERROR;
+ failf(data, "Proxy CONNECT aborted");
+ }
+ ts->keepon = KEEPON_DONE;
+ break;
+ }
+
+ if(ts->keepon == KEEPON_IGNORE) {
+ /* This means we are currently ignoring a response-body */
+
+ if(ts->cl) {
+ /* A Content-Length based body: simply count down the counter
+ and make sure to break out of the loop when we're done! */
+ ts->cl--;
+ if(ts->cl <= 0) {
+ ts->keepon = KEEPON_DONE;
+ break;
+ }
+ }
+ else {
+ /* chunked-encoded body, so we need to do the chunked dance
+ properly to know when the end of the body is reached */
+ CHUNKcode r;
+ CURLcode extra;
+ ssize_t tookcareof = 0;
+
+ /* now parse the chunked piece of data so that we can
+ properly tell when the stream ends */
+ r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra);
+ if(r == CHUNKE_STOP) {
+ /* we're done reading chunks! */
+ infof(data, "chunk reading DONE");
+ ts->keepon = KEEPON_DONE;
+ }
+ }
+ continue;
+ }
+
+ if(Curl_dyn_addn(&ts->rcvbuf, &byte, 1)) {
+ failf(data, "CONNECT response too large");
+ return CURLE_RECV_ERROR;
+ }
+
+ /* if this is not the end of a header line then continue */
+ if(byte != 0x0a)
+ continue;
+
+ ts->headerlines++;
+ linep = Curl_dyn_ptr(&ts->rcvbuf);
+ perline = Curl_dyn_len(&ts->rcvbuf); /* amount of bytes in this line */
+
+ /* output debug if that is requested */
+ Curl_debug(data, CURLINFO_HEADER_IN, linep, perline);
+
+ if(!data->set.suppress_connect_headers) {
+ /* send the header to the callback */
+ int writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT |
+ (data->set.include_header ? CLIENTWRITE_BODY : 0) |
+ (ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0);
+
+ result = Curl_client_write(data, writetype, linep, perline);
+ if(result)
+ return result;
+ }
+
+ data->info.header_size += (long)perline;
+
+ /* Newlines are CRLF, so the CR is ignored as the line isn't
+ really terminated until the LF comes. Treat a following CR
+ as end-of-headers as well.*/
+
+ if(('\r' == linep[0]) ||
+ ('\n' == linep[0])) {
+ /* end of response-headers from the proxy */
+
+ if((407 == k->httpcode) && !data->state.authproblem) {
+ /* If we get a 407 response code with content length
+ when we have no auth problem, we must ignore the
+ whole response-body */
+ ts->keepon = KEEPON_IGNORE;
+
+ if(ts->cl) {
+ infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
+ " bytes of response-body", ts->cl);
+ }
+ else if(ts->chunked_encoding) {
+ CHUNKcode r;
+ CURLcode extra;
+
+ infof(data, "Ignore chunked response-body");
+
+ /* We set ignorebody true here since the chunked decoder
+ function will acknowledge that. Pay attention so that this is
+ cleared again when this function returns! */
+ k->ignorebody = TRUE;
+
+ if(linep[1] == '\n')
+ /* this can only be a LF if the letter at index 0 was a CR */
+ linep++;
+
+ /* now parse the chunked piece of data so that we can properly
+ tell when the stream ends */
+ r = Curl_httpchunk_read(data, linep + 1, 1, &gotbytes,
+ &extra);
+ if(r == CHUNKE_STOP) {
+ /* we're done reading chunks! */
+ infof(data, "chunk reading DONE");
+ ts->keepon = KEEPON_DONE;
+ }
+ }
+ else {
+ /* without content-length or chunked encoding, we
+ can't keep the connection alive since the close is
+ the end signal so we bail out at once instead */
+ DEBUGF(LOG_CF(data, cf, "CONNECT: no content-length or chunked"));
+ ts->keepon = KEEPON_DONE;
+ }
+ }
+ else {
+ ts->keepon = KEEPON_DONE;
+ }
+
+ DEBUGASSERT(ts->keepon == KEEPON_IGNORE
+ || ts->keepon == KEEPON_DONE);
+ continue;
+ }
+
+ result = on_resp_header(cf, data, ts, linep);
+ if(result)
+ return result;
+
+ Curl_dyn_reset(&ts->rcvbuf);
+ } /* while there's buffer left and loop is requested */
+
+ if(error)
+ result = CURLE_RECV_ERROR;
+ *done = (ts->keepon == KEEPON_DONE);
+ 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);
+ }
+ return result;
+}
+
+#else /* USE_HYPER */
+/* The Hyper version of CONNECT */
+static CURLcode start_CONNECT(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h1_tunnel_state *ts)
+{
+ struct connectdata *conn = cf->conn;
+ struct hyptransfer *h = &data->hyp;
+ curl_socket_t tunnelsocket = Curl_conn_cf_get_socket(cf, data);
+ hyper_io *io = NULL;
+ hyper_request *req = NULL;
+ hyper_headers *headers = NULL;
+ hyper_clientconn_options *options = NULL;
+ hyper_task *handshake = NULL;
+ hyper_task *task = NULL; /* for the handshake */
+ hyper_clientconn *client = NULL;
+ hyper_task *sendtask = NULL; /* for the send */
+ char *hostheader = NULL; /* for CONNECT */
+ char *host = NULL; /* Host: */
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+
+ io = hyper_io_new();
+ if(!io) {
+ failf(data, "Couldn't create hyper IO");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ /* tell Hyper how to read/write network data */
+ hyper_io_set_userdata(io, data);
+ hyper_io_set_read(io, Curl_hyper_recv);
+ hyper_io_set_write(io, Curl_hyper_send);
+ conn->sockfd = tunnelsocket;
+
+ data->state.hconnect = TRUE;
+
+ /* create an executor to poll futures */
+ if(!h->exec) {
+ h->exec = hyper_executor_new();
+ if(!h->exec) {
+ failf(data, "Couldn't create hyper executor");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ }
+
+ options = hyper_clientconn_options_new();
+ hyper_clientconn_options_set_preserve_header_case(options, 1);
+ hyper_clientconn_options_set_preserve_header_order(options, 1);
+
+ if(!options) {
+ failf(data, "Couldn't create hyper client options");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+
+ hyper_clientconn_options_exec(options, h->exec);
+
+ /* "Both the `io` and the `options` are consumed in this function
+ call" */
+ handshake = hyper_clientconn_handshake(io, options);
+ if(!handshake) {
+ failf(data, "Couldn't create hyper client handshake");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ io = NULL;
+ options = NULL;
+
+ if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
+ failf(data, "Couldn't hyper_executor_push the handshake");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ handshake = NULL; /* ownership passed on */
+
+ task = hyper_executor_poll(h->exec);
+ if(!task) {
+ failf(data, "Couldn't hyper_executor_poll the handshake");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+
+ client = hyper_task_value(task);
+ hyper_task_free(task);
+ req = hyper_request_new();
+ if(!req) {
+ failf(data, "Couldn't hyper_request_new");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ if(hyper_request_set_method(req, (uint8_t *)"CONNECT",
+ strlen("CONNECT"))) {
+ failf(data, "error setting method");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+
+ infof(data, "Establish HTTP proxy tunnel to %s:%d",
+ ts->hostname, ts->remote_port);
+
+ /* This only happens if we've looped here due to authentication
+ reasons, and we don't really use the newly cloned URL here
+ then. Just free() it. */
+ Curl_safefree(data->req.newurl);
+
+ result = CONNECT_host(data, conn, ts->hostname, ts->remote_port,
+ &hostheader, &host);
+ if(result)
+ goto error;
+
+ if(hyper_request_set_uri(req, (uint8_t *)hostheader,
+ strlen(hostheader))) {
+ failf(data, "error setting path");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ if(data->set.verbose) {
+ char *se = aprintf("CONNECT %s HTTP/1.1\r\n", hostheader);
+ if(!se) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ Curl_debug(data, CURLINFO_HEADER_OUT, se, strlen(se));
+ free(se);
+ }
+ /* Setup the proxy-authorization header, if any */
+ result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
+ hostheader, TRUE);
+ if(result)
+ goto error;
+ Curl_safefree(hostheader);
+
+ /* default is 1.1 */
+ if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) &&
+ (HYPERE_OK != hyper_request_set_version(req,
+ HYPER_HTTP_VERSION_1_0))) {
+ failf(data, "error setting HTTP version");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+
+ headers = hyper_request_headers(req);
+ if(!headers) {
+ failf(data, "hyper_request_headers");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ if(host) {
+ result = Curl_hyper_header(data, headers, host);
+ if(result)
+ goto error;
+ Curl_safefree(host);
+ }
+
+ if(data->state.aptr.proxyuserpwd) {
+ result = Curl_hyper_header(data, headers,
+ data->state.aptr.proxyuserpwd);
+ if(result)
+ goto error;
+ }
+
+ if(!Curl_checkProxyheaders(data, conn, STRCONST("User-Agent")) &&
+ data->set.str[STRING_USERAGENT]) {
+ struct dynbuf ua;
+ Curl_dyn_init(&ua, DYN_HTTP_REQUEST);
+ result = Curl_dyn_addf(&ua, "User-Agent: %s\r\n",
+ data->set.str[STRING_USERAGENT]);
+ if(result)
+ goto error;
+ result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&ua));
+ if(result)
+ goto error;
+ Curl_dyn_free(&ua);
+ }
+
+ if(!Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection"))) {
+ result = Curl_hyper_header(data, headers,
+ "Proxy-Connection: Keep-Alive");
+ if(result)
+ goto error;
+ }
+
+ result = Curl_add_custom_headers(data, TRUE, headers);
+ if(result)
+ goto error;
+
+ sendtask = hyper_clientconn_send(client, req);
+ if(!sendtask) {
+ failf(data, "hyper_clientconn_send");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+
+ if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
+ failf(data, "Couldn't hyper_executor_push the send");
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+
+error:
+ free(host);
+ free(hostheader);
+ if(io)
+ hyper_io_free(io);
+ if(options)
+ hyper_clientconn_options_free(options);
+ if(handshake)
+ hyper_task_free(handshake);
+ if(client)
+ hyper_clientconn_free(client);
+ return result;
+}
+
+static CURLcode send_CONNECT(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct h1_tunnel_state *ts,
+ bool *done)
+{
+ struct hyptransfer *h = &data->hyp;
+ hyper_task *task = NULL;
+ hyper_error *hypererr = NULL;
+ CURLcode result = CURLE_OK;
+
+ (void)ts;
+ (void)conn;
+ do {
+ task = hyper_executor_poll(h->exec);
+ if(task) {
+ bool error = hyper_task_type(task) == HYPER_TASK_ERROR;
+ if(error)
+ hypererr = hyper_task_value(task);
+ hyper_task_free(task);
+ if(error) {
+ /* this could probably use a better error code? */
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ }
+ } while(task);
+error:
+ *done = (result == CURLE_OK);
+ if(hypererr) {
+ uint8_t errbuf[256];
+ size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
+ failf(data, "Hyper: %.*s", (int)errlen, errbuf);
+ hyper_error_free(hypererr);
+ }
+ return result;
+}
+
+static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h1_tunnel_state *ts,
+ bool *done)
+{
+ struct hyptransfer *h = &data->hyp;
+ CURLcode result;
+ int didwhat;
+
+ (void)ts;
+ *done = FALSE;
+ result = Curl_hyper_stream(data, cf->conn, &didwhat, done,
+ CURL_CSELECT_IN | CURL_CSELECT_OUT);
+ if(result || !*done)
+ return result;
+ if(h->exec) {
+ hyper_executor_free(h->exec);
+ h->exec = NULL;
+ }
+ if(h->read_waker) {
+ hyper_waker_free(h->read_waker);
+ h->read_waker = NULL;
+ }
+ if(h->write_waker) {
+ hyper_waker_free(h->write_waker);
+ h->write_waker = NULL;
+ }
+ return result;
+}
+
+#endif /* USE_HYPER */
+
+static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h1_tunnel_state *ts)
+{
+ struct connectdata *conn = cf->conn;
+ CURLcode result;
+ bool done;
+
+ if(tunnel_is_established(ts))
+ return CURLE_OK;
+ if(tunnel_is_failed(ts))
+ return CURLE_RECV_ERROR; /* Need a cfilter close and new bootstrap */
+
+ do {
+ timediff_t check;
+
+ check = Curl_timeleft(data, NULL, TRUE);
+ if(check <= 0) {
+ failf(data, "Proxy CONNECT aborted due to timeout");
+ result = CURLE_OPERATION_TIMEDOUT;
+ goto out;
+ }
+
+ switch(ts->tunnel_state) {
+ case H1_TUNNEL_INIT:
+ /* Prepare the CONNECT request and make a first attempt to send. */
+ DEBUGF(LOG_CF(data, cf, "CONNECT start"));
+ result = start_CONNECT(cf, data, ts);
+ if(result)
+ goto out;
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_CONNECT, data);
+ /* FALLTHROUGH */
+
+ case H1_TUNNEL_CONNECT:
+ /* see that the request is completely sent */
+ DEBUGF(LOG_CF(data, cf, "CONNECT send"));
+ result = send_CONNECT(data, cf->conn, ts, &done);
+ if(result || !done)
+ goto out;
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_RECEIVE, data);
+ /* FALLTHROUGH */
+
+ case H1_TUNNEL_RECEIVE:
+ /* read what is there */
+ DEBUGF(LOG_CF(data, cf, "CONNECT receive"));
+ result = recv_CONNECT_resp(cf, data, ts, &done);
+ if(Curl_pgrsUpdate(data)) {
+ result = CURLE_ABORTED_BY_CALLBACK;
+ goto out;
+ }
+ /* error or not complete yet. return for more multi-multi */
+ if(result || !done)
+ goto out;
+ /* got it */
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_RESPONSE, data);
+ /* FALLTHROUGH */
+
+ case H1_TUNNEL_RESPONSE:
+ DEBUGF(LOG_CF(data, cf, "CONNECT response"));
+ if(data->req.newurl) {
+ /* not the "final" response, we need to do a follow up request.
+ * If the other side indicated a connection close, or if someone
+ * else told us to close this connection, do so now.
+ */
+ if(ts->close_connection || conn->bits.close) {
+ /* Close this filter and the sub-chain, re-connect the
+ * sub-chain and continue. Closing this filter will
+ * reset our tunnel state. To avoid recursion, we return
+ * and expect to be called again.
+ */
+ DEBUGF(LOG_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, FALSE, &done);
+ goto out;
+ }
+ else {
+ /* staying on this connection, reset state */
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_INIT, data);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ } while(data->req.newurl);
+
+ DEBUGASSERT(ts->tunnel_state == H1_TUNNEL_RESPONSE);
+ 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 re-use */
+ 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;
+ }
+ /* 2xx response, SUCCESS! */
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_ESTABLISHED, data);
+ infof(data, "CONNECT tunnel established, response %d",
+ data->info.httpproxycode);
+ result = CURLE_OK;
+
+out:
+ if(result)
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
+ return result;
+}
+
+static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ CURLcode result;
+ struct h1_tunnel_state *ts = cf->ctx;
+
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ DEBUGF(LOG_CF(data, cf, "connect"));
+ result = cf->next->cft->do_connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ return result;
+
+ *done = FALSE;
+ if(!ts) {
+ result = tunnel_init(&ts, data, cf->conn, cf->sockindex);
+ if(result)
+ return result;
+ cf->ctx = ts;
+ }
+
+ /* TODO: can we do blocking? */
+ /* We want "seamless" operations through HTTP proxy tunnel */
+
+ result = H1_CONNECT(cf, data, ts);
+ if(result)
+ goto out;
+ Curl_safefree(data->state.aptr.proxyuserpwd);
+
+out:
+ *done = (result == CURLE_OK) && tunnel_is_established(cf->ctx);
+ if(*done) {
+ cf->connected = TRUE;
+ tunnel_free(cf, data);
+ }
+ return result;
+}
+
+static int cf_h1_proxy_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ struct h1_tunnel_state *ts = cf->ctx;
+ int fds;
+
+ fds = cf->next->cft->get_select_socks(cf->next, data, socks);
+ if(!fds && cf->next->connected && !cf->connected) {
+ /* If we are not connected, but the filter "below" is
+ * and not waiting on something, we are tunneling. */
+ socks[0] = Curl_conn_cf_get_socket(cf, data);
+ if(ts) {
+ /* when we've sent a CONNECT to a proxy, we should rather either
+ wait for the socket to become readable to be able to get the
+ response headers or if we're still sending the request, wait
+ for write. */
+ if(ts->CONNECT.sending == HTTPSEND_REQUEST) {
+ return GETSOCK_WRITESOCK(0);
+ }
+ return GETSOCK_READSOCK(0);
+ }
+ return GETSOCK_WRITESOCK(0);
+ }
+ return fds;
+}
+
+static void cf_h1_proxy_destroy(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ DEBUGF(LOG_CF(data, cf, "destroy"));
+ tunnel_free(cf, data);
+}
+
+static void cf_h1_proxy_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ DEBUGF(LOG_CF(data, cf, "close"));
+ cf->connected = FALSE;
+ if(cf->ctx) {
+ h1_tunnel_go_state(cf, cf->ctx, H1_TUNNEL_INIT, data);
+ }
+ if(cf->next)
+ cf->next->cft->do_close(cf->next, data);
+}
+
+
+struct Curl_cftype Curl_cft_h1_proxy = {
+ "H1-PROXY",
+ CF_TYPE_IP_CONNECT,
+ 0,
+ cf_h1_proxy_destroy,
+ cf_h1_proxy_connect,
+ cf_h1_proxy_close,
+ Curl_cf_http_proxy_get_host,
+ cf_h1_proxy_get_select_socks,
+ Curl_cf_def_data_pending,
+ Curl_cf_def_send,
+ Curl_cf_def_recv,
+ Curl_cf_def_cntrl,
+ Curl_cf_def_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ Curl_cf_def_query,
+};
+
+CURLcode Curl_cf_h1_proxy_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result;
+
+ (void)data;
+ result = Curl_cf_create(&cf, &Curl_cft_h1_proxy, NULL);
+ if(!result)
+ Curl_conn_cf_insert_after(cf_at, cf);
+ return result;
+}
+
+#endif /* !CURL_DISABLE_PROXY && ! CURL_DISABLE_HTTP */
diff --git a/lib/vquic/msh3.h b/lib/cf-h1-proxy.h
similarity index 68%
copy from lib/vquic/msh3.h
copy to lib/cf-h1-proxy.h
index ce884d9..ac5bed0 100644
--- a/lib/vquic/msh3.h
+++ b/lib/cf-h1-proxy.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_VQUIC_MSH3_H
-#define HEADER_CURL_VQUIC_MSH3_H
+#ifndef HEADER_CURL_H1_PROXY_H
+#define HEADER_CURL_H1_PROXY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,15 +26,14 @@
#include "curl_setup.h"
-#ifdef USE_MSH3
+#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
-#include <msh3.h>
+CURLcode Curl_cf_h1_proxy_insert_after(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
-struct quicsocket {
- MSH3_API* api;
- MSH3_CONNECTION* conn;
-};
+extern struct Curl_cftype Curl_cft_h1_proxy;
-#endif /* USE_MSQUIC */
-#endif /* HEADER_CURL_VQUIC_MSH3_H */
+#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
new file mode 100644
index 0000000..f6acfc5
--- /dev/null
+++ b/lib/cf-h2-proxy.c
@@ -0,0 +1,1483 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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_NGHTTP2) && !defined(CURL_DISABLE_PROXY)
+
+#include <nghttp2/nghttp2.h>
+#include "urldata.h"
+#include "cfilters.h"
+#include "connect.h"
+#include "curl_log.h"
+#include "bufq.h"
+#include "dynbuf.h"
+#include "dynhds.h"
+#include "http1.h"
+#include "http_proxy.h"
+#include "multiif.h"
+#include "cf-h2-proxy.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define 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 / H2_CHUNK_SIZE)
+#define PROXY_H2_NW_SEND_CHUNKS 1
+
+#define H2_TUNNEL_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / H2_CHUNK_SIZE)
+#define H2_TUNNEL_SEND_CHUNKS ((128 * 1024) / H2_CHUNK_SIZE)
+
+
+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_state;
+
+struct tunnel_stream {
+ struct http_resp *resp;
+ struct bufq recvbuf;
+ struct bufq sendbuf;
+ char *authority;
+ int32_t stream_id;
+ uint32_t error;
+ size_t upload_blocked_len;
+ h2_tunnel_state state;
+ BIT(has_final_response);
+ BIT(closed);
+ BIT(reset);
+};
+
+static CURLcode tunnel_stream_init(struct Curl_cfilter *cf,
+ struct tunnel_stream *ts)
+{
+ const char *hostname;
+ int port;
+ bool ipv6_ip = cf->conn->bits.ipv6_ip;
+
+ ts->state = H2_TUNNEL_INIT;
+ ts->stream_id = -1;
+ Curl_bufq_init2(&ts->recvbuf, H2_CHUNK_SIZE, H2_TUNNEL_RECV_CHUNKS,
+ BUFQ_OPT_SOFT_LIMIT);
+ Curl_bufq_init(&ts->sendbuf, H2_CHUNK_SIZE, H2_TUNNEL_SEND_CHUNKS);
+
+ if(cf->conn->bits.conn_to_host)
+ hostname = cf->conn->conn_to_host.name;
+ else if(cf->sockindex == SECONDARYSOCKET)
+ hostname = cf->conn->secondaryhostname;
+ else
+ hostname = cf->conn->host.name;
+
+ if(cf->sockindex == SECONDARYSOCKET)
+ port = cf->conn->secondary_port;
+ else if(cf->conn->bits.conn_to_port)
+ port = cf->conn->conn_to_port;
+ else
+ port = cf->conn->remote_port;
+
+ if(hostname != cf->conn->host.name)
+ ipv6_ip = (strchr(hostname, ':') != NULL);
+
+ ts->authority = /* host:port with IPv6 support */
+ aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"", port);
+ if(!ts->authority)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+static void tunnel_stream_clear(struct tunnel_stream *ts)
+{
+ Curl_http_resp_free(ts->resp);
+ Curl_bufq_free(&ts->recvbuf);
+ Curl_bufq_free(&ts->sendbuf);
+ Curl_safefree(ts->authority);
+ memset(ts, 0, sizeof(*ts));
+ ts->state = H2_TUNNEL_INIT;
+}
+
+static void h2_tunnel_go_state(struct Curl_cfilter *cf,
+ struct tunnel_stream *ts,
+ h2_tunnel_state new_state,
+ struct Curl_easy *data)
+{
+ (void)cf;
+
+ if(ts->state == new_state)
+ return;
+ /* leaving this one */
+ switch(ts->state) {
+ case H2_TUNNEL_CONNECT:
+ data->req.ignorebody = FALSE;
+ break;
+ default:
+ break;
+ }
+ /* entering this one */
+ switch(new_state) {
+ case H2_TUNNEL_INIT:
+ DEBUGF(LOG_CF(data, cf, "new tunnel state 'init'"));
+ tunnel_stream_clear(ts);
+ break;
+
+ case H2_TUNNEL_CONNECT:
+ DEBUGF(LOG_CF(data, cf, "new tunnel state 'connect'"));
+ ts->state = H2_TUNNEL_CONNECT;
+ break;
+
+ case H2_TUNNEL_RESPONSE:
+ DEBUGF(LOG_CF(data, cf, "new tunnel state 'response'"));
+ ts->state = H2_TUNNEL_RESPONSE;
+ break;
+
+ case H2_TUNNEL_ESTABLISHED:
+ DEBUGF(LOG_CF(data, cf, "new tunnel state 'established'"));
+ infof(data, "CONNECT phase completed");
+ data->state.authproxy.done = TRUE;
+ data->state.authproxy.multipass = FALSE;
+ /* FALLTHROUGH */
+ case H2_TUNNEL_FAILED:
+ if(new_state == H2_TUNNEL_FAILED)
+ DEBUGF(LOG_CF(data, cf, "new tunnel state 'failed'"));
+ ts->state = new_state;
+ /* If a proxy-authorization header was used for the proxy, then we should
+ make sure that it isn't accidentally used for the document request
+ after we've connected. So let's free and clear it here. */
+ Curl_safefree(data->state.aptr.proxyuserpwd);
+ break;
+ }
+}
+
+struct cf_h2_proxy_ctx {
+ nghttp2_session *h2;
+ /* The easy handle used in the current filter call, cleared at return */
+ struct cf_call_data call_data;
+
+ struct bufq inbufq; /* network receive buffer */
+ struct bufq outbufq; /* network send buffer */
+
+ struct tunnel_stream tunnel; /* our tunnel CONNECT stream */
+ int32_t goaway_error;
+ int32_t last_stream_id;
+ BIT(conn_closed);
+ BIT(goaway);
+ BIT(nw_out_blocked);
+};
+
+/* 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
+
+static void cf_h2_proxy_ctx_clear(struct cf_h2_proxy_ctx *ctx)
+{
+ struct cf_call_data save = ctx->call_data;
+
+ if(ctx->h2) {
+ nghttp2_session_del(ctx->h2);
+ }
+ Curl_bufq_free(&ctx->inbufq);
+ Curl_bufq_free(&ctx->outbufq);
+ tunnel_stream_clear(&ctx->tunnel);
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->call_data = save;
+}
+
+static void cf_h2_proxy_ctx_free(struct cf_h2_proxy_ctx *ctx)
+{
+ if(ctx) {
+ cf_h2_proxy_ctx_clear(ctx);
+ free(ctx);
+ }
+}
+
+static void drain_tunnel(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct tunnel_stream *tunnel)
+{
+ unsigned char bits;
+
+ (void)cf;
+ bits = CURL_CSELECT_IN;
+ if(!tunnel->closed && !tunnel->reset && tunnel->upload_blocked_len)
+ bits |= CURL_CSELECT_OUT;
+ if(data->state.dselect_bits != bits) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] DRAIN dselect_bits=%x",
+ tunnel->stream_id, bits));
+ data->state.dselect_bits = bits;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+}
+
+static ssize_t proxy_nw_in_reader(void *reader_ctx,
+ unsigned char *buf, size_t buflen,
+ CURLcode *err)
+{
+ struct Curl_cfilter *cf = reader_ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nread;
+
+ nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, buflen, err);
+ DEBUGF(LOG_CF(data, cf, "nw_in_reader(len=%zu) -> %zd, %d",
+ buflen, nread, *err));
+ return nread;
+}
+
+static ssize_t proxy_h2_nw_out_writer(void *writer_ctx,
+ const unsigned char *buf, size_t buflen,
+ CURLcode *err)
+{
+ struct Curl_cfilter *cf = writer_ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nwritten;
+
+ nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err);
+ DEBUGF(LOG_CF(data, cf, "nw_out_writer(len=%zu) -> %zd, %d",
+ buflen, nwritten, *err));
+ return nwritten;
+}
+
+static int proxy_h2_client_new(struct Curl_cfilter *cf,
+ nghttp2_session_callbacks *cbs)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ nghttp2_option *o;
+
+ int rc = nghttp2_option_new(&o);
+ if(rc)
+ return rc;
+ /* We handle window updates ourself to enforce buffer limits */
+ nghttp2_option_set_no_auto_window_update(o, 1);
+#if NGHTTP2_VERSION_NUM >= 0x013200
+ /* with 1.50.0 */
+ /* turn off RFC 9113 leading and trailing white spaces validation against
+ HTTP field value. */
+ nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(o, 1);
+#endif
+ rc = nghttp2_session_client_new2(&ctx->h2, cbs, cf, o);
+ nghttp2_option_del(o);
+ return rc;
+}
+
+static ssize_t on_session_send(nghttp2_session *h2,
+ const uint8_t *buf, size_t blen,
+ int flags, void *userp);
+static int proxy_h2_on_frame_recv(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *userp);
+static int proxy_h2_on_stream_close(nghttp2_session *session,
+ int32_t stream_id,
+ uint32_t error_code, void *userp);
+static int proxy_h2_on_header(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ const uint8_t *name, size_t namelen,
+ const uint8_t *value, size_t valuelen,
+ uint8_t flags,
+ void *userp);
+static int tunnel_recv_callback(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const uint8_t *mem, size_t len, void *userp);
+
+/*
+ * Initialize the cfilter context
+ */
+static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+ nghttp2_session_callbacks *cbs = NULL;
+ int rc;
+
+ DEBUGASSERT(!ctx->h2);
+ memset(&ctx->tunnel, 0, sizeof(ctx->tunnel));
+
+ Curl_bufq_init(&ctx->inbufq, H2_CHUNK_SIZE, PROXY_H2_NW_RECV_CHUNKS);
+ Curl_bufq_init(&ctx->outbufq, H2_CHUNK_SIZE, PROXY_H2_NW_SEND_CHUNKS);
+
+ if(tunnel_stream_init(cf, &ctx->tunnel))
+ goto out;
+
+ rc = nghttp2_session_callbacks_new(&cbs);
+ if(rc) {
+ failf(data, "Couldn't initialize nghttp2 callbacks");
+ goto out;
+ }
+
+ nghttp2_session_callbacks_set_send_callback(cbs, on_session_send);
+ nghttp2_session_callbacks_set_on_frame_recv_callback(
+ cbs, proxy_h2_on_frame_recv);
+ nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
+ cbs, tunnel_recv_callback);
+ nghttp2_session_callbacks_set_on_stream_close_callback(
+ cbs, proxy_h2_on_stream_close);
+ nghttp2_session_callbacks_set_on_header_callback(cbs, proxy_h2_on_header);
+
+ /* The nghttp2 session is not yet setup, do it */
+ rc = proxy_h2_client_new(cf, cbs);
+ if(rc) {
+ failf(data, "Couldn't initialize nghttp2");
+ goto out;
+ }
+
+ {
+ nghttp2_settings_entry iv[3];
+
+ 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_TUNNEL_WINDOW_SIZE;
+ iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
+ iv[2].value = 0;
+ rc = nghttp2_submit_settings(ctx->h2, NGHTTP2_FLAG_NONE, iv, 3);
+ if(rc) {
+ failf(data, "nghttp2_submit_settings() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ result = CURLE_HTTP2;
+ goto out;
+ }
+ }
+
+ rc = nghttp2_session_set_local_window_size(ctx->h2, NGHTTP2_FLAG_NONE, 0,
+ PROXY_HTTP2_HUGE_WINDOW_SIZE);
+ if(rc) {
+ failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ result = CURLE_HTTP2;
+ goto out;
+ }
+
+
+ /* all set, traffic will be send on connect */
+ result = CURLE_OK;
+
+out:
+ if(cbs)
+ nghttp2_session_callbacks_del(cbs);
+ DEBUGF(LOG_CF(data, cf, "init proxy ctx -> %d", result));
+ return result;
+}
+
+static int should_close_session(struct cf_h2_proxy_ctx *ctx)
+{
+ return !nghttp2_session_want_read(ctx->h2) &&
+ !nghttp2_session_want_write(ctx->h2);
+}
+
+static CURLcode proxy_h2_nw_out_flush(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ ssize_t nwritten;
+ CURLcode result;
+
+ (void)data;
+ if(Curl_bufq_is_empty(&ctx->outbufq))
+ return CURLE_OK;
+
+ nwritten = Curl_bufq_pass(&ctx->outbufq, proxy_h2_nw_out_writer, cf,
+ &result);
+ if(nwritten < 0) {
+ if(result == CURLE_AGAIN) {
+ DEBUGF(LOG_CF(data, cf, "flush nw send buffer(%zu) -> EAGAIN",
+ Curl_bufq_len(&ctx->outbufq)));
+ ctx->nw_out_blocked = 1;
+ }
+ return result;
+ }
+ DEBUGF(LOG_CF(data, cf, "nw send buffer flushed"));
+ return Curl_bufq_is_empty(&ctx->outbufq)? CURLE_OK: CURLE_AGAIN;
+}
+
+/*
+ * Processes pending input left in network input buffer.
+ * 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)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ const unsigned char *buf;
+ size_t blen;
+ ssize_t rv;
+
+ while(Curl_bufq_peek(&ctx->inbufq, &buf, &blen)) {
+
+ rv = nghttp2_session_mem_recv(ctx->h2, (const uint8_t *)buf, blen);
+ DEBUGF(LOG_CF(data, cf,
+ "fed %zu bytes from nw to nghttp2 -> %zd", blen, rv));
+ if(rv < 0) {
+ failf(data,
+ "process_pending_input: nghttp2_session_mem_recv() returned "
+ "%zd:%s", rv, nghttp2_strerror((int)rv));
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+ Curl_bufq_skip(&ctx->inbufq, (size_t)rv);
+ if(Curl_bufq_is_empty(&ctx->inbufq)) {
+ DEBUGF(LOG_CF(data, cf, "all data in connection buffer processed"));
+ break;
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "process_pending_input: %zu bytes left "
+ "in connection buffer", Curl_bufq_len(&ctx->inbufq)));
+ }
+ }
+
+ return 0;
+}
+
+static CURLcode proxy_h2_progress_ingress(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+ ssize_t nread;
+
+ /* Process network input buffer fist */
+ if(!Curl_bufq_is_empty(&ctx->inbufq)) {
+ DEBUGF(LOG_CF(data, cf, "Process %zu bytes in connection buffer",
+ Curl_bufq_len(&ctx->inbufq)));
+ if(proxy_h2_process_pending_input(cf, data, &result) < 0)
+ 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 */
+ Curl_bufq_is_empty(&ctx->inbufq) && /* and we consumed our input */
+ !Curl_bufq_is_full(&ctx->tunnel.recvbuf)) {
+
+ nread = Curl_bufq_slurp(&ctx->inbufq, proxy_nw_in_reader, cf, &result);
+ DEBUGF(LOG_CF(data, cf, "read %zu bytes nw data -> %zd, %d",
+ Curl_bufq_len(&ctx->inbufq), nread, result));
+ if(nread < 0) {
+ if(result != CURLE_AGAIN) {
+ failf(data, "Failed receiving HTTP2 data");
+ return result;
+ }
+ break;
+ }
+ else if(nread == 0) {
+ ctx->conn_closed = TRUE;
+ break;
+ }
+
+ if(proxy_h2_process_pending_input(cf, data, &result))
+ return result;
+ }
+
+ if(ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) {
+ connclose(cf->conn, "GOAWAY received");
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode proxy_h2_progress_egress(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ int rv = 0;
+
+ ctx->nw_out_blocked = 0;
+ while(!rv && !ctx->nw_out_blocked && nghttp2_session_want_write(ctx->h2))
+ rv = nghttp2_session_send(ctx->h2);
+
+ if(nghttp2_is_fatal(rv)) {
+ DEBUGF(LOG_CF(data, cf, "nghttp2_session_send error (%s)%d",
+ nghttp2_strerror(rv), rv));
+ return CURLE_SEND_ERROR;
+ }
+ return proxy_h2_nw_out_flush(cf, data);
+}
+
+static ssize_t on_session_send(nghttp2_session *h2,
+ const uint8_t *buf, size_t blen, int flags,
+ void *userp)
+{
+ struct Curl_cfilter *cf = userp;
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nwritten;
+ CURLcode result = CURLE_OK;
+
+ (void)h2;
+ (void)flags;
+ DEBUGASSERT(data);
+
+ nwritten = Curl_bufq_write_pass(&ctx->outbufq, buf, blen,
+ proxy_h2_nw_out_writer, cf, &result);
+ if(nwritten < 0) {
+ if(result == CURLE_AGAIN) {
+ return NGHTTP2_ERR_WOULDBLOCK;
+ }
+ failf(data, "Failed sending HTTP2 data");
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ if(!nwritten)
+ return NGHTTP2_ERR_WOULDBLOCK;
+
+ return nwritten;
+}
+
+static int proxy_h2_on_frame_recv(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *userp)
+{
+ struct Curl_cfilter *cf = userp;
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ int32_t stream_id = frame->hd.stream_id;
+
+ (void)session;
+ DEBUGASSERT(data);
+ if(!stream_id) {
+ /* stream ID zero is for connection-oriented stuff */
+ DEBUGASSERT(data);
+ switch(frame->hd.type) {
+ case NGHTTP2_SETTINGS:
+ /* we do not do anything with this for now */
+ break;
+ case NGHTTP2_GOAWAY:
+ infof(data, "recveived GOAWAY, error=%d, last_stream=%u",
+ frame->goaway.error_code, frame->goaway.last_stream_id);
+ ctx->goaway = TRUE;
+ break;
+ case NGHTTP2_WINDOW_UPDATE:
+ DEBUGF(LOG_CF(data, cf, "recv frame WINDOW_UPDATE"));
+ break;
+ default:
+ DEBUGF(LOG_CF(data, cf, "recv frame %x on 0", frame->hd.type));
+ }
+ return 0;
+ }
+
+ if(stream_id != ctx->tunnel.stream_id) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] rcvd FRAME not for tunnel",
+ stream_id));
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ switch(frame->hd.type) {
+ case NGHTTP2_DATA:
+ /* If body started on this stream, then receiving DATA is illegal. */
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv frame DATA", stream_id));
+ break;
+ case NGHTTP2_HEADERS:
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv frame HEADERS", stream_id));
+
+ /* nghttp2 guarantees that :status is received, and we store it to
+ stream->status_code. Fuzzing has proven this can still be reached
+ without status code having been set. */
+ if(!ctx->tunnel.resp)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ /* Only final status code signals the end of header */
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] got http status: %d",
+ stream_id, ctx->tunnel.resp->status));
+ if(!ctx->tunnel.has_final_response) {
+ if(ctx->tunnel.resp->status / 100 != 1) {
+ ctx->tunnel.has_final_response = TRUE;
+ }
+ }
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv PUSH_PROMISE", stream_id));
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ case NGHTTP2_RST_STREAM:
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv RST", stream_id));
+ ctx->tunnel.reset = TRUE;
+ break;
+ case NGHTTP2_WINDOW_UPDATE:
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv WINDOW_UPDATE", stream_id));
+ if((data->req.keepon & KEEP_SEND_HOLD) &&
+ (data->req.keepon & KEEP_SEND)) {
+ data->req.keepon &= ~KEEP_SEND_HOLD;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] unpausing after win update",
+ stream_id));
+ }
+ break;
+ default:
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv frame %x",
+ stream_id, frame->hd.type));
+ break;
+ }
+ return 0;
+}
+
+static int proxy_h2_on_header(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ const uint8_t *name, size_t namelen,
+ const uint8_t *value, size_t valuelen,
+ uint8_t flags,
+ void *userp)
+{
+ struct Curl_cfilter *cf = userp;
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ int32_t stream_id = frame->hd.stream_id;
+ CURLcode result;
+
+ (void)flags;
+ (void)data;
+ (void)session;
+ DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
+ if(stream_id != ctx->tunnel.stream_id) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] header for non-tunnel stream: "
+ "%.*s: %.*s", stream_id,
+ (int)namelen, name,
+ (int)valuelen, value));
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ if(frame->hd.type == NGHTTP2_PUSH_PROMISE)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+
+ if(ctx->tunnel.has_final_response) {
+ /* we do not do anything with trailers for tunnel streams */
+ return 0;
+ }
+
+ if(namelen == sizeof(HTTP_PSEUDO_STATUS) - 1 &&
+ memcmp(HTTP_PSEUDO_STATUS, name, namelen) == 0) {
+ int http_status;
+ struct http_resp *resp;
+
+ /* status: always comes first, we might get more than one response,
+ * link the previous ones for keepers */
+ result = Curl_http_decode_status(&http_status,
+ (const char *)value, valuelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_http_resp_make(&resp, http_status, NULL);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ resp->prev = ctx->tunnel.resp;
+ ctx->tunnel.resp = resp;
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] status: HTTP/2 %03d",
+ stream_id, ctx->tunnel.resp->status));
+ return 0;
+ }
+
+ if(!ctx->tunnel.resp)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+
+ result = Curl_dynhds_add(&ctx->tunnel.resp->headers,
+ (const char *)name, namelen,
+ (const char *)value, valuelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] header: %.*s: %.*s",
+ stream_id,
+ (int)namelen, name,
+ (int)valuelen, value));
+
+ return 0; /* 0 is successful */
+}
+
+static ssize_t tunnel_send_callback(nghttp2_session *session,
+ int32_t stream_id,
+ uint8_t *buf, size_t length,
+ uint32_t *data_flags,
+ nghttp2_data_source *source,
+ void *userp)
+{
+ struct Curl_cfilter *cf = userp;
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ struct tunnel_stream *ts;
+ CURLcode result;
+ ssize_t nread;
+
+ (void)source;
+ (void)data;
+ (void)ctx;
+
+ if(!stream_id)
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+
+ ts = nghttp2_session_get_stream_user_data(session, stream_id);
+ if(!ts)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ DEBUGASSERT(ts == &ctx->tunnel);
+
+ nread = Curl_bufq_read(&ts->sendbuf, buf, length, &result);
+ if(nread < 0) {
+ if(result != CURLE_AGAIN)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ return NGHTTP2_ERR_DEFERRED;
+ }
+ if(ts->closed && Curl_bufq_is_empty(&ts->sendbuf))
+ *data_flags = NGHTTP2_DATA_FLAG_EOF;
+
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] tunnel_send_callback -> %zd",
+ ts->stream_id, nread));
+ return nread;
+}
+
+static int tunnel_recv_callback(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const uint8_t *mem, size_t len, void *userp)
+{
+ struct Curl_cfilter *cf = userp;
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ ssize_t nwritten;
+ CURLcode result;
+
+ (void)flags;
+ (void)session;
+ DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
+
+ if(stream_id != ctx->tunnel.stream_id)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+
+ nwritten = Curl_bufq_write(&ctx->tunnel.recvbuf, mem, len, &result);
+ if(nwritten < 0) {
+ if(result != CURLE_AGAIN)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ nwritten = 0;
+ }
+ DEBUGASSERT((size_t)nwritten == len);
+ return 0;
+}
+
+static int proxy_h2_on_stream_close(nghttp2_session *session,
+ int32_t stream_id,
+ uint32_t error_code, void *userp)
+{
+ struct Curl_cfilter *cf = userp;
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+
+ (void)session;
+ (void)data;
+
+ if(stream_id != ctx->tunnel.stream_id)
+ return 0;
+
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] proxy_h2_on_stream_close, %s (err %d)",
+ stream_id, nghttp2_http2_strerror(error_code), error_code));
+ ctx->tunnel.closed = TRUE;
+ ctx->tunnel.error = error_code;
+
+ return 0;
+}
+
+static CURLcode proxy_h2_submit(int32_t *pstream_id,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ nghttp2_session *h2,
+ struct httpreq *req,
+ const nghttp2_priority_spec *pri_spec,
+ void *stream_user_data,
+ nghttp2_data_source_read_callback read_callback,
+ void *read_ctx)
+{
+ struct dynhds h2_headers;
+ nghttp2_nv *nva = NULL;
+ unsigned int i;
+ int32_t stream_id = -1;
+ size_t nheader;
+ CURLcode result;
+
+ (void)cf;
+ Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
+ result = Curl_http_req_to_h2(&h2_headers, req, data);
+ if(result)
+ goto out;
+
+ nheader = Curl_dynhds_count(&h2_headers);
+ nva = malloc(sizeof(nghttp2_nv) * nheader);
+ if(!nva) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ for(i = 0; i < nheader; ++i) {
+ struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
+ nva[i].name = (unsigned char *)e->name;
+ nva[i].namelen = e->namelen;
+ nva[i].value = (unsigned char *)e->value;
+ nva[i].valuelen = e->valuelen;
+ nva[i].flags = NGHTTP2_NV_FLAG_NONE;
+ }
+
+ if(read_callback) {
+ nghttp2_data_provider data_prd;
+
+ data_prd.read_callback = read_callback;
+ data_prd.source.ptr = read_ctx;
+ stream_id = nghttp2_submit_request(h2, pri_spec, nva, nheader,
+ &data_prd, stream_user_data);
+ }
+ else {
+ stream_id = nghttp2_submit_request(h2, pri_spec, nva, nheader,
+ NULL, stream_user_data);
+ }
+
+ if(stream_id < 0) {
+ failf(data, "nghttp2_session_upgrade2() failed: %s(%d)",
+ nghttp2_strerror(stream_id), stream_id);
+ result = CURLE_SEND_ERROR;
+ goto out;
+ }
+ result = CURLE_OK;
+
+out:
+ free(nva);
+ Curl_dynhds_free(&h2_headers);
+ *pstream_id = stream_id;
+ return result;
+}
+
+static CURLcode submit_CONNECT(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct tunnel_stream *ts)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ CURLcode result;
+ struct httpreq *req = NULL;
+
+ infof(data, "Establish HTTP/2 proxy tunnel to %s", ts->authority);
+
+ result = Curl_http_req_make(&req, "CONNECT", sizeof("CONNECT")-1,
+ NULL, 0, ts->authority, strlen(ts->authority),
+ NULL, 0);
+ if(result)
+ goto out;
+
+ /* Setup the proxy-authorization header, if any */
+ result = Curl_http_output_auth(data, cf->conn, req->method, HTTPREQ_GET,
+ req->authority, TRUE);
+ if(result)
+ goto out;
+
+ if(data->state.aptr.proxyuserpwd) {
+ result = Curl_dynhds_h1_cadd_line(&req->headers,
+ data->state.aptr.proxyuserpwd);
+ if(result)
+ goto out;
+ }
+
+ if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent"))
+ && data->set.str[STRING_USERAGENT]) {
+ result = Curl_dynhds_cadd(&req->headers, "User-Agent",
+ data->set.str[STRING_USERAGENT]);
+ if(result)
+ goto out;
+ }
+
+ result = Curl_dynhds_add_custom(data, TRUE, &req->headers);
+ if(result)
+ goto out;
+
+ result = proxy_h2_submit(&ts->stream_id, cf, data, ctx->h2, req,
+ NULL, ts, tunnel_send_callback, cf);
+ if(result) {
+ DEBUGF(LOG_CF(data, cf, "send: nghttp2_submit_request error (%s)%u",
+ nghttp2_strerror(ts->stream_id), ts->stream_id));
+ }
+
+out:
+ if(req)
+ Curl_http_req_free(req);
+ if(result)
+ failf(data, "Failed sending CONNECT to proxy");
+ return result;
+}
+
+static CURLcode inspect_response(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct tunnel_stream *ts)
+{
+ CURLcode result = CURLE_OK;
+ struct dynhds_entry *auth_reply = NULL;
+ (void)cf;
+
+ DEBUGASSERT(ts->resp);
+ 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;
+ }
+
+ if(ts->resp->status == 401) {
+ auth_reply = Curl_dynhds_cget(&ts->resp->headers, "WWW-Authenticate");
+ }
+ else if(ts->resp->status == 407) {
+ auth_reply = Curl_dynhds_cget(&ts->resp->headers, "Proxy-Authenticate");
+ }
+
+ if(auth_reply) {
+ DEBUGF(LOG_CF(data, cf, "CONNECT: fwd auth header '%s'",
+ auth_reply->value));
+ result = Curl_http_input_auth(data, ts->resp->status == 407,
+ auth_reply->value);
+ if(result)
+ return result;
+ if(data->req.newurl) {
+ /* Inidicator that we should try again */
+ Curl_safefree(data->req.newurl);
+ h2_tunnel_go_state(cf, ts, H2_TUNNEL_INIT, data);
+ return CURLE_OK;
+ }
+ }
+
+ /* Seems to have failed */
+ return CURLE_RECV_ERROR;
+}
+
+static CURLcode H2_CONNECT(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct tunnel_stream *ts)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+
+ DEBUGASSERT(ts);
+ DEBUGASSERT(ts->authority);
+ do {
+ switch(ts->state) {
+ case H2_TUNNEL_INIT:
+ /* Prepare the CONNECT request and make a first attempt to send. */
+ DEBUGF(LOG_CF(data, cf, "CONNECT start for %s", ts->authority));
+ result = submit_CONNECT(cf, data, ts);
+ if(result)
+ goto out;
+ h2_tunnel_go_state(cf, ts, H2_TUNNEL_CONNECT, data);
+ /* FALLTHROUGH */
+
+ case H2_TUNNEL_CONNECT:
+ /* see that the request is completely sent */
+ result = proxy_h2_progress_ingress(cf, data);
+ if(!result)
+ result = proxy_h2_progress_egress(cf, data);
+ if(result && result != CURLE_AGAIN) {
+ h2_tunnel_go_state(cf, ts, H2_TUNNEL_FAILED, data);
+ break;
+ }
+
+ if(ts->has_final_response) {
+ h2_tunnel_go_state(cf, ts, H2_TUNNEL_RESPONSE, data);
+ }
+ else {
+ result = CURLE_OK;
+ goto out;
+ }
+ /* FALLTHROUGH */
+
+ case H2_TUNNEL_RESPONSE:
+ DEBUGASSERT(ts->has_final_response);
+ result = inspect_response(cf, data, ts);
+ if(result)
+ goto out;
+ break;
+
+ case H2_TUNNEL_ESTABLISHED:
+ return CURLE_OK;
+
+ case H2_TUNNEL_FAILED:
+ return CURLE_RECV_ERROR;
+
+ default:
+ break;
+ }
+
+ } while(ts->state == H2_TUNNEL_INIT);
+
+out:
+ if(result || ctx->tunnel.closed)
+ h2_tunnel_go_state(cf, ts, H2_TUNNEL_FAILED, data);
+ return result;
+}
+
+static CURLcode cf_h2_proxy_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ 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) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ /* Connect the lower filters first */
+ if(!cf->next->connected) {
+ result = Curl_conn_cf_connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ return result;
+ }
+
+ *done = FALSE;
+
+ CF_DATA_SAVE(save, cf, data);
+ if(!ctx->h2) {
+ result = cf_h2_proxy_ctx_init(cf, data);
+ if(result)
+ goto out;
+ }
+ DEBUGASSERT(ts->authority);
+
+ check = Curl_timeleft(data, NULL, TRUE);
+ if(check <= 0) {
+ failf(data, "Proxy CONNECT aborted due to timeout");
+ result = CURLE_OPERATION_TIMEDOUT;
+ goto out;
+ }
+
+ /* for the secondary socket (FTP), use the "connect to host"
+ * but ignore the "connect to port" (use the secondary port)
+ */
+ result = H2_CONNECT(cf, data, ts);
+
+out:
+ *done = (result == CURLE_OK) && (ts->state == H2_TUNNEL_ESTABLISHED);
+ cf->connected = *done;
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static void cf_h2_proxy_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+
+ if(ctx) {
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ cf_h2_proxy_ctx_clear(ctx);
+ CF_DATA_RESTORE(cf, save);
+ }
+}
+
+static void cf_h2_proxy_destroy(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+
+ (void)data;
+ if(ctx) {
+ cf_h2_proxy_ctx_free(ctx);
+ cf->ctx = NULL;
+ }
+}
+
+static bool cf_h2_proxy_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ if((ctx && !Curl_bufq_is_empty(&ctx->inbufq)) ||
+ (ctx && ctx->tunnel.state == H2_TUNNEL_ESTABLISHED &&
+ !Curl_bufq_is_empty(&ctx->tunnel.recvbuf)))
+ return TRUE;
+ return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
+}
+
+static int cf_h2_proxy_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *sock)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ int bitmap = GETSOCK_BLANK;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ sock[0] = Curl_conn_cf_get_socket(cf, data);
+ bitmap |= GETSOCK_READSOCK(0);
+
+ /* HTTP/2 layer wants to send data) AND there's a window to send data in */
+ if(nghttp2_session_want_write(ctx->h2) &&
+ nghttp2_session_get_remote_window_size(ctx->h2))
+ bitmap |= GETSOCK_WRITESOCK(0);
+
+ CF_DATA_RESTORE(cf, save);
+ return bitmap;
+}
+
+static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ CURLcode *err)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ ssize_t rv = 0;
+
+ if(ctx->tunnel.error == NGHTTP2_REFUSED_STREAM) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] REFUSED_STREAM, try again on a new "
+ "connection", ctx->tunnel.stream_id));
+ connclose(cf->conn, "REFUSED_STREAM"); /* don't use this anymore */
+ *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
+ return -1;
+ }
+ else if(ctx->tunnel.error != NGHTTP2_NO_ERROR) {
+ failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %u)",
+ ctx->tunnel.stream_id, nghttp2_http2_strerror(ctx->tunnel.error),
+ ctx->tunnel.error);
+ *err = CURLE_HTTP2_STREAM;
+ return -1;
+ }
+ else if(ctx->tunnel.reset) {
+ failf(data, "HTTP/2 stream %u was reset", ctx->tunnel.stream_id);
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ *err = CURLE_OK;
+ rv = 0;
+ DEBUGF(LOG_CF(data, cf, "handle_tunnel_close -> %zd, %d", rv, *err));
+ return rv;
+}
+
+static ssize_t tunnel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ ssize_t nread = -1;
+
+ *err = CURLE_AGAIN;
+ if(!Curl_bufq_is_empty(&ctx->tunnel.recvbuf)) {
+ nread = Curl_bufq_read(&ctx->tunnel.recvbuf,
+ (unsigned char *)buf, len, err);
+ if(nread < 0)
+ goto out;
+ DEBUGASSERT(nread > 0);
+ }
+
+ if(nread < 0) {
+ if(ctx->tunnel.closed) {
+ nread = h2_handle_tunnel_close(cf, data, err);
+ }
+ else if(ctx->tunnel.reset ||
+ (ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) ||
+ (ctx->goaway && ctx->last_stream_id < ctx->tunnel.stream_id)) {
+ *err = CURLE_RECV_ERROR;
+ nread = -1;
+ }
+ }
+ else if(nread == 0) {
+ *err = CURLE_AGAIN;
+ nread = -1;
+ }
+
+out:
+ DEBUGF(LOG_CF(data, cf, "tunnel_recv(len=%zu) -> %zd, %d",
+ len, nread, *err));
+ return nread;
+}
+
+static ssize_t cf_h2_proxy_recv(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ ssize_t nread = -1;
+ struct cf_call_data save;
+ CURLcode result;
+
+ if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+ CF_DATA_SAVE(save, cf, data);
+
+ if(Curl_bufq_is_empty(&ctx->tunnel.recvbuf)) {
+ *err = proxy_h2_progress_ingress(cf, data);
+ if(*err)
+ goto out;
+ }
+
+ nread = tunnel_recv(cf, data, buf, len, err);
+
+ if(nread > 0) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] increase window by %zd",
+ ctx->tunnel.stream_id, nread));
+ nghttp2_session_consume(ctx->h2, ctx->tunnel.stream_id, (size_t)nread);
+ }
+
+ result = proxy_h2_progress_egress(cf, data);
+ if(result && result != CURLE_AGAIN) {
+ *err = result;
+ nread = -1;
+ }
+
+out:
+ if(!Curl_bufq_is_empty(&ctx->tunnel.recvbuf) &&
+ (nread >= 0 || *err == CURLE_AGAIN)) {
+ /* data pending and no fatal error to report. Need to trigger
+ * draining to avoid stalling when no socket events happen. */
+ drain_tunnel(cf, data, &ctx->tunnel);
+ }
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] cf_recv(len=%zu) -> %zd %d",
+ ctx->tunnel.stream_id, len, nread, *err));
+ CF_DATA_RESTORE(cf, save);
+ return nread;
+}
+
+static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ struct cf_call_data save;
+ int rv;
+ ssize_t nwritten;
+ CURLcode result;
+ int blocked = 0;
+
+ if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+ CF_DATA_SAVE(save, cf, data);
+
+ if(ctx->tunnel.closed) {
+ nwritten = -1;
+ *err = CURLE_SEND_ERROR;
+ goto out;
+ }
+ else if(ctx->tunnel.upload_blocked_len) {
+ /* the data in `buf` has alread been submitted or added to the
+ * buffers, but have been EAGAINed on the last invocation. */
+ DEBUGASSERT(len >= ctx->tunnel.upload_blocked_len);
+ if(len < ctx->tunnel.upload_blocked_len) {
+ /* Did we get called again with a smaller `len`? This should not
+ * happend. We are not prepared to handle that. */
+ failf(data, "HTTP/2 proxy, send again with decreased length");
+ *err = CURLE_HTTP2;
+ nwritten = -1;
+ goto out;
+ }
+ nwritten = (ssize_t)ctx->tunnel.upload_blocked_len;
+ ctx->tunnel.upload_blocked_len = 0;
+ }
+ else {
+ nwritten = Curl_bufq_write(&ctx->tunnel.sendbuf, buf, len, err);
+ if(nwritten < 0) {
+ if(*err != CURLE_AGAIN)
+ goto out;
+ nwritten = 0;
+ }
+ }
+
+ if(!Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) {
+ /* req body data is buffered, resume the potentially suspended stream */
+ rv = nghttp2_session_resume_data(ctx->h2, ctx->tunnel.stream_id);
+ if(nghttp2_is_fatal(rv)) {
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ goto out;
+ }
+ }
+
+ /* Call the nghttp2 send loop and flush to write ALL buffered data,
+ * headers and/or request body completely out to the network */
+ result = proxy_h2_progress_egress(cf, data);
+ if(result == CURLE_AGAIN) {
+ blocked = 1;
+ }
+ else if(result) {
+ *err = result;
+ nwritten = -1;
+ goto out;
+ }
+ else if(!Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) {
+ /* although we wrote everything that nghttp2 wants to send now,
+ * there is data left in our stream send buffer unwritten. This may
+ * be due to the stream's HTTP/2 flow window being exhausted. */
+ blocked = 1;
+ }
+
+ if(blocked) {
+ /* Unable to send all data, due to connection blocked or H2 window
+ * exhaustion. Data is left in our stream buffer, or nghttp2's internal
+ * frame buffer or our network out buffer. */
+ size_t rwin = nghttp2_session_get_stream_remote_window_size(
+ ctx->h2, ctx->tunnel.stream_id);
+ if(rwin == 0) {
+ /* H2 flow window exhaustion.
+ * FIXME: there is no way to HOLD all transfers that use this
+ * proxy connection AND to UNHOLD all of them again when the
+ * window increases.
+ * We *could* iterate over all data on this conn maybe? */
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] remote flow "
+ "window is exhausted", ctx->tunnel.stream_id));
+ }
+
+ /* Whatever the cause, we need to return CURL_EAGAIN for this call.
+ * We have unwritten state that needs us being invoked again and EAGAIN
+ * is the only way to ensure that. */
+ ctx->tunnel.upload_blocked_len = nwritten;
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) BLOCK: win %u/%zu "
+ "blocked_len=%zu",
+ ctx->tunnel.stream_id, len,
+ nghttp2_session_get_remote_window_size(ctx->h2), rwin,
+ nwritten));
+ *err = CURLE_AGAIN;
+ nwritten = -1;
+ goto out;
+ }
+ else if(should_close_session(ctx)) {
+ /* nghttp2 thinks this session is done. If the stream has not been
+ * closed, this is an error state for out transfer */
+ if(ctx->tunnel.closed) {
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "send: nothing to do in this session"));
+ *err = CURLE_HTTP2;
+ nwritten = -1;
+ }
+ }
+
+out:
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) -> %zd, %d, "
+ "h2 windows %d-%d (stream-conn), "
+ "buffers %zu-%zu (stream-conn)",
+ ctx->tunnel.stream_id, len, nwritten, *err,
+ nghttp2_session_get_stream_remote_window_size(
+ 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)));
+ CF_DATA_RESTORE(cf, save);
+ return nwritten;
+}
+
+static bool proxy_h2_connisalive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ bool alive = TRUE;
+
+ *input_pending = FALSE;
+ if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
+ return FALSE;
+
+ if(*input_pending) {
+ /* This happens before we've sent off a request and the connection is
+ not in use by any other transfer, there shouldn't be any data here,
+ only "protocol frames" */
+ CURLcode result;
+ ssize_t nread = -1;
+
+ *input_pending = FALSE;
+ nread = Curl_bufq_slurp(&ctx->inbufq, proxy_nw_in_reader, cf, &result);
+ if(nread != -1) {
+ if(proxy_h2_process_pending_input(cf, data, &result) < 0)
+ /* immediate error, considered dead */
+ alive = FALSE;
+ else {
+ alive = !should_close_session(ctx);
+ }
+ }
+ else if(result != CURLE_AGAIN) {
+ /* the read failed so let's say this is dead anyway */
+ alive = FALSE;
+ }
+ }
+
+ return alive;
+}
+
+static bool cf_h2_proxy_is_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ CURLcode result;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ result = (ctx && ctx->h2 && proxy_h2_connisalive(cf, data, input_pending));
+ DEBUGF(LOG_CF(data, cf, "conn alive -> %d, input_pending=%d",
+ result, *input_pending));
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+struct Curl_cftype Curl_cft_h2_proxy = {
+ "H2-PROXY",
+ CF_TYPE_IP_CONNECT,
+ CURL_LOG_DEFAULT,
+ cf_h2_proxy_destroy,
+ cf_h2_proxy_connect,
+ cf_h2_proxy_close,
+ Curl_cf_http_proxy_get_host,
+ cf_h2_proxy_get_select_socks,
+ cf_h2_proxy_data_pending,
+ cf_h2_proxy_send,
+ cf_h2_proxy_recv,
+ Curl_cf_def_cntrl,
+ cf_h2_proxy_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ Curl_cf_def_query,
+};
+
+CURLcode Curl_cf_h2_proxy_insert_after(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf_h2_proxy = NULL;
+ struct cf_h2_proxy_ctx *ctx;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+
+ (void)data;
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx)
+ goto out;
+
+ result = Curl_cf_create(&cf_h2_proxy, &Curl_cft_h2_proxy, ctx);
+ if(result)
+ goto out;
+
+ Curl_conn_cf_insert_after(cf, cf_h2_proxy);
+ result = CURLE_OK;
+
+out:
+ if(result)
+ cf_h2_proxy_ctx_free(ctx);
+ return result;
+}
+
+#endif /* defined(USE_NGHTTP2) && !defined(CURL_DISABLE_PROXY) */
diff --git a/lib/vquic/msh3.h b/lib/cf-h2-proxy.h
similarity index 68%
copy from lib/vquic/msh3.h
copy to lib/cf-h2-proxy.h
index ce884d9..c01bf62 100644
--- a/lib/vquic/msh3.h
+++ b/lib/cf-h2-proxy.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_VQUIC_MSH3_H
-#define HEADER_CURL_VQUIC_MSH3_H
+#ifndef HEADER_CURL_H2_PROXY_H
+#define HEADER_CURL_H2_PROXY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,15 +26,14 @@
#include "curl_setup.h"
-#ifdef USE_MSH3
+#if defined(USE_NGHTTP2) && !defined(CURL_DISABLE_PROXY)
-#include <msh3.h>
+CURLcode Curl_cf_h2_proxy_insert_after(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
-struct quicsocket {
- MSH3_API* api;
- MSH3_CONNECTION* conn;
-};
+extern struct Curl_cftype Curl_cft_h2_proxy;
-#endif /* USE_MSQUIC */
-#endif /* HEADER_CURL_VQUIC_MSH3_H */
+#endif /* defined(USE_NGHTTP2) && !defined(CURL_DISABLE_PROXY) */
+
+#endif /* HEADER_CURL_H2_PROXY_H */
diff --git a/lib/cf-haproxy.c b/lib/cf-haproxy.c
new file mode 100644
index 0000000..ec0100c
--- /dev/null
+++ b/lib/cf-haproxy.c
@@ -0,0 +1,251 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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(CURL_DISABLE_PROXY)
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "cfilters.h"
+#include "cf-haproxy.h"
+#include "curl_log.h"
+#include "multiif.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#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_state;
+
+struct cf_haproxy_ctx {
+ int state;
+ struct dynbuf data_out;
+};
+
+static void cf_haproxy_ctx_reset(struct cf_haproxy_ctx *ctx)
+{
+ DEBUGASSERT(ctx);
+ ctx->state = HAPROXY_INIT;
+ Curl_dyn_reset(&ctx->data_out);
+}
+
+static void cf_haproxy_ctx_free(struct cf_haproxy_ctx *ctx)
+{
+ if(ctx) {
+ Curl_dyn_free(&ctx->data_out);
+ free(ctx);
+ }
+}
+
+static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
+ struct Curl_easy *data)
+{
+ struct cf_haproxy_ctx *ctx = cf->ctx;
+ CURLcode result;
+ const char *tcp_version;
+ const char *client_ip;
+
+ DEBUGASSERT(ctx);
+ DEBUGASSERT(ctx->state == HAPROXY_INIT);
+#ifdef USE_UNIX_SOCKETS
+ if(cf->conn->unix_domain_socket)
+ /* the buffer is large enough to hold this! */
+ result = Curl_dyn_addn(&ctx->data_out, STRCONST("PROXY UNKNOWN\r\n"));
+ else {
+#endif /* USE_UNIX_SOCKETS */
+ /* Emit the correct prefix for IPv6 */
+ tcp_version = cf->conn->bits.ipv6 ? "TCP6" : "TCP4";
+ if(data->set.str[STRING_HAPROXY_CLIENT_IP])
+ client_ip = data->set.str[STRING_HAPROXY_CLIENT_IP];
+ else
+ client_ip = data->info.conn_primary_ip;
+
+ result = Curl_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
+ tcp_version,
+ data->info.conn_local_ip,
+ client_ip,
+ data->info.conn_local_port,
+ data->info.conn_primary_port);
+
+#ifdef USE_UNIX_SOCKETS
+ }
+#endif /* USE_UNIX_SOCKETS */
+ return result;
+}
+
+static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct cf_haproxy_ctx *ctx = cf->ctx;
+ CURLcode result;
+ size_t len;
+
+ DEBUGASSERT(ctx);
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ result = cf->next->cft->do_connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ return result;
+
+ switch(ctx->state) {
+ case HAPROXY_INIT:
+ result = cf_haproxy_date_out_set(cf, data);
+ if(result)
+ goto out;
+ ctx->state = HAPROXY_SEND;
+ /* FALLTHROUGH */
+ case HAPROXY_SEND:
+ len = Curl_dyn_len(&ctx->data_out);
+ if(len > 0) {
+ ssize_t written = Curl_conn_send(data, cf->sockindex,
+ Curl_dyn_ptr(&ctx->data_out),
+ len, &result);
+ if(written < 0)
+ goto out;
+ Curl_dyn_tail(&ctx->data_out, len - (size_t)written);
+ if(Curl_dyn_len(&ctx->data_out) > 0) {
+ result = CURLE_OK;
+ goto out;
+ }
+ }
+ ctx->state = HAPROXY_DONE;
+ /* FALLTHROUGH */
+ default:
+ Curl_dyn_free(&ctx->data_out);
+ break;
+ }
+
+out:
+ *done = (!result) && (ctx->state == HAPROXY_DONE);
+ cf->connected = *done;
+ return result;
+}
+
+static void cf_haproxy_destroy(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ (void)data;
+ DEBUGF(LOG_CF(data, cf, "destroy"));
+ cf_haproxy_ctx_free(cf->ctx);
+}
+
+static void cf_haproxy_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ DEBUGF(LOG_CF(data, cf, "close"));
+ cf->connected = FALSE;
+ cf_haproxy_ctx_reset(cf->ctx);
+ if(cf->next)
+ cf->next->cft->do_close(cf->next, data);
+}
+
+static int cf_haproxy_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ int fds;
+
+ fds = cf->next->cft->get_select_socks(cf->next, data, socks);
+ if(!fds && cf->next->connected && !cf->connected) {
+ /* If we are not connected, but the filter "below" is
+ * and not waiting on something, we are sending. */
+ socks[0] = Curl_conn_cf_get_socket(cf, data);
+ return GETSOCK_WRITESOCK(0);
+ }
+ return fds;
+}
+
+
+struct Curl_cftype Curl_cft_haproxy = {
+ "HAPROXY",
+ 0,
+ 0,
+ cf_haproxy_destroy,
+ cf_haproxy_connect,
+ cf_haproxy_close,
+ Curl_cf_def_get_host,
+ cf_haproxy_get_select_socks,
+ Curl_cf_def_data_pending,
+ Curl_cf_def_send,
+ Curl_cf_def_recv,
+ Curl_cf_def_cntrl,
+ Curl_cf_def_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ Curl_cf_def_query,
+};
+
+static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf = NULL;
+ struct cf_haproxy_ctx *ctx;
+ CURLcode result;
+
+ (void)data;
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ ctx->state = HAPROXY_INIT;
+ Curl_dyn_init(&ctx->data_out, DYN_HAXPROXY);
+
+ result = Curl_cf_create(&cf, &Curl_cft_haproxy, ctx);
+ if(result)
+ goto out;
+ ctx = NULL;
+
+out:
+ cf_haproxy_ctx_free(ctx);
+ *pcf = result? NULL : cf;
+ return result;
+}
+
+CURLcode Curl_cf_haproxy_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result;
+
+ result = cf_haproxy_create(&cf, data);
+ if(result)
+ goto out;
+ Curl_conn_cf_insert_after(cf_at, cf);
+
+out:
+ return result;
+}
+
+#endif /* !CURL_DISABLE_PROXY */
diff --git a/lib/vquic/msh3.h b/lib/cf-haproxy.h
similarity index 70%
copy from lib/vquic/msh3.h
copy to lib/cf-haproxy.h
index ce884d9..d02c323 100644
--- a/lib/vquic/msh3.h
+++ b/lib/cf-haproxy.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_VQUIC_MSH3_H
-#define HEADER_CURL_VQUIC_MSH3_H
+#ifndef HEADER_CURL_CF_HAPROXY_H
+#define HEADER_CURL_CF_HAPROXY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,16 +25,15 @@
***************************************************************************/
#include "curl_setup.h"
+#include "urldata.h"
-#ifdef USE_MSH3
+#if !defined(CURL_DISABLE_PROXY)
-#include <msh3.h>
+CURLcode Curl_cf_haproxy_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data);
-struct quicsocket {
- MSH3_API* api;
- MSH3_CONNECTION* conn;
-};
+extern struct Curl_cftype Curl_cft_haproxy;
-#endif /* USE_MSQUIC */
+#endif /* !CURL_DISABLE_PROXY */
-#endif /* HEADER_CURL_VQUIC_MSH3_H */
+#endif /* HEADER_CURL_CF_HAPROXY_H */
diff --git a/lib/cf-https-connect.c b/lib/cf-https-connect.c
new file mode 100644
index 0000000..4e4d4b1
--- /dev/null
+++ b/lib/cf-https-connect.c
@@ -0,0 +1,551 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "curl_log.h"
+#include "cfilters.h"
+#include "connect.h"
+#include "multiif.h"
+#include "cf-https-connect.h"
+#include "http2.h"
+#include "vquic/vquic.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+
+typedef enum {
+ CF_HC_INIT,
+ CF_HC_CONNECT,
+ CF_HC_SUCCESS,
+ CF_HC_FAILURE
+} cf_hc_state;
+
+struct cf_hc_baller {
+ const char *name;
+ struct Curl_cfilter *cf;
+ CURLcode result;
+ struct curltime started;
+ int reply_ms;
+ bool enabled;
+};
+
+static void cf_hc_baller_reset(struct cf_hc_baller *b,
+ struct Curl_easy *data)
+{
+ if(b->cf) {
+ Curl_conn_cf_close(b->cf, data);
+ Curl_conn_cf_discard_chain(&b->cf, data);
+ b->cf = NULL;
+ }
+ b->result = CURLE_OK;
+ b->reply_ms = -1;
+}
+
+static bool cf_hc_baller_is_active(struct cf_hc_baller *b)
+{
+ return b->enabled && b->cf && !b->result;
+}
+
+static bool cf_hc_baller_has_started(struct cf_hc_baller *b)
+{
+ return !!b->cf;
+}
+
+static int cf_hc_baller_reply_ms(struct cf_hc_baller *b,
+ struct Curl_easy *data)
+{
+ if(b->reply_ms < 0)
+ b->cf->cft->query(b->cf, data, CF_QUERY_CONNECT_REPLY_MS,
+ &b->reply_ms, NULL);
+ return b->reply_ms;
+}
+
+static bool cf_hc_baller_data_pending(struct cf_hc_baller *b,
+ const struct Curl_easy *data)
+{
+ return b->cf && !b->result && b->cf->cft->has_data_pending(b->cf, data);
+}
+
+struct cf_hc_ctx {
+ cf_hc_state state;
+ const struct Curl_dns_entry *remotehost;
+ struct curltime started; /* when connect started */
+ CURLcode result; /* overall result */
+ struct cf_hc_baller h3_baller;
+ struct cf_hc_baller h21_baller;
+ int soft_eyeballs_timeout_ms;
+ int hard_eyeballs_timeout_ms;
+};
+
+static void cf_hc_baller_init(struct cf_hc_baller *b,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *name,
+ int transport)
+{
+ struct cf_hc_ctx *ctx = cf->ctx;
+ struct Curl_cfilter *save = cf->next;
+
+ b->name = name;
+ cf->next = NULL;
+ b->started = Curl_now();
+ b->result = Curl_cf_setup_insert_after(cf, data, ctx->remotehost,
+ transport, CURL_CF_SSL_ENABLE);
+ b->cf = cf->next;
+ cf->next = save;
+}
+
+static CURLcode cf_hc_baller_connect(struct cf_hc_baller *b,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done)
+{
+ struct Curl_cfilter *save = cf->next;
+
+ cf->next = b->cf;
+ b->result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
+ b->cf = cf->next; /* it might mutate */
+ cf->next = save;
+ return b->result;
+}
+
+static void cf_hc_reset(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_hc_ctx *ctx = cf->ctx;
+
+ if(ctx) {
+ cf_hc_baller_reset(&ctx->h3_baller, data);
+ cf_hc_baller_reset(&ctx->h21_baller, data);
+ ctx->state = CF_HC_INIT;
+ ctx->result = CURLE_OK;
+ ctx->hard_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout;
+ ctx->soft_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout / 2;
+ }
+}
+
+static CURLcode baller_connected(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct cf_hc_baller *winner)
+{
+ struct cf_hc_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+
+ DEBUGASSERT(winner->cf);
+ if(winner != &ctx->h3_baller)
+ cf_hc_baller_reset(&ctx->h3_baller, data);
+ if(winner != &ctx->h21_baller)
+ cf_hc_baller_reset(&ctx->h21_baller, data);
+
+ DEBUGF(LOG_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms",
+ winner->name, (int)Curl_timediff(Curl_now(), winner->started),
+ cf_hc_baller_reply_ms(winner, data)));
+ cf->next = winner->cf;
+ winner->cf = NULL;
+
+ switch(cf->conn->alpn) {
+ case CURL_HTTP_VERSION_3:
+ infof(data, "using HTTP/3");
+ break;
+ case CURL_HTTP_VERSION_2:
+#ifdef USE_NGHTTP2
+ /* Using nghttp2, we add the filter "below" us, so when the conn
+ * closes, we tear it down for a fresh reconnect */
+ result = Curl_http2_switch_at(cf, data);
+ if(result) {
+ ctx->state = CF_HC_FAILURE;
+ ctx->result = result;
+ return result;
+ }
+#endif
+ infof(data, "using HTTP/2");
+ break;
+ case CURL_HTTP_VERSION_1_1:
+ infof(data, "using HTTP/1.1");
+ break;
+ default:
+ infof(data, "using HTTP/1.x");
+ break;
+ }
+ ctx->state = CF_HC_SUCCESS;
+ cf->connected = TRUE;
+ Curl_conn_cf_cntrl(cf->next, data, TRUE,
+ CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
+ return result;
+}
+
+
+static bool time_to_start_h21(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct curltime now)
+{
+ struct cf_hc_ctx *ctx = cf->ctx;
+ timediff_t elapsed_ms;
+
+ if(!ctx->h21_baller.enabled || cf_hc_baller_has_started(&ctx->h21_baller))
+ return FALSE;
+
+ if(!ctx->h3_baller.enabled || !cf_hc_baller_is_active(&ctx->h3_baller))
+ return TRUE;
+
+ elapsed_ms = Curl_timediff(now, ctx->started);
+ if(elapsed_ms >= ctx->hard_eyeballs_timeout_ms) {
+ DEBUGF(LOG_CF(data, cf, "hard timeout of %dms reached, starting h21",
+ ctx->hard_eyeballs_timeout_ms));
+ return TRUE;
+ }
+
+ if(elapsed_ms >= ctx->soft_eyeballs_timeout_ms) {
+ if(cf_hc_baller_reply_ms(&ctx->h3_baller, data) < 0) {
+ DEBUGF(LOG_CF(data, cf, "soft timeout of %dms reached, h3 has not "
+ "seen any data, starting h21",
+ ctx->soft_eyeballs_timeout_ms));
+ return TRUE;
+ }
+ /* set the effective hard timeout again */
+ Curl_expire(data, ctx->hard_eyeballs_timeout_ms - elapsed_ms,
+ EXPIRE_ALPN_EYEBALLS);
+ }
+ return FALSE;
+}
+
+static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct cf_hc_ctx *ctx = cf->ctx;
+ struct curltime now;
+ CURLcode result = CURLE_OK;
+
+ (void)blocking;
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ *done = FALSE;
+ now = Curl_now();
+ switch(ctx->state) {
+ case CF_HC_INIT:
+ DEBUGASSERT(!ctx->h3_baller.cf);
+ DEBUGASSERT(!ctx->h21_baller.cf);
+ DEBUGASSERT(!cf->next);
+ DEBUGF(LOG_CF(data, cf, "connect, init"));
+ ctx->started = now;
+ if(ctx->h3_baller.enabled) {
+ cf_hc_baller_init(&ctx->h3_baller, cf, data, "h3", TRNSPRT_QUIC);
+ if(ctx->h21_baller.enabled)
+ Curl_expire(data, ctx->soft_eyeballs_timeout_ms, EXPIRE_ALPN_EYEBALLS);
+ }
+ else if(ctx->h21_baller.enabled)
+ cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
+ cf->conn->transport);
+ ctx->state = CF_HC_CONNECT;
+ /* FALLTHROUGH */
+
+ case CF_HC_CONNECT:
+ if(cf_hc_baller_is_active(&ctx->h3_baller)) {
+ result = cf_hc_baller_connect(&ctx->h3_baller, cf, data, done);
+ if(!result && *done) {
+ result = baller_connected(cf, data, &ctx->h3_baller);
+ goto out;
+ }
+ }
+
+ if(time_to_start_h21(cf, data, now)) {
+ cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
+ cf->conn->transport);
+ }
+
+ if(cf_hc_baller_is_active(&ctx->h21_baller)) {
+ DEBUGF(LOG_CF(data, cf, "connect, check h21"));
+ result = cf_hc_baller_connect(&ctx->h21_baller, cf, data, done);
+ if(!result && *done) {
+ result = baller_connected(cf, data, &ctx->h21_baller);
+ goto out;
+ }
+ }
+
+ if((!ctx->h3_baller.enabled || ctx->h3_baller.result) &&
+ (!ctx->h21_baller.enabled || ctx->h21_baller.result)) {
+ /* both failed or disabled. we give up */
+ DEBUGF(LOG_CF(data, cf, "connect, all failed"));
+ result = ctx->result = ctx->h3_baller.enabled?
+ ctx->h3_baller.result : ctx->h21_baller.result;
+ ctx->state = CF_HC_FAILURE;
+ goto out;
+ }
+ result = CURLE_OK;
+ *done = FALSE;
+ break;
+
+ case CF_HC_FAILURE:
+ result = ctx->result;
+ cf->connected = FALSE;
+ *done = FALSE;
+ break;
+
+ case CF_HC_SUCCESS:
+ result = CURLE_OK;
+ cf->connected = TRUE;
+ *done = TRUE;
+ break;
+ }
+
+out:
+ DEBUGF(LOG_CF(data, cf, "connect -> %d, done=%d", result, *done));
+ return result;
+}
+
+static int cf_hc_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ struct cf_hc_ctx *ctx = cf->ctx;
+ size_t i, j, s;
+ int brc, rc = GETSOCK_BLANK;
+ curl_socket_t bsocks[MAX_SOCKSPEREASYHANDLE];
+ struct cf_hc_baller *ballers[2];
+
+ if(cf->connected)
+ return cf->next->cft->get_select_socks(cf->next, data, socks);
+
+ ballers[0] = &ctx->h3_baller;
+ ballers[1] = &ctx->h21_baller;
+ for(i = s = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
+ struct cf_hc_baller *b = ballers[i];
+ if(!cf_hc_baller_is_active(b))
+ continue;
+ brc = Curl_conn_cf_get_select_socks(b->cf, data, bsocks);
+ DEBUGF(LOG_CF(data, cf, "get_selected_socks(%s) -> %x", b->name, brc));
+ if(!brc)
+ continue;
+ for(j = 0; j < MAX_SOCKSPEREASYHANDLE && s < MAX_SOCKSPEREASYHANDLE; ++j) {
+ if((brc & GETSOCK_WRITESOCK(j)) || (brc & GETSOCK_READSOCK(j))) {
+ socks[s] = bsocks[j];
+ if(brc & GETSOCK_WRITESOCK(j))
+ rc |= GETSOCK_WRITESOCK(s);
+ if(brc & GETSOCK_READSOCK(j))
+ rc |= GETSOCK_READSOCK(s);
+ s++;
+ }
+ }
+ }
+ DEBUGF(LOG_CF(data, cf, "get_selected_socks -> %x", rc));
+ return rc;
+}
+
+static bool cf_hc_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ struct cf_hc_ctx *ctx = cf->ctx;
+
+ if(cf->connected)
+ return cf->next->cft->has_data_pending(cf->next, data);
+
+ DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "data_pending"));
+ return cf_hc_baller_data_pending(&ctx->h3_baller, data)
+ || cf_hc_baller_data_pending(&ctx->h21_baller, data);
+}
+
+static struct curltime cf_get_max_baller_time(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query)
+{
+ struct cf_hc_ctx *ctx = cf->ctx;
+ struct Curl_cfilter *cfb;
+ struct curltime t, tmax;
+
+ memset(&tmax, 0, sizeof(tmax));
+ memset(&t, 0, sizeof(t));
+ cfb = ctx->h21_baller.enabled? ctx->h21_baller.cf : NULL;
+ if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
+ if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
+ tmax = t;
+ }
+ memset(&t, 0, sizeof(t));
+ cfb = ctx->h3_baller.enabled? ctx->h3_baller.cf : NULL;
+ if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
+ if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
+ tmax = t;
+ }
+ return tmax;
+}
+
+static CURLcode cf_hc_query(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query, int *pres1, void *pres2)
+{
+ if(!cf->connected) {
+ switch(query) {
+ case CF_QUERY_TIMER_CONNECT: {
+ struct curltime *when = pres2;
+ *when = cf_get_max_baller_time(cf, data, CF_QUERY_TIMER_CONNECT);
+ return CURLE_OK;
+ }
+ case CF_QUERY_TIMER_APPCONNECT: {
+ struct curltime *when = pres2;
+ *when = cf_get_max_baller_time(cf, data, CF_QUERY_TIMER_APPCONNECT);
+ return CURLE_OK;
+ }
+ default:
+ break;
+ }
+ }
+ return cf->next?
+ cf->next->cft->query(cf->next, data, query, pres1, pres2) :
+ CURLE_UNKNOWN_OPTION;
+}
+
+static void cf_hc_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ DEBUGF(LOG_CF(data, cf, "close"));
+ cf_hc_reset(cf, data);
+ cf->connected = FALSE;
+
+ if(cf->next) {
+ cf->next->cft->do_close(cf->next, data);
+ Curl_conn_cf_discard_chain(&cf->next, data);
+ }
+}
+
+static void cf_hc_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_hc_ctx *ctx = cf->ctx;
+
+ (void)data;
+ DEBUGF(LOG_CF(data, cf, "destroy"));
+ cf_hc_reset(cf, data);
+ Curl_safefree(ctx);
+}
+
+struct Curl_cftype Curl_cft_http_connect = {
+ "HTTPS-CONNECT",
+ 0,
+ CURL_LOG_DEFAULT,
+ cf_hc_destroy,
+ cf_hc_connect,
+ cf_hc_close,
+ Curl_cf_def_get_host,
+ cf_hc_get_select_socks,
+ cf_hc_data_pending,
+ Curl_cf_def_send,
+ Curl_cf_def_recv,
+ Curl_cf_def_cntrl,
+ Curl_cf_def_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ cf_hc_query,
+};
+
+static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ const struct Curl_dns_entry *remotehost,
+ bool try_h3, bool try_h21)
+{
+ struct Curl_cfilter *cf = NULL;
+ struct cf_hc_ctx *ctx;
+ CURLcode result = CURLE_OK;
+
+ (void)data;
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ ctx->remotehost = remotehost;
+ ctx->h3_baller.enabled = try_h3;
+ ctx->h21_baller.enabled = try_h21;
+
+ result = Curl_cf_create(&cf, &Curl_cft_http_connect, ctx);
+ if(result)
+ goto out;
+ ctx = NULL;
+ cf_hc_reset(cf, data);
+
+out:
+ *pcf = result? NULL : cf;
+ free(ctx);
+ return result;
+}
+
+static CURLcode cf_http_connect_add(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
+ const struct Curl_dns_entry *remotehost,
+ bool try_h3, bool try_h21)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result = CURLE_OK;
+
+ DEBUGASSERT(data);
+ result = cf_hc_create(&cf, data, remotehost, try_h3, try_h21);
+ if(result)
+ goto out;
+ Curl_conn_cf_add(data, conn, sockindex, cf);
+out:
+ return result;
+}
+
+CURLcode Curl_cf_https_setup(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
+ const struct Curl_dns_entry *remotehost)
+{
+ bool try_h3 = FALSE, try_h21 = TRUE; /* defaults, for now */
+ CURLcode result = CURLE_OK;
+
+ (void)sockindex;
+ (void)remotehost;
+
+ if(!conn->bits.tls_enable_alpn)
+ goto out;
+
+ if(data->state.httpwant == CURL_HTTP_VERSION_3ONLY) {
+ result = Curl_conn_may_http3(data, conn);
+ if(result) /* can't do it */
+ goto out;
+ try_h3 = TRUE;
+ try_h21 = FALSE;
+ }
+ else if(data->state.httpwant >= CURL_HTTP_VERSION_3) {
+ /* We assume that silently not even trying H3 is ok here */
+ /* TODO: should we fail instead? */
+ try_h3 = (Curl_conn_may_http3(data, conn) == CURLE_OK);
+ try_h21 = TRUE;
+ }
+
+ result = cf_http_connect_add(data, conn, sockindex, remotehost,
+ try_h3, try_h21);
+out:
+ return result;
+}
+
+#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */
diff --git a/lib/cf-https-connect.h b/lib/cf-https-connect.h
new file mode 100644
index 0000000..6a39527
--- /dev/null
+++ b/lib/cf-https-connect.h
@@ -0,0 +1,58 @@
+#ifndef HEADER_CURL_CF_HTTP_H
+#define HEADER_CURL_CF_HTTP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
+
+struct Curl_cfilter;
+struct Curl_easy;
+struct connectdata;
+struct Curl_cftype;
+struct Curl_dns_entry;
+
+extern struct Curl_cftype Curl_cft_http_connect;
+
+CURLcode Curl_cf_http_connect_add(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
+ const struct Curl_dns_entry *remotehost,
+ bool try_h3, bool try_h21);
+
+CURLcode
+Curl_cf_http_connect_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data,
+ const struct Curl_dns_entry *remotehost,
+ bool try_h3, bool try_h21);
+
+
+CURLcode Curl_cf_https_setup(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
+ const struct Curl_dns_entry *remotehost);
+
+
+#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */
+#endif /* HEADER_CURL_CF_HTTP_H */
diff --git a/lib/cf-socket.c b/lib/cf-socket.c
new file mode 100644
index 0000000..5729fe0
--- /dev/null
+++ b/lib/cf-socket.c
@@ -0,0 +1,1925 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h> /* <netinet/tcp.h> may need it */
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h> /* for sockaddr_un */
+#endif
+#ifdef HAVE_LINUX_TCP_H
+#include <linux/tcp.h>
+#elif defined(HAVE_NETINET_TCP_H)
+#include <netinet/tcp.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#include "urldata.h"
+#include "bufq.h"
+#include "sendf.h"
+#include "if2ip.h"
+#include "strerror.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 "inet_ntop.h"
+#include "inet_pton.h"
+#include "progress.h"
+#include "warnless.h"
+#include "conncache.h"
+#include "multihandle.h"
+#include "share.h"
+#include "version_win32.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+
+#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) && defined(WIN32)
+/* It makes support for IPv4-mapped IPv6 addresses.
+ * Linux kernel, NetBSD, FreeBSD and Darwin: default is off;
+ * Windows Vista and later: default is on;
+ * 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)
+{
+#if defined(TCP_NODELAY)
+ curl_socklen_t onoff = (curl_socklen_t) 1;
+ int level = IPPROTO_TCP;
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ char buffer[STRERROR_LEN];
+#else
+ (void) data;
+#endif
+
+ if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
+ sizeof(onoff)) < 0)
+ infof(data, "Could not set TCP_NODELAY: %s",
+ Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
+#else
+ (void)data;
+ (void)sockfd;
+#endif
+}
+
+#ifdef SO_NOSIGPIPE
+/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
+ 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,
+ curl_socket_t sockfd)
+{
+ int onoff = 1;
+ if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
+ sizeof(onoff)) < 0) {
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ char buffer[STRERROR_LEN];
+ infof(data, "Could not set SO_NOSIGPIPE: %s",
+ Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
+#endif
+ }
+}
+#else
+#define nosigpipe(x,y) Curl_nop_stmt
+#endif
+
+#if defined(__DragonFly__) || defined(HAVE_WINSOCK2_H)
+/* DragonFlyBSD and Windows use millisecond units */
+#define KEEPALIVE_FACTOR(x) (x *= 1000)
+#else
+#define KEEPALIVE_FACTOR(x)
+#endif
+
+#if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
+#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)
+{
+ 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 %d", sockfd);
+ }
+ else {
+#if defined(SIO_KEEPALIVE_VALS)
+ struct tcp_keepalive vals;
+ DWORD dummy;
+ vals.onoff = 1;
+ optval = curlx_sltosi(data->set.tcp_keepidle);
+ KEEPALIVE_FACTOR(optval);
+ vals.keepalivetime = optval;
+ optval = curlx_sltosi(data->set.tcp_keepintvl);
+ KEEPALIVE_FACTOR(optval);
+ vals.keepaliveinterval = optval;
+ if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
+ NULL, 0, &dummy, NULL, NULL) != 0) {
+ infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d",
+ (int)sockfd, WSAGetLastError());
+ }
+#else
+#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 %d", sockfd);
+ }
+#elif defined(TCP_KEEPALIVE)
+ /* Mac OS X style */
+ optval = curlx_sltosi(data->set.tcp_keepidle);
+ KEEPALIVE_FACTOR(optval);
+ if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
+ (void *)&optval, sizeof(optval)) < 0) {
+ infof(data, "Failed to set TCP_KEEPALIVE on fd %d", sockfd);
+ }
+#endif
+#ifdef TCP_KEEPINTVL
+ optval = curlx_sltosi(data->set.tcp_keepintvl);
+ KEEPALIVE_FACTOR(optval);
+ if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
+ (void *)&optval, sizeof(optval)) < 0) {
+ infof(data, "Failed to set TCP_KEEPINTVL on fd %d", sockfd);
+ }
+#endif
+#endif
+ }
+}
+
+/**
+ * Assign the address `ai` to the Curl_sockaddr_ex `dest` and
+ * set the transport used.
+ */
+void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
+ const struct Curl_addrinfo *ai,
+ int transport)
+{
+ /*
+ * The Curl_sockaddr_ex structure is basically libcurl's external API
+ * curl_sockaddr structure with enough space available to directly hold
+ * any protocol-specific address structures. The variable declared here
+ * will be used to pass / receive data to/from the fopensocket callback
+ * if this has been set, before that, it is initialized from parameters.
+ */
+ dest->family = ai->ai_family;
+ switch(transport) {
+ case TRNSPRT_TCP:
+ dest->socktype = SOCK_STREAM;
+ dest->protocol = IPPROTO_TCP;
+ break;
+ case TRNSPRT_UNIX:
+ dest->socktype = SOCK_STREAM;
+ dest->protocol = IPPROTO_IP;
+ break;
+ default: /* UDP and QUIC */
+ dest->socktype = SOCK_DGRAM;
+ dest->protocol = IPPROTO_UDP;
+ break;
+ }
+ dest->addrlen = ai->ai_addrlen;
+
+ if(dest->addrlen > sizeof(struct Curl_sockaddr_storage))
+ dest->addrlen = sizeof(struct Curl_sockaddr_storage);
+ memcpy(&dest->sa_addr, ai->ai_addr, dest->addrlen);
+}
+
+static CURLcode socket_open(struct Curl_easy *data,
+ struct Curl_sockaddr_ex *addr,
+ curl_socket_t *sockfd)
+{
+ 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.
+ */
+ Curl_set_in_callback(data, true);
+ *sockfd = data->set.fopensocket(data->set.opensocket_client,
+ CURLSOCKTYPE_IPCXN,
+ (struct curl_sockaddr *)addr);
+ Curl_set_in_callback(data, false);
+ }
+ else {
+ /* opensocket callback not set, so simply create the socket now */
+ *sockfd = socket(addr->family, addr->socktype, addr->protocol);
+ }
+
+ if(*sockfd == CURL_SOCKET_BAD)
+ /* no socket, no connection */
+ return CURLE_COULDNT_CONNECT;
+
+#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
+ if(data->conn->scope_id && (addr->family == AF_INET6)) {
+ struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
+ sa6->sin6_scope_id = data->conn->scope_id;
+ }
+#endif
+ return CURLE_OK;
+}
+
+/*
+ * Create a socket based on info from 'conn' and 'ai'.
+ *
+ * 'addr' should be a pointer to the correct struct to get data back, or NULL.
+ * 'sockfd' must be a pointer to a socket descriptor.
+ *
+ * If the open socket callback is set, used that!
+ *
+ */
+CURLcode Curl_socket_open(struct Curl_easy *data,
+ const struct Curl_addrinfo *ai,
+ struct Curl_sockaddr_ex *addr,
+ int transport,
+ curl_socket_t *sockfd)
+{
+ struct Curl_sockaddr_ex dummy;
+
+ if(!addr)
+ /* if the caller doesn't want info back, use a local temp copy */
+ addr = &dummy;
+
+ Curl_sock_assign_addr(addr, ai, transport);
+ return socket_open(data, addr, sockfd);
+}
+
+static int socket_close(struct Curl_easy *data, struct connectdata *conn,
+ int use_callback, curl_socket_t sock)
+{
+ if(use_callback && conn && conn->fclosesocket) {
+ int rc;
+ Curl_multi_closed(data, sock);
+ Curl_set_in_callback(data, true);
+ rc = conn->fclosesocket(conn->closesocket_client, sock);
+ Curl_set_in_callback(data, false);
+ return rc;
+ }
+
+ if(conn)
+ /* tell the multi-socket code about this */
+ Curl_multi_closed(data, sock);
+
+ sclose(sock);
+
+ return 0;
+}
+
+/*
+ * Close a socket.
+ *
+ * 'conn' can be NULL, beware!
+ */
+int Curl_socket_close(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t sock)
+{
+ return socket_close(data, conn, FALSE, sock);
+}
+
+#ifdef USE_WINSOCK
+/* When you run a program that uses the Windows Sockets API, you may
+ experience slow performance when you copy data to a TCP server.
+
+ https://support.microsoft.com/kb/823764
+
+ Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
+ Buffer Size
+
+ The problem described in this knowledge-base is applied only to pre-Vista
+ Windows. Following function trying to detect OS version and skips
+ SO_SNDBUF adjustment for Windows Vista and above.
+*/
+#define DETECT_OS_NONE 0
+#define DETECT_OS_PREVISTA 1
+#define DETECT_OS_VISTA_OR_LATER 2
+
+void Curl_sndbufset(curl_socket_t sockfd)
+{
+ int val = CURL_MAX_WRITE_SIZE + 32;
+ int curval = 0;
+ int curlen = sizeof(curval);
+
+ static int detectOsState = DETECT_OS_NONE;
+
+ if(detectOsState == DETECT_OS_NONE) {
+ if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL))
+ detectOsState = DETECT_OS_VISTA_OR_LATER;
+ else
+ detectOsState = DETECT_OS_PREVISTA;
+ }
+
+ if(detectOsState == DETECT_OS_VISTA_OR_LATER)
+ return;
+
+ if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
+ if(curval > val)
+ return;
+
+ setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
+}
+#endif
+
+static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t sockfd, int af, unsigned int scope)
+{
+ struct Curl_sockaddr_storage sa;
+ struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
+ curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
+ struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
+#endif
+
+ struct Curl_dns_entry *h = NULL;
+ unsigned short port = data->set.localport; /* use this port number, 0 for
+ "random" */
+ /* how many port numbers to try to bind to, increasing one at a time */
+ int portnum = data->set.localportrange;
+ const char *dev = data->set.str[STRING_DEVICE];
+ int error;
+#ifdef IP_BIND_ADDRESS_NO_PORT
+ int on = 1;
+#endif
+#ifndef ENABLE_IPV6
+ (void)scope;
+#endif
+
+ /*************************************************************
+ * Select device to bind socket to
+ *************************************************************/
+ if(!dev && !port)
+ /* no local kind of binding was requested */
+ return CURLE_OK;
+
+ memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
+
+ if(dev && (strlen(dev)<255) ) {
+ char myhost[256] = "";
+ int done = 0; /* -1 for error, 1 for address found */
+ bool is_interface = FALSE;
+ bool is_host = FALSE;
+ static const char *if_prefix = "if!";
+ static const char *host_prefix = "host!";
+
+ if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
+ dev += strlen(if_prefix);
+ is_interface = TRUE;
+ }
+ else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
+ dev += strlen(host_prefix);
+ is_host = TRUE;
+ }
+
+ /* interface */
+ if(!is_host) {
+#ifdef SO_BINDTODEVICE
+ /* I am not sure any other OSs than Linux that provide this feature,
+ * and at the least I cannot test. --Ben
+ *
+ * This feature allows one to tightly bind the local socket to a
+ * particular interface. This will force even requests to other
+ * local interfaces to go out the external interface.
+ *
+ *
+ * Only bind to the interface when specified as interface, not just
+ * as a hostname or ip address.
+ *
+ * interface might be a VRF, eg: vrf-blue, which means it cannot be
+ * converted to an IP address and would fail Curl_if2ip. Simply try
+ * to use it straight away.
+ */
+ if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
+ dev, (curl_socklen_t)strlen(dev) + 1) == 0) {
+ /* This is typically "errno 1, error: Operation not permitted" if
+ * you're not running as root or another suitable privileged
+ * user.
+ * If it succeeds it means the parameter was a valid interface and
+ * not an IP address. Return immediately.
+ */
+ return CURLE_OK;
+ }
+#endif
+
+ switch(Curl_if2ip(af,
+#ifdef ENABLE_IPV6
+ scope, conn->scope_id,
+#endif
+ dev, myhost, sizeof(myhost))) {
+ case IF2IP_NOT_FOUND:
+ if(is_interface) {
+ /* Do not fall back to treating it as a host name */
+ failf(data, "Couldn't bind to interface '%s'", dev);
+ 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:
+ is_interface = TRUE;
+ /*
+ * We now have the numerical IP address in the 'myhost' buffer
+ */
+ infof(data, "Local Interface %s is ip %s using address family %i",
+ dev, myhost, af);
+ done = 1;
+ break;
+ }
+ }
+ if(!is_interface) {
+ /*
+ * This was not an interface, resolve the name as a host name
+ * or IP number
+ *
+ * Temporarily force name resolution to use only the address type
+ * of the connection. The resolve functions should really be changed
+ * to take a type parameter instead.
+ */
+ unsigned char ipver = conn->ip_version;
+ int rc;
+
+ if(af == AF_INET)
+ conn->ip_version = CURL_IPRESOLVE_V4;
+#ifdef ENABLE_IPV6
+ else if(af == AF_INET6)
+ conn->ip_version = CURL_IPRESOLVE_V6;
+#endif
+
+ rc = Curl_resolv(data, dev, 80, FALSE, &h);
+ if(rc == CURLRESOLV_PENDING)
+ (void)Curl_resolver_wait_resolv(data, &h);
+ conn->ip_version = ipver;
+
+ if(h) {
+ /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
+ Curl_printable_address(h->addr, myhost, sizeof(myhost));
+ infof(data, "Name '%s' family %i resolved to '%s' family %i",
+ dev, af, myhost, h->addr->ai_family);
+ Curl_resolv_unlock(data, h);
+ if(af != h->addr->ai_family) {
+ /* bad IP version combo, signal the caller to try another address
+ family if available */
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+ done = 1;
+ }
+ else {
+ /*
+ * provided dev was no interface (or interfaces are not supported
+ * e.g. solaris) no ip address and no domain we fail here
+ */
+ done = -1;
+ }
+ }
+
+ if(done > 0) {
+#ifdef ENABLE_IPV6
+ /* IPv6 address */
+ if(af == AF_INET6) {
+#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
+ char *scope_ptr = strchr(myhost, '%');
+ if(scope_ptr)
+ *(scope_ptr++) = '\0';
+#endif
+ if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
+ si6->sin6_family = AF_INET6;
+ si6->sin6_port = htons(port);
+#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
+ if(scope_ptr) {
+ /* The "myhost" string either comes from Curl_if2ip or from
+ Curl_printable_address. The latter returns only numeric scope
+ IDs and the former returns none at all. So the scope ID, if
+ present, is known to be numeric */
+ unsigned long scope_id = strtoul(scope_ptr, NULL, 10);
+ if(scope_id > UINT_MAX)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+
+ si6->sin6_scope_id = (unsigned int)scope_id;
+ }
+#endif
+ }
+ sizeof_sa = sizeof(struct sockaddr_in6);
+ }
+ else
+#endif
+ /* IPv4 address */
+ if((af == AF_INET) &&
+ (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
+ si4->sin_family = AF_INET;
+ si4->sin_port = htons(port);
+ sizeof_sa = sizeof(struct sockaddr_in);
+ }
+ }
+
+ if(done < 1) {
+ /* errorbuf is set false so failf will overwrite any message already in
+ the error buffer, so the user receives this error message instead of a
+ generic resolve error. */
+ data->state.errorbuf = FALSE;
+ failf(data, "Couldn't bind to '%s'", dev);
+ return CURLE_INTERFACE_FAILED;
+ }
+ }
+ else {
+ /* no device was given, prepare sa to match af's needs */
+#ifdef ENABLE_IPV6
+ if(af == AF_INET6) {
+ si6->sin6_family = AF_INET6;
+ si6->sin6_port = htons(port);
+ sizeof_sa = sizeof(struct sockaddr_in6);
+ }
+ else
+#endif
+ if(af == AF_INET) {
+ si4->sin_family = AF_INET;
+ si4->sin_port = htons(port);
+ sizeof_sa = sizeof(struct sockaddr_in);
+ }
+ }
+#ifdef IP_BIND_ADDRESS_NO_PORT
+ (void)setsockopt(sockfd, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &on, sizeof(on));
+#endif
+ for(;;) {
+ if(bind(sockfd, sock, sizeof_sa) >= 0) {
+ /* we succeeded to bind */
+ struct Curl_sockaddr_storage add;
+ curl_socklen_t size = sizeof(add);
+ memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
+ if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
+ char buffer[STRERROR_LEN];
+ data->state.os_errno = error = SOCKERRNO;
+ failf(data, "getsockname() failed with errno %d: %s",
+ error, Curl_strerror(error, buffer, sizeof(buffer)));
+ return CURLE_INTERFACE_FAILED;
+ }
+ infof(data, "Local port: %hu", port);
+ conn->bits.bound = TRUE;
+ return CURLE_OK;
+ }
+
+ if(--portnum > 0) {
+ port++; /* try next port */
+ if(port == 0)
+ break;
+ infof(data, "Bind to local port %hu failed, trying next", port - 1);
+ /* We re-use/clobber the port variable here below */
+ if(sock->sa_family == AF_INET)
+ si4->sin_port = ntohs(port);
+#ifdef ENABLE_IPV6
+ else
+ si6->sin6_port = ntohs(port);
+#endif
+ }
+ else
+ break;
+ }
+ {
+ char buffer[STRERROR_LEN];
+ data->state.os_errno = error = SOCKERRNO;
+ failf(data, "bind failed with errno %d: %s",
+ error, Curl_strerror(error, buffer, sizeof(buffer)));
+ }
+
+ return CURLE_INTERFACE_FAILED;
+}
+
+/*
+ * verifyconnect() returns TRUE if the connect really has happened.
+ */
+static bool verifyconnect(curl_socket_t sockfd, int *error)
+{
+ bool rc = TRUE;
+#ifdef SO_ERROR
+ int err = 0;
+ curl_socklen_t errSize = sizeof(err);
+
+#ifdef WIN32
+ /*
+ * In October 2003 we effectively nullified this function on Windows due to
+ * problems with it using all CPU in multi-threaded cases.
+ *
+ * In May 2004, we bring it back to offer more info back on connect failures.
+ * Gisle Vanem could reproduce the former problems with this function, but
+ * could avoid them by adding this SleepEx() call below:
+ *
+ * "I don't have Rational Quantify, but the hint from his post was
+ * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
+ * just Sleep(0) would be enough?) would release whatever
+ * mutex/critical-section the ntdll call is waiting on.
+ *
+ * Someone got to verify this on Win-NT 4.0, 2000."
+ */
+
+#ifdef _WIN32_WCE
+ Sleep(0);
+#else
+ SleepEx(0, FALSE);
+#endif
+
+#endif
+
+ if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
+ err = SOCKERRNO;
+#ifdef _WIN32_WCE
+ /* Old WinCE versions don't support SO_ERROR */
+ if(WSAENOPROTOOPT == err) {
+ SET_SOCKERRNO(0);
+ err = 0;
+ }
+#endif
+#if defined(EBADIOCTL) && defined(__minix)
+ /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
+ if(EBADIOCTL == err) {
+ SET_SOCKERRNO(0);
+ err = 0;
+ }
+#endif
+ if((0 == err) || (EISCONN == err))
+ /* we are connected, awesome! */
+ rc = TRUE;
+ else
+ /* This wasn't a successful connect */
+ rc = FALSE;
+ if(error)
+ *error = err;
+#else
+ (void)sockfd;
+ if(error)
+ *error = SOCKERRNO;
+#endif
+ return rc;
+}
+
+/**
+ * Determine the curl code for a socket connect() == -1 with errno.
+ */
+static CURLcode socket_connect_result(struct Curl_easy *data,
+ const char *ipaddress, int error)
+{
+ char buffer[STRERROR_LEN];
+
+ switch(error) {
+ case EINPROGRESS:
+ case EWOULDBLOCK:
+#if defined(EAGAIN)
+#if (EAGAIN) != (EWOULDBLOCK)
+ /* On some platforms EAGAIN and EWOULDBLOCK are the
+ * same value, and on others they are different, hence
+ * the odd #if
+ */
+ case EAGAIN:
+#endif
+#endif
+ return CURLE_OK;
+
+ default:
+ /* unknown error, fallthrough and try another address! */
+ infof(data, "Immediate connect fail for %s: %s",
+ ipaddress, Curl_strerror(error, buffer, sizeof(buffer)));
+ data->state.os_errno = error;
+ /* connect failed */
+ return CURLE_COULDNT_CONNECT;
+ }
+}
+
+/* We have a recv buffer to enhance reads with len < NW_SMALL_READS.
+ * This happens often on TLS connections where the TLS implementation
+ * tries to read the head of a TLS record, determine the length of the
+ * full record and then make a subsequent read for that.
+ * On large reads, we will not fill the buffer to avoid the double copy. */
+#define NW_RECV_CHUNK_SIZE (64 * 1024)
+#define NW_RECV_CHUNKS 1
+#define NW_SMALL_READS (1024)
+
+struct cf_socket_ctx {
+ int transport;
+ struct Curl_sockaddr_ex addr; /* address to connect to */
+ curl_socket_t sock; /* current attempt socket */
+ struct bufq recvbuf; /* used when `buffer_recv` is set */
+ char r_ip[MAX_IPADR_LEN]; /* remote IP as string */
+ int r_port; /* remote port number */
+ char l_ip[MAX_IPADR_LEN]; /* local IP as string */
+ int l_port; /* local port number */
+ struct curltime started_at; /* when socket was created */
+ struct curltime connected_at; /* when socket connected/got first byte */
+ struct curltime first_byte_at; /* when first byte was recvd */
+ int error; /* errno of last failure or 0 */
+ BIT(got_first_byte); /* if first byte was received */
+ BIT(accepted); /* socket was accepted, not connected */
+ BIT(active);
+ BIT(buffer_recv);
+};
+
+static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
+ const struct Curl_addrinfo *ai,
+ int transport)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->sock = CURL_SOCKET_BAD;
+ ctx->transport = transport;
+ Curl_sock_assign_addr(&ctx->addr, ai, transport);
+ Curl_bufq_init(&ctx->recvbuf, NW_RECV_CHUNK_SIZE, NW_RECV_CHUNKS);
+}
+
+struct reader_ctx {
+ struct Curl_cfilter *cf;
+ struct Curl_easy *data;
+};
+
+static ssize_t nw_in_read(void *reader_ctx,
+ unsigned char *buf, size_t len,
+ CURLcode *err)
+{
+ struct reader_ctx *rctx = reader_ctx;
+ struct cf_socket_ctx *ctx = rctx->cf->ctx;
+ ssize_t nread;
+
+ *err = CURLE_OK;
+ nread = sread(ctx->sock, buf, len);
+
+ if(-1 == nread) {
+ int sockerr = SOCKERRNO;
+
+ if(
+#ifdef WSAEWOULDBLOCK
+ /* This is how Windows does it */
+ (WSAEWOULDBLOCK == sockerr)
+#else
+ /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
+ due to its inability to send off data without blocking. We therefore
+ treat both error codes the same here */
+ (EWOULDBLOCK == sockerr) || (EAGAIN == sockerr) || (EINTR == sockerr)
+#endif
+ ) {
+ /* this is just a case of EWOULDBLOCK */
+ *err = CURLE_AGAIN;
+ nread = -1;
+ }
+ else {
+ char buffer[STRERROR_LEN];
+
+ failf(rctx->data, "Recv failure: %s",
+ Curl_strerror(sockerr, buffer, sizeof(buffer)));
+ rctx->data->state.os_errno = sockerr;
+ *err = CURLE_RECV_ERROR;
+ nread = -1;
+ }
+ }
+ DEBUGF(LOG_CF(rctx->data, rctx->cf, "nw_in_read(len=%zu) -> %d, err=%d",
+ len, (int)nread, *err));
+ return nread;
+}
+
+static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+
+ if(ctx && CURL_SOCKET_BAD != ctx->sock) {
+ if(ctx->active) {
+ /* We share our socket at cf->conn->sock[cf->sockindex] when active.
+ * If it is no longer there, someone has stolen (and hopefully
+ * closed it) and we just forget about it.
+ */
+ if(ctx->sock == cf->conn->sock[cf->sockindex]) {
+ DEBUGF(LOG_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
+ ", active)", ctx->sock));
+ socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
+ cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
+ ") no longer at conn->sock[], discarding", ctx->sock));
+ /* TODO: we do not want this to happen. Need to check which
+ * code is messing with conn->sock[cf->sockindex] */
+ }
+ ctx->sock = CURL_SOCKET_BAD;
+ if(cf->sockindex == FIRSTSOCKET)
+ cf->conn->remote_addr = NULL;
+ }
+ else {
+ /* this is our local socket, we did never publish it */
+ DEBUGF(LOG_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
+ ", not active)", ctx->sock));
+ socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
+ ctx->sock = CURL_SOCKET_BAD;
+ }
+ Curl_bufq_reset(&ctx->recvbuf);
+ ctx->active = FALSE;
+ ctx->buffer_recv = FALSE;
+ memset(&ctx->started_at, 0, sizeof(ctx->started_at));
+ memset(&ctx->connected_at, 0, sizeof(ctx->connected_at));
+ }
+
+ cf->connected = FALSE;
+}
+
+static void cf_socket_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+
+ cf_socket_close(cf, data);
+ DEBUGF(LOG_CF(data, cf, "destroy"));
+ Curl_bufq_free(&ctx->recvbuf);
+ free(ctx);
+ cf->ctx = NULL;
+}
+
+static CURLcode set_local_ip(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+
+#ifdef HAVE_GETSOCKNAME
+ if(!(data->conn->handler->protocol & CURLPROTO_TFTP)) {
+ /* TFTP does not connect, so it cannot get the IP like this */
+
+ char buffer[STRERROR_LEN];
+ struct Curl_sockaddr_storage ssloc;
+ curl_socklen_t slen = sizeof(struct Curl_sockaddr_storage);
+
+ memset(&ssloc, 0, sizeof(ssloc));
+ if(getsockname(ctx->sock, (struct sockaddr*) &ssloc, &slen)) {
+ int error = SOCKERRNO;
+ failf(data, "getsockname() failed with errno %d: %s",
+ error, Curl_strerror(error, buffer, sizeof(buffer)));
+ return CURLE_FAILED_INIT;
+ }
+ if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
+ ctx->l_ip, &ctx->l_port)) {
+ failf(data, "ssloc inet_ntop() failed with errno %d: %s",
+ errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+ return CURLE_FAILED_INIT;
+ }
+ }
+#else
+ (void)data;
+ ctx->l_ip[0] = 0;
+ ctx->l_port = -1;
+#endif
+ return CURLE_OK;
+}
+
+static CURLcode set_remote_ip(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+
+ /* store remote address and port used in this connection attempt */
+ if(!Curl_addr2string(&ctx->addr.sa_addr, ctx->addr.addrlen,
+ ctx->r_ip, &ctx->r_port)) {
+ char buffer[STRERROR_LEN];
+
+ ctx->error = errno;
+ /* malformed address or bug in inet_ntop, try next address */
+ failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
+ errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+ return CURLE_FAILED_INIT;
+ }
+ return CURLE_OK;
+}
+
+static CURLcode cf_socket_open(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+ int error = 0;
+ bool isconnected = FALSE;
+ CURLcode result = CURLE_COULDNT_CONNECT;
+ bool is_tcp;
+ const char *ipmsg;
+
+ (void)data;
+ DEBUGASSERT(ctx->sock == CURL_SOCKET_BAD);
+ ctx->started_at = Curl_now();
+ result = socket_open(data, &ctx->addr, &ctx->sock);
+ if(result)
+ goto out;
+
+ result = set_remote_ip(cf, data);
+ if(result)
+ goto out;
+
+#ifdef ENABLE_IPV6
+ if(ctx->addr.family == AF_INET6) {
+ set_ipv6_v6only(ctx->sock, 0);
+ ipmsg = " Trying [%s]:%d...";
+ }
+ else
+#endif
+ ipmsg = " Trying %s:%d...";
+ infof(data, ipmsg, ctx->r_ip, ctx->r_port);
+
+#ifdef ENABLE_IPV6
+ 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);
+
+ nosigpipe(data, ctx->sock);
+
+ Curl_sndbufset(ctx->sock);
+
+ if(is_tcp && data->set.tcp_keepalive)
+ tcpkeepalive(data, ctx->sock);
+
+ if(data->set.fsockopt) {
+ /* activate callback for setting socket options */
+ Curl_set_in_callback(data, true);
+ error = data->set.fsockopt(data->set.sockopt_client,
+ ctx->sock,
+ CURLSOCKTYPE_IPCXN);
+ Curl_set_in_callback(data, false);
+
+ if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
+ isconnected = TRUE;
+ else if(error) {
+ result = CURLE_ABORTED_BY_CALLBACK;
+ goto out;
+ }
+ }
+
+ /* possibly bind the local end to an IP, interface or port */
+ if(ctx->addr.family == AF_INET
+#ifdef ENABLE_IPV6
+ || ctx->addr.family == AF_INET6
+#endif
+ ) {
+ result = bindlocal(data, cf->conn, ctx->sock, ctx->addr.family,
+ Curl_ipv6_scope(&ctx->addr.sa_addr));
+ if(result) {
+ if(result == CURLE_UNSUPPORTED_PROTOCOL) {
+ /* The address family is not supported on this interface.
+ We can continue trying addresses */
+ result = CURLE_COULDNT_CONNECT;
+ }
+ goto out;
+ }
+ }
+
+ /* set socket non-blocking */
+ (void)curlx_nonblock(ctx->sock, TRUE);
+
+out:
+ if(result) {
+ if(ctx->sock != CURL_SOCKET_BAD) {
+ socket_close(data, cf->conn, TRUE, ctx->sock);
+ ctx->sock = CURL_SOCKET_BAD;
+ }
+ }
+ else if(isconnected) {
+ set_local_ip(cf, data);
+ ctx->connected_at = Curl_now();
+ cf->connected = TRUE;
+ }
+ DEBUGF(LOG_CF(data, cf, "cf_socket_open() -> %d, fd=%" CURL_FORMAT_SOCKET_T,
+ result, ctx->sock));
+ return result;
+}
+
+static int do_connect(struct Curl_cfilter *cf, struct Curl_easy *data,
+ bool is_tcp_fastopen)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+#ifdef TCP_FASTOPEN_CONNECT
+ int optval = 1;
+#endif
+ int rc = -1;
+
+ (void)data;
+ if(is_tcp_fastopen) {
+#if defined(CONNECT_DATA_IDEMPOTENT) /* Darwin */
+# if defined(HAVE_BUILTIN_AVAILABLE)
+ /* while connectx function is available since macOS 10.11 / iOS 9,
+ it did not have the interface declared correctly until
+ Xcode 9 / macOS SDK 10.13 */
+ if(__builtin_available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *)) {
+ sa_endpoints_t endpoints;
+ endpoints.sae_srcif = 0;
+ endpoints.sae_srcaddr = NULL;
+ endpoints.sae_srcaddrlen = 0;
+ endpoints.sae_dstaddr = &ctx->addr.sa_addr;
+ endpoints.sae_dstaddrlen = ctx->addr.addrlen;
+
+ rc = connectx(ctx->sock, &endpoints, SAE_ASSOCID_ANY,
+ CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
+ NULL, 0, NULL, NULL);
+ }
+ else {
+ rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
+ }
+# else
+ rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
+# endif /* HAVE_BUILTIN_AVAILABLE */
+#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 %"
+ CURL_FORMAT_SOCKET_T, ctx->sock);
+
+ rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
+#elif defined(MSG_FASTOPEN) /* old Linux */
+ if(cf->conn->given->flags & PROTOPT_SSL)
+ rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
+ else
+ rc = 0; /* Do nothing */
+#endif
+ }
+ else {
+ rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
+ }
+ return rc;
+}
+
+static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_COULDNT_CONNECT;
+ int rc = 0;
+
+ (void)data;
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ /* TODO: need to support blocking connect? */
+ if(blocking)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+
+ *done = FALSE; /* a very negative world view is best */
+ if(ctx->sock == CURL_SOCKET_BAD) {
+
+ result = cf_socket_open(cf, data);
+ if(result)
+ goto out;
+
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ /* Connect TCP socket */
+ rc = do_connect(cf, data, cf->conn->bits.tcp_fastopen);
+ if(-1 == rc) {
+ result = socket_connect_result(data, ctx->r_ip, SOCKERRNO);
+ goto out;
+ }
+ }
+
+#ifdef mpeix
+ /* Call this function once now, and ignore the results. We do this to
+ "clear" the error state on the socket so that we can later read it
+ reliably. This is reported necessary on the MPE/iX operating
+ system. */
+ (void)verifyconnect(ctx->sock, NULL);
+#endif
+ /* check socket for connect */
+ rc = SOCKET_WRITABLE(ctx->sock, 0);
+
+ if(rc == 0) { /* no connection yet */
+ DEBUGF(LOG_CF(data, cf, "not connected yet"));
+ 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 = Curl_now();
+ set_local_ip(cf, data);
+ *done = TRUE;
+ cf->connected = TRUE;
+ DEBUGF(LOG_CF(data, cf, "connected"));
+ return CURLE_OK;
+ }
+ }
+ else if(rc & CURL_CSELECT_ERR) {
+ (void)verifyconnect(ctx->sock, &ctx->error);
+ result = CURLE_COULDNT_CONNECT;
+ }
+
+out:
+ if(result) {
+ if(ctx->error) {
+ data->state.os_errno = ctx->error;
+ SET_SOCKERRNO(ctx->error);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ {
+ char buffer[STRERROR_LEN];
+ infof(data, "connect to %s port %u failed: %s",
+ ctx->r_ip, ctx->r_port,
+ Curl_strerror(ctx->error, buffer, sizeof(buffer)));
+ }
+#endif
+ }
+ if(ctx->sock != CURL_SOCKET_BAD) {
+ socket_close(data, cf->conn, TRUE, ctx->sock);
+ ctx->sock = CURL_SOCKET_BAD;
+ }
+ *done = FALSE;
+ }
+ return result;
+}
+
+static void cf_socket_get_host(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char **phost,
+ const char **pdisplay_host,
+ int *pport)
+{
+ (void)data;
+ *phost = cf->conn->host.name;
+ *pdisplay_host = cf->conn->host.dispname;
+ *pport = cf->conn->port;
+}
+
+static int cf_socket_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+ int rc = GETSOCK_BLANK;
+
+ (void)data;
+ if(!cf->connected && ctx->sock != CURL_SOCKET_BAD) {
+ socks[0] = ctx->sock;
+ rc |= GETSOCK_WRITESOCK(0);
+ }
+
+ return rc;
+}
+
+static bool cf_socket_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+ int readable;
+
+ (void)data;
+ if(!Curl_bufq_is_empty(&ctx->recvbuf))
+ return TRUE;
+
+ readable = SOCKET_READABLE(ctx->sock, 0);
+ return (readable > 0 && (readable & CURL_CSELECT_IN));
+}
+
+static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+ curl_socket_t fdsave;
+ ssize_t nwritten;
+
+ *err = CURLE_OK;
+ fdsave = cf->conn->sock[cf->sockindex];
+ cf->conn->sock[cf->sockindex] = ctx->sock;
+
+#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
+ if(cf->conn->bits.tcp_fastopen) {
+ nwritten = sendto(ctx->sock, buf, len, MSG_FASTOPEN,
+ &cf->conn->remote_addr->sa_addr,
+ cf->conn->remote_addr->addrlen);
+ cf->conn->bits.tcp_fastopen = FALSE;
+ }
+ else
+#endif
+ nwritten = swrite(ctx->sock, buf, len);
+
+ if(-1 == nwritten) {
+ int sockerr = SOCKERRNO;
+
+ if(
+#ifdef WSAEWOULDBLOCK
+ /* This is how Windows does it */
+ (WSAEWOULDBLOCK == sockerr)
+#else
+ /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
+ due to its inability to send off data without blocking. We therefore
+ treat both error codes the same here */
+ (EWOULDBLOCK == sockerr) || (EAGAIN == sockerr) || (EINTR == sockerr) ||
+ (EINPROGRESS == sockerr)
+#endif
+ ) {
+ /* this is just a case of EWOULDBLOCK */
+ *err = CURLE_AGAIN;
+ }
+ else {
+ char buffer[STRERROR_LEN];
+ failf(data, "Send failure: %s",
+ Curl_strerror(sockerr, buffer, sizeof(buffer)));
+ data->state.os_errno = sockerr;
+ *err = CURLE_SEND_ERROR;
+ }
+ }
+
+ DEBUGF(LOG_CF(data, cf, "send(len=%zu) -> %d, err=%d",
+ len, (int)nwritten, *err));
+ cf->conn->sock[cf->sockindex] = fdsave;
+ return nwritten;
+}
+
+static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+ curl_socket_t fdsave;
+ ssize_t nread;
+
+ *err = CURLE_OK;
+
+ fdsave = cf->conn->sock[cf->sockindex];
+ cf->conn->sock[cf->sockindex] = ctx->sock;
+
+ if(ctx->buffer_recv && !Curl_bufq_is_empty(&ctx->recvbuf)) {
+ DEBUGF(LOG_CF(data, cf, "recv from buffer"));
+ nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);
+ }
+ else {
+ struct reader_ctx rctx;
+
+ rctx.cf = cf;
+ rctx.data = data;
+
+ /* "small" reads may trigger filling our buffer, "large" reads
+ * are probably not worth the additional copy */
+ if(ctx->buffer_recv && len < NW_SMALL_READS) {
+ ssize_t nwritten;
+ nwritten = Curl_bufq_slurp(&ctx->recvbuf, nw_in_read, &rctx, err);
+ if(nwritten < 0 && !Curl_bufq_is_empty(&ctx->recvbuf)) {
+ /* we have a partial read with an error. need to deliver
+ * what we got, return the error later. */
+ DEBUGF(LOG_CF(data, cf, "partial read: empty buffer first"));
+ nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);
+ }
+ else if(nwritten < 0) {
+ nread = -1;
+ goto out;
+ }
+ else if(nwritten == 0) {
+ /* eof */
+ *err = CURLE_OK;
+ nread = 0;
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "buffered %zd additional bytes", nwritten));
+ nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);
+ }
+ }
+ else {
+ nread = nw_in_read(&rctx, (unsigned char *)buf, len, err);
+ }
+ }
+
+out:
+ DEBUGF(LOG_CF(data, cf, "recv(len=%zu) -> %d, err=%d", len, (int)nread,
+ *err));
+ if(nread > 0 && !ctx->got_first_byte) {
+ ctx->first_byte_at = Curl_now();
+ ctx->got_first_byte = TRUE;
+ }
+ cf->conn->sock[cf->sockindex] = fdsave;
+ return nread;
+}
+
+static void conn_set_primary_ip(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+#ifdef HAVE_GETPEERNAME
+ struct cf_socket_ctx *ctx = cf->ctx;
+ if(!(data->conn->handler->protocol & CURLPROTO_TFTP)) {
+ /* TFTP does not connect the endpoint: getpeername() failed with errno
+ 107: Transport endpoint is not connected */
+
+ char buffer[STRERROR_LEN];
+ struct Curl_sockaddr_storage ssrem;
+ curl_socklen_t plen;
+ int port;
+
+ plen = sizeof(ssrem);
+ memset(&ssrem, 0, plen);
+ if(getpeername(ctx->sock, (struct sockaddr*) &ssrem, &plen)) {
+ int error = SOCKERRNO;
+ failf(data, "getpeername() failed with errno %d: %s",
+ error, Curl_strerror(error, buffer, sizeof(buffer)));
+ return;
+ }
+ if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
+ cf->conn->primary_ip, &port)) {
+ failf(data, "ssrem inet_ntop() failed with errno %d: %s",
+ errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+ return;
+ }
+ }
+#else
+ cf->conn->primary_ip[0] = 0;
+ (void)data;
+#endif
+}
+
+static void cf_socket_active(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+
+ /* use this socket from now on */
+ cf->conn->sock[cf->sockindex] = ctx->sock;
+ /* the first socket info gets set at conn and data */
+ if(cf->sockindex == FIRSTSOCKET) {
+ cf->conn->remote_addr = &ctx->addr;
+ #ifdef ENABLE_IPV6
+ cf->conn->bits.ipv6 = (ctx->addr.family == AF_INET6)? TRUE : FALSE;
+ #endif
+ conn_set_primary_ip(cf, data);
+ set_local_ip(cf, data);
+ Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port);
+ /* buffering is currently disabled by default because we have stalls
+ * in parallel transfers where not all buffered data is consumed and no
+ * socket events happen.
+ */
+ ctx->buffer_recv = FALSE;
+ }
+ ctx->active = TRUE;
+}
+
+static CURLcode cf_socket_cntrl(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+
+ (void)arg1;
+ (void)arg2;
+ switch(event) {
+ case CF_CTRL_CONN_INFO_UPDATE:
+ cf_socket_active(cf, data);
+ break;
+ case CF_CTRL_DATA_SETUP:
+ Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port);
+ break;
+ }
+ return CURLE_OK;
+}
+
+static bool cf_socket_conn_is_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+ struct pollfd pfd[1];
+ int r;
+
+ *input_pending = FALSE;
+ (void)data;
+ if(!ctx || ctx->sock == CURL_SOCKET_BAD)
+ return FALSE;
+
+ /* 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].revents = 0;
+
+ r = Curl_poll(pfd, 1, 0);
+ if(r < 0) {
+ DEBUGF(LOG_CF(data, cf, "is_alive: poll error, assume dead"));
+ return FALSE;
+ }
+ else if(r == 0) {
+ DEBUGF(LOG_CF(data, cf, "is_alive: poll timeout, assume alive"));
+ return TRUE;
+ }
+ else if(pfd[0].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL)) {
+ DEBUGF(LOG_CF(data, cf, "is_alive: err/hup/etc events, assume dead"));
+ return FALSE;
+ }
+
+ DEBUGF(LOG_CF(data, cf, "is_alive: valid events, looks alive"));
+ *input_pending = TRUE;
+ return TRUE;
+}
+
+static CURLcode cf_socket_query(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query, int *pres1, void *pres2)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+
+ switch(query) {
+ case CF_QUERY_SOCKET:
+ DEBUGASSERT(pres2);
+ *((curl_socket_t *)pres2) = ctx->sock;
+ return CURLE_OK;
+ case CF_QUERY_CONNECT_REPLY_MS:
+ if(ctx->got_first_byte) {
+ timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
+ *pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
+ }
+ else
+ *pres1 = -1;
+ return CURLE_OK;
+ case CF_QUERY_TIMER_CONNECT: {
+ struct curltime *when = pres2;
+ switch(ctx->transport) {
+ case TRNSPRT_UDP:
+ case TRNSPRT_QUIC:
+ /* Since UDP connected sockets work different from TCP, we use the
+ * time of the first byte from the peer as the "connect" time. */
+ if(ctx->got_first_byte) {
+ *when = ctx->first_byte_at;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ *when = ctx->connected_at;
+ break;
+ }
+ return CURLE_OK;
+ }
+ default:
+ break;
+ }
+ return cf->next?
+ cf->next->cft->query(cf->next, data, query, pres1, pres2) :
+ CURLE_UNKNOWN_OPTION;
+}
+
+struct Curl_cftype Curl_cft_tcp = {
+ "TCP",
+ CF_TYPE_IP_CONNECT,
+ CURL_LOG_DEFAULT,
+ cf_socket_destroy,
+ cf_tcp_connect,
+ cf_socket_close,
+ cf_socket_get_host,
+ cf_socket_get_select_socks,
+ cf_socket_data_pending,
+ cf_socket_send,
+ cf_socket_recv,
+ cf_socket_cntrl,
+ cf_socket_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ cf_socket_query,
+};
+
+CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai,
+ int transport)
+{
+ struct cf_socket_ctx *ctx = NULL;
+ struct Curl_cfilter *cf = NULL;
+ CURLcode result;
+
+ (void)data;
+ (void)conn;
+ DEBUGASSERT(transport == TRNSPRT_TCP);
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ cf_socket_ctx_init(ctx, ai, transport);
+
+ result = Curl_cf_create(&cf, &Curl_cft_tcp, ctx);
+
+out:
+ *pcf = (!result)? cf : NULL;
+ if(result) {
+ Curl_safefree(cf);
+ Curl_safefree(ctx);
+ }
+
+ return result;
+}
+
+static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+ int rc;
+
+ /* QUIC needs a connected socket, nonblocking */
+ DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
+
+ rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
+ if(-1 == rc) {
+ return socket_connect_result(data, ctx->r_ip, SOCKERRNO);
+ }
+ set_local_ip(cf, data);
+ DEBUGF(LOG_CF(data, cf, "%s socket %" CURL_FORMAT_SOCKET_T
+ " connected: [%s:%d] -> [%s:%d]",
+ (ctx->transport == TRNSPRT_QUIC)? "QUIC" : "UDP",
+ ctx->sock, ctx->l_ip, ctx->l_port, ctx->r_ip, ctx->r_port));
+
+ (void)curlx_nonblock(ctx->sock, TRUE);
+ switch(ctx->addr.family) {
+#if defined(__linux__) && defined(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
+#if defined(__linux__) && defined(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
+ }
+ return CURLE_OK;
+}
+
+static CURLcode cf_udp_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_COULDNT_CONNECT;
+
+ (void)blocking;
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+ *done = FALSE;
+ if(ctx->sock == CURL_SOCKET_BAD) {
+ result = cf_socket_open(cf, data);
+ if(result) {
+ DEBUGF(LOG_CF(data, cf, "cf_udp_connect(), open failed -> %d", result));
+ goto out;
+ }
+
+ if(ctx->transport == TRNSPRT_QUIC) {
+ result = cf_udp_setup_quic(cf, data);
+ if(result)
+ goto out;
+ DEBUGF(LOG_CF(data, cf, "cf_udp_connect(), opened socket=%"
+ CURL_FORMAT_SOCKET_T " (%s:%d)",
+ ctx->sock, ctx->l_ip, ctx->l_port));
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "cf_udp_connect(), opened socket=%"
+ CURL_FORMAT_SOCKET_T " (unconnected)", ctx->sock));
+ }
+ *done = TRUE;
+ cf->connected = TRUE;
+ }
+out:
+ return result;
+}
+
+struct Curl_cftype Curl_cft_udp = {
+ "UDP",
+ CF_TYPE_IP_CONNECT,
+ CURL_LOG_DEFAULT,
+ cf_socket_destroy,
+ cf_udp_connect,
+ cf_socket_close,
+ cf_socket_get_host,
+ cf_socket_get_select_socks,
+ cf_socket_data_pending,
+ cf_socket_send,
+ cf_socket_recv,
+ cf_socket_cntrl,
+ cf_socket_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ cf_socket_query,
+};
+
+CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai,
+ int transport)
+{
+ struct cf_socket_ctx *ctx = NULL;
+ struct Curl_cfilter *cf = NULL;
+ CURLcode result;
+
+ (void)data;
+ (void)conn;
+ DEBUGASSERT(transport == TRNSPRT_UDP || transport == TRNSPRT_QUIC);
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ cf_socket_ctx_init(ctx, ai, transport);
+
+ result = Curl_cf_create(&cf, &Curl_cft_udp, ctx);
+
+out:
+ *pcf = (!result)? cf : NULL;
+ if(result) {
+ Curl_safefree(cf);
+ Curl_safefree(ctx);
+ }
+
+ return result;
+}
+
+/* this is the TCP filter which can also handle this case */
+struct Curl_cftype Curl_cft_unix = {
+ "UNIX",
+ CF_TYPE_IP_CONNECT,
+ CURL_LOG_DEFAULT,
+ cf_socket_destroy,
+ cf_tcp_connect,
+ cf_socket_close,
+ cf_socket_get_host,
+ cf_socket_get_select_socks,
+ cf_socket_data_pending,
+ cf_socket_send,
+ cf_socket_recv,
+ cf_socket_cntrl,
+ cf_socket_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ cf_socket_query,
+};
+
+CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai,
+ int transport)
+{
+ struct cf_socket_ctx *ctx = NULL;
+ struct Curl_cfilter *cf = NULL;
+ CURLcode result;
+
+ (void)data;
+ (void)conn;
+ DEBUGASSERT(transport == TRNSPRT_UNIX);
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ cf_socket_ctx_init(ctx, ai, transport);
+
+ result = Curl_cf_create(&cf, &Curl_cft_unix, ctx);
+
+out:
+ *pcf = (!result)? cf : NULL;
+ if(result) {
+ Curl_safefree(cf);
+ Curl_safefree(ctx);
+ }
+
+ return result;
+}
+
+static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ /* we start accepted, if we ever close, we cannot go on */
+ (void)data;
+ (void)blocking;
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+ return CURLE_FAILED_INIT;
+}
+
+struct Curl_cftype Curl_cft_tcp_accept = {
+ "TCP-ACCEPT",
+ CF_TYPE_IP_CONNECT,
+ CURL_LOG_DEFAULT,
+ cf_socket_destroy,
+ cf_tcp_accept_connect,
+ cf_socket_close,
+ cf_socket_get_host, /* TODO: not accurate */
+ cf_socket_get_select_socks,
+ cf_socket_data_pending,
+ cf_socket_send,
+ cf_socket_recv,
+ cf_socket_cntrl,
+ cf_socket_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ cf_socket_query,
+};
+
+CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, curl_socket_t *s)
+{
+ CURLcode result;
+ struct Curl_cfilter *cf = NULL;
+ struct cf_socket_ctx *ctx = NULL;
+
+ /* replace any existing */
+ Curl_conn_cf_discard_all(data, conn, sockindex);
+ DEBUGASSERT(conn->sock[sockindex] == CURL_SOCKET_BAD);
+
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ ctx->transport = conn->transport;
+ ctx->sock = *s;
+ ctx->accepted = FALSE;
+ result = Curl_cf_create(&cf, &Curl_cft_tcp_accept, ctx);
+ if(result)
+ goto out;
+ Curl_conn_cf_add(data, conn, sockindex, cf);
+
+ conn->sock[sockindex] = ctx->sock;
+ set_local_ip(cf, data);
+ ctx->active = TRUE;
+ ctx->connected_at = Curl_now();
+ cf->connected = TRUE;
+ DEBUGF(LOG_CF(data, cf, "Curl_conn_tcp_listen_set(%"
+ CURL_FORMAT_SOCKET_T ")", ctx->sock));
+
+out:
+ if(result) {
+ Curl_safefree(cf);
+ Curl_safefree(ctx);
+ }
+ return result;
+}
+
+static void set_accepted_remote_ip(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_socket_ctx *ctx = cf->ctx;
+#ifdef HAVE_GETPEERNAME
+ char buffer[STRERROR_LEN];
+ struct Curl_sockaddr_storage ssrem;
+ curl_socklen_t plen;
+
+ ctx->r_ip[0] = 0;
+ ctx->r_port = 0;
+ plen = sizeof(ssrem);
+ memset(&ssrem, 0, plen);
+ if(getpeername(ctx->sock, (struct sockaddr*) &ssrem, &plen)) {
+ int error = SOCKERRNO;
+ failf(data, "getpeername() failed with errno %d: %s",
+ error, Curl_strerror(error, buffer, sizeof(buffer)));
+ return;
+ }
+ if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
+ ctx->r_ip, &ctx->r_port)) {
+ failf(data, "ssrem inet_ntop() failed with errno %d: %s",
+ errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+ return;
+ }
+#else
+ ctx->r_ip[0] = 0;
+ ctx->r_port = 0;
+ (void)data;
+#endif
+}
+
+CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, curl_socket_t *s)
+{
+ struct Curl_cfilter *cf = NULL;
+ struct cf_socket_ctx *ctx = NULL;
+
+ cf = conn->cfilter[sockindex];
+ if(!cf || cf->cft != &Curl_cft_tcp_accept)
+ return CURLE_FAILED_INIT;
+
+ ctx = cf->ctx;
+ /* discard the listen socket */
+ socket_close(data, conn, TRUE, ctx->sock);
+ ctx->sock = *s;
+ conn->sock[sockindex] = ctx->sock;
+ set_accepted_remote_ip(cf, data);
+ set_local_ip(cf, data);
+ ctx->active = TRUE;
+ ctx->accepted = TRUE;
+ ctx->connected_at = Curl_now();
+ cf->connected = TRUE;
+ DEBUGF(LOG_CF(data, cf, "accepted_set(sock=%" CURL_FORMAT_SOCKET_T
+ ", remote=%s port=%d)",
+ ctx->sock, ctx->r_ip, ctx->r_port));
+
+ return CURLE_OK;
+}
+
+/**
+ * Return TRUE iff `cf` is a socket filter.
+ */
+static bool cf_is_socket(struct Curl_cfilter *cf)
+{
+ return cf && (cf->cft == &Curl_cft_tcp ||
+ cf->cft == &Curl_cft_udp ||
+ cf->cft == &Curl_cft_unix ||
+ cf->cft == &Curl_cft_tcp_accept);
+}
+
+CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *psock,
+ const struct Curl_sockaddr_ex **paddr,
+ const char **pr_ip_str, int *pr_port,
+ const char **pl_ip_str, int *pl_port)
+{
+ if(cf_is_socket(cf) && cf->ctx) {
+ struct cf_socket_ctx *ctx = cf->ctx;
+
+ if(psock)
+ *psock = ctx->sock;
+ if(paddr)
+ *paddr = &ctx->addr;
+ if(pr_ip_str)
+ *pr_ip_str = ctx->r_ip;
+ if(pr_port)
+ *pr_port = ctx->r_port;
+ if(pl_port ||pl_ip_str) {
+ set_local_ip(cf, data);
+ if(pl_ip_str)
+ *pl_ip_str = ctx->l_ip;
+ if(pl_port)
+ *pl_port = ctx->l_port;
+ }
+ return CURLE_OK;
+ }
+ return CURLE_FAILED_INIT;
+}
+
diff --git a/lib/cf-socket.h b/lib/cf-socket.h
new file mode 100644
index 0000000..1d40df7
--- /dev/null
+++ b/lib/cf-socket.h
@@ -0,0 +1,191 @@
+#ifndef HEADER_CURL_CF_SOCKET_H
+#define HEADER_CURL_CF_SOCKET_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */
+#include "sockaddr.h"
+
+struct Curl_addrinfo;
+struct Curl_cfilter;
+struct Curl_easy;
+struct connectdata;
+struct Curl_sockaddr_ex;
+
+#ifndef SIZEOF_CURL_SOCKET_T
+/* configure and cmake check and set the define */
+# ifdef _WIN64
+# define SIZEOF_CURL_SOCKET_T 8
+# else
+/* default guess */
+# define SIZEOF_CURL_SOCKET_T 4
+# endif
+#endif
+
+#if SIZEOF_CURL_SOCKET_T < 8
+# define CURL_FORMAT_SOCKET_T "d"
+#else
+# define CURL_FORMAT_SOCKET_T "qd"
+#endif
+
+
+/*
+ * The Curl_sockaddr_ex structure is basically libcurl's external API
+ * curl_sockaddr structure with enough space available to directly hold any
+ * protocol-specific address structures. The variable declared here will be
+ * used to pass / receive data to/from the fopensocket callback if this has
+ * been set, before that, it is initialized from parameters.
+ */
+struct Curl_sockaddr_ex {
+ int family;
+ int socktype;
+ int protocol;
+ unsigned int addrlen;
+ union {
+ struct sockaddr addr;
+ struct Curl_sockaddr_storage buff;
+ } _sa_ex_u;
+};
+#define sa_addr _sa_ex_u.addr
+
+
+/*
+ * Create a socket based on info from 'conn' and 'ai'.
+ *
+ * Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open
+ * socket callback is set, used that!
+ *
+ */
+CURLcode Curl_socket_open(struct Curl_easy *data,
+ const struct Curl_addrinfo *ai,
+ struct Curl_sockaddr_ex *addr,
+ int transport,
+ curl_socket_t *sockfd);
+
+int Curl_socket_close(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t sock);
+
+#ifdef USE_WINSOCK
+/* When you run a program that uses the Windows Sockets API, you may
+ experience slow performance when you copy data to a TCP server.
+
+ https://support.microsoft.com/kb/823764
+
+ Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
+ Buffer Size
+
+*/
+void Curl_sndbufset(curl_socket_t sockfd);
+#else
+#define Curl_sndbufset(y) Curl_nop_stmt
+#endif
+
+/**
+ * Assign the address `ai` to the Curl_sockaddr_ex `dest` and
+ * set the transport used.
+ */
+void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
+ const struct Curl_addrinfo *ai,
+ int transport);
+
+/**
+ * Creates a cfilter that opens a TCP socket to the given address
+ * when calling its `connect` implementation.
+ * The filter will not touch any connection/data flags and can be
+ * used in happy eyeballing. Once selected for use, its `_active()`
+ * method needs to be called.
+ */
+CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai,
+ int transport);
+
+/**
+ * Creates a cfilter that opens a UDP socket to the given address
+ * when calling its `connect` implementation.
+ * The filter will not touch any connection/data flags and can be
+ * used in happy eyeballing. Once selected for use, its `_active()`
+ * method needs to be called.
+ */
+CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai,
+ int transport);
+
+/**
+ * Creates a cfilter that opens a UNIX socket to the given address
+ * when calling its `connect` implementation.
+ * The filter will not touch any connection/data flags and can be
+ * used in happy eyeballing. Once selected for use, its `_active()`
+ * method needs to be called.
+ */
+CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai,
+ int transport);
+
+/**
+ * Creates a cfilter that keeps a listening socket.
+ */
+CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
+ curl_socket_t *s);
+
+/**
+ * Replace the listen socket with the accept()ed one.
+ */
+CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
+ curl_socket_t *s);
+
+/**
+ * Peek at the socket and remote ip/port the socket filter is using.
+ * The filter owns all returned values.
+ * @param psock pointer to hold socket descriptor or NULL
+ * @param paddr pointer to hold addr reference or NULL
+ * @param pr_ip_str pointer to hold remote addr as string or NULL
+ * @param pr_port pointer to hold remote port number or NULL
+ * @param pl_ip_str pointer to hold local addr as string or NULL
+ * @param pl_port pointer to hold local port number or NULL
+ * Returns error if the filter is of invalid type.
+ */
+CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *psock,
+ const struct Curl_sockaddr_ex **paddr,
+ const char **pr_ip_str, int *pr_port,
+ const char **pl_ip_str, int *pl_port);
+
+extern struct Curl_cftype Curl_cft_tcp;
+extern struct Curl_cftype Curl_cft_udp;
+extern struct Curl_cftype Curl_cft_unix;
+extern struct Curl_cftype Curl_cft_tcp_accept;
+
+#endif /* HEADER_CURL_CF_SOCKET_H */
diff --git a/lib/cfilters.c b/lib/cfilters.c
new file mode 100644
index 0000000..216d0b4
--- /dev/null
+++ b/lib/cfilters.c
@@ -0,0 +1,649 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 "urldata.h"
+#include "strerror.h"
+#include "cfilters.h"
+#include "connect.h"
+#include "url.h" /* for Curl_safefree() */
+#include "sendf.h"
+#include "sockaddr.h" /* required for Curl_sockaddr_storage */
+#include "multiif.h"
+#include "progress.h"
+#include "warnless.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
+
+#ifdef DEBUGBUILD
+/* used by unit2600.c */
+void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ cf->connected = FALSE;
+ if(cf->next)
+ cf->next->cft->do_close(cf->next, data);
+}
+#endif
+
+static void conn_report_connect_stats(struct Curl_easy *data,
+ struct connectdata *conn);
+
+void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const char **phost, const char **pdisplay_host,
+ int *pport)
+{
+ if(cf->next)
+ cf->next->cft->get_host(cf->next, data, phost, pdisplay_host, pport);
+ else {
+ *phost = cf->conn->host.name;
+ *pdisplay_host = cf->conn->host.dispname;
+ *pport = cf->conn->port;
+ }
+}
+
+int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ return cf->next?
+ cf->next->cft->get_select_socks(cf->next, data, socks) : 0;
+}
+
+bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ return cf->next?
+ cf->next->cft->has_data_pending(cf->next, data) : FALSE;
+}
+
+ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err)
+{
+ return cf->next?
+ cf->next->cft->do_send(cf->next, data, buf, len, err) :
+ CURLE_RECV_ERROR;
+}
+
+ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err)
+{
+ return cf->next?
+ cf->next->cft->do_recv(cf->next, data, buf, len, err) :
+ CURLE_SEND_ERROR;
+}
+
+bool Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending)
+{
+ return cf->next?
+ cf->next->cft->is_alive(cf->next, data, input_pending) :
+ FALSE; /* pessimistic in absence of data */
+}
+
+CURLcode Curl_cf_def_conn_keep_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ return cf->next?
+ cf->next->cft->keep_alive(cf->next, data) :
+ CURLE_OK;
+}
+
+CURLcode Curl_cf_def_query(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query, int *pres1, void *pres2)
+{
+ return cf->next?
+ cf->next->cft->query(cf->next, data, query, pres1, pres2) :
+ CURLE_UNKNOWN_OPTION;
+}
+
+void Curl_conn_cf_discard_chain(struct Curl_cfilter **pcf,
+ struct Curl_easy *data)
+{
+ struct Curl_cfilter *cfn, *cf = *pcf;
+
+ if(cf) {
+ *pcf = NULL;
+ while(cf) {
+ cfn = cf->next;
+ /* prevent destroying filter to mess with its sub-chain, since
+ * we have the reference now and will call destroy on it.
+ */
+ cf->next = NULL;
+ cf->cft->destroy(cf, data);
+ free(cf);
+ cf = cfn;
+ }
+ }
+}
+
+void Curl_conn_cf_discard_all(struct Curl_easy *data,
+ struct connectdata *conn, int index)
+{
+ Curl_conn_cf_discard_chain(&conn->cfilter[index], data);
+}
+
+void Curl_conn_close(struct Curl_easy *data, int index)
+{
+ struct Curl_cfilter *cf;
+
+ DEBUGASSERT(data->conn);
+ /* it is valid to call that without filters being present */
+ cf = data->conn->cfilter[index];
+ if(cf) {
+ cf->cft->do_close(cf, data);
+ }
+}
+
+ssize_t Curl_conn_recv(struct Curl_easy *data, int num, char *buf,
+ size_t len, CURLcode *code)
+{
+ struct Curl_cfilter *cf;
+
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
+ cf = data->conn->cfilter[num];
+ while(cf && !cf->connected) {
+ cf = cf->next;
+ }
+ if(cf) {
+ return cf->cft->do_recv(cf, data, buf, len, code);
+ }
+ failf(data, "recv: no filter connected");
+ *code = CURLE_FAILED_INIT;
+ return -1;
+}
+
+ssize_t Curl_conn_send(struct Curl_easy *data, int num,
+ const void *mem, size_t len, CURLcode *code)
+{
+ struct Curl_cfilter *cf;
+
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
+ cf = data->conn->cfilter[num];
+ while(cf && !cf->connected) {
+ cf = cf->next;
+ }
+ if(cf) {
+ return cf->cft->do_send(cf, data, mem, len, code);
+ }
+ failf(data, "send: no filter connected");
+ DEBUGASSERT(0);
+ *code = CURLE_FAILED_INIT;
+ return -1;
+}
+
+CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
+ const struct Curl_cftype *cft,
+ void *ctx)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+
+ DEBUGASSERT(cft);
+ cf = calloc(sizeof(*cf), 1);
+ if(!cf)
+ goto out;
+
+ cf->cft = cft;
+ cf->ctx = ctx;
+ result = CURLE_OK;
+out:
+ *pcf = cf;
+ return result;
+}
+
+void Curl_conn_cf_add(struct Curl_easy *data,
+ struct connectdata *conn,
+ int index,
+ struct Curl_cfilter *cf)
+{
+ (void)data;
+ DEBUGASSERT(conn);
+ DEBUGASSERT(!cf->conn);
+ DEBUGASSERT(!cf->next);
+
+ cf->next = conn->cfilter[index];
+ cf->conn = conn;
+ cf->sockindex = index;
+ conn->cfilter[index] = cf;
+ DEBUGF(LOG_CF(data, cf, "added"));
+}
+
+void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_cfilter *cf_new)
+{
+ struct Curl_cfilter *tail, **pnext;
+
+ DEBUGASSERT(cf_at);
+ DEBUGASSERT(cf_new);
+ DEBUGASSERT(!cf_new->conn);
+
+ tail = cf_at->next;
+ cf_at->next = cf_new;
+ do {
+ cf_new->conn = cf_at->conn;
+ cf_new->sockindex = cf_at->sockindex;
+ pnext = &cf_new->next;
+ cf_new = cf_new->next;
+ } while(cf_new);
+ *pnext = tail;
+}
+
+bool Curl_conn_cf_discard_sub(struct Curl_cfilter *cf,
+ struct Curl_cfilter *discard,
+ struct Curl_easy *data,
+ bool destroy_always)
+{
+ struct Curl_cfilter **pprev = &cf->next;
+ bool found = FALSE;
+
+ /* remove from sub-chain and destroy */
+ DEBUGASSERT(cf);
+ while(*pprev) {
+ if(*pprev == cf) {
+ *pprev = discard->next;
+ discard->next = NULL;
+ found = TRUE;
+ break;
+ }
+ pprev = &((*pprev)->next);
+ }
+ if(found || destroy_always) {
+ discard->next = NULL;
+ discard->cft->destroy(discard, data);
+ free(discard);
+ }
+ return found;
+}
+
+CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ if(cf)
+ return cf->cft->do_connect(cf, data, blocking, done);
+ return CURLE_FAILED_INIT;
+}
+
+void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ if(cf)
+ cf->cft->do_close(cf, data);
+}
+
+int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ if(cf)
+ return cf->cft->get_select_socks(cf, data, socks);
+ return 0;
+}
+
+ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err)
+{
+ if(cf)
+ return cf->cft->do_send(cf, data, buf, len, err);
+ *err = CURLE_SEND_ERROR;
+ return -1;
+}
+
+ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err)
+{
+ if(cf)
+ return cf->cft->do_recv(cf, data, buf, len, err);
+ *err = CURLE_RECV_ERROR;
+ return -1;
+}
+
+CURLcode Curl_conn_connect(struct Curl_easy *data,
+ int sockindex,
+ bool blocking,
+ bool *done)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result = CURLE_OK;
+
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
+
+ cf = data->conn->cfilter[sockindex];
+ DEBUGASSERT(cf);
+ if(!cf)
+ return CURLE_FAILED_INIT;
+
+ *done = cf->connected;
+ if(!*done) {
+ result = cf->cft->do_connect(cf, data, blocking, done);
+ if(!result && *done) {
+ Curl_conn_ev_update_info(data, data->conn);
+ conn_report_connect_stats(data, data->conn);
+ data->conn->keepalive = Curl_now();
+ }
+ else if(result) {
+ conn_report_connect_stats(data, data->conn);
+ }
+ }
+
+ return result;
+}
+
+bool Curl_conn_is_connected(struct connectdata *conn, int sockindex)
+{
+ struct Curl_cfilter *cf;
+
+ cf = conn->cfilter[sockindex];
+ return cf && cf->connected;
+}
+
+bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex)
+{
+ struct Curl_cfilter *cf;
+
+ cf = data->conn->cfilter[sockindex];
+ while(cf) {
+ if(cf->connected)
+ return TRUE;
+ if(cf->cft->flags & CF_TYPE_IP_CONNECT)
+ return FALSE;
+ cf = cf->next;
+ }
+ return FALSE;
+}
+
+bool Curl_conn_cf_is_ssl(struct Curl_cfilter *cf)
+{
+ for(; cf; cf = cf->next) {
+ if(cf->cft->flags & CF_TYPE_SSL)
+ return TRUE;
+ if(cf->cft->flags & CF_TYPE_IP_CONNECT)
+ return FALSE;
+ }
+ return FALSE;
+}
+
+bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex)
+{
+ return conn? Curl_conn_cf_is_ssl(conn->cfilter[sockindex]) : FALSE;
+}
+
+bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex)
+{
+ struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL;
+
+ for(; cf; cf = cf->next) {
+ if(cf->cft->flags & CF_TYPE_MULTIPLEX)
+ return TRUE;
+ if(cf->cft->flags & CF_TYPE_IP_CONNECT
+ || cf->cft->flags & CF_TYPE_SSL)
+ return FALSE;
+ }
+ return FALSE;
+}
+
+bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
+{
+ struct Curl_cfilter *cf;
+
+ (void)data;
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
+
+ cf = data->conn->cfilter[sockindex];
+ while(cf && !cf->connected) {
+ cf = cf->next;
+ }
+ if(cf) {
+ return cf->cft->has_data_pending(cf, data);
+ }
+ return FALSE;
+}
+
+int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
+ curl_socket_t *socks)
+{
+ struct Curl_cfilter *cf;
+
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
+ cf = data->conn->cfilter[sockindex];
+
+ /* if the next one is not yet connected, that's the one we want */
+ while(cf && cf->next && !cf->next->connected)
+ cf = cf->next;
+ if(cf) {
+ return cf->cft->get_select_socks(cf, data, socks);
+ }
+ return GETSOCK_BLANK;
+}
+
+void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
+ const char **phost, const char **pdisplay_host,
+ int *pport)
+{
+ struct Curl_cfilter *cf;
+
+ DEBUGASSERT(data->conn);
+ cf = data->conn->cfilter[sockindex];
+ if(cf) {
+ cf->cft->get_host(cf, data, phost, pdisplay_host, pport);
+ }
+ else {
+ /* Some filter ask during shutdown for this, mainly for debugging
+ * purposes. We hand out the defaults, however this is not always
+ * accurate, as the connection might be tunneled, etc. But all that
+ * state is already gone here. */
+ *phost = data->conn->host.name;
+ *pdisplay_host = data->conn->host.dispname;
+ *pport = data->conn->remote_port;
+ }
+}
+
+CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
+{
+ (void)cf;
+ (void)data;
+ (void)event;
+ (void)arg1;
+ (void)arg2;
+ return CURLE_OK;
+}
+
+CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool ignore_result,
+ int event, int arg1, void *arg2)
+{
+ CURLcode result = CURLE_OK;
+
+ for(; cf; cf = cf->next) {
+ if(Curl_cf_def_cntrl == cf->cft->cntrl)
+ continue;
+ result = cf->cft->cntrl(cf, data, event, arg1, arg2);
+ if(!ignore_result && result)
+ break;
+ }
+ return result;
+}
+
+curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ curl_socket_t sock;
+ if(cf && !cf->cft->query(cf, data, CF_QUERY_SOCKET, NULL, &sock))
+ return sock;
+ return CURL_SOCKET_BAD;
+}
+
+curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex)
+{
+ struct Curl_cfilter *cf;
+
+ cf = data->conn? data->conn->cfilter[sockindex] : NULL;
+ /* if the top filter has not connected, ask it (and its sub-filters)
+ * for the socket. Otherwise conn->sock[sockindex] should have it.
+ */
+ if(cf && !cf->connected)
+ return Curl_conn_cf_get_socket(cf, data);
+ return data->conn? data->conn->sock[sockindex] : CURL_SOCKET_BAD;
+}
+
+static CURLcode cf_cntrl_all(struct connectdata *conn,
+ struct Curl_easy *data,
+ bool ignore_result,
+ int event, int arg1, void *arg2)
+{
+ CURLcode result = CURLE_OK;
+ size_t i;
+
+ for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
+ result = Curl_conn_cf_cntrl(conn->cfilter[i], data, ignore_result,
+ event, arg1, arg2);
+ if(!ignore_result && result)
+ break;
+ }
+ return result;
+}
+
+void Curl_conn_ev_data_attach(struct connectdata *conn,
+ struct Curl_easy *data)
+{
+ cf_cntrl_all(conn, data, TRUE, CF_CTRL_DATA_ATTACH, 0, NULL);
+}
+
+void Curl_conn_ev_data_detach(struct connectdata *conn,
+ struct Curl_easy *data)
+{
+ cf_cntrl_all(conn, data, TRUE, CF_CTRL_DATA_DETACH, 0, NULL);
+}
+
+CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data)
+{
+ return cf_cntrl_all(data->conn, data, FALSE,
+ CF_CTRL_DATA_SETUP, 0, NULL);
+}
+
+CURLcode Curl_conn_ev_data_idle(struct Curl_easy *data)
+{
+ return cf_cntrl_all(data->conn, data, FALSE,
+ CF_CTRL_DATA_IDLE, 0, NULL);
+}
+
+/**
+ * Notify connection filters that the transfer represented by `data`
+ * is donw with sending data (e.g. has uploaded everything).
+ */
+void Curl_conn_ev_data_done_send(struct Curl_easy *data)
+{
+ cf_cntrl_all(data->conn, data, TRUE, CF_CTRL_DATA_DONE_SEND, 0, NULL);
+}
+
+/**
+ * Notify connection filters that the transfer represented by `data`
+ * is finished - eventually premature, e.g. before being complete.
+ */
+void Curl_conn_ev_data_done(struct Curl_easy *data, bool premature)
+{
+ cf_cntrl_all(data->conn, data, TRUE, CF_CTRL_DATA_DONE, premature, NULL);
+}
+
+CURLcode Curl_conn_ev_data_pause(struct Curl_easy *data, bool do_pause)
+{
+ return cf_cntrl_all(data->conn, data, FALSE,
+ CF_CTRL_DATA_PAUSE, do_pause, NULL);
+}
+
+void Curl_conn_ev_update_info(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ cf_cntrl_all(conn, data, TRUE, CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
+}
+
+/**
+ * Update connection statistics
+ */
+static void conn_report_connect_stats(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET];
+ if(cf) {
+ struct curltime connected;
+ struct curltime appconnected;
+
+ memset(&connected, 0, sizeof(connected));
+ cf->cft->query(cf, data, CF_QUERY_TIMER_CONNECT, NULL, &connected);
+ if(connected.tv_sec || connected.tv_usec)
+ Curl_pgrsTimeWas(data, TIMER_CONNECT, connected);
+
+ memset(&appconnected, 0, sizeof(appconnected));
+ cf->cft->query(cf, data, CF_QUERY_TIMER_APPCONNECT, NULL, &appconnected);
+ if(appconnected.tv_sec || appconnected.tv_usec)
+ Curl_pgrsTimeWas(data, TIMER_APPCONNECT, appconnected);
+ }
+}
+
+bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
+ bool *input_pending)
+{
+ struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET];
+ return cf && !cf->conn->bits.close &&
+ cf->cft->is_alive(cf, data, input_pending);
+}
+
+CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
+{
+ struct Curl_cfilter *cf = conn->cfilter[sockindex];
+ return cf? cf->cft->keep_alive(cf, data) : CURLE_OK;
+}
+
+size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode result;
+ int n = 0;
+
+ struct Curl_cfilter *cf = conn->cfilter[sockindex];
+ result = cf? cf->cft->query(cf, data, CF_QUERY_MAX_CONCURRENT,
+ &n, NULL) : CURLE_UNKNOWN_OPTION;
+ return (result || n <= 0)? 1 : (size_t)n;
+}
+
diff --git a/lib/cfilters.h b/lib/cfilters.h
new file mode 100644
index 0000000..2c65264
--- /dev/null
+++ b/lib/cfilters.h
@@ -0,0 +1,539 @@
+#ifndef HEADER_CURL_CFILTERS_H
+#define HEADER_CURL_CFILTERS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+
+struct Curl_cfilter;
+struct Curl_easy;
+struct Curl_dns_entry;
+struct connectdata;
+
+/* Callback to destroy resources held by this filter instance.
+ * Implementations MUST NOT chain calls to cf->next.
+ */
+typedef void Curl_cft_destroy_this(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+typedef void Curl_cft_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+typedef CURLcode Curl_cft_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done);
+
+/* Return the hostname and port the connection goes to.
+ * This may change with the connection state of filters when tunneling
+ * is involved.
+ * @param cf the filter to ask
+ * @param data the easy handle currently active
+ * @param phost on return, points to the relevant, real hostname.
+ * this is owned by the connection.
+ * @param pdisplay_host on return, points to the printable hostname.
+ * this is owned by the connection.
+ * @param pport on return, contains the port number
+ */
+typedef void Curl_cft_get_host(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char **phost,
+ const char **pdisplay_host,
+ int *pport);
+
+/* Filters may return sockets and fdset flags they are waiting for.
+ * The passes array has room for up to MAX_SOCKSPEREASYHANDLE sockets.
+ * @return read/write fdset for index in socks
+ * or GETSOCK_BLANK when nothing to wait on
+ */
+typedef int Curl_cft_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks);
+
+typedef bool Curl_cft_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data);
+
+typedef ssize_t Curl_cft_send(struct Curl_cfilter *cf,
+ struct Curl_easy *data, /* transfer */
+ const void *buf, /* data to write */
+ size_t len, /* amount to write */
+ CURLcode *err); /* error to return */
+
+typedef ssize_t Curl_cft_recv(struct Curl_cfilter *cf,
+ struct Curl_easy *data, /* transfer */
+ char *buf, /* store data here */
+ size_t len, /* amount to read */
+ CURLcode *err); /* error to return */
+
+typedef bool Curl_cft_conn_is_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending);
+
+typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+/**
+ * Events/controls for connection filters, their arguments and
+ * return code handling. Filter callbacks are invoked "top down".
+ * Return code handling:
+ * "first fail" meaning that the first filter returning != CURLE_OK, will
+ * abort further event distribution and determine the result.
+ * "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_ATTACH 1 /* 0 NULL ignored */
+#define CF_CTRL_DATA_DETACH 2 /* 0 NULL ignored */
+#define CF_CTRL_DATA_SETUP 4 /* 0 NULL first fail */
+#define CF_CTRL_DATA_IDLE 5 /* 0 NULL first fail */
+#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 */
+
+/**
+ * Handle event/control for the filter.
+ * Implementations MUST NOT chain calls to cf->next.
+ */
+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
+ * chain expects to handle at the same time.
+ * default: 1 if no filter overrides.
+ * - CONNECT_REPLY_MS: milliseconds until the first indication of a server
+ * response was received on a connect. For TCP, this
+ * reflects the time until the socket connected. On UDP
+ * this gives the time the first bytes from the server
+ * were received.
+ * -1 if not determined yet.
+ * - CF_QUERY_SOCKET: the socket used by the filter chain
+ */
+/* query res1 res2 */
+#define CF_QUERY_MAX_CONCURRENT 1 /* number - */
+#define CF_QUERY_CONNECT_REPLY_MS 2 /* number - */
+#define CF_QUERY_SOCKET 3 /* - curl_socket_t */
+#define CF_QUERY_TIMER_CONNECT 4 /* - struct curltime */
+#define CF_QUERY_TIMER_APPCONNECT 5 /* - struct curltime */
+
+/**
+ * Query the cfilter for properties. Filters ignorant of a query will
+ * pass it "down" the filter chain.
+ */
+typedef CURLcode Curl_cft_query(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query, int *pres1, void *pres2);
+
+/**
+ * Type flags for connection filters. A filter can have none, one or
+ * many of those. Use to evaluate state/capabilities of a filter chain.
+ *
+ * CF_TYPE_IP_CONNECT: provides an IP connection or sth equivalent, like
+ * a CONNECT tunnel, a UNIX domain socket, a QUIC
+ * connection, etc.
+ * CF_TYPE_SSL: provide SSL/TLS
+ * CF_TYPE_MULTIPLEX: provides multiplexing of easy handles
+ */
+#define CF_TYPE_IP_CONNECT (1 << 0)
+#define CF_TYPE_SSL (1 << 1)
+#define CF_TYPE_MULTIPLEX (1 << 2)
+
+/* 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_get_host *get_host; /* host filter talks to */
+ Curl_cft_get_select_socks *get_select_socks;/* sockets to select on */
+ 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 */
+struct Curl_cfilter {
+ const struct Curl_cftype *cft; /* the type providing implementation */
+ struct Curl_cfilter *next; /* next filter in chain */
+ void *ctx; /* filter type specific settings */
+ struct connectdata *conn; /* the connection this filter belongs to */
+ int sockindex; /* the index the filter is installed at */
+ BIT(connected); /* != 0 iff this filter is connected */
+};
+
+/* Default implementations for the type functions, implementing nop. */
+void Curl_cf_def_destroy_this(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+/* Default implementations for the type functions, implementing pass-through
+ * the filter chain. */
+void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const char **phost, const char **pdisplay_host,
+ int *pport);
+int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks);
+bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data);
+ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err);
+ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err);
+CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2);
+bool Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending);
+CURLcode Curl_cf_def_conn_keep_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+CURLcode Curl_cf_def_query(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query, int *pres1, void *pres2);
+
+/**
+ * Create a new filter instance, unattached to the filter chain.
+ * Use Curl_conn_cf_add() to add it to the chain.
+ * @param pcf on success holds the created instance
+ * @param cft the filter type
+ * @param ctx the type specific context to use
+ */
+CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
+ const struct Curl_cftype *cft,
+ void *ctx);
+
+/**
+ * Add a filter instance to the `sockindex` filter chain at connection
+ * `conn`. The filter must not already be attached. It is inserted at
+ * the start of the chain (top).
+ */
+void Curl_conn_cf_add(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
+ struct Curl_cfilter *cf);
+
+/**
+ * Insert a filter (chain) after `cf_at`.
+ * `cf_new` must not already be attached.
+ */
+void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_cfilter *cf_new);
+
+/**
+ * Discard, e.g. remove and destroy `discard` iff
+ * it still is in the filter chain below `cf`. If `discard`
+ * is no longer found beneath `cf` return FALSE.
+ * if `destroy_always` is TRUE, will call `discard`s destroy
+ * function and free it even if not found in the subchain.
+ */
+bool Curl_conn_cf_discard_sub(struct Curl_cfilter *cf,
+ struct Curl_cfilter *discard,
+ struct Curl_easy *data,
+ bool destroy_always);
+
+/**
+ * Discard all cfilters starting with `*pcf` and clearing it afterwards.
+ */
+void Curl_conn_cf_discard_chain(struct Curl_cfilter **pcf,
+ struct Curl_easy *data);
+
+/**
+ * Remove and destroy all filters at chain `sockindex` on connection `conn`.
+ */
+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 blocking, bool *done);
+void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data);
+int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks);
+ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err);
+ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err);
+CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool ignore_result,
+ int event, int arg1, void *arg2);
+
+/**
+ * Determine if the connection filter chain is using SSL to the remote host
+ * (or will be once connected).
+ */
+bool Curl_conn_cf_is_ssl(struct Curl_cfilter *cf);
+
+/**
+ * Get the socket used by the filter chain starting at `cf`.
+ * Returns CURL_SOCKET_BAD if not available.
+ */
+curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+
+#define CURL_CF_SSL_DEFAULT -1
+#define CURL_CF_SSL_DISABLE 0
+#define CURL_CF_SSL_ENABLE 1
+
+/**
+ * Bring the filter chain at `sockindex` for connection `data->conn` into
+ * connected state. Which will set `*done` to TRUE.
+ * This can be called on an already connected chain with no side effects.
+ * When not `blocking`, calls may return without error and `*done != TRUE`,
+ * while the individual filters negotiated the connection.
+ */
+CURLcode Curl_conn_connect(struct Curl_easy *data, int sockindex,
+ bool blocking, bool *done);
+
+/**
+ * Check if the filter chain at `sockindex` for connection `conn` is
+ * completely connected.
+ */
+bool Curl_conn_is_connected(struct connectdata *conn, int sockindex);
+
+/**
+ * Determine if we have reached the remote host on IP level, e.g.
+ * have a TCP connection. This turns TRUE before a possible SSL
+ * handshake has been started/done.
+ */
+bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex);
+
+/**
+ * Determine if the connection is using SSL to the remote host
+ * (or will be once connected). This will return FALSE, if SSL
+ * is only used in proxying and not for the tunnel itself.
+ */
+bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex);
+
+/**
+ * Connection provides multiplexing of easy handles at `socketindex`.
+ */
+bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex);
+
+/**
+ * Close the filter chain at `sockindex` for connection `data->conn`.
+ * Filters remain in place and may be connected again afterwards.
+ */
+void Curl_conn_close(struct Curl_easy *data, int sockindex);
+
+/**
+ * Return if data is pending in some connection filter at chain
+ * `sockindex` for connection `data->conn`.
+ */
+bool Curl_conn_data_pending(struct Curl_easy *data,
+ int sockindex);
+
+/**
+ * Return the socket used on data's connection for the index.
+ * Returns CURL_SOCKET_BAD if not available.
+ */
+curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex);
+
+/**
+ * Get any select fd flags and the socket filters at chain `sockindex`
+ * at connection `conn` might be waiting for.
+ */
+int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
+ curl_socket_t *socks);
+
+/**
+ * Receive data through the filter chain at `sockindex` for connection
+ * `data->conn`. Copy at most `len` bytes into `buf`. Return the
+ * actuel number of bytes copied or a negative value on error.
+ * The error code is placed into `*code`.
+ */
+ssize_t Curl_conn_recv(struct Curl_easy *data, int sockindex, char *buf,
+ size_t len, CURLcode *code);
+
+/**
+ * Send `len` bytes of data from `buf` through the filter chain `sockindex`
+ * at connection `data->conn`. Return the actual number of bytes written
+ * or a negative value on error.
+ * The error code is placed into `*code`.
+ */
+ssize_t Curl_conn_send(struct Curl_easy *data, int sockindex,
+ const void *buf, size_t len, CURLcode *code);
+
+/**
+ * The easy handle `data` is being attached to `conn`. This does
+ * not mean that data will actually do a transfer. Attachment is
+ * also used for temporary actions on the connection.
+ */
+void Curl_conn_ev_data_attach(struct connectdata *conn,
+ struct Curl_easy *data);
+
+/**
+ * The easy handle `data` is being detached (no longer served)
+ * by connection `conn`. All filters are informed to release any resources
+ * related to `data`.
+ * Note: there may be several `data` attached to a connection at the same
+ * time.
+ */
+void Curl_conn_ev_data_detach(struct connectdata *conn,
+ struct Curl_easy *data);
+
+/**
+ * Notify connection filters that they need to setup data for
+ * a transfer.
+ */
+CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data);
+
+/**
+ * Notify connection filters that now would be a good time to
+ * perform any idle, e.g. time related, actions.
+ */
+CURLcode Curl_conn_ev_data_idle(struct Curl_easy *data);
+
+/**
+ * Notify connection filters that the transfer represented by `data`
+ * is donw with sending data (e.g. has uploaded everything).
+ */
+void Curl_conn_ev_data_done_send(struct Curl_easy *data);
+
+/**
+ * Notify connection filters that the transfer represented by `data`
+ * is finished - eventually premature, e.g. before being complete.
+ */
+void Curl_conn_ev_data_done(struct Curl_easy *data, bool premature);
+
+/**
+ * Notify connection filters that the transfer of data is paused/unpaused.
+ */
+CURLcode Curl_conn_ev_data_pause(struct Curl_easy *data, bool do_pause);
+
+/**
+ * Inform connection filters to update their info in `conn`.
+ */
+void Curl_conn_ev_update_info(struct Curl_easy *data,
+ struct connectdata *conn);
+
+/**
+ * Check if FIRSTSOCKET's cfilter chain deems connection alive.
+ */
+bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
+ bool *input_pending);
+
+/**
+ * Try to upkeep the connection filters at sockindex.
+ */
+CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex);
+
+void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data);
+void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
+ const char **phost, const char **pdisplay_host,
+ int *pport);
+
+/**
+ * Get the maximum number of parallel transfers the connection
+ * expects to be able to handle at `sockindex`.
+ */
+size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex);
+
+
+/**
+ * Types and macros used to keep the current easy handle in filter calls,
+ * allowing for nested invocations. See #10336.
+ *
+ * `cf_call_data` is intended to be a member of the cfilter's `ctx` type.
+ * A filter defines the macro `CF_CTX_CALL_DATA` to give access to that.
+ *
+ * With all values 0, the default, this indicates that there is no cfilter
+ * call with `data` ongoing.
+ * Macro `CF_DATA_SAVE` preserves the current `cf_call_data` in a local
+ * variable and sets the `data` given, incrementing the `depth` counter.
+ *
+ * Macro `CF_DATA_RESTORE` restores the old values from the local variable,
+ * while checking that `depth` values are as expected (debug build), catching
+ * cases where a "lower" RESTORE was not called.
+ *
+ * Finally, macro `CF_DATA_CURRENT` gives the easy handle of the current
+ * invocation.
+ */
+struct cf_call_data {
+ struct Curl_easy *data;
+#ifdef DEBUGBUILD
+ int depth;
+#endif
+};
+
+/**
+ * define to access the `struct cf_call_data for a cfilter. Normally
+ * a member in the cfilter's `ctx`.
+ *
+ * #define CF_CTX_CALL_DATA(cf) -> struct cf_call_data instance
+*/
+
+#ifdef DEBUGBUILD
+
+#define CF_DATA_SAVE(save, cf, data) \
+ do { \
+ (save) = CF_CTX_CALL_DATA(cf); \
+ DEBUGASSERT((save).data == NULL || (save).depth > 0); \
+ CF_CTX_CALL_DATA(cf).depth++; \
+ CF_CTX_CALL_DATA(cf).data = (struct Curl_easy *)data; \
+ } while(0)
+
+#define CF_DATA_RESTORE(cf, save) \
+ do { \
+ DEBUGASSERT(CF_CTX_CALL_DATA(cf).depth == (save).depth + 1); \
+ DEBUGASSERT((save).data == NULL || (save).depth > 0); \
+ CF_CTX_CALL_DATA(cf) = (save); \
+ } while(0)
+
+#else /* DEBUGBUILD */
+
+#define CF_DATA_SAVE(save, cf, data) \
+ do { \
+ (save) = CF_CTX_CALL_DATA(cf); \
+ CF_CTX_CALL_DATA(cf).data = (struct Curl_easy *)data; \
+ } while(0)
+
+#define CF_DATA_RESTORE(cf, save) \
+ do { \
+ CF_CTX_CALL_DATA(cf) = (save); \
+ } while(0)
+
+#endif /* !DEBUGBUILD */
+
+#define CF_DATA_CURRENT(cf) \
+ ((cf)? (CF_CTX_CALL_DATA(cf).data) : NULL)
+
+#endif /* HEADER_CURL_CFILTERS_H */
diff --git a/lib/config-amigaos.h b/lib/config-amigaos.h
index 79186c6..11f36a1 100644
--- a/lib/config-amigaos.h
+++ b/lib/config-amigaos.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -32,27 +32,15 @@
#define HAVE_ARPA_INET_H 1
#define HAVE_CLOSESOCKET_CAMEL 1
-#define HAVE_ERRNO_H 1
-#define HAVE_INET_ADDR 1
#define HAVE_INTTYPES_H 1
#define HAVE_IOCTLSOCKET_CAMEL 1
#define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1
-#define HAVE_LIBZ 1
#define HAVE_LONGLONG 1
-#define HAVE_MALLOC_H 1
-#define HAVE_MEMORY_H 1
#define HAVE_NETDB_H 1
#define HAVE_NETINET_IN_H 1
#define HAVE_NET_IF_H 1
-#define HAVE_OPENSSL_CRYPTO_H 1
-#define HAVE_OPENSSL_ERR_H 1
-#define HAVE_OPENSSL_PEM_H 1
-#define HAVE_OPENSSL_RSA_H 1
-#define HAVE_OPENSSL_SSL_H 1
-#define HAVE_OPENSSL_X509_H 1
#define HAVE_PWD_H 1
#define HAVE_RAND_EGD 1
-#define HAVE_RAND_STATUS 1
#define HAVE_SELECT 1
#define HAVE_SETJMP_H 1
#define HAVE_SIGNAL 1
@@ -60,11 +48,9 @@
#define HAVE_SOCKET 1
#define HAVE_STRCASECMP 1
#define HAVE_STRDUP 1
-#define HAVE_STRFTIME 1
#define HAVE_STRICMP 1
#define HAVE_STRINGS_H 1
#define HAVE_STRING_H 1
-#define HAVE_STRSTR 1
#define HAVE_STRUCT_TIMEVAL 1
#define HAVE_SYS_PARAM_H 1
#define HAVE_SYS_SOCKET_H 1
@@ -73,25 +59,27 @@
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_TIME_H 1
-#define HAVE_UNAME 1
#define HAVE_UNISTD_H 1
#define HAVE_UTIME 1
#define HAVE_UTIME_H 1
#define HAVE_WRITABLE_ARGV 1
-#define HAVE_ZLIB_H 1
#define HAVE_SYS_IOCTL_H 1
#define NEED_MALLOC_H 1
#define SIZEOF_INT 4
-#define SIZEOF_SHORT 2
#define SIZEOF_SIZE_T 4
+#ifndef SIZEOF_CURL_OFF_T
+#define SIZEOF_CURL_OFF_T 8
+#endif
+
#define USE_MANUAL 1
-#define USE_OPENSSL 1
#define CURL_DISABLE_LDAP 1
+#ifndef OS
#define OS "AmigaOS"
+#endif
#define PACKAGE "curl"
#define PACKAGE_BUGREPORT "a suitable mailing list: https://curl.se/mail/"
@@ -99,11 +87,14 @@
#define PACKAGE_STRING "curl -"
#define PACKAGE_TARNAME "curl"
#define PACKAGE_VERSION "-"
-#define CURL_CA_BUNDLE "s:curl-ca-bundle.crt"
-#define SELECT_TYPE_ARG1 int
-#define SELECT_TYPE_ARG234 (fd_set *)
-#define SELECT_TYPE_ARG5 (struct timeval *)
+#if defined(USE_AMISSL)
+#define CURL_CA_PATH "AmiSSL:Certs"
+#elif defined(__MORPHOS__)
+#define CURL_CA_BUNDLE "MOSSYS:Data/SSL/curl-ca-bundle.crt"
+#else
+#define CURL_CA_BUNDLE "s:curl-ca-bundle.crt"
+#endif
#define STDC_HEADERS 1
#define TIME_WITH_SYS_TIME 1
@@ -133,15 +124,6 @@
#define RECV_TYPE_ARG4 long
#define RECV_TYPE_RETV long
-#define HAVE_RECVFROM 1
-#define RECVFROM_TYPE_ARG1 long
-#define RECVFROM_TYPE_ARG2 char
-#define RECVFROM_TYPE_ARG3 long
-#define RECVFROM_TYPE_ARG4 long
-#define RECVFROM_TYPE_ARG5 struct sockaddr
-#define RECVFROM_TYPE_ARG6 long
-#define RECVFROM_TYPE_RETV long
-
#define HAVE_SEND 1
#define SEND_TYPE_ARG1 int
#define SEND_QUAL_ARG2 const
diff --git a/lib/config-dos.h b/lib/config-dos.h
index 9fb7743..05c1a81 100644
--- a/lib/config-dos.h
+++ b/lib/config-dos.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,6 +29,7 @@
/* lib/config-dos.h - Hand crafted config file for DOS */
/* ================================================================ */
+#ifndef OS
#if defined(DJGPP)
#define OS "MSDOS/djgpp"
#elif defined(__HIGHC__)
@@ -36,32 +37,28 @@
#else
#define OS "MSDOS/?"
#endif
+#endif
#define PACKAGE "curl"
+#define USE_MANUAL 1
+
#define HAVE_ARPA_INET_H 1
-#define HAVE_ASSERT_H 1
-#define HAVE_ERRNO_H 1
#define HAVE_FCNTL_H 1
#define HAVE_FREEADDRINFO 1
#define HAVE_GETADDRINFO 1
-#define HAVE_GETPROTOBYNAME 1
#define HAVE_GETTIMEOFDAY 1
#define HAVE_IO_H 1
-#define HAVE_IOCTL 1
#define HAVE_IOCTL_FIONBIO 1
#define HAVE_IOCTLSOCKET 1
#define HAVE_IOCTLSOCKET_FIONBIO 1
#define HAVE_LOCALE_H 1
#define HAVE_LONGLONG 1
-#define HAVE_MEMORY_H 1
#define HAVE_NETDB_H 1
#define HAVE_NETINET_IN_H 1
#define HAVE_NETINET_TCP_H 1
#define HAVE_NET_IF_H 1
-#define HAVE_PROCESS_H 1
#define HAVE_RECV 1
-#define HAVE_RECVFROM 1
#define HAVE_SELECT 1
#define HAVE_SEND 1
#define HAVE_SETJMP_H 1
@@ -73,7 +70,6 @@
#define HAVE_STRICMP 1
#define HAVE_STRTOLL 1
#define HAVE_STRUCT_TIMEVAL 1
-#define HAVE_STRUCT_IN6_ADDR 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_SYS_SOCKET_H 1
#define HAVE_SYS_STAT_H 1
@@ -85,14 +81,12 @@
#define SIZEOF_INT 4
#define SIZEOF_LONG 4
-#define SIZEOF_LONG_DOUBLE 16
-#define SIZEOF_SHORT 2
#define SIZEOF_SIZE_T 4
-#define SIZEOF_CURL_OFF_T 4
+#define SIZEOF_CURL_OFF_T 8
#define STDC_HEADERS 1
#define TIME_WITH_SYS_TIME 1
-/* Qualifiers for send(), recv(), and recvfrom() */
+/* Qualifiers for send() and recv() */
#define SEND_TYPE_ARG1 int
#define SEND_QUAL_ARG2 const
@@ -107,32 +101,11 @@
#define RECV_TYPE_ARG4 int
#define RECV_TYPE_RETV int
-#define RECVFROM_TYPE_ARG1 int
-#define RECVFROM_TYPE_ARG2 void
-#define RECVFROM_TYPE_ARG3 int
-#define RECVFROM_TYPE_ARG4 int
-#define RECVFROM_TYPE_ARG5 struct sockaddr
-#define RECVFROM_TYPE_ARG6 int
-#define RECVFROM_TYPE_RETV int
-#define RECVFROM_TYPE_ARG2_IS_VOID 1
-
#define BSD
/* CURLDEBUG definition enables memory tracking */
/* #define CURLDEBUG */
-/* USE_ZLIB on cmd-line */
-#ifdef USE_ZLIB
- #define HAVE_ZLIB_H 1
- #define HAVE_LIBZ 1
-#endif
-
-/* USE_OPENSSL on cmd-line */
-#ifdef USE_OPENSSL
- #define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
- #define OPENSSL_NO_KRB5 1
-#endif
-
/* to disable LDAP */
#define CURL_DISABLE_LDAP 1
diff --git a/lib/config-mac.h b/lib/config-mac.h
index dd1d9a7..8bd2fbd 100644
--- a/lib/config-mac.h
+++ b/lib/config-mac.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,15 +30,20 @@
/* On Mac OS X you must run configure to generate curl_config.h file */
/* =================================================================== */
+#ifndef OS
#define OS "mac"
+#endif
+
+#include <ConditionalMacros.h>
+#if TYPE_LONGLONG
+#define HAVE_LONGLONG 1
+#endif
/* Define if you want the built-in manual */
#define USE_MANUAL 1
-#define HAVE_ERRNO_H 1
#define HAVE_NETINET_IN_H 1
#define HAVE_SYS_SOCKET_H 1
-#define HAVE_SYS_SELECT_H 1
#define HAVE_NETDB_H 1
#define HAVE_ARPA_INET_H 1
#define HAVE_UNISTD_H 1
@@ -47,22 +52,18 @@
#define HAVE_GETTIMEOFDAY 1
#define HAVE_FCNTL_H 1
#define HAVE_SYS_STAT_H 1
-#define HAVE_ALLOCA_H 1
#define HAVE_STDLIB_H 1
#define HAVE_TIME_H 1
#define HAVE_UTIME_H 1
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_UTIME_H 1
+#define HAVE_SYS_IOCTL_H 1
#define TIME_WITH_SYS_TIME 1
#define HAVE_ALARM 1
#define HAVE_FTRUNCATE 1
#define HAVE_UTIME 1
-#define HAVE_SETVBUF 1
-#define HAVE_STRFTIME 1
-#define HAVE_INET_ADDR 1
-#define HAVE_MEMCPY 1
#define HAVE_SELECT 1
#define HAVE_SOCKET 1
#define HAVE_STRUCT_TIMEVAL 1
@@ -76,15 +77,18 @@
#define CURL_DISABLE_LDAP 1
-#define HAVE_RAND_STATUS 1
#define HAVE_RAND_EGD 1
-#define HAVE_IOCTL 1
#define HAVE_IOCTL_FIONBIO 1
#define SIZEOF_INT 4
-#define SIZEOF_SHORT 2
+#define SIZEOF_LONG 4
#define SIZEOF_SIZE_T 4
+#ifdef HAVE_LONGLONG
+#define SIZEOF_CURL_OFF_T 8
+#else
+#define SIZEOF_CURL_OFF_T 4
+#endif
#define HAVE_RECV 1
#define RECV_TYPE_ARG1 int
@@ -93,21 +97,11 @@
#define RECV_TYPE_ARG4 int
#define RECV_TYPE_RETV ssize_t
-#define HAVE_RECVFROM 1
-#define RECVFROM_TYPE_ARG1 int
-#define RECVFROM_TYPE_ARG2 void
-#define RECVFROM_TYPE_ARG3 size_t
-#define RECVFROM_TYPE_ARG4 int
-#define RECVFROM_TYPE_ARG5 struct sockaddr
-#define RECVFROM_TYPE_ARG6 int
-#define RECVFROM_TYPE_RETV ssize_t
-#define RECVFROM_TYPE_ARG2_IS_VOID 1
-
#define HAVE_SEND 1
#define SEND_TYPE_ARG1 int
#define SEND_QUAL_ARG2 const
#define SEND_TYPE_ARG2 void *
-#define SEND_TYPE_ARG3 size_T
+#define SEND_TYPE_ARG3 size_t
#define SEND_TYPE_ARG4 int
#define SEND_TYPE_RETV ssize_t
diff --git a/lib/config-os400.h b/lib/config-os400.h
index f6113fc..8d48955 100644
--- a/lib/config-os400.h
+++ b/lib/config-os400.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,11 +35,10 @@
/* Version number of this archive. */
#undef VERSION
-/* Define if you have the getpass function. */
-#undef HAVE_GETPASS
-
/* Define cpu-machine-OS */
+#ifndef OS
#define OS "OS/400"
+#endif
/* OS400 supports a 3-argument ASCII version of gethostbyaddr_r(), but its
* prototype is incompatible with the "standard" one (1st argument is not
@@ -57,9 +56,6 @@
/* Define if you need the _REENTRANT define for some functions */
#undef NEED_REENTRANT
-/* Define if you have the Kerberos4 libraries (including -ldes) */
-#undef HAVE_KRB4
-
/* Define if you want to enable IPv6 support */
#define ENABLE_IPV6
@@ -78,18 +74,12 @@
/* Define to 1 if you have the alarm function. */
#define HAVE_ALARM 1
-/* Define if you have the <alloca.h> header file. */
-#undef HAVE_ALLOCA_H
-
/* Define if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H
/* Define if you have the `closesocket' function. */
#undef HAVE_CLOSESOCKET
-/* Define if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H
-
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H
@@ -99,9 +89,6 @@
/* Define if you have the `gethostname' function. */
#define HAVE_GETHOSTNAME
-/* Define if you have the <getopt.h> header file. */
-#undef HAVE_GETOPT_H
-
/* Define if you have the `getpass_r' function. */
#undef HAVE_GETPASS_R
@@ -111,9 +98,6 @@
/* Define if you have the `getpwuid' function. */
#define HAVE_GETPWUID
-/* Define if you have the `getservbyname' function. */
-#define HAVE_GETSERVBYNAME
-
/* Define to 1 if you have the getsockname function. */
#define HAVE_GETSOCKNAME 1
@@ -123,30 +107,12 @@
/* Define if you have the `timeval' struct. */
#define HAVE_STRUCT_TIMEVAL
-/* Define if you have the `inet_addr' function. */
-#define HAVE_INET_ADDR
-
/* Define if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H
/* Define if you have the <io.h> header file. */
#undef HAVE_IO_H
-/* Define if you have the `krb_get_our_ip_for_realm' function. */
-#undef HAVE_KRB_GET_OUR_IP_FOR_REALM
-
-/* Define if you have the <krb.h> header file. */
-#undef HAVE_KRB_H
-
-/* Define if you have the `nsl' library (-lnsl). */
-#undef HAVE_LIBNSL
-
-/* Define if you have the `resolv' library (-lresolv). */
-#undef HAVE_LIBRESOLV
-
-/* Define if you have the `resolve' library (-lresolve). */
-#undef HAVE_LIBRESOLVE
-
/* Define if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
@@ -162,72 +128,27 @@
/* Define if you have the MIT gssapi libraries */
#undef HAVE_GSSMIT
-/* Define if you have the `ucb' library (-lucb). */
-#undef HAVE_LIBUCB
-
-/* Define if you have the `localtime_r' function. */
-#define HAVE_LOCALTIME_R
-
-/* Define if you have the <malloc.h> header file. */
-#define HAVE_MALLOC_H
-
/* Define if you need the malloc.h header file even with stdlib.h */
/* #define NEED_MALLOC_H 1 */
-/* Define if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
/* Define if you have the <netdb.h> header file. */
#define HAVE_NETDB_H
-/* Define if you have the <netinet/if_ether.h> header file. */
-#undef HAVE_NETINET_IF_ETHER_H
-
/* Define if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H
/* Define if you have the <net/if.h> header file. */
#define HAVE_NET_IF_H
-/* Define if you have the <openssl/crypto.h> header file. */
-#undef HAVE_OPENSSL_CRYPTO_H
-
-/* Define if you have the <openssl/err.h> header file. */
-#undef HAVE_OPENSSL_ERR_H
-
-/* Define if you have the <openssl/pem.h> header file. */
-#undef HAVE_OPENSSL_PEM_H
-
-/* Define if you have the <openssl/rsa.h> header file. */
-#undef HAVE_OPENSSL_RSA_H
-
-/* Define if you have the <openssl/ssl.h> header file. */
-#undef HAVE_OPENSSL_SSL_H
-
-/* Define if you have the <openssl/x509.h> header file. */
-#undef HAVE_OPENSSL_X509_H
-
-/* Define if you have the <pem.h> header file. */
-#undef HAVE_PEM_H
-
/* Define if you have the <pwd.h> header file. */
#define HAVE_PWD_H
/* Define if you have the `RAND_egd' function. */
#undef HAVE_RAND_EGD
-/* Define if you have the `RAND_screen' function. */
-#undef HAVE_RAND_SCREEN
-
-/* Define if you have the `RAND_status' function. */
-#undef HAVE_RAND_STATUS
-
/* Define if you have the `select' function. */
#define HAVE_SELECT
-/* Define if you have the `setvbuf' function. */
-#define HAVE_SETVBUF
-
/* Define if you have the `sigaction' function. */
#define HAVE_SIGACTION
@@ -266,10 +187,6 @@
/* Define if you have the `strdup' function. */
#define HAVE_STRDUP
-
-/* Define if you have the `strftime' function. */
-#define HAVE_STRFTIME
-
/* Define if you have the <strings.h> header file. */
#define HAVE_STRINGS_H
@@ -279,9 +196,6 @@
/* Define if you have the <stropts.h> header file. */
#undef HAVE_STROPTS_H
-/* Define if you have the `strstr' function. */
-#define HAVE_STRSTR
-
/* Define if you have the `strtok_r' function. */
#define HAVE_STRTOK_R
@@ -324,33 +238,21 @@
/* Define if you have the <time.h> header file. */
#define HAVE_TIME_H
-/* Define if you have the `uname' function. */
-#undef HAVE_UNAME
-
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H
-/* Define if you have the <x509.h> header file. */
-#undef HAVE_X509_H
-
/* Name of package */
#undef PACKAGE
/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
-/* The size of a `long double', as computed by sizeof. */
-#define SIZEOF_LONG_DOUBLE 8
-
/* Define if the compiler supports the 'long long' data type. */
#define HAVE_LONGLONG
/* The size of a `long long', as computed by sizeof. */
#define SIZEOF_LONG_LONG 8
-/* The size of `short', as computed by sizeof. */
-#define SIZEOF_SHORT 2
-
/* The size of `long', as computed by sizeof. */
#define SIZEOF_LONG 4
@@ -360,10 +262,6 @@
/* The size of `curl_off_t', as computed by sizeof. */
#define SIZEOF_CURL_OFF_T 8
-/* Whether long long constants must be suffixed by LL. */
-
-#define HAVE_LL
-
/* Define this if you have struct sockaddr_storage */
#define HAVE_STRUCT_SOCKADDR_STORAGE
@@ -395,9 +293,6 @@
/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t
-/* Define if you have the ioctl function. */
-#define HAVE_IOCTL
-
/* Define if you have a working ioctl FIONBIO function. */
#define HAVE_IOCTL_FIONBIO
@@ -431,30 +326,6 @@
/* Define to the function return type for recv. */
#define RECV_TYPE_RETV int
-/* Define if you have the recvfrom function. */
-#define HAVE_RECVFROM
-
-/* Define to the type of arg 1 for recvfrom. */
-#define RECVFROM_TYPE_ARG1 int
-
-/* Define to the type pointed by arg 2 for recvfrom. */
-#define RECVFROM_TYPE_ARG2 char
-
-/* Define to the type of arg 3 for recvfrom. */
-#define RECVFROM_TYPE_ARG3 int
-
-/* Define to the type of arg 4 for recvfrom. */
-#define RECVFROM_TYPE_ARG4 int
-
-/* Define to the type pointed by arg 5 for recvfrom. */
-#define RECVFROM_TYPE_ARG5 struct sockaddr
-
-/* Define to the type pointed by arg 6 for recvfrom. */
-#define RECVFROM_TYPE_ARG6 int
-
-/* Define to the function return type for recvfrom. */
-#define RECVFROM_TYPE_RETV int
-
/* Define if you have the send function. */
#define HAVE_SEND
diff --git a/lib/config-plan9.h b/lib/config-plan9.h
index 75aac72..54f89b0 100644
--- a/lib/config-plan9.h
+++ b/lib/config-plan9.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -32,7 +32,9 @@
#define CURL_DISABLE_LDAP 1
#define NEED_REENTRANT 1
+#ifndef OS
#define OS "plan9"
+#endif
#define PACKAGE "curl"
#define PACKAGE_NAME "curl"
#define PACKAGE_BUGREPORT "a suitable mailing list: https://curl.se/mail/"
@@ -48,7 +50,6 @@
#error not implement
#else
#define SIZEOF_INT 4
-#define SIZEOF_SHORT 2
#define SIZEOF_LONG 4
#define SIZEOF_OFF_T 8
#define SIZEOF_CURL_OFF_T 4 /* curl_off_t = timediff_t = int */
@@ -63,23 +64,7 @@
#define RECV_TYPE_ARG4 int
#define RECV_TYPE_RETV int
-#define HAVE_RECVFROM 1
-#define RECVFROM_TYPE_ARG1 int
-#define RECVFROM_TYPE_ARG2 void
-#define RECVFROM_TYPE_ARG2_IS_VOID 1
-#define RECVFROM_TYPE_ARG3 int
-#define RECVFROM_TYPE_ARG4 int
-#define RECVFROM_TYPE_ARG5 void
-#define RECVFROM_TYPE_ARG5_IS_VOID 1
-#define RECVFROM_TYPE_ARG6 int
-#define RECVFROM_TYPE_ARG6_IS_VOID 1
-#define RECVFROM_TYPE_RETV int
-
#define HAVE_SELECT 1
-#define SELECT_TYPE_ARG1 int
-#define SELECT_TYPE_ARG234 fd_set *
-#define SELECT_TYPE_ARG5 struct timeval *
-#define SELECT_TYPE_RETV int
#define HAVE_SEND 1
#define SEND_TYPE_ARG1 int
@@ -91,34 +76,25 @@
#define HAVE_ALARM 1
#define HAVE_ARPA_INET_H 1
-#define HAVE_ASSERT_H 1
#define HAVE_BASENAME 1
#define HAVE_BOOL_T 1
-#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
-#define HAVE_ERRNO_H 1
#define HAVE_FCNTL 1
#define HAVE_FCNTL_H 1
#define HAVE_FREEADDRINFO 1
#define HAVE_FTRUNCATE 1
#define HAVE_GETADDRINFO 1
#define HAVE_GETEUID 1
-#define HAVE_GETHOSTBYNAME 1
#define HAVE_GETHOSTNAME 1
#define HAVE_GETPPID 1
-#define HAVE_GETPROTOBYNAME 1
#define HAVE_GETPWUID 1
#define HAVE_GETTIMEOFDAY 1
#define HAVE_GMTIME_R 1
-#define HAVE_INET_ADDR 1
#define HAVE_INET_NTOP 1
#define HAVE_INET_PTON 1
#define HAVE_INTTYPES_H 1
-#define HAVE_IOCTL 1
#define HAVE_LIBGEN_H 1
#define HAVE_LIBZ 1
-#define HAVE_LL 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
@@ -127,26 +103,14 @@
#define HAVE_SYS_SELECT_H 1
#define USE_OPENSSL 1
-#define HAVE_OPENSSL_CRYPTO_H 1
-#define HAVE_OPENSSL_ERR_H 1
-#define HAVE_OPENSSL_PEM_H 1
-#define HAVE_OPENSSL_PKCS12_H 1
-#define HAVE_OPENSSL_RSA_H 1
-#define HAVE_OPENSSL_SSL_H 1
-#define HAVE_OPENSSL_X509_H 1
#define HAVE_PIPE 1
-#define HAVE_POLL 1
#define HAVE_POLL_FINE 1
#define HAVE_POLL_H 1
#define HAVE_PTHREAD_H 1
-#define HAVE_RAND_STATUS 1
#define HAVE_SETJMP_H 1
#define HAVE_SETLOCALE 1
-#define HAVE_SETSOCKOPT 1
-#define HAVE_SOCK_OPTS 1 /* for /sys/include/ape/sys/socket.h */
-
#define HAVE_SIGACTION 1
#define HAVE_SIGNAL 1
#define HAVE_SIGNAL_H 1
@@ -156,12 +120,10 @@
#define HAVE_SSL_GET_SHUTDOWN 1
#define HAVE_STDBOOL_H 1
#define HAVE_STDINT_H 1
-#define HAVE_STDIO_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRCASECMP 1
#define HAVE_STRDUP 1
#define HAVE_STRING_H 1
-#define HAVE_STRSTR 1
#define HAVE_STRTOK_R 1
#define HAVE_STRTOLL 1
#define HAVE_STRUCT_TIMEVAL 1
@@ -172,21 +134,15 @@
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_TYPES_H 1
-#define HAVE_SYS_UIO_H 1
#define HAVE_SYS_UN_H 1
#define HAVE_TERMIOS_H 1
#define HAVE_TIME_H 1
-#define HAVE_UNAME 1
#define HAVE_UNISTD_H 1
#define HAVE_UTIME 1
#define HAVE_UTIME_H 1
-#define HAVE_WRITEV 1
-
-#define HAVE_ZLIB_H 1
#define HAVE_POSIX_STRERROR_R 1
#define HAVE_STRERROR_R 1
-#define STRERROR_R_TYPE_ARG3 int
#define TIME_WITH_SYS_TIME 1
#define USE_MANUAL 1
diff --git a/lib/config-riscos.h b/lib/config-riscos.h
index 3836562..2464731 100644
--- a/lib/config-riscos.h
+++ b/lib/config-riscos.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,11 +34,10 @@
/* Version number of this archive. */
#undef VERSION
-/* Define if you have the getpass function. */
-#undef HAVE_GETPASS
-
/* Define cpu-machine-OS */
+#ifndef OS
#define OS "ARM-RISC OS"
+#endif
/* Define if you want the built-in manual */
#define USE_MANUAL
@@ -55,9 +54,6 @@
/* Define if you need the _REENTRANT define for some functions */
#undef NEED_REENTRANT
-/* Define if you have the Kerberos4 libraries (including -ldes) */
-#undef HAVE_KRB4
-
/* Define if you want to enable IPv6 support */
#undef ENABLE_IPV6
@@ -79,18 +75,12 @@
/* Define if you have the alarm function. */
#define HAVE_ALARM
-/* Define if you have the <alloca.h> header file. */
-#define HAVE_ALLOCA_H
-
/* Define if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H
/* Define if you have the `closesocket' function. */
#undef HAVE_CLOSESOCKET
-/* Define if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H
-
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H
@@ -109,117 +99,48 @@
/* Define if you have the `gethostname' function. */
#define HAVE_GETHOSTNAME
-/* Define if you have the <getopt.h> header file. */
-#define HAVE_GETOPT_H
-
/* Define if you have the `getpass_r' function. */
#undef HAVE_GETPASS_R
/* Define if you have the `getpwuid' function. */
#undef HAVE_GETPWUID
-/* Define if you have the `getservbyname' function. */
-#undef HAVE_GETSERVBYNAME
-
/* Define if you have the `gettimeofday' function. */
#define HAVE_GETTIMEOFDAY
/* Define if you have the `timeval' struct. */
#define HAVE_STRUCT_TIMEVAL
-/* Define if you have the `inet_addr' function. */
-#undef HAVE_INET_ADDR
-
/* Define if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H
/* Define if you have the <io.h> header file. */
#undef HAVE_IO_H
-/* Define if you have the `krb_get_our_ip_for_realm' function. */
-#undef HAVE_KRB_GET_OUR_IP_FOR_REALM
-
-/* Define if you have the <krb.h> header file. */
-#undef HAVE_KRB_H
-
-/* Define if you have the `nsl' library (-lnsl). */
-#undef HAVE_LIBNSL
-
-/* Define if you have the `resolv' library (-lresolv). */
-#undef HAVE_LIBRESOLV
-
-/* Define if you have the `resolve' library (-lresolve). */
-#undef HAVE_LIBRESOLVE
-
/* Define if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
-/* Define if you have the `ucb' library (-lucb). */
-#undef HAVE_LIBUCB
-
-/* Define if you have the `localtime_r' function. */
-#undef HAVE_LOCALTIME_R
-
-/* Define if you have the <malloc.h> header file. */
-#define HAVE_MALLOC_H
-
/* Define if you need the malloc.h header file even with stdlib.h */
/* #define NEED_MALLOC_H 1 */
-/* Define if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
/* Define if you have the <netdb.h> header file. */
#define HAVE_NETDB_H
-/* Define if you have the <netinet/if_ether.h> header file. */
-#undef HAVE_NETINET_IF_ETHER_H
-
/* Define if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H
/* Define if you have the <net/if.h> header file. */
#define HAVE_NET_IF_H
-/* Define if you have the <openssl/crypto.h> header file. */
-#undef HAVE_OPENSSL_CRYPTO_H
-
-/* Define if you have the <openssl/err.h> header file. */
-#undef HAVE_OPENSSL_ERR_H
-
-/* Define if you have the <openssl/pem.h> header file. */
-#undef HAVE_OPENSSL_PEM_H
-
-/* Define if you have the <openssl/rsa.h> header file. */
-#undef HAVE_OPENSSL_RSA_H
-
-/* Define if you have the <openssl/ssl.h> header file. */
-#undef HAVE_OPENSSL_SSL_H
-
-/* Define if you have the <openssl/x509.h> header file. */
-#undef HAVE_OPENSSL_X509_H
-
-/* Define if you have the <pem.h> header file. */
-#undef HAVE_PEM_H
-
/* Define if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define if you have the `RAND_egd' function. */
#undef HAVE_RAND_EGD
-/* Define if you have the `RAND_screen' function. */
-#undef HAVE_RAND_SCREEN
-
-/* Define if you have the `RAND_status' function. */
-#undef HAVE_RAND_STATUS
-
/* Define if you have the `select' function. */
#define HAVE_SELECT
-/* Define if you have the `setvbuf' function. */
-#undef HAVE_SETVBUF
-
/* Define if you have the `sigaction' function. */
#undef HAVE_SIGACTION
@@ -250,9 +171,6 @@
/* Define if you have the `strdup' function. */
#define HAVE_STRDUP
-/* Define if you have the `strftime' function. */
-#define HAVE_STRFTIME
-
/* Define if you have the `stricmp' function. */
#define HAVE_STRICMP
@@ -262,9 +180,6 @@
/* Define if you have the <string.h> header file. */
#define HAVE_STRING_H
-/* Define if you have the `strstr' function. */
-#define HAVE_STRSTR
-
/* Define if you have the `strtok_r' function. */
#undef HAVE_STRTOK_R
@@ -301,30 +216,18 @@
/* Define if you have the <time.h> header file. */
#undef HAVE_TIME_H
-/* Define if you have the `uname' function. */
-#define HAVE_UNAME
-
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H
-/* Define if you have the <x509.h> header file. */
-#undef HAVE_X509_H
-
/* Name of package */
#undef PACKAGE
/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
-/* The size of `long double', as computed by sizeof. */
-#undef SIZEOF_LONG_DOUBLE
-
/* The size of `long long', as computed by sizeof. */
#undef SIZEOF_LONG_LONG
-/* The size of `short', as computed by sizeof. */
-#define SIZEOF_SHORT 2
-
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 4
@@ -359,9 +262,6 @@
/* Define to `int' if <sys/types.h> does not define. */
#undef ssize_t
-/* Define if you have the ioctl function. */
-#define HAVE_IOCTL
-
/* Define if you have a working ioctl FIONBIO function. */
#define HAVE_IOCTL_FIONBIO
@@ -386,33 +286,6 @@
/* Define to the function return type for recv. */
#define RECV_TYPE_RETV ssize_t
-/* Define 1 if you have the recvfrom function. */
-#define HAVE_RECVFROM 1
-
-/* Define to the type of arg 1 for recvfrom. */
-#define RECVFROM_TYPE_ARG1 int
-
-/* Define to the type pointed by arg 2 for recvfrom. */
-#define RECVFROM_TYPE_ARG2 void
-
-/* Define if the type pointed by arg 2 for recvfrom is void. */
-#define RECVFROM_TYPE_ARG2_IS_VOID
-
-/* Define to the type of arg 3 for recvfrom. */
-#define RECVFROM_TYPE_ARG3 size_t
-
-/* Define to the type of arg 4 for recvfrom. */
-#define RECVFROM_TYPE_ARG4 int
-
-/* Define to the type pointed by arg 5 for recvfrom. */
-#define RECVFROM_TYPE_ARG5 struct sockaddr
-
-/* Define to the type pointed by arg 6 for recvfrom. */
-#define RECVFROM_TYPE_ARG6 int
-
-/* Define to the function return type for recvfrom. */
-#define RECVFROM_TYPE_RETV ssize_t
-
/* Define if you have the send function. */
#define HAVE_SEND 1
diff --git a/lib/config-win32.h b/lib/config-win32.h
index 9325156..0879e23 100644
--- a/lib/config-win32.h
+++ b/lib/config-win32.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,23 +35,20 @@
/* Define if you have the <arpa/inet.h> header file. */
/* #define HAVE_ARPA_INET_H 1 */
-/* Define if you have the <assert.h> header file. */
-#define HAVE_ASSERT_H 1
-
-/* Define if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H 1
-
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
-/* Define if you have the <getopt.h> header file. */
-#if defined(__MINGW32__) || defined(__POCC__)
-#define HAVE_GETOPT_H 1
+/* Define to 1 if you have the <inttypes.h> header file. */
+#if defined(__MINGW32__) || \
+ (defined(_MSC_VER) && (_MSC_VER >= 1800))
+#define HAVE_INTTYPES_H 1
#endif
-/* Define to 1 if you have the <inttypes.h> header file. */
-#if defined(_MSC_VER) && (_MSC_VER >= 1800)
-#define HAVE_INTTYPES_H 1
+/* Define to 1 if you have the <stdint.h> header file. */
+#if defined(__MINGW32__) || defined(__POCC__) || \
+ (defined(_MSC_VER) && (_MSC_VER >= 1600)) || \
+ (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0582))
+#define HAVE_STDINT_H 1
#endif
/* Define if you have the <io.h> header file. */
@@ -71,11 +68,6 @@
/* Define if you have the <netinet/in.h> header file. */
/* #define HAVE_NETINET_IN_H 1 */
-/* Define if you have the <process.h> header file. */
-#ifndef __SALFORDC__
-#define HAVE_PROCESS_H 1
-#endif
-
/* Define if you have the <signal.h> header file. */
#define HAVE_SIGNAL_H 1
@@ -83,7 +75,8 @@
/* #define HAVE_SSL_H 1 */
/* Define to 1 if you have the <stdbool.h> header file. */
-#if defined(_MSC_VER) && (_MSC_VER >= 1800)
+#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || \
+ defined(__MINGW64_VERSION_MAJOR)
#define HAVE_STDBOOL_H 1
#endif
@@ -143,6 +136,17 @@
#define HAVE_WS2TCPIP_H 1
#endif
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#if defined(__MINGW64_VERSION_MAJOR)
+#define HAVE_LIBGEN_H 1
+#endif
+
/* ---------------------------------------------------------------- */
/* OTHER HEADER INFO */
/* ---------------------------------------------------------------- */
@@ -154,7 +158,8 @@
/* #define TIME_WITH_SYS_TIME 1 */
/* Define to 1 if bool is an available type. */
-#if defined(_MSC_VER) && (_MSC_VER >= 1800)
+#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || \
+ defined(__MINGW64_VERSION_MAJOR)
#define HAVE_BOOL_T 1
#endif
@@ -165,11 +170,10 @@
/* Define if you have the closesocket function. */
#define HAVE_CLOSESOCKET 1
-/* Define if you don't have vprintf but do have _doprnt. */
-/* #define HAVE_DOPRNT 1 */
-
/* Define if you have the ftruncate function. */
-/* #define HAVE_FTRUNCATE 1 */
+#if defined(__MINGW64_VERSION_MAJOR)
+#define HAVE_FTRUNCATE 1
+#endif
/* Define to 1 if you have the `getpeername' function. */
#define HAVE_GETPEERNAME 1
@@ -180,37 +184,15 @@
/* Define if you have the gethostname function. */
#define HAVE_GETHOSTNAME 1
-/* Define if you have the getpass function. */
-/* #define HAVE_GETPASS 1 */
-
-/* Define if you have the getservbyname function. */
-#define HAVE_GETSERVBYNAME 1
-
-/* Define if you have the getprotobyname function. */
-#define HAVE_GETPROTOBYNAME
-
/* Define if you have the gettimeofday function. */
/* #define HAVE_GETTIMEOFDAY 1 */
-/* Define if you have the inet_addr function. */
-#define HAVE_INET_ADDR 1
-
/* Define if you have the ioctlsocket function. */
#define HAVE_IOCTLSOCKET 1
/* Define if you have a working ioctlsocket FIONBIO function. */
#define HAVE_IOCTLSOCKET_FIONBIO 1
-/* Define if you have the RAND_screen function when using SSL. */
-#define HAVE_RAND_SCREEN 1
-
-/* Define if you have the `RAND_status' function when using SSL. */
-#define HAVE_RAND_STATUS 1
-
-/* Define if you have the `CRYPTO_cleanup_all_ex_data' function.
- This is present in OpenSSL versions after 0.9.6b */
-#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
-
/* Define if you have the select function. */
#define HAVE_SELECT 1
@@ -220,9 +202,6 @@
/* Define if you have the setmode function. */
#define HAVE_SETMODE 1
-/* Define if you have the setvbuf function. */
-#define HAVE_SETVBUF 1
-
/* Define if you have the socket function. */
#define HAVE_SOCKET 1
@@ -234,18 +213,9 @@
/* Define if you have the strdup function. */
#define HAVE_STRDUP 1
-/* Define if you have the strftime function. */
-#define HAVE_STRFTIME 1
-
/* Define if you have the stricmp function. */
#define HAVE_STRICMP 1
-/* Define if you have the strnicmp function. */
-#define HAVE_STRNICMP 1
-
-/* Define if you have the strstr function. */
-#define HAVE_STRSTR 1
-
/* Define if you have the strtoll function. */
#if defined(__MINGW32__) || defined(__POCC__) || \
(defined(_MSC_VER) && (_MSC_VER >= 1800))
@@ -275,30 +245,6 @@
/* Define to the function return type for recv. */
#define RECV_TYPE_RETV int
-/* Define if you have the recvfrom function. */
-#define HAVE_RECVFROM 1
-
-/* Define to the type of arg 1 for recvfrom. */
-#define RECVFROM_TYPE_ARG1 SOCKET
-
-/* Define to the type pointed by arg 2 for recvfrom. */
-#define RECVFROM_TYPE_ARG2 char
-
-/* Define to the type of arg 3 for recvfrom. */
-#define RECVFROM_TYPE_ARG3 int
-
-/* Define to the type of arg 4 for recvfrom. */
-#define RECVFROM_TYPE_ARG4 int
-
-/* Define to the type pointed by arg 5 for recvfrom. */
-#define RECVFROM_TYPE_ARG5 struct sockaddr
-
-/* Define to the type pointed by arg 6 for recvfrom. */
-#define RECVFROM_TYPE_ARG6 int
-
-/* Define to the function return type for recvfrom. */
-#define RECVFROM_TYPE_RETV int
-
/* Define if you have the send function. */
#define HAVE_SEND 1
@@ -320,6 +266,31 @@
/* Define to the function return type for send. */
#define SEND_TYPE_RETV int
+/* Define to 1 if you have the snprintf function. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+#define HAVE_SNPRINTF 1
+#endif
+
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 /* Vista */
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+#define HAVE_INET_NTOP 1
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+#define HAVE_INET_PTON 1
+#endif
+
+/* Define to 1 if you have the `basename' function. */
+#if defined(__MINGW64_VERSION_MAJOR)
+#define HAVE_BASENAME 1
+#endif
+
+/* Define to 1 if you have the strtok_r function. */
+#if defined(__MINGW64_VERSION_MAJOR)
+#define HAVE_STRTOK_R 1
+#endif
+
+/* Define to 1 if you have the signal function. */
+#define HAVE_SIGNAL 1
+
/* ---------------------------------------------------------------- */
/* TYPEDEF REPLACEMENTS */
/* ---------------------------------------------------------------- */
@@ -346,15 +317,9 @@
/* Define to the size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
-/* Define to the size of `long double', as computed by sizeof. */
-#define SIZEOF_LONG_DOUBLE 16
-
/* Define to the size of `long long', as computed by sizeof. */
/* #define SIZEOF_LONG_LONG 8 */
-/* Define to the size of `short', as computed by sizeof. */
-#define SIZEOF_SHORT 2
-
/* Define to the size of `long', as computed by sizeof. */
#define SIZEOF_LONG 4
@@ -379,7 +344,6 @@
# undef USE_WINSOCK
# undef HAVE_WINSOCK2_H
# undef HAVE_WS2TCPIP_H
-# undef HAVE_ERRNO_H
# undef HAVE_GETHOSTNAME
# undef LWIP_POSIX_SOCKETS_IO_NAMES
# undef RECV_TYPE_ARG1
@@ -388,7 +352,6 @@
# undef SEND_TYPE_ARG3
# define HAVE_FREEADDRINFO
# define HAVE_GETADDRINFO
-# define HAVE_GETHOSTBYNAME
# define HAVE_GETHOSTBYNAME_R
# define HAVE_GETHOSTBYNAME_R_6
# define LWIP_POSIX_SOCKETS_IO_NAMES 0
@@ -579,11 +542,6 @@
/* Define if struct sockaddr_in6 has the sin6_scope_id member. */
#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
-#if defined(HAVE_WINSOCK2_H) && defined(_WIN32_WINNT) && \
- (_WIN32_WINNT >= 0x0600)
-#define HAVE_STRUCT_POLLFD 1
-#endif
-
/* ---------------------------------------------------------------- */
/* LARGE FILE SUPPORT */
/* ---------------------------------------------------------------- */
@@ -608,6 +566,21 @@
# define USE_WIN32_SMALL_FILES
#endif
+/* Number of bits in a file offset, on hosts where this is settable. */
+#if defined(USE_WIN32_LARGE_FILES) && defined(__MINGW64_VERSION_MAJOR)
+# ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+# endif
+#endif
+
+/* Define to the size of `off_t', as computed by sizeof. */
+#if defined(__MINGW64_VERSION_MAJOR) && \
+ defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
+# define SIZEOF_OFF_T 8
+#else
+# define SIZEOF_OFF_T 4
+#endif
+
/* ---------------------------------------------------------------- */
/* DNS RESOLVER SPECIALTY */
/* ---------------------------------------------------------------- */
@@ -633,7 +606,7 @@
/* LDAP SUPPORT */
/* ---------------------------------------------------------------- */
-#if defined(CURL_HAS_NOVELL_LDAPSDK) || defined(CURL_HAS_MOZILLA_LDAPSDK)
+#if defined(CURL_HAS_NOVELL_LDAPSDK)
#undef USE_WIN32_LDAP
#define HAVE_LDAP_SSL_H 1
#define HAVE_LDAP_URL_PARSE 1
@@ -663,7 +636,7 @@
/* ---------------------------------------------------------------- */
/* Define cpu-machine-OS */
-#undef OS
+#ifndef OS
#if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */
#define OS "i386-pc-win32"
#elif defined(_M_X64) || defined(__x86_64__) /* x86_64 (MSVC >=2005 or gcc) */
@@ -677,6 +650,7 @@
#else
#define OS "unknown-pc-win32"
#endif
+#endif
/* Name of package */
#define PACKAGE "curl"
diff --git a/lib/config-win32ce.h b/lib/config-win32ce.h
index 90f9eea..825f5e6 100644
--- a/lib/config-win32ce.h
+++ b/lib/config-win32ce.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,18 +35,9 @@
/* Define if you have the <arpa/inet.h> header file. */
/* #define HAVE_ARPA_INET_H 1 */
-/* Define if you have the <assert.h> header file. */
-/* #define HAVE_ASSERT_H 1 */
-
-/* Define if you have the <errno.h> header file. */
-/* #define HAVE_ERRNO_H 1 */
-
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
-/* Define if you have the <getopt.h> header file. */
-/* #define HAVE_GETOPT_H 1 */
-
/* Define if you have the <io.h> header file. */
#define HAVE_IO_H 1
@@ -68,9 +59,6 @@
/* Define if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
-/* Define if you have the <process.h> header file. */
-/* #define HAVE_PROCESS_H 1 */
-
/* Define if you have the <sys/param.h> header file. */
/* #define HAVE_SYS_PARAM_H 1 */
@@ -135,42 +123,21 @@
/* Define if you have the closesocket function. */
#define HAVE_CLOSESOCKET 1
-/* Define if you don't have vprintf but do have _doprnt. */
-/* #define HAVE_DOPRNT 1 */
-
/* Define if you have the gethostname function. */
#define HAVE_GETHOSTNAME 1
-/* Define if you have the getpass function. */
-/* #define HAVE_GETPASS 1 */
-
-/* Define if you have the getservbyname function. */
-#define HAVE_GETSERVBYNAME 1
-
/* Define if you have the gettimeofday function. */
/* #define HAVE_GETTIMEOFDAY 1 */
-/* Define if you have the inet_addr function. */
-#define HAVE_INET_ADDR 1
-
/* Define if you have the ioctlsocket function. */
#define HAVE_IOCTLSOCKET 1
/* Define if you have a working ioctlsocket FIONBIO function. */
#define HAVE_IOCTLSOCKET_FIONBIO 1
-/* Define if you have the RAND_screen function when using SSL */
-#define HAVE_RAND_SCREEN 1
-
-/* Define if you have the `RAND_status' function when using SSL. */
-#define HAVE_RAND_STATUS 1
-
/* Define if you have the select function. */
#define HAVE_SELECT 1
-/* Define if you have the setvbuf function. */
-#define HAVE_SETVBUF 1
-
/* Define if you have the socket function. */
#define HAVE_SOCKET 1
@@ -180,18 +147,9 @@
/* Define if you have the strdup function. */
/* #define HAVE_STRDUP 1 */
-/* Define if you have the strftime function. */
-/* #define HAVE_STRFTIME 1 */
-
/* Define if you have the stricmp function. */
/* #define HAVE_STRICMP 1 */
-/* Define if you have the strnicmp function. */
-/* #define HAVE_STRNICMP 1 */
-
-/* Define if you have the strstr function. */
-#define HAVE_STRSTR 1
-
/* Define if you have the strtoll function. */
#if defined(__MINGW32__)
#define HAVE_STRTOLL 1
@@ -218,30 +176,6 @@
/* Define to the function return type for recv. */
#define RECV_TYPE_RETV int
-/* Define if you have the recvfrom function. */
-#define HAVE_RECVFROM 1
-
-/* Define to the type of arg 1 for recvfrom. */
-#define RECVFROM_TYPE_ARG1 SOCKET
-
-/* Define to the type pointed by arg 2 for recvfrom. */
-#define RECVFROM_TYPE_ARG2 char
-
-/* Define to the type of arg 3 for recvfrom. */
-#define RECVFROM_TYPE_ARG3 int
-
-/* Define to the type of arg 4 for recvfrom. */
-#define RECVFROM_TYPE_ARG4 int
-
-/* Define to the type pointed by arg 5 for recvfrom. */
-#define RECVFROM_TYPE_ARG5 struct sockaddr
-
-/* Define to the type pointed by arg 6 for recvfrom. */
-#define RECVFROM_TYPE_ARG6 int
-
-/* Define to the function return type for recvfrom. */
-#define RECVFROM_TYPE_RETV int
-
/* Define if you have the send function. */
#define HAVE_SEND 1
@@ -285,15 +219,9 @@
/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
-/* The size of `long double', as computed by sizeof. */
-#define SIZEOF_LONG_DOUBLE 16
-
/* The size of `long long', as computed by sizeof. */
/* #define SIZEOF_LONG_LONG 8 */
-/* The size of `short', as computed by sizeof. */
-#define SIZEOF_SHORT 2
-
/* Define to the size of `long', as computed by sizeof. */
#define SIZEOF_LONG 4
@@ -368,8 +296,9 @@
/* ---------------------------------------------------------------- */
/* Define cpu-machine-OS */
-#undef OS
+#ifndef OS
#define OS "i386-pc-win32ce"
+#endif
/* Name of package */
#define PACKAGE "curl"
diff --git a/lib/conncache.c b/lib/conncache.c
index 2a399c8..a21409c 100644
--- a/lib/conncache.c
+++ b/lib/conncache.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se>
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -45,13 +45,6 @@
#define HASHKEY_SIZE 128
-static void conn_llist_dtor(void *user, void *element)
-{
- struct connectdata *conn = element;
- (void)user;
- conn->bundle = NULL;
-}
-
static CURLcode bundle_create(struct connectbundle **bundlep)
{
DEBUGASSERT(*bundlep == NULL);
@@ -62,17 +55,12 @@
(*bundlep)->num_connections = 0;
(*bundlep)->multiuse = BUNDLE_UNKNOWN;
- Curl_llist_init(&(*bundlep)->conn_list, (Curl_llist_dtor) conn_llist_dtor);
+ Curl_llist_init(&(*bundlep)->conn_list, NULL);
return CURLE_OK;
}
static void bundle_destroy(struct connectbundle *bundle)
{
- if(!bundle)
- return;
-
- Curl_llist_destroy(&bundle->conn_list, NULL);
-
free(bundle);
}
@@ -258,7 +246,7 @@
"The cache now contains %zu members",
conn->connection_id, connc->num_conn));
- unlock:
+unlock:
CONNCACHE_UNLOCK(data);
return result;
@@ -498,7 +486,7 @@
conn = curr->ptr;
if(!CONN_INUSE(conn) && !conn->bits.close &&
- !conn->bits.connect_only) {
+ !conn->connect_only) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->lastused);
diff --git a/lib/conncache.h b/lib/conncache.h
index 6ec2757..c60f844 100644
--- a/lib/conncache.h
+++ b/lib/conncache.h
@@ -7,8 +7,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2015 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Linus Nielsen Feltzing, <linus@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,6 +31,7 @@
* be shared.
*/
+#include <curl/curl.h>
#include "timeval.h"
struct connectdata;
@@ -38,7 +39,8 @@
struct conncache {
struct Curl_hash hash;
size_t num_conn;
- long next_connection_id;
+ curl_off_t next_connection_id;
+ curl_off_t next_easy_id;
struct curltime last_cleanup;
/* handle used for closing cached connections */
struct Curl_easy *closure_handle;
diff --git a/lib/connect.c b/lib/connect.c
index 4241972..dc93533 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,13 +48,6 @@
#include <arpa/inet.h>
#endif
-#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
-#include <sys/filio.h>
-#endif
-#ifdef NETWARE
-#undef in_addr_t
-#define in_addr_t unsigned long
-#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
@@ -64,21 +57,26 @@
#include "sendf.h"
#include "if2ip.h"
#include "strerror.h"
+#include "cfilters.h"
#include "connect.h"
+#include "cf-haproxy.h"
+#include "cf-https-connect.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 "inet_ntop.h"
#include "inet_pton.h"
-#include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
+#include "vtls/vtls.h" /* for vtsl cfilters */
#include "progress.h"
#include "warnless.h"
#include "conncache.h"
#include "multihandle.h"
#include "share.h"
#include "version_win32.h"
-#include "quic.h"
+#include "vquic/vquic.h" /* for quic cfilters */
+#include "http_proxy.h"
#include "socks.h"
/* The last 3 #include files should be in this order */
@@ -86,86 +84,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-static bool verifyconnect(curl_socket_t sockfd, int *error);
-
-#if defined(__DragonFly__) || defined(HAVE_WINSOCK2_H)
-/* DragonFlyBSD and Windows use millisecond units */
-#define KEEPALIVE_FACTOR(x) (x *= 1000)
-#else
-#define KEEPALIVE_FACTOR(x)
-#endif
-
-#if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
-#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)
-{
- 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 %d", sockfd);
- }
- else {
-#if defined(SIO_KEEPALIVE_VALS)
- struct tcp_keepalive vals;
- DWORD dummy;
- vals.onoff = 1;
- optval = curlx_sltosi(data->set.tcp_keepidle);
- KEEPALIVE_FACTOR(optval);
- vals.keepalivetime = optval;
- optval = curlx_sltosi(data->set.tcp_keepintvl);
- KEEPALIVE_FACTOR(optval);
- vals.keepaliveinterval = optval;
- if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
- NULL, 0, &dummy, NULL, NULL) != 0) {
- infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d",
- (int)sockfd, WSAGetLastError());
- }
-#else
-#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 %d", sockfd);
- }
-#elif defined(TCP_KEEPALIVE)
- /* Mac OS X style */
- optval = curlx_sltosi(data->set.tcp_keepidle);
- KEEPALIVE_FACTOR(optval);
- if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
- (void *)&optval, sizeof(optval)) < 0) {
- infof(data, "Failed to set TCP_KEEPALIVE on fd %d", sockfd);
- }
-#endif
-#ifdef TCP_KEEPINTVL
- optval = curlx_sltosi(data->set.tcp_keepintvl);
- KEEPALIVE_FACTOR(optval);
- if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
- (void *)&optval, sizeof(optval)) < 0) {
- infof(data, "Failed to set TCP_KEEPINTVL on fd %d", sockfd);
- }
-#endif
-#endif
- }
-}
-
-static CURLcode
-singleipconnect(struct Curl_easy *data,
- struct connectdata *conn,
- const struct Curl_addrinfo *ai, /* start connecting to this */
- int tempindex); /* 0 or 1 among the temp ones */
/*
* Curl_timeleft() returns the amount of milliseconds left allowed for the
@@ -237,383 +155,6 @@
return timeout_ms;
}
-static CURLcode bindlocal(struct Curl_easy *data,
- curl_socket_t sockfd, int af, unsigned int scope)
-{
- struct connectdata *conn = data->conn;
- struct Curl_sockaddr_storage sa;
- struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
- curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
- struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
-#ifdef ENABLE_IPV6
- struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
-#endif
-
- struct Curl_dns_entry *h = NULL;
- unsigned short port = data->set.localport; /* use this port number, 0 for
- "random" */
- /* how many port numbers to try to bind to, increasing one at a time */
- int portnum = data->set.localportrange;
- const char *dev = data->set.str[STRING_DEVICE];
- int error;
-#ifdef IP_BIND_ADDRESS_NO_PORT
- int on = 1;
-#endif
-#ifndef ENABLE_IPV6
- (void)scope;
-#endif
-
- /*************************************************************
- * Select device to bind socket to
- *************************************************************/
- if(!dev && !port)
- /* no local kind of binding was requested */
- return CURLE_OK;
-
- memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
-
- if(dev && (strlen(dev)<255) ) {
- char myhost[256] = "";
- int done = 0; /* -1 for error, 1 for address found */
- bool is_interface = FALSE;
- bool is_host = FALSE;
- static const char *if_prefix = "if!";
- static const char *host_prefix = "host!";
-
- if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
- dev += strlen(if_prefix);
- is_interface = TRUE;
- }
- else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
- dev += strlen(host_prefix);
- is_host = TRUE;
- }
-
- /* interface */
- if(!is_host) {
-#ifdef SO_BINDTODEVICE
- /* I am not sure any other OSs than Linux that provide this feature,
- * and at the least I cannot test. --Ben
- *
- * This feature allows one to tightly bind the local socket to a
- * particular interface. This will force even requests to other
- * local interfaces to go out the external interface.
- *
- *
- * Only bind to the interface when specified as interface, not just
- * as a hostname or ip address.
- *
- * interface might be a VRF, eg: vrf-blue, which means it cannot be
- * converted to an IP address and would fail Curl_if2ip. Simply try
- * to use it straight away.
- */
- if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
- dev, (curl_socklen_t)strlen(dev) + 1) == 0) {
- /* This is typically "errno 1, error: Operation not permitted" if
- * you're not running as root or another suitable privileged
- * user.
- * If it succeeds it means the parameter was a valid interface and
- * not an IP address. Return immediately.
- */
- return CURLE_OK;
- }
-#endif
-
- switch(Curl_if2ip(af,
-#ifdef ENABLE_IPV6
- scope, conn->scope_id,
-#endif
- dev, myhost, sizeof(myhost))) {
- case IF2IP_NOT_FOUND:
- if(is_interface) {
- /* Do not fall back to treating it as a host name */
- failf(data, "Couldn't bind to interface '%s'", dev);
- 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:
- is_interface = TRUE;
- /*
- * We now have the numerical IP address in the 'myhost' buffer
- */
- infof(data, "Local Interface %s is ip %s using address family %i",
- dev, myhost, af);
- done = 1;
- break;
- }
- }
- if(!is_interface) {
- /*
- * This was not an interface, resolve the name as a host name
- * or IP number
- *
- * Temporarily force name resolution to use only the address type
- * of the connection. The resolve functions should really be changed
- * to take a type parameter instead.
- */
- unsigned char ipver = conn->ip_version;
- int rc;
-
- if(af == AF_INET)
- conn->ip_version = CURL_IPRESOLVE_V4;
-#ifdef ENABLE_IPV6
- else if(af == AF_INET6)
- conn->ip_version = CURL_IPRESOLVE_V6;
-#endif
-
- rc = Curl_resolv(data, dev, 0, FALSE, &h);
- if(rc == CURLRESOLV_PENDING)
- (void)Curl_resolver_wait_resolv(data, &h);
- conn->ip_version = ipver;
-
- if(h) {
- /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
- Curl_printable_address(h->addr, myhost, sizeof(myhost));
- infof(data, "Name '%s' family %i resolved to '%s' family %i",
- dev, af, myhost, h->addr->ai_family);
- Curl_resolv_unlock(data, h);
- if(af != h->addr->ai_family) {
- /* bad IP version combo, signal the caller to try another address
- family if available */
- return CURLE_UNSUPPORTED_PROTOCOL;
- }
- done = 1;
- }
- else {
- /*
- * provided dev was no interface (or interfaces are not supported
- * e.g. solaris) no ip address and no domain we fail here
- */
- done = -1;
- }
- }
-
- if(done > 0) {
-#ifdef ENABLE_IPV6
- /* IPv6 address */
- if(af == AF_INET6) {
-#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
- char *scope_ptr = strchr(myhost, '%');
- if(scope_ptr)
- *(scope_ptr++) = 0;
-#endif
- if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
- si6->sin6_family = AF_INET6;
- si6->sin6_port = htons(port);
-#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
- if(scope_ptr)
- /* The "myhost" string either comes from Curl_if2ip or from
- Curl_printable_address. The latter returns only numeric scope
- IDs and the former returns none at all. So the scope ID, if
- present, is known to be numeric */
- si6->sin6_scope_id = atoi(scope_ptr);
-#endif
- }
- sizeof_sa = sizeof(struct sockaddr_in6);
- }
- else
-#endif
- /* IPv4 address */
- if((af == AF_INET) &&
- (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
- si4->sin_family = AF_INET;
- si4->sin_port = htons(port);
- sizeof_sa = sizeof(struct sockaddr_in);
- }
- }
-
- if(done < 1) {
- /* errorbuf is set false so failf will overwrite any message already in
- the error buffer, so the user receives this error message instead of a
- generic resolve error. */
- data->state.errorbuf = FALSE;
- failf(data, "Couldn't bind to '%s'", dev);
- return CURLE_INTERFACE_FAILED;
- }
- }
- else {
- /* no device was given, prepare sa to match af's needs */
-#ifdef ENABLE_IPV6
- if(af == AF_INET6) {
- si6->sin6_family = AF_INET6;
- si6->sin6_port = htons(port);
- sizeof_sa = sizeof(struct sockaddr_in6);
- }
- else
-#endif
- if(af == AF_INET) {
- si4->sin_family = AF_INET;
- si4->sin_port = htons(port);
- sizeof_sa = sizeof(struct sockaddr_in);
- }
- }
-#ifdef IP_BIND_ADDRESS_NO_PORT
- (void)setsockopt(sockfd, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &on, sizeof(on));
-#endif
- for(;;) {
- if(bind(sockfd, sock, sizeof_sa) >= 0) {
- /* we succeeded to bind */
- struct Curl_sockaddr_storage add;
- curl_socklen_t size = sizeof(add);
- memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
- if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
- char buffer[STRERROR_LEN];
- data->state.os_errno = error = SOCKERRNO;
- failf(data, "getsockname() failed with errno %d: %s",
- error, Curl_strerror(error, buffer, sizeof(buffer)));
- return CURLE_INTERFACE_FAILED;
- }
- infof(data, "Local port: %hu", port);
- conn->bits.bound = TRUE;
- return CURLE_OK;
- }
-
- if(--portnum > 0) {
- port++; /* try next port */
- if(port == 0)
- break;
- infof(data, "Bind to local port %hu failed, trying next", port - 1);
- /* We re-use/clobber the port variable here below */
- if(sock->sa_family == AF_INET)
- si4->sin_port = ntohs(port);
-#ifdef ENABLE_IPV6
- else
- si6->sin6_port = ntohs(port);
-#endif
- }
- else
- break;
- }
- {
- char buffer[STRERROR_LEN];
- data->state.os_errno = error = SOCKERRNO;
- failf(data, "bind failed with errno %d: %s",
- error, Curl_strerror(error, buffer, sizeof(buffer)));
- }
-
- return CURLE_INTERFACE_FAILED;
-}
-
-/*
- * verifyconnect() returns TRUE if the connect really has happened.
- */
-static bool verifyconnect(curl_socket_t sockfd, int *error)
-{
- bool rc = TRUE;
-#ifdef SO_ERROR
- int err = 0;
- curl_socklen_t errSize = sizeof(err);
-
-#ifdef WIN32
- /*
- * In October 2003 we effectively nullified this function on Windows due to
- * problems with it using all CPU in multi-threaded cases.
- *
- * In May 2004, we bring it back to offer more info back on connect failures.
- * Gisle Vanem could reproduce the former problems with this function, but
- * could avoid them by adding this SleepEx() call below:
- *
- * "I don't have Rational Quantify, but the hint from his post was
- * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
- * just Sleep(0) would be enough?) would release whatever
- * mutex/critical-section the ntdll call is waiting on.
- *
- * Someone got to verify this on Win-NT 4.0, 2000."
- */
-
-#ifdef _WIN32_WCE
- Sleep(0);
-#else
- SleepEx(0, FALSE);
-#endif
-
-#endif
-
- if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
- err = SOCKERRNO;
-#ifdef _WIN32_WCE
- /* Old WinCE versions don't support SO_ERROR */
- if(WSAENOPROTOOPT == err) {
- SET_SOCKERRNO(0);
- err = 0;
- }
-#endif
-#if defined(EBADIOCTL) && defined(__minix)
- /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
- if(EBADIOCTL == err) {
- SET_SOCKERRNO(0);
- err = 0;
- }
-#endif
- if((0 == err) || (EISCONN == err))
- /* we are connected, awesome! */
- rc = TRUE;
- else
- /* This wasn't a successful connect */
- rc = FALSE;
- if(error)
- *error = err;
-#else
- (void)sockfd;
- if(error)
- *error = SOCKERRNO;
-#endif
- return rc;
-}
-
-/* update tempaddr[tempindex] (to the next entry), makes sure to stick
- to the correct family */
-static struct Curl_addrinfo *ainext(struct connectdata *conn,
- int tempindex,
- bool next) /* use next entry? */
-{
- struct Curl_addrinfo *ai = conn->tempaddr[tempindex];
- if(ai && next)
- ai = ai->ai_next;
- while(ai && (ai->ai_family != conn->tempfamily[tempindex]))
- ai = ai->ai_next;
- conn->tempaddr[tempindex] = ai;
- return ai;
-}
-
-/* Used within the multi interface. Try next IP address, returns error if no
- more address exists or error */
-static CURLcode trynextip(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
- int tempindex)
-{
- CURLcode result = CURLE_COULDNT_CONNECT;
-
- /* First clean up after the failed socket.
- Don't close it yet to ensure that the next IP's socket gets a different
- file descriptor, which can prevent bugs when the curl_multi_socket_action
- interface is used with certain select() replacements such as kqueue. */
- curl_socket_t fd_to_close = conn->tempsock[tempindex];
- conn->tempsock[tempindex] = CURL_SOCKET_BAD;
-
- if(sockindex == FIRSTSOCKET) {
- struct Curl_addrinfo *ai = conn->tempaddr[tempindex];
-
- while(ai) {
- result = singleipconnect(data, conn, ai, tempindex);
- if(result == CURLE_COULDNT_CONNECT) {
- ai = ainext(conn, tempindex, TRUE);
- continue;
- }
- break;
- }
- }
-
- if(fd_to_close != CURL_SOCKET_BAD)
- Curl_closesocket(data, conn, fd_to_close);
-
- return result;
-}
-
/* Copies connection info into the transfer handle to make it available when
the transfer handle is no longer associated with the connection. */
void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
@@ -625,12 +166,35 @@
else
data->info.conn_local_ip[0] = 0;
data->info.conn_scheme = conn->handler->scheme;
- data->info.conn_protocol = conn->handler->protocol;
+ /* conn_protocol can only provide "old" protocols */
+ data->info.conn_protocol = (conn->handler->protocol) & CURLPROTO_MASK;
data->info.conn_primary_port = conn->port;
data->info.conn_remote_port = conn->remote_port;
data->info.conn_local_port = local_port;
}
+static const struct Curl_addrinfo *
+addr_first_match(const struct Curl_addrinfo *addr, int family)
+{
+ while(addr) {
+ if(addr->ai_family == family)
+ return addr;
+ addr = addr->ai_next;
+ }
+ return NULL;
+}
+
+static const struct Curl_addrinfo *
+addr_next_match(const struct Curl_addrinfo *addr, int family)
+{
+ while(addr && addr->ai_next) {
+ addr = addr->ai_next;
+ if(addr->ai_family == family)
+ return addr;
+ }
+ return NULL;
+}
+
/* retrieves ip address and port from a sockaddr structure.
note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
@@ -688,773 +252,8 @@
return FALSE;
}
-/* retrieves the start/end point information of a socket of an established
- connection */
-void Curl_conninfo_remote(struct Curl_easy *data,
- struct connectdata *conn, curl_socket_t sockfd)
-{
-#ifdef HAVE_GETPEERNAME
- char buffer[STRERROR_LEN];
- struct Curl_sockaddr_storage ssrem;
- curl_socklen_t plen;
- int port;
- plen = sizeof(struct Curl_sockaddr_storage);
- memset(&ssrem, 0, sizeof(ssrem));
- if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
- int error = SOCKERRNO;
- failf(data, "getpeername() failed with errno %d: %s",
- error, Curl_strerror(error, buffer, sizeof(buffer)));
- return;
- }
- if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
- conn->primary_ip, &port)) {
- failf(data, "ssrem inet_ntop() failed with errno %d: %s",
- errno, Curl_strerror(errno, buffer, sizeof(buffer)));
- return;
- }
-#else
- (void)data;
- (void)conn;
- (void)sockfd;
-#endif
-}
-
-/* retrieves the start/end point information of a socket of an established
- connection */
-void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd,
- char *local_ip, int *local_port)
-{
-#ifdef HAVE_GETSOCKNAME
- char buffer[STRERROR_LEN];
- struct Curl_sockaddr_storage ssloc;
- curl_socklen_t slen;
- slen = sizeof(struct Curl_sockaddr_storage);
- memset(&ssloc, 0, sizeof(ssloc));
- if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) {
- int error = SOCKERRNO;
- failf(data, "getsockname() failed with errno %d: %s",
- error, Curl_strerror(error, buffer, sizeof(buffer)));
- return;
- }
- if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
- local_ip, local_port)) {
- failf(data, "ssloc inet_ntop() failed with errno %d: %s",
- errno, Curl_strerror(errno, buffer, sizeof(buffer)));
- return;
- }
-#else
- (void)data;
- (void)sockfd;
- (void)local_ip;
- (void)local_port;
-#endif
-}
-
-/* retrieves the start/end point information of a socket of an established
- connection */
-void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
- curl_socket_t sockfd)
-{
- /* 'local_ip' and 'local_port' get filled with local's numerical
- ip address and port number whenever an outgoing connection is
- **established** from the primary socket to a remote address. */
- char local_ip[MAX_IPADR_LEN] = "";
- int local_port = -1;
-
- if(conn->transport == TRNSPRT_TCP) {
- if(!conn->bits.reuse && !conn->bits.tcp_fastopen)
- Curl_conninfo_remote(data, conn, sockfd);
- Curl_conninfo_local(data, sockfd, local_ip, &local_port);
- } /* end of TCP-only section */
-
- /* persist connection info in session handle */
- Curl_persistconninfo(data, conn, local_ip, local_port);
-}
-
-/* After a TCP connection to the proxy has been verified, this function does
- the next magic steps. If 'done' isn't set TRUE, it is not done yet and
- must be called again.
-
- Note: this function's sub-functions call failf()
-
-*/
-static CURLcode connect_SOCKS(struct Curl_easy *data, int sockindex,
- bool *done)
-{
- CURLcode result = CURLE_OK;
-#ifndef CURL_DISABLE_PROXY
- CURLproxycode pxresult = CURLPX_OK;
- struct connectdata *conn = data->conn;
- if(conn->bits.socksproxy) {
- /* for the secondary socket (FTP), use the "connect to host"
- * but ignore the "connect to port" (use the secondary port)
- */
- const char * const host =
- conn->bits.httpproxy ?
- conn->http_proxy.host.name :
- conn->bits.conn_to_host ?
- conn->conn_to_host.name :
- sockindex == SECONDARYSOCKET ?
- conn->secondaryhostname : conn->host.name;
- const int port =
- conn->bits.httpproxy ? (int)conn->http_proxy.port :
- sockindex == SECONDARYSOCKET ? conn->secondary_port :
- conn->bits.conn_to_port ? conn->conn_to_port :
- conn->remote_port;
- switch(conn->socks_proxy.proxytype) {
- case CURLPROXY_SOCKS5:
- case CURLPROXY_SOCKS5_HOSTNAME:
- pxresult = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
- host, port, sockindex, data, done);
- break;
-
- case CURLPROXY_SOCKS4:
- case CURLPROXY_SOCKS4A:
- pxresult = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
- data, done);
- break;
-
- default:
- failf(data, "unknown proxytype option given");
- result = CURLE_COULDNT_CONNECT;
- } /* switch proxytype */
- if(pxresult) {
- result = CURLE_PROXY;
- data->info.pxcode = pxresult;
- }
- }
- else
-#else
- (void)data;
- (void)sockindex;
-#endif /* CURL_DISABLE_PROXY */
- *done = TRUE; /* no SOCKS proxy, so consider us connected */
-
- return result;
-}
-
-/*
- * post_SOCKS() is called after a successful connect to the peer, which
- * *could* be a SOCKS proxy
- */
-static void post_SOCKS(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
- bool *connected)
-{
- conn->bits.tcpconnect[sockindex] = TRUE;
-
- *connected = TRUE;
- if(sockindex == FIRSTSOCKET)
- Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
- Curl_updateconninfo(data, conn, conn->sock[sockindex]);
- Curl_verboseconnect(data, conn);
- data->info.numconnects++; /* to track the number of connections made */
-}
-
-/*
- * Curl_is_connected() checks if the socket has connected.
- */
-
-CURLcode Curl_is_connected(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
- bool *connected)
-{
- CURLcode result = CURLE_OK;
- timediff_t allow;
- int error = 0;
- struct curltime now;
- int rc = 0;
- unsigned int i;
-
- DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
-
- *connected = FALSE; /* a very negative world view is best */
-
- if(conn->bits.tcpconnect[sockindex]) {
- /* we are connected already! */
- *connected = TRUE;
- return CURLE_OK;
- }
-
- now = Curl_now();
-
- if(SOCKS_STATE(conn->cnnct.state)) {
- /* still doing SOCKS */
- result = connect_SOCKS(data, sockindex, connected);
- if(!result && *connected)
- post_SOCKS(data, conn, sockindex, connected);
- return result;
- }
-
- for(i = 0; i<2; i++) {
- const int other = i ^ 1;
- if(conn->tempsock[i] == CURL_SOCKET_BAD)
- continue;
- error = 0;
-#ifdef ENABLE_QUIC
- if(conn->transport == TRNSPRT_QUIC) {
- result = Curl_quic_is_connected(data, conn, i, connected);
- if(!result && *connected) {
- /* use this socket from now on */
- conn->sock[sockindex] = conn->tempsock[i];
- conn->ip_addr = conn->tempaddr[i];
- conn->tempsock[i] = CURL_SOCKET_BAD;
- post_SOCKS(data, conn, sockindex, connected);
- connkeep(conn, "HTTP/3 default");
- return CURLE_OK;
- }
- /* When a QUIC connect attempt fails, the better error explanation is in
- 'result' and not in errno */
- if(result) {
- conn->tempsock[i] = CURL_SOCKET_BAD;
- error = SOCKERRNO;
- }
- }
- else
-#endif
- {
-#ifdef mpeix
- /* Call this function once now, and ignore the results. We do this to
- "clear" the error state on the socket so that we can later read it
- reliably. This is reported necessary on the MPE/iX operating
- system. */
- (void)verifyconnect(conn->tempsock[i], NULL);
-#endif
-
- /* check socket for connect */
- rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
- }
-
- if(rc == 0) { /* no connection yet */
- if(Curl_timediff(now, conn->connecttime) >=
- conn->timeoutms_per_addr[i]) {
- infof(data, "After %" CURL_FORMAT_TIMEDIFF_T
- "ms connect time, move on!", conn->timeoutms_per_addr[i]);
- error = ETIMEDOUT;
- }
-
- /* should we try another protocol family? */
- if(i == 0 && !conn->bits.parallel_connect &&
- (Curl_timediff(now, conn->connecttime) >=
- data->set.happy_eyeballs_timeout)) {
- conn->bits.parallel_connect = TRUE; /* starting now */
- trynextip(data, conn, sockindex, 1);
- }
- }
- else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
- if(verifyconnect(conn->tempsock[i], &error)) {
- /* we are connected with TCP, awesome! */
-
- /* use this socket from now on */
- conn->sock[sockindex] = conn->tempsock[i];
- conn->ip_addr = conn->tempaddr[i];
- conn->tempsock[i] = CURL_SOCKET_BAD;
-#ifdef ENABLE_IPV6
- conn->bits.ipv6 = (conn->ip_addr->ai_family == AF_INET6)?TRUE:FALSE;
-#endif
-
- /* close the other socket, if open */
- if(conn->tempsock[other] != CURL_SOCKET_BAD) {
- Curl_closesocket(data, conn, conn->tempsock[other]);
- conn->tempsock[other] = CURL_SOCKET_BAD;
- }
-
- /* see if we need to kick off any SOCKS proxy magic once we
- connected */
- result = connect_SOCKS(data, sockindex, connected);
- if(result || !*connected)
- return result;
-
- post_SOCKS(data, conn, sockindex, connected);
-
- return CURLE_OK;
- }
- }
- else if(rc & CURL_CSELECT_ERR) {
- (void)verifyconnect(conn->tempsock[i], &error);
- }
-
- /*
- * The connection failed here, we should attempt to connect to the "next
- * address" for the given host. But first remember the latest error.
- */
- if(error) {
- data->state.os_errno = error;
- SET_SOCKERRNO(error);
- if(conn->tempaddr[i]) {
- CURLcode status;
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- char ipaddress[MAX_IPADR_LEN];
- char buffer[STRERROR_LEN];
- Curl_printable_address(conn->tempaddr[i], ipaddress,
- sizeof(ipaddress));
-#ifdef ENABLE_QUIC
- if(conn->transport == TRNSPRT_QUIC) {
- infof(data, "connect to %s port %u failed: %s",
- ipaddress, conn->port, curl_easy_strerror(result));
- }
- else
-#endif
- infof(data, "connect to %s port %u failed: %s",
- ipaddress, conn->port,
- Curl_strerror(error, buffer, sizeof(buffer)));
-#endif
-
- allow = Curl_timeleft(data, &now, TRUE);
- conn->timeoutms_per_addr[i] = conn->tempaddr[i]->ai_next == NULL ?
- allow : allow / 2;
- ainext(conn, i, TRUE);
- status = trynextip(data, conn, sockindex, i);
- if((status != CURLE_COULDNT_CONNECT) ||
- conn->tempsock[other] == CURL_SOCKET_BAD) {
- /* the last attempt failed and no other sockets remain open */
- if(!result)
- result = status;
- }
- }
- }
- }
-
- /*
- * Now that we've checked whether we are connected, check whether we've
- * already timed out.
- *
- * First figure out how long time we have left to connect */
-
- allow = Curl_timeleft(data, &now, TRUE);
-
- if(allow < 0) {
- /* time-out, bail out, go home */
- failf(data, "Connection timeout after %ld ms",
- Curl_timediff(now, data->progress.t_startsingle));
- return CURLE_OPERATION_TIMEDOUT;
- }
-
- if(result &&
- (conn->tempsock[0] == CURL_SOCKET_BAD) &&
- (conn->tempsock[1] == CURL_SOCKET_BAD)) {
- /* no more addresses to try */
- const char *hostname;
- char buffer[STRERROR_LEN];
- CURLcode failreason = result;
-
- /* if the first address family runs out of addresses to try before the
- happy eyeball timeout, go ahead and try the next family now */
- result = trynextip(data, conn, sockindex, 1);
- if(!result)
- return result;
-
- result = failreason;
-
-#ifndef CURL_DISABLE_PROXY
- if(conn->bits.socksproxy)
- hostname = conn->socks_proxy.host.name;
- else if(conn->bits.httpproxy)
- hostname = conn->http_proxy.host.name;
- else
-#endif
- if(conn->bits.conn_to_host)
- hostname = conn->conn_to_host.name;
- else
- hostname = conn->host.name;
-
- failf(data, "Failed to connect to %s port %u after "
- "%" CURL_FORMAT_TIMEDIFF_T " ms: %s",
- hostname, conn->port,
- Curl_timediff(now, data->progress.t_startsingle),
-#ifdef ENABLE_QUIC
- (conn->transport == TRNSPRT_QUIC) ?
- curl_easy_strerror(result) :
-#endif
- Curl_strerror(error, buffer, sizeof(buffer)));
-
- Curl_quic_disconnect(data, conn, 0);
- Curl_quic_disconnect(data, conn, 1);
-
-#ifdef WSAETIMEDOUT
- if(WSAETIMEDOUT == data->state.os_errno)
- result = CURLE_OPERATION_TIMEDOUT;
-#elif defined(ETIMEDOUT)
- if(ETIMEDOUT == data->state.os_errno)
- result = CURLE_OPERATION_TIMEDOUT;
-#endif
- }
- else
- result = CURLE_OK; /* still trying */
-
- return result;
-}
-
-static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
-{
-#if defined(TCP_NODELAY)
- curl_socklen_t onoff = (curl_socklen_t) 1;
- int level = IPPROTO_TCP;
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
- char buffer[STRERROR_LEN];
-#else
- (void) data;
-#endif
-
- if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
- sizeof(onoff)) < 0)
- infof(data, "Could not set TCP_NODELAY: %s",
- Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
-#else
- (void)data;
- (void)sockfd;
-#endif
-}
-
-#ifdef SO_NOSIGPIPE
-/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
- 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,
- curl_socket_t sockfd)
-{
- int onoff = 1;
- if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
- sizeof(onoff)) < 0) {
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
- char buffer[STRERROR_LEN];
- infof(data, "Could not set SO_NOSIGPIPE: %s",
- Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
-#endif
- }
-}
-#else
-#define nosigpipe(x,y) Curl_nop_stmt
-#endif
-
-#ifdef USE_WINSOCK
-/* When you run a program that uses the Windows Sockets API, you may
- experience slow performance when you copy data to a TCP server.
-
- https://support.microsoft.com/kb/823764
-
- Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
- Buffer Size
-
- The problem described in this knowledge-base is applied only to pre-Vista
- Windows. Following function trying to detect OS version and skips
- SO_SNDBUF adjustment for Windows Vista and above.
-*/
-#define DETECT_OS_NONE 0
-#define DETECT_OS_PREVISTA 1
-#define DETECT_OS_VISTA_OR_LATER 2
-
-void Curl_sndbufset(curl_socket_t sockfd)
-{
- int val = CURL_MAX_WRITE_SIZE + 32;
- int curval = 0;
- int curlen = sizeof(curval);
-
- static int detectOsState = DETECT_OS_NONE;
-
- if(detectOsState == DETECT_OS_NONE) {
- if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
- VERSION_GREATER_THAN_EQUAL))
- detectOsState = DETECT_OS_VISTA_OR_LATER;
- else
- detectOsState = DETECT_OS_PREVISTA;
- }
-
- if(detectOsState == DETECT_OS_VISTA_OR_LATER)
- return;
-
- if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
- if(curval > val)
- return;
-
- setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
-}
-#endif
-
-/*
- * singleipconnect()
- *
- * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
- * CURL_SOCKET_BAD. Other errors will however return proper errors.
- *
- * singleipconnect() connects to the given IP only, and it may return without
- * having connected.
- */
-static CURLcode singleipconnect(struct Curl_easy *data,
- struct connectdata *conn,
- const struct Curl_addrinfo *ai,
- int tempindex)
-{
- struct Curl_sockaddr_ex addr;
- int rc = -1;
- int error = 0;
- bool isconnected = FALSE;
- curl_socket_t sockfd;
- CURLcode result;
- char ipaddress[MAX_IPADR_LEN];
- int port;
- bool is_tcp;
-#ifdef TCP_FASTOPEN_CONNECT
- int optval = 1;
-#endif
- char buffer[STRERROR_LEN];
- curl_socket_t *sockp = &conn->tempsock[tempindex];
- *sockp = CURL_SOCKET_BAD;
-
- result = Curl_socket(data, ai, &addr, &sockfd);
- if(result)
- return result;
-
- /* store remote address and port used in this connection attempt */
- if(!Curl_addr2string((struct sockaddr*)&addr.sa_addr, addr.addrlen,
- ipaddress, &port)) {
- /* malformed address or bug in inet_ntop, try next address */
- failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
- errno, Curl_strerror(errno, buffer, sizeof(buffer)));
- Curl_closesocket(data, conn, sockfd);
- return CURLE_OK;
- }
- infof(data, " Trying %s:%d...", ipaddress, port);
-
-#ifdef ENABLE_IPV6
- is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
- addr.socktype == SOCK_STREAM;
-#else
- is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
-#endif
- if(is_tcp && data->set.tcp_nodelay)
- tcpnodelay(data, sockfd);
-
- nosigpipe(data, sockfd);
-
- Curl_sndbufset(sockfd);
-
- if(is_tcp && data->set.tcp_keepalive)
- tcpkeepalive(data, sockfd);
-
- if(data->set.fsockopt) {
- /* activate callback for setting socket options */
- Curl_set_in_callback(data, true);
- error = data->set.fsockopt(data->set.sockopt_client,
- sockfd,
- CURLSOCKTYPE_IPCXN);
- Curl_set_in_callback(data, false);
-
- if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
- isconnected = TRUE;
- else if(error) {
- Curl_closesocket(data, conn, sockfd); /* close the socket and bail out */
- return CURLE_ABORTED_BY_CALLBACK;
- }
- }
-
- /* possibly bind the local end to an IP, interface or port */
- if(addr.family == AF_INET
-#ifdef ENABLE_IPV6
- || addr.family == AF_INET6
-#endif
- ) {
- result = bindlocal(data, sockfd, addr.family,
- Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
- if(result) {
- Curl_closesocket(data, conn, sockfd); /* close socket and bail out */
- if(result == CURLE_UNSUPPORTED_PROTOCOL) {
- /* The address family is not supported on this interface.
- We can continue trying addresses */
- return CURLE_COULDNT_CONNECT;
- }
- return result;
- }
- }
-
- /* set socket non-blocking */
- (void)curlx_nonblock(sockfd, TRUE);
-
- conn->connecttime = Curl_now();
- if(conn->num_addr > 1) {
- Curl_expire(data, conn->timeoutms_per_addr[0], EXPIRE_DNS_PER_NAME);
- Curl_expire(data, conn->timeoutms_per_addr[1], EXPIRE_DNS_PER_NAME2);
- }
-
- /* Connect TCP and QUIC sockets */
- if(!isconnected && (conn->transport != TRNSPRT_UDP)) {
- if(conn->bits.tcp_fastopen) {
-#if defined(CONNECT_DATA_IDEMPOTENT) /* Darwin */
-# if defined(HAVE_BUILTIN_AVAILABLE)
- /* while connectx function is available since macOS 10.11 / iOS 9,
- it did not have the interface declared correctly until
- Xcode 9 / macOS SDK 10.13 */
- if(__builtin_available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *)) {
- sa_endpoints_t endpoints;
- endpoints.sae_srcif = 0;
- endpoints.sae_srcaddr = NULL;
- endpoints.sae_srcaddrlen = 0;
- endpoints.sae_dstaddr = &addr.sa_addr;
- endpoints.sae_dstaddrlen = addr.addrlen;
-
- rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
- CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
- NULL, 0, NULL, NULL);
- }
- else {
- rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
- }
-# else
- rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
-# endif /* HAVE_BUILTIN_AVAILABLE */
-#elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */
- if(setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
- (void *)&optval, sizeof(optval)) < 0)
- infof(data, "Failed to enable TCP Fast Open on fd %d", sockfd);
-
- rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
-#elif defined(MSG_FASTOPEN) /* old Linux */
- if(conn->given->flags & PROTOPT_SSL)
- rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
- else
- rc = 0; /* Do nothing */
-#endif
- }
- else {
- rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
- }
-
- if(-1 == rc)
- error = SOCKERRNO;
-#ifdef ENABLE_QUIC
- else if(conn->transport == TRNSPRT_QUIC) {
- /* pass in 'sockfd' separately since it hasn't been put into the
- tempsock array at this point */
- result = Curl_quic_connect(data, conn, sockfd, tempindex,
- &addr.sa_addr, addr.addrlen);
- if(result)
- error = SOCKERRNO;
- }
-#endif
- }
- else {
- *sockp = sockfd;
- return CURLE_OK;
- }
-
- if(-1 == rc) {
- switch(error) {
- case EINPROGRESS:
- case EWOULDBLOCK:
-#if defined(EAGAIN)
-#if (EAGAIN) != (EWOULDBLOCK)
- /* On some platforms EAGAIN and EWOULDBLOCK are the
- * same value, and on others they are different, hence
- * the odd #if
- */
- case EAGAIN:
-#endif
-#endif
- result = CURLE_OK;
- break;
-
- default:
- /* unknown error, fallthrough and try another address! */
- infof(data, "Immediate connect fail for %s: %s",
- ipaddress, Curl_strerror(error, buffer, sizeof(buffer)));
- data->state.os_errno = error;
-
- /* connect failed */
- Curl_closesocket(data, conn, sockfd);
- result = CURLE_COULDNT_CONNECT;
- }
- }
-
- if(!result)
- *sockp = sockfd;
-
- return result;
-}
-
-/*
- * TCP connect to the given host with timeout, proxy or remote doesn't matter.
- * There might be more than one IP address to try out. Fill in the passed
- * pointer with the connected socket.
- */
-
-CURLcode Curl_connecthost(struct Curl_easy *data,
- struct connectdata *conn, /* context */
- const struct Curl_dns_entry *remotehost)
-{
- CURLcode result = CURLE_COULDNT_CONNECT;
- int i;
- timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
-
- if(timeout_ms < 0) {
- /* a precaution, no need to continue if time already is up */
- failf(data, "Connection time-out");
- return CURLE_OPERATION_TIMEDOUT;
- }
-
- conn->num_addr = Curl_num_addresses(remotehost->addr);
- conn->tempaddr[0] = conn->tempaddr[1] = remotehost->addr;
- conn->tempsock[0] = conn->tempsock[1] = CURL_SOCKET_BAD;
-
- /* Max time for the next connection attempt */
- conn->timeoutms_per_addr[0] =
- conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
- conn->timeoutms_per_addr[1] =
- conn->tempaddr[1]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
-
- if(conn->ip_version == CURL_IPRESOLVE_WHATEVER) {
- /* any IP version is allowed */
- conn->tempfamily[0] = conn->tempaddr[0]?
- conn->tempaddr[0]->ai_family:0;
-#ifdef ENABLE_IPV6
- conn->tempfamily[1] = conn->tempfamily[0] == AF_INET6 ?
- AF_INET : AF_INET6;
-#else
- conn->tempfamily[1] = AF_UNSPEC;
-#endif
- }
- else {
- /* only one IP version is allowed */
- conn->tempfamily[0] = (conn->ip_version == CURL_IPRESOLVE_V4) ?
- AF_INET :
-#ifdef ENABLE_IPV6
- AF_INET6;
-#else
- AF_UNSPEC;
-#endif
- conn->tempfamily[1] = AF_UNSPEC;
-
- ainext(conn, 0, FALSE); /* find first address of the right type */
- }
-
- ainext(conn, 1, FALSE); /* assigns conn->tempaddr[1] accordingly */
-
- DEBUGF(infof(data, "family0 == %s, family1 == %s",
- conn->tempfamily[0] == AF_INET ? "v4" : "v6",
- conn->tempfamily[1] == AF_INET ? "v4" : "v6"));
-
- /* get through the list in family order in case of quick failures */
- for(i = 0; (i < 2) && result; i++) {
- while(conn->tempaddr[i]) {
- result = singleipconnect(data, conn, conn->tempaddr[i], i);
- if(!result)
- break;
- ainext(conn, i, TRUE);
- }
- }
- if(result)
- return result;
-
- Curl_expire(data, data->set.happy_eyeballs_timeout,
- EXPIRE_HAPPY_EYEBALLS);
-
- return CURLE_OK;
-}
-
struct connfind {
- long id_tofind;
+ curl_off_t id_tofind;
struct connectdata *found;
};
@@ -1515,176 +314,6 @@
}
/*
- * Check if a connection seems to be alive.
- */
-bool Curl_connalive(struct connectdata *conn)
-{
- /* First determine if ssl */
- if(conn->ssl[FIRSTSOCKET].use) {
- /* use the SSL context */
- if(!Curl_ssl_check_cxn(conn))
- return false; /* FIN received */
- }
-/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
-#ifdef MSG_PEEK
- else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD)
- return false;
- else {
- /* use the socket */
- char buf;
- if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
- (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
- return false; /* FIN received */
- }
- }
-#endif
- return true;
-}
-
-/*
- * Close a socket.
- *
- * 'conn' can be NULL, beware!
- */
-int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn,
- curl_socket_t sock)
-{
- if(conn && conn->fclosesocket) {
- if((sock == conn->sock[SECONDARYSOCKET]) && conn->bits.sock_accepted)
- /* if this socket matches the second socket, and that was created with
- accept, then we MUST NOT call the callback but clear the accepted
- status */
- conn->bits.sock_accepted = FALSE;
- else {
- int rc;
- Curl_multi_closed(data, sock);
- Curl_set_in_callback(data, true);
- rc = conn->fclosesocket(conn->closesocket_client, sock);
- Curl_set_in_callback(data, false);
- return rc;
- }
- }
-
- if(conn)
- /* tell the multi-socket code about this */
- Curl_multi_closed(data, sock);
-
- sclose(sock);
-
- return 0;
-}
-
-/*
- * Create a socket based on info from 'conn' and 'ai'.
- *
- * 'addr' should be a pointer to the correct struct to get data back, or NULL.
- * 'sockfd' must be a pointer to a socket descriptor.
- *
- * If the open socket callback is set, used that!
- *
- */
-CURLcode Curl_socket(struct Curl_easy *data,
- const struct Curl_addrinfo *ai,
- struct Curl_sockaddr_ex *addr,
- curl_socket_t *sockfd)
-{
- struct connectdata *conn = data->conn;
- struct Curl_sockaddr_ex dummy;
-
- if(!addr)
- /* if the caller doesn't want info back, use a local temp copy */
- addr = &dummy;
-
- /*
- * The Curl_sockaddr_ex structure is basically libcurl's external API
- * curl_sockaddr structure with enough space available to directly hold
- * any protocol-specific address structures. The variable declared here
- * will be used to pass / receive data to/from the fopensocket callback
- * if this has been set, before that, it is initialized from parameters.
- */
-
- addr->family = ai->ai_family;
- addr->socktype = (conn->transport == TRNSPRT_TCP) ? SOCK_STREAM : SOCK_DGRAM;
- addr->protocol = conn->transport != TRNSPRT_TCP ? IPPROTO_UDP :
- ai->ai_protocol;
- addr->addrlen = ai->ai_addrlen;
-
- if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
- addr->addrlen = sizeof(struct Curl_sockaddr_storage);
- memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
-
- 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.
- */
- Curl_set_in_callback(data, true);
- *sockfd = data->set.fopensocket(data->set.opensocket_client,
- CURLSOCKTYPE_IPCXN,
- (struct curl_sockaddr *)addr);
- Curl_set_in_callback(data, false);
- }
- else
- /* opensocket callback not set, so simply create the socket now */
- *sockfd = socket(addr->family, addr->socktype, addr->protocol);
-
- if(*sockfd == CURL_SOCKET_BAD)
- /* no socket, no connection */
- return CURLE_COULDNT_CONNECT;
-
- if(conn->transport == TRNSPRT_QUIC) {
- /* QUIC sockets need to be nonblocking */
- (void)curlx_nonblock(*sockfd, TRUE);
- switch(addr->family) {
-#if defined(__linux__) && defined(IP_MTU_DISCOVER)
- case AF_INET: {
- int val = IP_PMTUDISC_DO;
- (void)setsockopt(*sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &val,
- sizeof(val));
- break;
- }
-#endif
-#if defined(__linux__) && defined(IPV6_MTU_DISCOVER)
- case AF_INET6: {
- int val = IPV6_PMTUDISC_DO;
- (void)setsockopt(*sockfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val,
- sizeof(val));
- break;
- }
-#endif
- }
- }
-
-#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
- if(conn->scope_id && (addr->family == AF_INET6)) {
- struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
- sa6->sin6_scope_id = conn->scope_id;
- }
-#endif
-
-#if defined(__linux__) && defined(IP_RECVERR)
- if(addr->socktype == SOCK_DGRAM) {
- int one = 1;
- switch(addr->family) {
- case AF_INET:
- (void)setsockopt(*sockfd, SOL_IP, IP_RECVERR, &one, sizeof(one));
- break;
- case AF_INET6:
- (void)setsockopt(*sockfd, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one));
- break;
- }
- }
-#endif
-
- return CURLE_OK;
-}
-
-/*
* Curl_conncontrol() marks streams or connection for closure.
*/
void Curl_conncontrol(struct connectdata *conn,
@@ -1697,32 +326,1119 @@
/* close if a connection, or a stream that isn't multiplexed. */
/* This function will be called both before and after this connection is
associated with a transfer. */
- bool closeit;
+ bool closeit, is_multiplex;
DEBUGASSERT(conn);
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
(void)reason; /* useful for debugging */
#endif
+ is_multiplex = Curl_conn_is_multiplex(conn, FIRSTSOCKET);
closeit = (ctrl == CONNCTRL_CONNECTION) ||
- ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
- if((ctrl == CONNCTRL_STREAM) &&
- (conn->handler->flags & PROTOPT_STREAM))
- ;
+ ((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) {
conn->bits.close = closeit; /* the only place in the source code that
should assign this bit */
}
}
-/* Data received can be cached at various levels, so check them all here. */
-bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
+/**
+ * job walking the matching addr infos, creating a sub-cfilter with the
+ * provided method `cf_create` and running setup/connect on it.
+ */
+struct eyeballer {
+ const char *name;
+ const struct Curl_addrinfo *addr; /* List of addresses to try, not owned */
+ int ai_family; /* matching address family only */
+ cf_ip_connect_create *cf_create; /* for creating cf */
+ struct Curl_cfilter *cf; /* current sub-cfilter connecting */
+ struct eyeballer *primary; /* eyeballer this one is backup for */
+ timediff_t delay_ms; /* delay until start */
+ struct curltime started; /* start of current attempt */
+ timediff_t timeoutms; /* timeout for current attempt */
+ expire_id timeout_id; /* ID for Curl_expire() */
+ CURLcode result;
+ int error;
+ BIT(has_started); /* attempts have started */
+ BIT(is_done); /* out of addresses/time */
+ BIT(connected); /* cf has connected */
+};
+
+
+typedef enum {
+ SCFST_INIT,
+ SCFST_WAITING,
+ SCFST_DONE
+} cf_connect_state;
+
+struct cf_he_ctx {
+ int transport;
+ cf_ip_connect_create *cf_create;
+ const struct Curl_dns_entry *remotehost;
+ cf_connect_state state;
+ struct eyeballer *baller[2];
+ struct eyeballer *winner;
+ struct curltime started;
+};
+
+static CURLcode eyeballer_new(struct eyeballer **pballer,
+ cf_ip_connect_create *cf_create,
+ const struct Curl_addrinfo *addr,
+ int ai_family,
+ struct eyeballer *primary,
+ timediff_t delay_ms,
+ timediff_t timeout_ms,
+ expire_id timeout_id)
{
- int readable;
- DEBUGASSERT(conn);
+ struct eyeballer *baller;
- if(Curl_ssl_data_pending(conn, sockindex) ||
- Curl_recv_has_postponed_data(conn, sockindex))
- return true;
+ *pballer = NULL;
+ baller = calloc(1, sizeof(*baller) + 1000);
+ if(!baller)
+ return CURLE_OUT_OF_MEMORY;
- readable = SOCKET_READABLE(conn->sock[sockindex], 0);
- return (readable > 0 && (readable & CURL_CSELECT_IN));
+ baller->name = ((ai_family == AF_INET)? "ipv4" : (
+#ifdef ENABLE_IPV6
+ (ai_family == AF_INET6)? "ipv6" :
+#endif
+ "ip"));
+ baller->cf_create = cf_create;
+ baller->addr = addr;
+ baller->ai_family = ai_family;
+ baller->primary = primary;
+ baller->delay_ms = delay_ms;
+ baller->timeoutms = addr_next_match(baller->addr, baller->ai_family)?
+ timeout_ms / 2 : timeout_ms;
+ baller->timeout_id = timeout_id;
+ baller->result = CURLE_COULDNT_CONNECT;
+
+ *pballer = baller;
+ return CURLE_OK;
}
+
+static void baller_close(struct eyeballer *baller,
+ struct Curl_easy *data)
+{
+ if(baller && baller->cf) {
+ Curl_conn_cf_discard_chain(&baller->cf, data);
+ }
+}
+
+static void baller_free(struct eyeballer *baller,
+ struct Curl_easy *data)
+{
+ if(baller) {
+ baller_close(baller, data);
+ free(baller);
+ }
+}
+
+static void baller_next_addr(struct eyeballer *baller)
+{
+ baller->addr = addr_next_match(baller->addr, baller->ai_family);
+}
+
+/*
+ * Initiate a connect attempt walk.
+ *
+ * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
+ * CURL_SOCKET_BAD. Other errors will however return proper errors.
+ */
+static void baller_initiate(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct eyeballer *baller)
+{
+ struct cf_he_ctx *ctx = cf->ctx;
+ struct Curl_cfilter *cf_prev = baller->cf;
+ struct Curl_cfilter *wcf;
+ CURLcode result;
+
+
+ /* Don't close a previous cfilter yet to ensure that the next IP's
+ socket gets a different file descriptor, which can prevent bugs when
+ the curl_multi_socket_action interface is used with certain select()
+ replacements such as kqueue. */
+ result = baller->cf_create(&baller->cf, data, cf->conn, baller->addr,
+ ctx->transport);
+ if(result)
+ goto out;
+
+ /* the new filter might have sub-filters */
+ for(wcf = baller->cf; wcf; wcf = wcf->next) {
+ wcf->conn = cf->conn;
+ wcf->sockindex = cf->sockindex;
+ }
+
+ if(addr_next_match(baller->addr, baller->ai_family)) {
+ Curl_expire(data, baller->timeoutms, baller->timeout_id);
+ }
+
+out:
+ if(result) {
+ DEBUGF(LOG_CF(data, cf, "%s failed", baller->name));
+ baller_close(baller, data);
+ }
+ if(cf_prev)
+ Curl_conn_cf_discard_chain(&cf_prev, data);
+ baller->result = result;
+}
+
+/**
+ * Start a connection attempt on the current baller address.
+ * Will return CURLE_OK on the first address where a socket
+ * could be created and the non-blocking connect started.
+ * Returns error when all remaining addresses have been tried.
+ */
+static CURLcode baller_start(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct eyeballer *baller,
+ timediff_t timeoutms)
+{
+ baller->error = 0;
+ baller->connected = FALSE;
+ baller->has_started = TRUE;
+
+ while(baller->addr) {
+ baller->started = Curl_now();
+ baller->timeoutms = addr_next_match(baller->addr, baller->ai_family) ?
+ timeoutms / 2 : timeoutms;
+ baller_initiate(cf, data, baller);
+ if(!baller->result)
+ break;
+ baller_next_addr(baller);
+ }
+ if(!baller->addr) {
+ baller->is_done = TRUE;
+ }
+ return baller->result;
+}
+
+
+/* Used within the multi interface. Try next IP address, returns error if no
+ more address exists or error */
+static CURLcode baller_start_next(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct eyeballer *baller,
+ timediff_t timeoutms)
+{
+ if(cf->sockindex == FIRSTSOCKET) {
+ baller_next_addr(baller);
+ baller_start(cf, data, baller, timeoutms);
+ }
+ else {
+ baller->error = 0;
+ baller->connected = FALSE;
+ baller->has_started = TRUE;
+ baller->is_done = TRUE;
+ baller->result = CURLE_COULDNT_CONNECT;
+ }
+ return baller->result;
+}
+
+static CURLcode baller_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct eyeballer *baller,
+ struct curltime *now,
+ bool *connected)
+{
+ (void)cf;
+ *connected = baller->connected;
+ if(!baller->result && !*connected) {
+ /* evaluate again */
+ baller->result = Curl_conn_cf_connect(baller->cf, data, 0, connected);
+
+ if(!baller->result) {
+ if(*connected) {
+ baller->connected = TRUE;
+ baller->is_done = TRUE;
+ }
+ else if(Curl_timediff(*now, baller->started) >= baller->timeoutms) {
+ infof(data, "%s connect timeout after %" CURL_FORMAT_TIMEDIFF_T
+ "ms, move on!", baller->name, baller->timeoutms);
+#if defined(ETIMEDOUT)
+ baller->error = ETIMEDOUT;
+#endif
+ baller->result = CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ }
+ return baller->result;
+}
+
+/*
+ * is_connected() checks if the socket has connected.
+ */
+static CURLcode is_connected(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *connected)
+{
+ struct cf_he_ctx *ctx = cf->ctx;
+ struct connectdata *conn = cf->conn;
+ CURLcode result;
+ struct curltime now;
+ size_t i;
+ int ongoing, not_started;
+ const char *hostname;
+
+ /* Check if any of the conn->tempsock we use for establishing connections
+ * succeeded and, if so, close any ongoing other ones.
+ * Transfer the successful conn->tempsock to conn->sock[sockindex]
+ * and set conn->tempsock to CURL_SOCKET_BAD.
+ * If transport is QUIC, we need to shutdown the ongoing 'other'
+ * cot ballers in a QUIC appropriate way. */
+evaluate:
+ *connected = FALSE; /* a very negative world view is best */
+ now = Curl_now();
+ ongoing = not_started = 0;
+ for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ struct eyeballer *baller = ctx->baller[i];
+
+ if(!baller || baller->is_done)
+ continue;
+
+ if(!baller->has_started) {
+ ++not_started;
+ continue;
+ }
+ baller->result = baller_connect(cf, data, baller, &now, connected);
+ DEBUGF(LOG_CF(data, cf, "%s connect -> %d, connected=%d",
+ baller->name, baller->result, *connected));
+
+ if(!baller->result) {
+ if(*connected) {
+ /* connected, declare the winner */
+ ctx->winner = baller;
+ ctx->baller[i] = NULL;
+ break;
+ }
+ else { /* still waiting */
+ ++ongoing;
+ }
+ }
+ else if(!baller->is_done) {
+ /* The baller failed to connect, start its next attempt */
+ if(baller->error) {
+ data->state.os_errno = baller->error;
+ SET_SOCKERRNO(baller->error);
+ }
+ baller_start_next(cf, data, baller, Curl_timeleft(data, &now, TRUE));
+ if(baller->is_done) {
+ DEBUGF(LOG_CF(data, cf, "%s done", baller->name));
+ }
+ else {
+ /* next attempt was started */
+ DEBUGF(LOG_CF(data, cf, "%s trying next", baller->name));
+ ++ongoing;
+ }
+ }
+ }
+
+ if(ctx->winner) {
+ *connected = TRUE;
+ return CURLE_OK;
+ }
+
+ /* Nothing connected, check the time before we might
+ * start new ballers or return ok. */
+ if((ongoing || not_started) && Curl_timeleft(data, &now, TRUE) < 0) {
+ failf(data, "Connection timeout after %ld ms",
+ Curl_timediff(now, data->progress.t_startsingle));
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* Check if we have any waiting ballers to start now. */
+ if(not_started > 0) {
+ int added = 0;
+
+ for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ struct eyeballer *baller = ctx->baller[i];
+
+ if(!baller || baller->has_started)
+ continue;
+ /* We start its primary baller has failed to connect or if
+ * its start delay_ms have expired */
+ if((baller->primary && baller->primary->is_done) ||
+ Curl_timediff(now, ctx->started) >= baller->delay_ms) {
+ baller_start(cf, data, baller, Curl_timeleft(data, &now, TRUE));
+ if(baller->is_done) {
+ DEBUGF(LOG_CF(data, cf, "%s done", baller->name));
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "%s starting (timeout=%"
+ CURL_FORMAT_TIMEDIFF_T "ms)",
+ baller->name, baller->timeoutms));
+ ++ongoing;
+ ++added;
+ }
+ }
+ }
+ if(added > 0)
+ goto evaluate;
+ }
+
+ if(ongoing > 0) {
+ /* We are still trying, return for more waiting */
+ *connected = FALSE;
+ return CURLE_OK;
+ }
+
+ /* all ballers have failed to connect. */
+ DEBUGF(LOG_CF(data, cf, "all eyeballers failed"));
+ result = CURLE_COULDNT_CONNECT;
+ for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ struct eyeballer *baller = ctx->baller[i];
+ DEBUGF(LOG_CF(data, cf, "%s assess started=%d, result=%d",
+ baller?baller->name:NULL,
+ baller?baller->has_started:0,
+ baller?baller->result:0));
+ if(baller && baller->has_started && baller->result) {
+ result = baller->result;
+ break;
+ }
+ }
+
+#ifndef CURL_DISABLE_PROXY
+ if(conn->bits.socksproxy)
+ hostname = conn->socks_proxy.host.name;
+ else if(conn->bits.httpproxy)
+ hostname = conn->http_proxy.host.name;
+ else
+#endif
+ if(conn->bits.conn_to_host)
+ hostname = conn->conn_to_host.name;
+ else
+ hostname = conn->host.name;
+
+ failf(data, "Failed to connect to %s port %u after "
+ "%" CURL_FORMAT_TIMEDIFF_T " ms: %s",
+ hostname, conn->port,
+ Curl_timediff(now, data->progress.t_startsingle),
+ curl_easy_strerror(result));
+
+#ifdef WSAETIMEDOUT
+ if(WSAETIMEDOUT == data->state.os_errno)
+ result = CURLE_OPERATION_TIMEDOUT;
+#elif defined(ETIMEDOUT)
+ if(ETIMEDOUT == data->state.os_errno)
+ result = CURLE_OPERATION_TIMEDOUT;
+#endif
+
+ return result;
+}
+
+/*
+ * Connect to the given host with timeout, proxy or remote doesn't matter.
+ * There might be more than one IP address to try out.
+ */
+static CURLcode start_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const struct Curl_dns_entry *remotehost)
+{
+ struct cf_he_ctx *ctx = cf->ctx;
+ struct connectdata *conn = cf->conn;
+ CURLcode result = CURLE_COULDNT_CONNECT;
+ int ai_family0, ai_family1;
+ timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ const struct Curl_addrinfo *addr0, *addr1;
+
+ if(timeout_ms < 0) {
+ /* a precaution, no need to continue if time already is up */
+ failf(data, "Connection time-out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ ctx->started = Curl_now();
+
+ /* remotehost->addr is the list of addresses from the resolver, each
+ * with an address family. The list has at least one entry, possibly
+ * many more.
+ * We try at most 2 at a time, until we either get a connection or
+ * run out of addresses to try. Since likelihood of success is tied
+ * to the address family (e.g. IPV6 might not work at all ), we want
+ * the 2 connect attempt ballers to try different families, if possible.
+ *
+ */
+ if(conn->ip_version == CURL_IPRESOLVE_WHATEVER) {
+ /* any IP version is allowed */
+ ai_family0 = remotehost->addr?
+ remotehost->addr->ai_family : 0;
+#ifdef ENABLE_IPV6
+ ai_family1 = ai_family0 == AF_INET6 ?
+ AF_INET : AF_INET6;
+#else
+ ai_family1 = AF_UNSPEC;
+#endif
+ }
+ else {
+ /* only one IP version is allowed */
+ ai_family0 = (conn->ip_version == CURL_IPRESOLVE_V4) ?
+ AF_INET :
+#ifdef ENABLE_IPV6
+ AF_INET6;
+#else
+ AF_UNSPEC;
+#endif
+ ai_family1 = AF_UNSPEC;
+ }
+
+ /* Get the first address in the list that matches the family,
+ * this might give NULL, if we do not have any matches. */
+ addr0 = addr_first_match(remotehost->addr, ai_family0);
+ addr1 = addr_first_match(remotehost->addr, ai_family1);
+ if(!addr0 && addr1) {
+ /* switch around, so a single baller always uses addr0 */
+ addr0 = addr1;
+ ai_family0 = ai_family1;
+ addr1 = NULL;
+ }
+
+ /* We found no address that matches our criteria, we cannot connect */
+ if(!addr0) {
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memset(ctx->baller, 0, sizeof(ctx->baller));
+ result = eyeballer_new(&ctx->baller[0], ctx->cf_create, addr0, ai_family0,
+ NULL, 0, /* no primary/delay, start now */
+ timeout_ms, EXPIRE_DNS_PER_NAME);
+ if(result)
+ return result;
+ DEBUGF(LOG_CF(data, cf, "created %s (timeout %"
+ CURL_FORMAT_TIMEDIFF_T "ms)",
+ ctx->baller[0]->name, ctx->baller[0]->timeoutms));
+ if(addr1) {
+ /* second one gets a delayed start */
+ result = eyeballer_new(&ctx->baller[1], ctx->cf_create, addr1, ai_family1,
+ ctx->baller[0], /* wait on that to fail */
+ /* or start this delayed */
+ data->set.happy_eyeballs_timeout,
+ timeout_ms, EXPIRE_DNS_PER_NAME2);
+ if(result)
+ return result;
+ DEBUGF(LOG_CF(data, cf, "created %s (timeout %"
+ CURL_FORMAT_TIMEDIFF_T "ms)",
+ ctx->baller[1]->name, ctx->baller[1]->timeoutms));
+ }
+
+ Curl_expire(data, data->set.happy_eyeballs_timeout,
+ EXPIRE_HAPPY_EYEBALLS);
+
+ return CURLE_OK;
+}
+
+static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_he_ctx *ctx = cf->ctx;
+ size_t i;
+
+ DEBUGASSERT(ctx);
+ DEBUGASSERT(data);
+ for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ baller_free(ctx->baller[i], data);
+ ctx->baller[i] = NULL;
+ }
+ baller_free(ctx->winner, data);
+ ctx->winner = NULL;
+}
+
+static int cf_he_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ struct cf_he_ctx *ctx = cf->ctx;
+ size_t i, s;
+ int wrc, rc = GETSOCK_BLANK;
+ curl_socket_t wsocks[MAX_SOCKSPEREASYHANDLE];
+
+ if(cf->connected)
+ return cf->next->cft->get_select_socks(cf->next, data, socks);
+
+ for(i = s = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ struct eyeballer *baller = ctx->baller[i];
+ if(!baller || !baller->cf)
+ continue;
+
+ wrc = Curl_conn_cf_get_select_socks(baller->cf, data, wsocks);
+ if(wrc) {
+ /* TODO: we assume we get at most one socket back */
+ socks[s] = wsocks[0];
+ if(wrc & GETSOCK_WRITESOCK(0))
+ rc |= GETSOCK_WRITESOCK(s);
+ if(wrc & GETSOCK_READSOCK(0))
+ rc |= GETSOCK_READSOCK(s);
+ s++;
+ }
+ }
+ return rc;
+}
+
+static CURLcode cf_he_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct cf_he_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ (void)blocking; /* TODO: do we want to support this? */
+ DEBUGASSERT(ctx);
+ *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, ctx->remotehost);
+ if(result)
+ return result;
+ ctx->state = SCFST_WAITING;
+ /* FALLTHROUGH */
+ case SCFST_WAITING:
+ result = is_connected(cf, data, done);
+ if(!result && *done) {
+ DEBUGASSERT(ctx->winner);
+ DEBUGASSERT(ctx->winner->cf);
+ DEBUGASSERT(ctx->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->winner->cf;
+ ctx->winner->cf = NULL;
+ cf_he_ctx_clear(cf, data);
+ Curl_conn_cf_cntrl(cf->next, data, TRUE,
+ CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
+
+ if(cf->conn->handler->protocol & PROTO_FAMILY_SSH)
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
+ Curl_verboseconnect(data, cf->conn);
+ data->info.numconnects++; /* to track the # of connections made */
+ }
+ break;
+ case SCFST_DONE:
+ *done = TRUE;
+ break;
+ }
+ return result;
+}
+
+static void cf_he_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_he_ctx *ctx = cf->ctx;
+
+ DEBUGF(LOG_CF(data, cf, "close"));
+ cf_he_ctx_clear(cf, data);
+ cf->connected = FALSE;
+ ctx->state = SCFST_INIT;
+
+ if(cf->next) {
+ cf->next->cft->do_close(cf->next, data);
+ Curl_conn_cf_discard_chain(&cf->next, data);
+ }
+}
+
+static bool cf_he_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ struct cf_he_ctx *ctx = cf->ctx;
+ size_t i;
+
+ if(cf->connected)
+ return cf->next->cft->has_data_pending(cf->next, data);
+
+ for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ struct eyeballer *baller = ctx->baller[i];
+ if(!baller || !baller->cf)
+ continue;
+ if(baller->cf->cft->has_data_pending(baller->cf, data))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static struct curltime get_max_baller_time(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query)
+{
+ struct cf_he_ctx *ctx = cf->ctx;
+ struct curltime t, tmax;
+ size_t i;
+
+ memset(&tmax, 0, sizeof(tmax));
+ for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ struct eyeballer *baller = ctx->baller[i];
+
+ memset(&t, 0, sizeof(t));
+ if(baller && baller->cf &&
+ !baller->cf->cft->query(baller->cf, data, query, NULL, &t)) {
+ if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
+ tmax = t;
+ }
+ }
+ return tmax;
+}
+
+static CURLcode cf_he_query(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query, int *pres1, void *pres2)
+{
+ struct cf_he_ctx *ctx = cf->ctx;
+
+ if(!cf->connected) {
+ switch(query) {
+ case CF_QUERY_CONNECT_REPLY_MS: {
+ int reply_ms = -1;
+ size_t i;
+
+ for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ struct eyeballer *baller = ctx->baller[i];
+ int breply_ms;
+
+ if(baller && baller->cf &&
+ !baller->cf->cft->query(baller->cf, data, query,
+ &breply_ms, NULL)) {
+ if(breply_ms >= 0 && (reply_ms < 0 || breply_ms < reply_ms))
+ reply_ms = breply_ms;
+ }
+ }
+ *pres1 = reply_ms;
+ DEBUGF(LOG_CF(data, cf, "query connect reply: %dms", *pres1));
+ return CURLE_OK;
+ }
+ case CF_QUERY_TIMER_CONNECT: {
+ struct curltime *when = pres2;
+ *when = get_max_baller_time(cf, data, CF_QUERY_TIMER_CONNECT);
+ return CURLE_OK;
+ }
+ case CF_QUERY_TIMER_APPCONNECT: {
+ struct curltime *when = pres2;
+ *when = get_max_baller_time(cf, data, CF_QUERY_TIMER_APPCONNECT);
+ return CURLE_OK;
+ }
+ default:
+ break;
+ }
+ }
+
+ return cf->next?
+ cf->next->cft->query(cf->next, data, query, pres1, pres2) :
+ CURLE_UNKNOWN_OPTION;
+}
+
+static void cf_he_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_he_ctx *ctx = cf->ctx;
+
+ DEBUGF(LOG_CF(data, cf, "destroy"));
+ if(ctx) {
+ cf_he_ctx_clear(cf, data);
+ }
+ /* release any resources held in state */
+ Curl_safefree(ctx);
+}
+
+struct Curl_cftype Curl_cft_happy_eyeballs = {
+ "HAPPY-EYEBALLS",
+ 0,
+ CURL_LOG_DEFAULT,
+ cf_he_destroy,
+ cf_he_connect,
+ cf_he_close,
+ Curl_cf_def_get_host,
+ cf_he_get_select_socks,
+ cf_he_data_pending,
+ Curl_cf_def_send,
+ Curl_cf_def_recv,
+ Curl_cf_def_cntrl,
+ Curl_cf_def_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ cf_he_query,
+};
+
+/**
+ * Create a happy eyeball connection filter that uses the, once resolved,
+ * address information to connect on ip families based on connection
+ * configuration.
+ * @param pcf output, the created cfilter
+ * @param data easy handle used in creation
+ * @param conn connection the filter is created for
+ * @param cf_create method to create the sub-filters performing the
+ * actual connects.
+ */
+static CURLcode
+cf_happy_eyeballs_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ cf_ip_connect_create *cf_create,
+ const struct Curl_dns_entry *remotehost,
+ int transport)
+{
+ struct cf_he_ctx *ctx = NULL;
+ CURLcode result;
+
+ (void)data;
+ (void)conn;
+ *pcf = NULL;
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ ctx->transport = transport;
+ ctx->cf_create = cf_create;
+ ctx->remotehost = remotehost;
+
+ result = Curl_cf_create(pcf, &Curl_cft_happy_eyeballs, ctx);
+
+out:
+ if(result) {
+ Curl_safefree(*pcf);
+ Curl_safefree(ctx);
+ }
+ return result;
+}
+
+struct transport_provider {
+ int transport;
+ cf_ip_connect_create *cf_create;
+};
+
+static
+#ifndef DEBUGBUILD
+const
+#endif
+struct transport_provider transport_providers[] = {
+ { TRNSPRT_TCP, Curl_cf_tcp_create },
+#ifdef ENABLE_QUIC
+ { TRNSPRT_QUIC, Curl_cf_quic_create },
+#endif
+ { TRNSPRT_UDP, Curl_cf_udp_create },
+ { TRNSPRT_UNIX, Curl_cf_unix_create },
+};
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
+
+static cf_ip_connect_create *get_cf_create(int transport)
+{
+ size_t i;
+ for(i = 0; i < ARRAYSIZE(transport_providers); ++i) {
+ if(transport == transport_providers[i].transport)
+ return transport_providers[i].cf_create;
+ }
+ return NULL;
+}
+
+static CURLcode cf_he_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data,
+ const struct Curl_dns_entry *remotehost,
+ int transport)
+{
+ cf_ip_connect_create *cf_create;
+ struct Curl_cfilter *cf;
+ CURLcode result;
+
+ /* Need to be first */
+ DEBUGASSERT(cf_at);
+ cf_create = get_cf_create(transport);
+ if(!cf_create) {
+ DEBUGF(LOG_CF(data, cf_at, "unsupported transport type %d", transport));
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+ result = cf_happy_eyeballs_create(&cf, data, cf_at->conn,
+ cf_create, remotehost,
+ transport);
+ if(result)
+ return result;
+
+ Curl_conn_cf_insert_after(cf_at, cf);
+ return CURLE_OK;
+}
+
+typedef enum {
+ CF_SETUP_INIT,
+ CF_SETUP_CNNCT_EYEBALLS,
+ CF_SETUP_CNNCT_SOCKS,
+ CF_SETUP_CNNCT_HTTP_PROXY,
+ CF_SETUP_CNNCT_HAPROXY,
+ CF_SETUP_CNNCT_SSL,
+ CF_SETUP_DONE
+} cf_setup_state;
+
+struct cf_setup_ctx {
+ cf_setup_state state;
+ const struct Curl_dns_entry *remotehost;
+ int ssl_mode;
+ int transport;
+};
+
+static CURLcode cf_setup_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct cf_setup_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ /* connect current sub-chain */
+connect_sub_chain:
+ if(cf->next && !cf->next->connected) {
+ result = Curl_conn_cf_connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ return result;
+ }
+
+ if(ctx->state < CF_SETUP_CNNCT_EYEBALLS) {
+ result = cf_he_insert_after(cf, data, ctx->remotehost, ctx->transport);
+ if(result)
+ return result;
+ ctx->state = CF_SETUP_CNNCT_EYEBALLS;
+ if(!cf->next || !cf->next->connected)
+ goto connect_sub_chain;
+ }
+
+ /* sub-chain connected, do we need to add more? */
+#ifndef CURL_DISABLE_PROXY
+ if(ctx->state < CF_SETUP_CNNCT_SOCKS && cf->conn->bits.socksproxy) {
+ result = Curl_cf_socks_proxy_insert_after(cf, data);
+ if(result)
+ return result;
+ ctx->state = CF_SETUP_CNNCT_SOCKS;
+ if(!cf->next || !cf->next->connected)
+ goto connect_sub_chain;
+ }
+
+ 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)) {
+ result = Curl_cf_ssl_proxy_insert_after(cf, data);
+ if(result)
+ return result;
+ }
+#endif /* USE_SSL */
+
+#if !defined(CURL_DISABLE_HTTP)
+ if(cf->conn->bits.tunnel_proxy) {
+ result = Curl_cf_http_proxy_insert_after(cf, data);
+ if(result)
+ return result;
+ }
+#endif /* !CURL_DISABLE_HTTP */
+ ctx->state = CF_SETUP_CNNCT_HTTP_PROXY;
+ if(!cf->next || !cf->next->connected)
+ goto connect_sub_chain;
+ }
+#endif /* !CURL_DISABLE_PROXY */
+
+ if(ctx->state < CF_SETUP_CNNCT_HAPROXY) {
+#if !defined(CURL_DISABLE_PROXY)
+ if(data->set.haproxyprotocol) {
+ if(Curl_conn_is_ssl(cf->conn, cf->sockindex)) {
+ failf(data, "haproxy protocol not support with SSL "
+ "encryption in place (QUIC?)");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+ result = Curl_cf_haproxy_insert_after(cf, data);
+ if(result)
+ return result;
+ }
+#endif /* !CURL_DISABLE_PROXY */
+ ctx->state = CF_SETUP_CNNCT_HAPROXY;
+ if(!cf->next || !cf->next->connected)
+ goto connect_sub_chain;
+ }
+
+ 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 */
+ && !Curl_conn_is_ssl(cf->conn, cf->sockindex)) { /* it is missing */
+ result = Curl_cf_ssl_insert_after(cf, data);
+ if(result)
+ return result;
+ }
+#endif /* USE_SSL */
+ ctx->state = CF_SETUP_CNNCT_SSL;
+ if(!cf->next || !cf->next->connected)
+ goto connect_sub_chain;
+ }
+
+ ctx->state = CF_SETUP_DONE;
+ cf->connected = TRUE;
+ *done = TRUE;
+ return CURLE_OK;
+}
+
+static void cf_setup_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_setup_ctx *ctx = cf->ctx;
+
+ DEBUGF(LOG_CF(data, cf, "close"));
+ cf->connected = FALSE;
+ ctx->state = CF_SETUP_INIT;
+
+ if(cf->next) {
+ cf->next->cft->do_close(cf->next, data);
+ Curl_conn_cf_discard_chain(&cf->next, data);
+ }
+}
+
+static void cf_setup_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_setup_ctx *ctx = cf->ctx;
+
+ (void)data;
+ DEBUGF(LOG_CF(data, cf, "destroy"));
+ Curl_safefree(ctx);
+}
+
+
+struct Curl_cftype Curl_cft_setup = {
+ "SETUP",
+ 0,
+ CURL_LOG_DEFAULT,
+ cf_setup_destroy,
+ cf_setup_connect,
+ cf_setup_close,
+ Curl_cf_def_get_host,
+ Curl_cf_def_get_select_socks,
+ Curl_cf_def_data_pending,
+ Curl_cf_def_send,
+ Curl_cf_def_recv,
+ Curl_cf_def_cntrl,
+ Curl_cf_def_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ Curl_cf_def_query,
+};
+
+static CURLcode cf_setup_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ const struct Curl_dns_entry *remotehost,
+ int transport,
+ int ssl_mode)
+{
+ struct Curl_cfilter *cf = NULL;
+ struct cf_setup_ctx *ctx;
+ CURLcode result = CURLE_OK;
+
+ (void)data;
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ ctx->state = CF_SETUP_INIT;
+ ctx->remotehost = remotehost;
+ ctx->ssl_mode = ssl_mode;
+ ctx->transport = transport;
+
+ result = Curl_cf_create(&cf, &Curl_cft_setup, ctx);
+ if(result)
+ goto out;
+ ctx = NULL;
+
+out:
+ *pcf = result? NULL : cf;
+ free(ctx);
+ return result;
+}
+
+static CURLcode cf_setup_add(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
+ const struct Curl_dns_entry *remotehost,
+ int transport,
+ int ssl_mode)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result = CURLE_OK;
+
+ DEBUGASSERT(data);
+ result = cf_setup_create(&cf, data, remotehost, transport, ssl_mode);
+ if(result)
+ goto out;
+ Curl_conn_cf_add(data, conn, sockindex, cf);
+out:
+ return result;
+}
+
+#ifdef DEBUGBUILD
+/* used by unit2600.c */
+void Curl_debug_set_transport_provider(int transport,
+ cf_ip_connect_create *cf_create)
+{
+ size_t i;
+ for(i = 0; i < ARRAYSIZE(transport_providers); ++i) {
+ if(transport == transport_providers[i].transport) {
+ transport_providers[i].cf_create = cf_create;
+ return;
+ }
+ }
+}
+#endif /* DEBUGBUILD */
+
+CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data,
+ const struct Curl_dns_entry *remotehost,
+ int transport,
+ int ssl_mode)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result;
+
+ DEBUGASSERT(data);
+ result = cf_setup_create(&cf, data, remotehost, transport, ssl_mode);
+ if(result)
+ goto out;
+ Curl_conn_cf_insert_after(cf_at, cf);
+out:
+ return result;
+}
+
+CURLcode Curl_conn_setup(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
+ const struct Curl_dns_entry *remotehost,
+ int ssl_mode)
+{
+ CURLcode result = CURLE_OK;
+
+ DEBUGASSERT(data);
+ DEBUGASSERT(conn->handler);
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
+ if(!conn->cfilter[sockindex] &&
+ conn->handler->protocol == CURLPROTO_HTTPS) {
+ DEBUGASSERT(ssl_mode != CURL_CF_SSL_DISABLE);
+ result = Curl_cf_https_setup(data, conn, sockindex, remotehost);
+ if(result)
+ goto out;
+ }
+#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */
+
+ /* Still no cfilter set, apply default. */
+ if(!conn->cfilter[sockindex]) {
+ result = cf_setup_add(data, conn, sockindex, remotehost,
+ conn->transport, ssl_mode);
+ if(result)
+ goto out;
+ }
+
+ DEBUGASSERT(conn->cfilter[sockindex]);
+out:
+ return result;
+}
+
diff --git a/lib/connect.h b/lib/connect.h
index 582ff08..58264bd 100644
--- a/lib/connect.h
+++ b/lib/connect.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,14 +29,7 @@
#include "sockaddr.h"
#include "timeval.h"
-CURLcode Curl_is_connected(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
- bool *connected);
-
-CURLcode Curl_connecthost(struct Curl_easy *data,
- struct connectdata *conn,
- const struct Curl_dns_entry *host);
+struct Curl_dns_entry;
/* generic function that returns how much time there's left to run, according
to the timeouts set */
@@ -58,67 +51,8 @@
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
char *addr, int *port);
-/*
- * Check if a connection seems to be alive.
- */
-bool Curl_connalive(struct connectdata *conn);
-
-#ifdef USE_WINSOCK
-/* When you run a program that uses the Windows Sockets API, you may
- experience slow performance when you copy data to a TCP server.
-
- https://support.microsoft.com/kb/823764
-
- Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
- Buffer Size
-
-*/
-void Curl_sndbufset(curl_socket_t sockfd);
-#else
-#define Curl_sndbufset(y) Curl_nop_stmt
-#endif
-
-void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
- curl_socket_t sockfd);
-void Curl_conninfo_remote(struct Curl_easy *data, struct connectdata *conn,
- curl_socket_t sockfd);
-void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd,
- char *local_ip, int *local_port);
void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
char *local_ip, int local_port);
-int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn,
- curl_socket_t sock);
-
-/*
- * The Curl_sockaddr_ex structure is basically libcurl's external API
- * curl_sockaddr structure with enough space available to directly hold any
- * protocol-specific address structures. The variable declared here will be
- * used to pass / receive data to/from the fopensocket callback if this has
- * been set, before that, it is initialized from parameters.
- */
-struct Curl_sockaddr_ex {
- int family;
- int socktype;
- int protocol;
- unsigned int addrlen;
- union {
- struct sockaddr addr;
- struct Curl_sockaddr_storage buff;
- } _sa_ex_u;
-};
-#define sa_addr _sa_ex_u.addr
-
-/*
- * Create a socket based on info from 'conn' and 'ai'.
- *
- * Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open
- * socket callback is set, used that!
- *
- */
-CURLcode Curl_socket(struct Curl_easy *data,
- const struct Curl_addrinfo *ai,
- struct Curl_sockaddr_ex *addr,
- curl_socket_t *sockfd);
/*
* Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
@@ -153,6 +87,46 @@
#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP)
#endif
-bool Curl_conn_data_pending(struct connectdata *conn, int sockindex);
+/**
+ * Create a cfilter for making an "ip" connection to the
+ * given address, using parameters from `conn`. The "ip" connection
+ * can be a TCP socket, a UDP socket or even a QUIC connection.
+ *
+ * It MUST use only the supplied `ai` for its connection attempt.
+ *
+ * Such a filter may be used in "happy eyeball" scenarios, and its
+ * `connect` implementation needs to support non-blocking. Once connected,
+ * it MAY be installed in the connection filter chain to serve transfers.
+ */
+typedef CURLcode cf_ip_connect_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai,
+ int transport);
+
+CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data,
+ const struct Curl_dns_entry *remotehost,
+ int transport,
+ int ssl_mode);
+
+/**
+ * Setup the cfilters at `sockindex` in connection `conn`.
+ * If no filter chain is installed yet, inspects the configuration
+ * in `data` and `conn? to install a suitable filter chain.
+ */
+CURLcode Curl_conn_setup(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
+ const struct Curl_dns_entry *remotehost,
+ int ssl_mode);
+
+extern struct Curl_cftype Curl_cft_happy_eyeballs;
+extern struct Curl_cftype Curl_cft_setup;
+
+#ifdef DEBUGBUILD
+void Curl_debug_set_transport_provider(int transport,
+ cf_ip_connect_create *cf_create);
+#endif
#endif /* HEADER_CURL_CONNECT_H */
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index 95ba48a..efbe7cb 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,12 +28,20 @@
#include <curl/curl.h>
#include <stddef.h>
-#ifdef HAVE_ZLIB_H
+#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
#ifdef HAVE_BROTLI
+#if defined(__GNUC__)
+/* Ignore -Wvla warnings in brotli headers */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wvla"
+#endif
#include <brotli/decode.h>
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
#endif
#ifdef HAVE_ZSTD
@@ -45,6 +53,9 @@
#include "content_encoding.h"
#include "strdup.h"
#include "strcase.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
@@ -82,8 +93,9 @@
ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
} zlibInitState;
-/* Writer parameters. */
-struct zlib_params {
+/* Deflate and gzip writer. */
+struct zlib_writer {
+ struct contenc_writer super;
zlibInitState zlib_init; /* zlib init state */
uInt trailerlen; /* Remaining trailer byte count. */
z_stream z; /* State structure for zlib. */
@@ -135,7 +147,7 @@
}
static CURLcode process_trailer(struct Curl_easy *data,
- struct zlib_params *zp)
+ struct zlib_writer *zp)
{
z_stream *z = &zp->z;
CURLcode result = CURLE_OK;
@@ -162,7 +174,7 @@
struct contenc_writer *writer,
zlibInitState started)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
uInt nread = z->avail_in;
Bytef *orig_in = z->next_in;
@@ -265,7 +277,7 @@
static CURLcode deflate_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
if(!writer->downstream)
@@ -285,7 +297,7 @@
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
/* Set the compressed input when this function is called */
@@ -302,7 +314,7 @@
static void deflate_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ 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);
@@ -314,7 +326,7 @@
deflate_init_writer,
deflate_unencode_write,
deflate_close_writer,
- sizeof(struct zlib_params)
+ sizeof(struct zlib_writer)
};
@@ -322,7 +334,7 @@
static CURLcode gzip_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
if(!writer->downstream)
@@ -439,7 +451,7 @@
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
if(zp->zlib_init == ZLIB_INIT_GZIP) {
@@ -566,7 +578,7 @@
static void gzip_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zlib_params *zp = (struct zlib_params *) &writer->params;
+ 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);
@@ -578,15 +590,16 @@
gzip_init_writer,
gzip_unencode_write,
gzip_close_writer,
- sizeof(struct zlib_params)
+ sizeof(struct zlib_writer)
};
#endif /* HAVE_LIBZ */
#ifdef HAVE_BROTLI
-/* Writer parameters. */
-struct brotli_params {
+/* Brotli writer. */
+struct brotli_writer {
+ struct contenc_writer super;
BrotliDecoderState *br; /* State structure for brotli. */
};
@@ -631,7 +644,7 @@
static CURLcode brotli_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct brotli_params *bp = (struct brotli_params *) &writer->params;
+ struct brotli_writer *bp = (struct brotli_writer *) writer;
(void) data;
if(!writer->downstream)
@@ -645,7 +658,7 @@
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- struct brotli_params *bp = (struct brotli_params *) &writer->params;
+ struct brotli_writer *bp = (struct brotli_writer *) writer;
const uint8_t *src = (const uint8_t *) buf;
char *decomp;
uint8_t *dst;
@@ -692,7 +705,8 @@
static void brotli_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct brotli_params *bp = (struct brotli_params *) &writer->params;
+ struct brotli_writer *bp = (struct brotli_writer *) writer;
+
(void) data;
if(bp->br) {
@@ -707,14 +721,15 @@
brotli_init_writer,
brotli_unencode_write,
brotli_close_writer,
- sizeof(struct brotli_params)
+ sizeof(struct brotli_writer)
};
#endif
#ifdef HAVE_ZSTD
-/* Writer parameters. */
-struct zstd_params {
+/* Zstd writer. */
+struct zstd_writer {
+ struct contenc_writer super;
ZSTD_DStream *zds; /* State structure for zstd. */
void *decomp;
};
@@ -722,7 +737,8 @@
static CURLcode zstd_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zstd_params *zp = (struct zstd_params *)&writer->params;
+ struct zstd_writer *zp = (struct zstd_writer *) writer;
+
(void)data;
if(!writer->downstream)
@@ -738,7 +754,7 @@
const char *buf, size_t nbytes)
{
CURLcode result = CURLE_OK;
- struct zstd_params *zp = (struct zstd_params *)&writer->params;
+ struct zstd_writer *zp = (struct zstd_writer *) writer;
ZSTD_inBuffer in;
ZSTD_outBuffer out;
size_t errorCode;
@@ -777,7 +793,8 @@
static void zstd_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- struct zstd_params *zp = (struct zstd_params *)&writer->params;
+ struct zstd_writer *zp = (struct zstd_writer *) writer;
+
(void)data;
if(zp->decomp) {
@@ -796,7 +813,7 @@
zstd_init_writer,
zstd_unencode_write,
zstd_close_writer,
- sizeof(struct zstd_params)
+ sizeof(struct zstd_writer)
};
#endif
@@ -829,7 +846,7 @@
identity_init_writer,
identity_unencode_write,
identity_close_writer,
- 0
+ sizeof(struct contenc_writer)
};
@@ -921,7 +938,7 @@
client_init_writer,
client_unencode_write,
client_close_writer,
- 0
+ sizeof(struct contenc_writer)
};
@@ -964,21 +981,25 @@
error_init_writer,
error_unencode_write,
error_close_writer,
- 0
+ sizeof(struct contenc_writer)
};
/* Create an unencoding writer stage using the given handler. */
static struct contenc_writer *
new_unencoding_writer(struct Curl_easy *data,
const struct content_encoding *handler,
- struct contenc_writer *downstream)
+ struct contenc_writer *downstream,
+ int order)
{
- size_t sz = offsetof(struct contenc_writer, params) + handler->paramsize;
- struct contenc_writer *writer = (struct contenc_writer *)calloc(1, sz);
+ struct contenc_writer *writer;
+
+ DEBUGASSERT(handler->writersize >= sizeof(struct contenc_writer));
+ writer = (struct contenc_writer *) calloc(1, handler->writersize);
if(writer) {
writer->handler = handler;
writer->downstream = downstream;
+ writer->order = order;
if(handler->init_writer(data, writer)) {
free(writer);
writer = NULL;
@@ -1034,17 +1055,17 @@
/* Set-up the unencoding stack from the Content-Encoding header value.
* See RFC 7231 section 3.1.2.2. */
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
- const char *enclist, int maybechunked)
+ const char *enclist, int is_transfer)
{
struct SingleRequest *k = &data->req;
- int counter = 0;
+ unsigned int order = is_transfer? 2: 1;
do {
const char *name;
size_t namelen;
/* Parse a single encoding name. */
- while(ISSPACE(*enclist) || *enclist == ',')
+ while(ISBLANK(*enclist) || *enclist == ',')
enclist++;
name = enclist;
@@ -1054,16 +1075,21 @@
namelen = enclist - name + 1;
/* Special case: chunked encoding is handled at the reader level. */
- if(maybechunked && namelen == 7 && strncasecompare(name, "chunked", 7)) {
+ if(is_transfer && namelen == 7 && strncasecompare(name, "chunked", 7)) {
k->chunk = TRUE; /* chunks coming our way. */
Curl_httpchunk_init(data); /* init our chunky engine. */
}
else if(namelen) {
- const struct content_encoding *encoding = find_encoding(name, namelen);
+ const struct content_encoding *encoding;
struct contenc_writer *writer;
+ if(is_transfer && !data->set.http_transfer_encoding)
+ /* not requested, ignore */
+ return CURLE_OK;
+ encoding = find_encoding(name, namelen);
if(!k->writer_stack) {
- k->writer_stack = new_unencoding_writer(data, &client_encoding, NULL);
+ k->writer_stack = new_unencoding_writer(data, &client_encoding,
+ NULL, 0);
if(!k->writer_stack)
return CURLE_OUT_OF_MEMORY;
@@ -1072,16 +1098,29 @@
if(!encoding)
encoding = &error_encoding; /* Defer error at stack use. */
- if(++counter >= MAX_ENCODE_STACK) {
- failf(data, "Reject response due to %u content encodings",
- counter);
+ if(k->writer_stack_depth++ >= MAX_ENCODE_STACK) {
+ failf(data, "Reject response due to more than %u content encodings",
+ MAX_ENCODE_STACK);
return CURLE_BAD_CONTENT_ENCODING;
}
/* Stack the unencoding stage. */
- writer = new_unencoding_writer(data, encoding, k->writer_stack);
- if(!writer)
- return CURLE_OUT_OF_MEMORY;
- k->writer_stack = writer;
+ if(order >= k->writer_stack->order) {
+ writer = new_unencoding_writer(data, encoding,
+ k->writer_stack, order);
+ if(!writer)
+ return CURLE_OUT_OF_MEMORY;
+ k->writer_stack = writer;
+ }
+ else {
+ struct contenc_writer *w = k->writer_stack;
+ while(w->downstream && order < w->downstream->order)
+ w = w->downstream;
+ writer = new_unencoding_writer(data, encoding,
+ w->downstream, order);
+ if(!writer)
+ return CURLE_OUT_OF_MEMORY;
+ w->downstream = writer;
+ }
}
} while(*enclist);
@@ -1091,11 +1130,11 @@
#else
/* Stubs for builds without HTTP. */
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
- const char *enclist, int maybechunked)
+ const char *enclist, int is_transfer)
{
(void) data;
(void) enclist;
- (void) maybechunked;
+ (void) is_transfer;
return CURLE_NOT_BUILT_IN;
}
diff --git a/lib/content_encoding.h b/lib/content_encoding.h
index 81bddd1..56e7f97 100644
--- a/lib/content_encoding.h
+++ b/lib/content_encoding.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,7 +28,7 @@
struct contenc_writer {
const struct content_encoding *handler; /* Encoding handler. */
struct contenc_writer *downstream; /* Downstream writer. */
- void *params; /* Encoding-specific storage (variable length). */
+ unsigned int order; /* Ordering within writer stack. */
};
/* Content encoding writer. */
@@ -42,12 +42,12 @@
const char *buf, size_t nbytes);
void (*close_writer)(struct Curl_easy *data,
struct contenc_writer *writer);
- size_t paramsize;
+ size_t writersize;
};
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
- const char *enclist, int maybechunked);
+ const char *enclist, int is_transfer);
CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes);
diff --git a/lib/cookie.c b/lib/cookie.c
index cb57b86..4345a84 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -101,13 +101,14 @@
#include "parsedate.h"
#include "rename.h"
#include "fopen.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-static void strstore(char **str, const char *newstr);
+static void strstore(char **str, const char *newstr, size_t len);
static void freecookie(struct Cookie *co)
{
@@ -122,15 +123,18 @@
free(co);
}
-static bool tailmatch(const char *cooke_domain, const char *hostname)
+static bool cookie_tailmatch(const char *cookie_domain,
+ size_t cookie_domain_len,
+ const char *hostname)
{
- size_t cookie_domain_len = strlen(cooke_domain);
size_t hostname_len = strlen(hostname);
if(hostname_len < cookie_domain_len)
return FALSE;
- if(!strcasecompare(cooke_domain, hostname + hostname_len-cookie_domain_len))
+ if(!strncasecompare(cookie_domain,
+ hostname + hostname_len-cookie_domain_len,
+ cookie_domain_len))
return FALSE;
/*
@@ -176,7 +180,7 @@
/* #-fragments are already cut off! */
if(0 == strlen(uri_path) || uri_path[0] != '/') {
- strstore(&uri_path, "/");
+ strstore(&uri_path, "/", 1);
if(!uri_path)
return FALSE;
}
@@ -300,18 +304,17 @@
/* some stupid site sends path attribute with '"'. */
len = strlen(new_path);
if(new_path[0] == '\"') {
- memmove((void *)new_path, (const void *)(new_path + 1), len);
+ memmove(new_path, new_path + 1, len);
len--;
}
if(len && (new_path[len - 1] == '\"')) {
- new_path[len - 1] = 0x0;
- len--;
+ new_path[--len] = 0x0;
}
/* RFC6265 5.2.4 The Path Attribute */
if(new_path[0] != '/') {
/* Let cookie-path be the default-path. */
- strstore(&new_path, "/");
+ strstore(&new_path, "/", 1);
return new_path;
}
@@ -330,14 +333,13 @@
*/
void Curl_cookie_loadfiles(struct Curl_easy *data)
{
- struct curl_slist *list = data->state.cookielist;
+ struct curl_slist *list = data->set.cookielist;
if(list) {
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
while(list) {
- struct CookieInfo *newcookies = Curl_cookie_init(data,
- list->data,
- data->cookies,
- data->set.cookiesession);
+ struct CookieInfo *newcookies =
+ Curl_cookie_init(data, list->data, data->cookies,
+ data->set.cookiesession);
if(!newcookies)
/*
* Failure may be due to OOM or a bad cookie; both are ignored
@@ -348,8 +350,6 @@
data->cookies = newcookies;
list = list->next;
}
- curl_slist_free_all(data->state.cookielist); /* clean up list */
- data->state.cookielist = NULL; /* don't do this again! */
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
}
@@ -363,10 +363,14 @@
* parsing in a last-wins scenario. The caller is responsible for checking
* for OOM errors.
*/
-static void strstore(char **str, const char *newstr)
+static void strstore(char **str, const char *newstr, size_t len)
{
+ DEBUGASSERT(newstr);
+ DEBUGASSERT(str);
free(*str);
- *str = strdup(newstr);
+ *str = Curl_memdup(newstr, len + 1);
+ if(*str)
+ (*str)[len] = 0;
}
/*
@@ -428,20 +432,47 @@
}
/* Make sure domain contains a dot or is localhost. */
-static bool bad_domain(const char *domain)
+static bool bad_domain(const char *domain, size_t len)
{
- if(strcasecompare(domain, "localhost"))
+ if((len == 9) && strncasecompare(domain, "localhost", 9))
return FALSE;
else {
/* there must be a dot present, but that dot must not be a trailing dot */
- char *dot = strchr(domain, '.');
- if(dot)
- return dot[1] ? FALSE : TRUE;
+ char *dot = memchr(domain, '.', len);
+ if(dot) {
+ size_t i = dot - domain;
+ if((len - i) > 1)
+ /* the dot is not the last byte */
+ return FALSE;
+ }
}
return TRUE;
}
/*
+ RFC 6265 section 4.1.1 says a server should accept this range:
+
+ cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
+
+ But Firefox and Chrome as of June 2022 accept space, comma and double-quotes
+ fine. The prime reason for filtering out control bytes is that some HTTP
+ servers return 400 for requests that contain such.
+*/
+static int invalid_octets(const char *p)
+{
+ /* Reject all bytes \x01 - \x1f (*except* \x09, TAB) + \x7f */
+ static const char badoctets[] = {
+ "\x01\x02\x03\x04\x05\x06\x07\x08\x0a"
+ "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
+ "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f"
+ };
+ size_t len;
+ /* scan for all the octets that are *not* in cookie-octet */
+ len = strcspn(p, badoctets);
+ return (p[len] != '\0');
+}
+
+/*
* Curl_cookie_add
*
* Add a single cookie line to the cookie keeping object. Be aware that
@@ -453,11 +484,6 @@
*/
struct Cookie *
Curl_cookie_add(struct Curl_easy *data,
- /*
- * The 'data' pointer here may be NULL at times, and thus
- * must only be used very carefully for things that can deal
- * with data being NULL. Such as infof() and similar
- */
struct CookieInfo *c,
bool httpheader, /* TRUE if HTTP header-style line */
bool noexpire, /* if TRUE, skip remove_expired() */
@@ -478,10 +504,7 @@
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
size_t myhash;
-#ifdef CURL_DISABLE_VERBOSE_STRINGS
- (void)data;
-#endif
-
+ DEBUGASSERT(data);
DEBUGASSERT(MAX_SET_COOKIE_AMOUNT <= 255); /* counter is an unsigned char */
if(data->req.setcookies >= MAX_SET_COOKIE_AMOUNT)
return NULL;
@@ -492,11 +515,8 @@
return NULL; /* bail out if we're this low on memory */
if(httpheader) {
- /* This line was read off a HTTP-header */
- char name[MAX_NAME];
- char what[MAX_NAME];
+ /* This line was read off an HTTP-header */
const char *ptr;
- const char *semiptr;
size_t linelength = strlen(lineptr);
if(linelength > MAX_COOKIE_LINE) {
@@ -505,82 +525,88 @@
return NULL;
}
- semiptr = strchr(lineptr, ';'); /* first, find a semicolon */
-
- while(*lineptr && ISBLANK(*lineptr))
- lineptr++;
-
ptr = lineptr;
do {
- /* we have a <what>=<this> pair or a stand-alone word here */
- name[0] = what[0] = 0; /* init the buffers */
- if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%"
- MAX_NAME_TXT "[^;\r\n]",
- name, what)) {
- /*
- * Use strstore() below to properly deal with received cookie
- * headers that have the same string property set more than once,
- * and then we use the last one.
- */
- const char *whatptr;
+ size_t vlen;
+ size_t nlen;
+
+ while(*ptr && ISBLANK(*ptr))
+ ptr++;
+
+ /* we have a <name>=<value> pair or a stand-alone word here */
+ nlen = strcspn(ptr, ";\t\r\n=");
+ if(nlen) {
bool done = FALSE;
- bool sep;
- size_t len = strlen(what);
- size_t nlen = strlen(name);
- const char *endofn = &ptr[ nlen ];
+ bool sep = FALSE;
+ const char *namep = ptr;
+ const char *valuep;
+
+ ptr += nlen;
+
+ /* trim trailing spaces and tabs after name */
+ while(nlen && ISBLANK(namep[nlen - 1]))
+ nlen--;
+
+ if(*ptr == '=') {
+ vlen = strcspn(++ptr, ";\r\n");
+ valuep = ptr;
+ sep = TRUE;
+ ptr = &valuep[vlen];
+
+ /* Strip off trailing whitespace from the value */
+ while(vlen && ISBLANK(valuep[vlen-1]))
+ vlen--;
+
+ /* Skip leading whitespace from the value */
+ while(vlen && ISBLANK(*valuep)) {
+ valuep++;
+ vlen--;
+ }
+
+ /* Reject cookies with a TAB inside the value */
+ if(memchr(valuep, '\t', vlen)) {
+ freecookie(co);
+ infof(data, "cookie contains TAB, dropping");
+ return NULL;
+ }
+ }
+ else {
+ valuep = NULL;
+ vlen = 0;
+ }
/*
* 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(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) ||
- ((nlen + len) > MAX_NAME)) {
+ if(nlen >= (MAX_NAME-1) || vlen >= (MAX_NAME-1) ||
+ ((nlen + vlen) > MAX_NAME)) {
freecookie(co);
infof(data, "oversized cookie dropped, name/val %zu + %zu bytes",
- nlen, len);
+ nlen, vlen);
return NULL;
}
- /* name ends with a '=' ? */
- sep = (*endofn == '=')?TRUE:FALSE;
-
- if(nlen) {
- endofn--; /* move to the last character */
- if(ISBLANK(*endofn)) {
- /* skip trailing spaces in name */
- while(*endofn && ISBLANK(*endofn) && nlen) {
- endofn--;
- nlen--;
- }
- name[nlen] = 0; /* new end of name */
- }
- }
-
- /* Strip off trailing whitespace from the 'what' */
- while(len && ISBLANK(what[len-1])) {
- what[len-1] = 0;
- len--;
- }
-
- /* Skip leading whitespace from the 'what' */
- whatptr = what;
- while(*whatptr && ISBLANK(*whatptr))
- whatptr++;
-
/*
* 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(nlen > 3 && name[0] == '_' && name[1] == '_') {
- if(!strncmp("__Secure-", name, 9))
+ if(nlen >= 7 && namep[0] == '_' && namep[1] == '_') {
+ if(strncasecompare("__Secure-", namep, 9))
co->prefix |= COOKIE_PREFIX__SECURE;
- else if(!strncmp("__Host-", name, 7))
+ else if(strncasecompare("__Host-", namep, 7))
co->prefix |= COOKIE_PREFIX__HOST;
}
+ /*
+ * 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.
+ */
+
if(!co->name) {
/* The very first name/value pair is the actual cookie name */
if(!sep) {
@@ -588,15 +614,20 @@
badcookie = TRUE;
break;
}
- co->name = strdup(name);
- co->value = strdup(whatptr);
+ strstore(&co->name, namep, nlen);
+ strstore(&co->value, valuep, vlen);
done = TRUE;
if(!co->name || !co->value) {
badcookie = TRUE;
break;
}
+ if(invalid_octets(co->value) || invalid_octets(co->name)) {
+ infof(data, "invalid octets in name/value, cookie dropped");
+ badcookie = TRUE;
+ break;
+ }
}
- else if(!len) {
+ else if(!vlen) {
/*
* this was a "<name>=" with no content, and we must allow
* 'secure' and 'httponly' specified this weirdly
@@ -607,7 +638,7 @@
* using a secure protocol, or when the cookie is being set by
* reading from file
*/
- if(strcasecompare("secure", name)) {
+ if((nlen == 6) && strncasecompare("secure", namep, 6)) {
if(secure || !c->running) {
co->secure = TRUE;
}
@@ -616,7 +647,7 @@
break;
}
}
- else if(strcasecompare("httponly", name))
+ else if((nlen == 8) && strncasecompare("httponly", namep, 8))
co->httponly = TRUE;
else if(sep)
/* there was a '=' so we're not done parsing this field */
@@ -624,8 +655,8 @@
}
if(done)
;
- else if(strcasecompare("path", name)) {
- strstore(&co->path, whatptr);
+ else if((nlen == 4) && strncasecompare("path", namep, 4)) {
+ strstore(&co->path, valuep, vlen);
if(!co->path) {
badcookie = TRUE; /* out of memory bad */
break;
@@ -637,7 +668,8 @@
break;
}
}
- else if(strcasecompare("domain", name)) {
+ else if((nlen == 6) &&
+ strncasecompare("domain", namep, 6) && vlen) {
bool is_ip;
/*
@@ -645,8 +677,10 @@
* the given domain is not valid and thus cannot be set.
*/
- if('.' == whatptr[0])
- whatptr++; /* ignore preceding dot */
+ if('.' == valuep[0]) {
+ valuep++; /* ignore preceding dot */
+ vlen--;
+ }
#ifndef USE_LIBPSL
/*
@@ -654,16 +688,17 @@
* TLD or otherwise "protected" suffix. To reduce risk, we require a
* dot OR the exact host name being "localhost".
*/
- if(bad_domain(whatptr))
+ if(bad_domain(valuep, vlen))
domain = ":";
#endif
- is_ip = Curl_host_is_ipnum(domain ? domain : whatptr);
+ is_ip = Curl_host_is_ipnum(domain ? domain : valuep);
if(!domain
- || (is_ip && !strcmp(whatptr, domain))
- || (!is_ip && tailmatch(whatptr, domain))) {
- strstore(&co->domain, whatptr);
+ || (is_ip && !strncmp(valuep, domain, vlen) &&
+ (vlen == strlen(domain)))
+ || (!is_ip && cookie_tailmatch(valuep, vlen, domain))) {
+ strstore(&co->domain, valuep, vlen);
if(!co->domain) {
badcookie = TRUE;
break;
@@ -679,17 +714,17 @@
*/
badcookie = TRUE;
infof(data, "skipped cookie with bad tailmatch domain: %s",
- whatptr);
+ valuep);
}
}
- else if(strcasecompare("version", name)) {
- strstore(&co->version, whatptr);
+ else if((nlen == 7) && strncasecompare("version", namep, 7)) {
+ strstore(&co->version, valuep, vlen);
if(!co->version) {
badcookie = TRUE;
break;
}
}
- else if(strcasecompare("max-age", name)) {
+ else if((nlen == 7) && strncasecompare("max-age", namep, 7)) {
/*
* Defined in RFC2109:
*
@@ -699,14 +734,14 @@
* client should discard the cookie. A value of zero means the
* cookie should be discarded immediately.
*/
- strstore(&co->maxage, whatptr);
+ strstore(&co->maxage, valuep, vlen);
if(!co->maxage) {
badcookie = TRUE;
break;
}
}
- else if(strcasecompare("expires", name)) {
- strstore(&co->expirestr, whatptr);
+ else if((nlen == 7) && strncasecompare("expires", namep, 7)) {
+ strstore(&co->expirestr, valuep, vlen);
if(!co->expirestr) {
badcookie = TRUE;
break;
@@ -721,34 +756,29 @@
/* this is an "illegal" <what>=<this> pair */
}
- if(!semiptr || !*semiptr) {
- /* we already know there are no more cookies */
- semiptr = NULL;
- continue;
- }
-
- ptr = semiptr + 1;
while(*ptr && ISBLANK(*ptr))
ptr++;
- semiptr = strchr(ptr, ';'); /* now, find the next semicolon */
-
- if(!semiptr && *ptr)
- /*
- * There are no more semicolons, but there's a final name=value pair
- * coming up
- */
- semiptr = strchr(ptr, '\0');
- } while(semiptr);
+ if(*ptr == ';')
+ ptr++;
+ else
+ break;
+ } while(1);
if(co->maxage) {
CURLofft offt;
offt = curlx_strtoofft((*co->maxage == '\"')?
&co->maxage[1]:&co->maxage[0], NULL, 10,
&co->expires);
- if(offt == CURL_OFFT_FLOW)
+ switch(offt) {
+ case CURL_OFFT_FLOW:
/* overflow, used max value */
co->expires = CURL_OFF_T_MAX;
- else if(!offt) {
+ break;
+ case CURL_OFFT_INVAL:
+ /* negative or otherwise bad, expire */
+ co->expires = 1;
+ break;
+ case CURL_OFFT_OK:
if(!co->expires)
/* already expired */
co->expires = 1;
@@ -757,6 +787,7 @@
co->expires = CURL_OFF_T_MAX;
else
co->expires += now;
+ break;
}
}
else if(co->expirestr) {
@@ -829,7 +860,7 @@
}
else {
/*
- * This line is NOT a HTTP header style line, we do offer support for
+ * This line is NOT an HTTP header style line, we do offer support for
* reading the odd netscape cookies-file format here
*/
char *ptr;
@@ -1018,7 +1049,7 @@
Curl_psl_release(data);
}
else
- acceptable = !bad_domain(domain);
+ acceptable = !bad_domain(domain, strlen(domain));
if(!acceptable) {
infof(data, "cookie '%s' dropped, domain '%s' must not "
@@ -1089,17 +1120,11 @@
if(replace_old) {
/* the domains were identical */
- if(clist->spath && co->spath) {
- if(strcasecompare(clist->spath, co->spath))
- replace_old = TRUE;
- else
- replace_old = FALSE;
- }
- else if(!clist->spath && !co->spath)
- replace_old = TRUE;
- else
+ if(clist->spath && co->spath &&
+ !strcasecompare(clist->spath, co->spath))
replace_old = FALSE;
-
+ else if(!clist->spath != !co->spath)
+ replace_old = FALSE;
}
if(replace_old && !co->livecookie && clist->livecookie) {
@@ -1180,7 +1205,8 @@
*
* If 'newsession' is TRUE, discard all "session cookies" on read from file.
*
- * Note that 'data' might be called as NULL pointer.
+ * 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.
*/
@@ -1190,9 +1216,8 @@
bool newsession)
{
struct CookieInfo *c;
- FILE *fp = NULL;
- bool fromfile = TRUE;
char *line = NULL;
+ FILE *handle = NULL;
if(!inc) {
/* we didn't get a struct, create one */
@@ -1212,61 +1237,59 @@
/* we got an already existing one, use that */
c = inc;
}
- c->running = FALSE; /* this is not running, this is init */
-
- if(file && !strcmp(file, "-")) {
- fp = stdin;
- fromfile = FALSE;
- }
- else if(!file || !*file) {
- /* points to an empty string or NULL */
- fp = NULL;
- }
- else {
- fp = fopen(file, FOPEN_READTEXT);
- if(!fp)
- infof(data, "WARNING: failed to open cookie file \"%s\"", file);
- }
-
c->newsession = newsession; /* new session? */
- if(fp) {
- char *lineptr;
- bool headerline;
-
- line = malloc(MAX_COOKIE_LINE);
- if(!line)
- goto fail;
- while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) {
- if(checkprefix("Set-Cookie:", line)) {
- /* This is a cookie line, get it! */
- lineptr = &line[11];
- headerline = TRUE;
- }
+ if(data) {
+ FILE *fp = NULL;
+ if(file) {
+ if(!strcmp(file, "-"))
+ fp = stdin;
else {
- lineptr = line;
- headerline = FALSE;
+ fp = fopen(file, "rb");
+ if(!fp)
+ infof(data, "WARNING: failed to open cookie file \"%s\"", file);
+ else
+ handle = fp;
}
- while(*lineptr && ISBLANK(*lineptr))
- lineptr++;
-
- Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
}
- free(line); /* 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(c);
+ c->running = FALSE; /* this is not running, this is init */
+ if(fp) {
+ char *lineptr;
+ bool headerline;
- if(fromfile && fp)
- fclose(fp);
- }
+ line = malloc(MAX_COOKIE_LINE);
+ if(!line)
+ goto fail;
+ while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) {
+ if(checkprefix("Set-Cookie:", line)) {
+ /* This is a cookie line, get it! */
+ lineptr = &line[11];
+ headerline = TRUE;
+ }
+ else {
+ lineptr = line;
+ headerline = FALSE;
+ }
+ while(*lineptr && ISBLANK(*lineptr))
+ lineptr++;
- c->running = TRUE; /* now, we're running */
- if(data)
+ Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
+ }
+ free(line); /* 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(c);
+
+ if(handle)
+ fclose(handle);
+ }
data->state.cookie_engine = TRUE;
+ c->running = TRUE; /* now, we're running */
+ }
return c;
@@ -1278,8 +1301,8 @@
*/
if(!inc)
Curl_cookie_cleanup(c);
- if(fromfile && fp)
- fclose(fp);
+ if(handle)
+ fclose(handle);
return NULL; /* out of memory */
}
@@ -1365,7 +1388,7 @@
}
return d;
- fail:
+fail:
freecookie(d);
return NULL;
}
@@ -1408,7 +1431,8 @@
/* now check if the domain is correct */
if(!co->domain ||
- (co->tailmatch && !is_ip && tailmatch(co->domain, host)) ||
+ (co->tailmatch && !is_ip &&
+ cookie_tailmatch(co->domain, strlen(co->domain), host)) ||
((!co->tailmatch || is_ip) && strcasecompare(host, co->domain)) ) {
/*
* the right part of the host matches the domain stuff in the
@@ -1436,7 +1460,7 @@
matches++;
if(matches >= MAX_COOKIE_SEND_AMOUNT) {
- infof(data, "Included max number of cookies (%u) in request!",
+ infof(data, "Included max number of cookies (%zu) in request!",
matches);
break;
}
@@ -1698,7 +1722,7 @@
}
/*
- * If we reach here we have successfully written a cookie file so theree is
+ * If we reach here we have successfully written a cookie file so there is
* no need to inspect the error, any error case should have jumped into the
* error block below.
*/
@@ -1759,13 +1783,6 @@
CURLcode res;
if(data->set.str[STRING_COOKIEJAR]) {
- if(data->state.cookielist) {
- /* If there is a list of cookie files to read, do it first so that
- we have all the told files read before we write the new jar.
- Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */
- Curl_cookie_loadfiles(data);
- }
-
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
/* if we have a destination file for all the cookies to get dumped to */
@@ -1775,12 +1792,6 @@
data->set.str[STRING_COOKIEJAR], curl_easy_strerror(res));
}
else {
- if(cleanup && data->state.cookielist) {
- /* since nothing is written, we can just free the list of cookie file
- names */
- curl_slist_free_all(data->state.cookielist); /* clean up list */
- data->state.cookielist = NULL;
- }
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
}
diff --git a/lib/cookie.h b/lib/cookie.h
index abc0a2e..b3c0063 100644
--- a/lib/cookie.h
+++ b/lib/cookie.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -61,7 +61,6 @@
struct CookieInfo {
/* linked list of cookies we know of */
struct Cookie *cookies[COOKIE_HASH_SIZE];
-
char *filename; /* file we read from/write to */
long numcookies; /* number of cookies in the "jar" */
bool running; /* state info, for cookie adding information */
@@ -70,23 +69,34 @@
curl_off_t next_expiration; /* the next time at which expiration happens */
};
-/* This is the maximum line length we accept for a cookie line. RFC 2109
- section 6.3 says:
+/* The maximum sizes we accept for cookies. RFC 6265 section 6.1 says
+ "general-use user agents SHOULD provide each of the following minimum
+ capabilities":
- "at least 4096 bytes per cookie (as measured by the size of the characters
- that comprise the cookie non-terminal in the syntax description of the
- Set-Cookie header)"
+ - At least 4096 bytes per cookie (as measured by the sum of the length of
+ the cookie's name, value, and attributes).
- We allow max 5000 bytes cookie header. Max 4095 bytes length per cookie
- name and value. Name + value may not exceed 4096 bytes.
-
+ In the 6265bis draft document section 5.4 it is phrased even stronger: "If
+ the sum of the lengths of the name string and the value string is more than
+ 4096 octets, abort these steps and ignore the set-cookie-string entirely."
*/
+
+/** Limits for INCOMING cookies **/
+
+/* The longest we allow a line to be when reading a cookie from a HTTP header
+ or from a cookie jar */
#define MAX_COOKIE_LINE 5000
/* Maximum length of an incoming cookie name or content we deal with. Longer
cookies are ignored. */
#define MAX_NAME 4096
-#define MAX_NAME_TXT "4095"
+
+/* Maximum number of Set-Cookie: lines accepted in a single response. If more
+ such header lines are received, they are ignored. This value must be less
+ than 256 since an unsigned char is used to count. */
+#define MAX_SET_COOKIE_AMOUNT 50
+
+/** Limits for OUTGOING cookies **/
/* Maximum size for an outgoing cookie line libcurl will use in an http
request. This is the default maximum length used in some versions of Apache
@@ -98,11 +108,6 @@
keep the maximum HTTP request within the maximum allowed size. */
#define MAX_COOKIE_SEND_AMOUNT 150
-/* Maximum number of Set-Cookie: lines accepted in a single response. If more
- such header lines are received, they are ignored. This value must be less
- than 256 since an unsigned char is used to count. */
-#define MAX_SET_COOKIE_AMOUNT 50
-
struct Curl_easy;
/*
* Add a cookie to the internal list of cookies. The domain and path arguments
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c
index d5d1111..f9211d3 100644
--- a/lib/curl_addrinfo.c
+++ b/lib/curl_addrinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,11 +47,6 @@
# include <inet.h>
#endif
-#if defined(NETWARE) && defined(__NOVELL_LIBC__)
-# undef in_addr_t
-# define in_addr_t unsigned long
-#endif
-
#include <stddef.h>
#include "curl_addrinfo.h"
@@ -279,7 +274,7 @@
for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) {
size_t ss_size;
- size_t namelen = strlen(he->h_name) + 1; /* include zero termination */
+ size_t namelen = strlen(he->h_name) + 1; /* include null-terminator */
#ifdef ENABLE_IPV6
if(he->h_addrtype == AF_INET6)
ss_size = sizeof(struct sockaddr_in6);
diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h
index b778121..c757c49 100644
--- a/lib/curl_addrinfo.h
+++ b/lib/curl_addrinfo.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_base64.h b/lib/curl_base64.h
index 85368a1..806d443 100644
--- a/lib/curl_base64.h
+++ b/lib/curl_base64.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index eb2c62b..2058712 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,9 +23,6 @@
***************************************************************************/
/* lib/curl_config.h.in. Generated somehow by cmake. */
-/* when building libcurl itself */
-#cmakedefine BUILDING_LIBCURL 1
-
/* Location of default ca bundle */
#cmakedefine CURL_CA_BUNDLE "${CURL_CA_BUNDLE}"
@@ -147,17 +144,14 @@
/* Define to 1 if you have the alarm function. */
#cmakedefine HAVE_ALARM 1
-/* Define to 1 if you have the <alloca.h> header file. */
-#cmakedefine HAVE_ALLOCA_H 1
-
/* Define to 1 if you have the <arpa/inet.h> header file. */
#cmakedefine HAVE_ARPA_INET_H 1
/* Define to 1 if you have the <arpa/tftp.h> header file. */
#cmakedefine HAVE_ARPA_TFTP_H 1
-/* Define to 1 if you have the <assert.h> header file. */
-#cmakedefine HAVE_ASSERT_H 1
+/* Define to 1 if you have _Atomic support. */
+#cmakedefine HAVE_ATOMIC 1
/* Define to 1 if you have the `fchmod' function. */
#cmakedefine HAVE_FCHMOD 1
@@ -177,15 +171,6 @@
/* Define to 1 if you have the `closesocket' function. */
#cmakedefine HAVE_CLOSESOCKET 1
-/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
-#cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#cmakedefine HAVE_DLFCN_H 1
-
-/* Define to 1 if you have the <errno.h> header file. */
-#cmakedefine HAVE_ERRNO_H 1
-
/* Define to 1 if you have the fcntl function. */
#cmakedefine HAVE_FCNTL 1
@@ -204,15 +189,15 @@
/* Define to 1 if you have a working getaddrinfo function. */
#cmakedefine HAVE_GETADDRINFO 1
+/* Define to 1 if the getaddrinfo function is threadsafe. */
+#cmakedefine HAVE_GETADDRINFO_THREADSAFE 1
+
/* Define to 1 if you have the `geteuid' function. */
#cmakedefine HAVE_GETEUID 1
/* Define to 1 if you have the `getppid' function. */
#cmakedefine HAVE_GETPPID 1
-/* Define to 1 if you have the gethostbyname function. */
-#cmakedefine HAVE_GETHOSTBYNAME 1
-
/* Define to 1 if you have the gethostbyname_r function. */
#cmakedefine HAVE_GETHOSTBYNAME_R 1
@@ -237,9 +222,6 @@
/* Define to 1 if you have the `getppid' function. */
#cmakedefine HAVE_GETPPID 1
-/* Define to 1 if you have the `getprotobyname' function. */
-#cmakedefine HAVE_GETPROTOBYNAME 1
-
/* Define to 1 if you have the `getpeername' function. */
#cmakedefine HAVE_GETPEERNAME 1
@@ -291,18 +273,9 @@
/* Define to 1 if you have the `idna_strerror' function. */
#cmakedefine HAVE_IDNA_STRERROR 1
-/* Define to 1 if you have the `idn_free' function. */
-#cmakedefine HAVE_IDN_FREE 1
-
-/* Define to 1 if you have the <idn-free.h> header file. */
-#cmakedefine HAVE_IDN_FREE_H 1
-
/* Define to 1 if you have the <ifaddrs.h> header file. */
#cmakedefine HAVE_IFADDRS_H 1
-/* Define to 1 if you have the `inet_addr' function. */
-#cmakedefine HAVE_INET_ADDR 1
-
/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
#cmakedefine HAVE_INET_NTOP 1
@@ -318,9 +291,6 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
-/* Define to 1 if you have the ioctl function. */
-#cmakedefine HAVE_IOCTL 1
-
/* Define to 1 if you have the ioctlsocket function. */
#cmakedefine HAVE_IOCTLSOCKET 1
@@ -343,21 +313,9 @@
/* Define to 1 if you have the <io.h> header file. */
#cmakedefine HAVE_IO_H 1
-/* if you have the Kerberos4 libraries (including -ldes) */
-#cmakedefine HAVE_KRB4 1
-
-/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
-#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM 1
-
-/* Define to 1 if you have the <krb.h> header file. */
-#cmakedefine HAVE_KRB_H 1
-
/* Define to 1 if you have the lber.h header file. */
#cmakedefine HAVE_LBER_H 1
-/* Define to 1 if you have the ldapssl.h header file. */
-#cmakedefine HAVE_LDAPSSL_H 1
-
/* Define to 1 if you have the ldap.h header file. */
#cmakedefine HAVE_LDAP_H 1
@@ -379,30 +337,12 @@
/* Define to 1 if you have the idn2.h header file. */
#cmakedefine HAVE_IDN2_H 1
-/* Define to 1 if you have the `resolv' library (-lresolv). */
-#cmakedefine HAVE_LIBRESOLV 1
-
-/* Define to 1 if you have the `resolve' library (-lresolve). */
-#cmakedefine HAVE_LIBRESOLVE 1
-
/* Define to 1 if you have the `socket' library (-lsocket). */
#cmakedefine HAVE_LIBSOCKET 1
-/* Define to 1 if you have the `psl' library (-lpsl). */
-#cmakedefine HAVE_LIBPSL 1
-
-/* Define to 1 if you have the <libpsl.h> header file. */
-#cmakedefine HAVE_LIBPSL_H 1
-
/* Define to 1 if you have the `ssh2' library (-lssh2). */
#cmakedefine HAVE_LIBSSH2 1
-/* Define to 1 if you have the <libssh2.h> header file. */
-#cmakedefine HAVE_LIBSSH2_H 1
-
-/* Define to 1 if you have the <libssh/libssh.h> header file. */
-#cmakedefine HAVE_LIBSSH_LIBSSH_H 1
-
/* if zlib is available */
#cmakedefine HAVE_LIBZ 1
@@ -412,24 +352,12 @@
/* if zstd is available */
#cmakedefine HAVE_ZSTD 1
-/* if your compiler supports LL */
-#cmakedefine HAVE_LL 1
-
/* Define to 1 if you have the <locale.h> 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
-/* Define to 1 if you have the malloc.h header file. */
-#cmakedefine HAVE_MALLOC_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#cmakedefine HAVE_MEMORY_H 1
-
/* Define to 1 if you have the MSG_NOSIGNAL flag. */
#cmakedefine HAVE_MSG_NOSIGNAL 1
@@ -448,42 +376,12 @@
/* Define to 1 if you have the <net/if.h> header file. */
#cmakedefine HAVE_NET_IF_H 1
-/* Define to 1 if NI_WITHSCOPEID exists and works. */
-#cmakedefine HAVE_NI_WITHSCOPEID 1
-
/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE */
#cmakedefine HAVE_OLD_GSSMIT 1
-/* Define to 1 if you have the <openssl/crypto.h> header file. */
-#cmakedefine HAVE_OPENSSL_CRYPTO_H 1
-
-/* Define to 1 if you have the <openssl/err.h> header file. */
-#cmakedefine HAVE_OPENSSL_ERR_H 1
-
-/* Define to 1 if you have the <openssl/pem.h> header file. */
-#cmakedefine HAVE_OPENSSL_PEM_H 1
-
-/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
-#cmakedefine HAVE_OPENSSL_PKCS12_H 1
-
-/* Define to 1 if you have the <openssl/rsa.h> header file. */
-#cmakedefine HAVE_OPENSSL_RSA_H 1
-
-/* Define to 1 if you have the <openssl/ssl.h> header file. */
-#cmakedefine HAVE_OPENSSL_SSL_H 1
-
-/* Define to 1 if you have the <openssl/x509.h> header file. */
-#cmakedefine HAVE_OPENSSL_X509_H 1
-
-/* Define to 1 if you have the <pem.h> header file. */
-#cmakedefine HAVE_PEM_H 1
-
/* Define to 1 if you have the `pipe' function. */
#cmakedefine HAVE_PIPE 1
-/* Define to 1 if you have a working poll function. */
-#cmakedefine HAVE_POLL 1
-
/* If you have a fine poll */
#cmakedefine HAVE_POLL_FINE 1
@@ -502,18 +400,9 @@
/* Define to 1 if you have the `RAND_egd' function. */
#cmakedefine HAVE_RAND_EGD 1
-/* Define to 1 if you have the `RAND_screen' function. */
-#cmakedefine HAVE_RAND_SCREEN 1
-
-/* Define to 1 if you have the `RAND_status' function. */
-#cmakedefine HAVE_RAND_STATUS 1
-
/* Define to 1 if you have the recv function. */
#cmakedefine HAVE_RECV 1
-/* Define to 1 if you have the recvfrom function. */
-#cmakedefine HAVE_RECVFROM 1
-
/* Define to 1 if you have the select function. */
#cmakedefine HAVE_SELECT 1
@@ -541,9 +430,6 @@
/* Define to 1 if you have the `setrlimit' function. */
#cmakedefine HAVE_SETRLIMIT 1
-/* Define to 1 if you have the setsockopt function. */
-#cmakedefine HAVE_SETSOCKOPT 1
-
/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
#cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK 1
@@ -562,33 +448,36 @@
/* Define to 1 if you have the sigsetjmp function or macro. */
#cmakedefine HAVE_SIGSETJMP 1
+/* Define to 1 if you have the `snprintf' function. */
+#cmakedefine HAVE_SNPRINTF
+
/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
/* Define to 1 if you have the `socket' function. */
#cmakedefine HAVE_SOCKET 1
+/* Define to 1 if you have the socketpair function. */
+#cmakedefine HAVE_SOCKETPAIR 1
+
/* Define to 1 if you have the <ssl.h> header file. */
#cmakedefine HAVE_SSL_H 1
+/* Define to 1 if you have the <stdatomic.h> header file. */
+#cmakedefine HAVE_STDATOMIC_H 1
+
/* Define to 1 if you have the <stdbool.h> header file. */
#cmakedefine HAVE_STDBOOL_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
-/* Define to 1 if you have the <stdio.h> header file. */
-#cmakedefine HAVE_STDIO_H 1
-
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H 1
/* Define to 1 if you have the strcasecmp function. */
#cmakedefine HAVE_STRCASECMP 1
-/* Define to 1 if you have the strcasestr function. */
-#cmakedefine HAVE_STRCASESTR 1
-
/* Define to 1 if you have the strcmpi function. */
#cmakedefine HAVE_STRCMPI 1
@@ -607,18 +496,9 @@
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H 1
-/* Define to 1 if you have the strncmpi function. */
-#cmakedefine HAVE_STRNCMPI 1
-
-/* Define to 1 if you have the strnicmp function. */
-#cmakedefine HAVE_STRNICMP 1
-
/* Define to 1 if you have the <stropts.h> header file. */
#cmakedefine HAVE_STROPTS_H 1
-/* Define to 1 if you have the strstr function. */
-#cmakedefine HAVE_STRSTR 1
-
/* Define to 1 if you have the strtok_r function. */
#cmakedefine HAVE_STRTOK_R 1
@@ -664,9 +544,6 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
-/* Define to 1 if you have the <sys/uio.h> header file. */
-#cmakedefine HAVE_SYS_UIO_H 1
-
/* Define to 1 if you have the <sys/un.h> header file. */
#cmakedefine HAVE_SYS_UN_H 1
@@ -682,15 +559,6 @@
/* Define to 1 if you have the <time.h> header file. */
#cmakedefine HAVE_TIME_H 1
-/* Define to 1 if you have the <tld.h> header file. */
-#cmakedefine HAVE_TLD_H 1
-
-/* Define to 1 if you have the `tld_strerror' function. */
-#cmakedefine HAVE_TLD_STRERROR 1
-
-/* Define to 1 if you have the `uname' function. */
-#cmakedefine HAVE_UNAME 1
-
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
@@ -709,43 +577,18 @@
/* Define to 1 if compiler supports old gcc variadic macro style. */
#cmakedefine HAVE_VARIADIC_MACROS_GCC 1
-/* Define to 1 if you have the winber.h header file. */
-#cmakedefine HAVE_WINBER_H 1
-
/* Define to 1 if you have the windows.h header file. */
#cmakedefine HAVE_WINDOWS_H 1
-/* Define to 1 if you have the winldap.h header file. */
-#cmakedefine HAVE_WINLDAP_H 1
-
/* Define to 1 if you have the winsock2.h header file. */
#cmakedefine HAVE_WINSOCK2_H 1
/* Define this symbol if your OS supports changing the contents of argv */
#cmakedefine HAVE_WRITABLE_ARGV 1
-/* Define to 1 if you have the writev function. */
-#cmakedefine HAVE_WRITEV 1
-
/* Define to 1 if you have the ws2tcpip.h header file. */
#cmakedefine HAVE_WS2TCPIP_H 1
-/* Define to 1 if you have the <x509.h> header file. */
-#cmakedefine HAVE_X509_H 1
-
-/* Define if you have the <process.h> header file. */
-#cmakedefine HAVE_PROCESS_H 1
-
-/* if you have the zlib.h header file */
-#cmakedefine HAVE_ZLIB_H 1
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#cmakedefine LT_OBJDIR ${LT_OBJDIR}
-
-/* If you lack a fine basename() prototype */
-#cmakedefine NEED_BASENAME_PROTO 1
-
/* Define to 1 if you need the lber.h header file even with ldap.h */
#cmakedefine NEED_LBER_H 1
@@ -779,84 +622,6 @@
/* a suitable file to read random data from */
#cmakedefine RANDOM_FILE "${RANDOM_FILE}"
-/* Define to the type of arg 1 for recvfrom. */
-#cmakedefine RECVFROM_TYPE_ARG1 ${RECVFROM_TYPE_ARG1}
-
-/* Define to the type pointed by arg 2 for recvfrom. */
-#cmakedefine RECVFROM_TYPE_ARG2 ${RECVFROM_TYPE_ARG2}
-
-/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */
-#cmakedefine RECVFROM_TYPE_ARG2_IS_VOID 1
-
-/* Define to the type of arg 3 for recvfrom. */
-#cmakedefine RECVFROM_TYPE_ARG3 ${RECVFROM_TYPE_ARG3}
-
-/* Define to the type of arg 4 for recvfrom. */
-#cmakedefine RECVFROM_TYPE_ARG4 ${RECVFROM_TYPE_ARG4}
-
-/* Define to the type pointed by arg 5 for recvfrom. */
-#cmakedefine RECVFROM_TYPE_ARG5 ${RECVFROM_TYPE_ARG5}
-
-/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */
-#cmakedefine RECVFROM_TYPE_ARG5_IS_VOID 1
-
-/* Define to the type pointed by arg 6 for recvfrom. */
-#cmakedefine RECVFROM_TYPE_ARG6 ${RECVFROM_TYPE_ARG6}
-
-/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */
-#cmakedefine RECVFROM_TYPE_ARG6_IS_VOID 1
-
-/* Define to the function return type for recvfrom. */
-#cmakedefine RECVFROM_TYPE_RETV ${RECVFROM_TYPE_RETV}
-
-/* Define to the type of arg 1 for recv. */
-#cmakedefine RECV_TYPE_ARG1 ${RECV_TYPE_ARG1}
-
-/* Define to the type of arg 2 for recv. */
-#cmakedefine RECV_TYPE_ARG2 ${RECV_TYPE_ARG2}
-
-/* Define to the type of arg 3 for recv. */
-#cmakedefine RECV_TYPE_ARG3 ${RECV_TYPE_ARG3}
-
-/* Define to the type of arg 4 for recv. */
-#cmakedefine RECV_TYPE_ARG4 ${RECV_TYPE_ARG4}
-
-/* Define to the function return type for recv. */
-#cmakedefine RECV_TYPE_RETV ${RECV_TYPE_RETV}
-
-/* Define to the type qualifier of arg 5 for select. */
-#cmakedefine SELECT_QUAL_ARG5 ${SELECT_QUAL_ARG5}
-
-/* Define to the type of arg 1 for select. */
-#cmakedefine SELECT_TYPE_ARG1 ${SELECT_TYPE_ARG1}
-
-/* Define to the type of args 2, 3 and 4 for select. */
-#cmakedefine SELECT_TYPE_ARG234 ${SELECT_TYPE_ARG234}
-
-/* Define to the type of arg 5 for select. */
-#cmakedefine SELECT_TYPE_ARG5 ${SELECT_TYPE_ARG5}
-
-/* Define to the function return type for select. */
-#cmakedefine SELECT_TYPE_RETV ${SELECT_TYPE_RETV}
-
-/* Define to the type qualifier of arg 2 for send. */
-#cmakedefine SEND_QUAL_ARG2 ${SEND_QUAL_ARG2}
-
-/* Define to the type of arg 1 for send. */
-#cmakedefine SEND_TYPE_ARG1 ${SEND_TYPE_ARG1}
-
-/* Define to the type of arg 2 for send. */
-#cmakedefine SEND_TYPE_ARG2 ${SEND_TYPE_ARG2}
-
-/* Define to the type of arg 3 for send. */
-#cmakedefine SEND_TYPE_ARG3 ${SEND_TYPE_ARG3}
-
-/* Define to the type of arg 4 for send. */
-#cmakedefine SEND_TYPE_ARG4 ${SEND_TYPE_ARG4}
-
-/* Define to the function return type for send. */
-#cmakedefine SEND_TYPE_RETV ${SEND_TYPE_RETV}
-
/*
Note: SIZEOF_* variables are fetched with CMake through check_type_size().
As per CMake documentation on CheckTypeSize, C preprocessor code is
@@ -869,9 +634,6 @@
/* The size of `int', as computed by sizeof. */
${SIZEOF_INT_CODE}
-/* The size of `short', as computed by sizeof. */
-${SIZEOF_SHORT_CODE}
-
/* The size of `long', as computed by sizeof. */
${SIZEOF_LONG_CODE}
@@ -890,9 +652,6 @@
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1
-/* Define to the type of arg 3 for strerror_r. */
-#cmakedefine STRERROR_R_TYPE_ARG3 ${STRERROR_R_TYPE_ARG3}
-
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#cmakedefine TIME_WITH_SYS_TIME 1
@@ -981,9 +740,6 @@
/* enable multiple SSL backends */
#cmakedefine CURL_WITH_MULTI_SSL 1
-/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
-#cmakedefine USE_YASSLEMUL 1
-
/* Version number of package */
#cmakedefine VERSION ${VERSION}
@@ -1025,5 +781,5 @@
/* to enable Windows IDN */
#cmakedefine USE_WIN32_IDN 1
-/* to make the compiler know the prototypes of Windows IDN APIs */
-#cmakedefine WANT_IDN_PROTOTYPES 1
+/* Define to 1 to enable websocket support. */
+#cmakedefine USE_WEBSOCKETS 1
diff --git a/lib/curl_ctype.c b/lib/curl_ctype.c
deleted file mode 100644
index e1a8445..0000000
--- a/lib/curl_ctype.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the 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"
-
-#undef _U
-#define _U (1<<0) /* upper case */
-#undef _L
-#define _L (1<<1) /* lower case */
-#undef _N
-#define _N (1<<2) /* decimal numerical digit */
-#undef _S
-#define _S (1<<3) /* space */
-#undef _P
-#define _P (1<<4) /* punctuation */
-#undef _C
-#define _C (1<<5) /* control */
-#undef _X
-#define _X (1<<6) /* hexadecimal letter */
-#undef _B
-#define _B (1<<7) /* blank */
-
-static const unsigned char ascii[128] = {
- _C, _C, _C, _C, _C, _C, _C, _C,
- _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C,
- _C, _C, _C, _C, _C, _C, _C, _C,
- _C, _C, _C, _C, _C, _C, _C, _C,
- _S|_B, _P, _P, _P, _P, _P, _P, _P,
- _P, _P, _P, _P, _P, _P, _P, _P,
- _N, _N, _N, _N, _N, _N, _N, _N,
- _N, _N, _P, _P, _P, _P, _P, _P,
- _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
- _U, _U, _U, _U, _U, _U, _U, _U,
- _U, _U, _U, _U, _U, _U, _U, _U,
- _U, _U, _U, _P, _P, _P, _P, _P,
- _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
- _L, _L, _L, _L, _L, _L, _L, _L,
- _L, _L, _L, _L, _L, _L, _L, _L,
- _L, _L, _L, _P, _P, _P, _P, _C
-};
-
-int Curl_isspace(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & _S);
-}
-
-int Curl_isdigit(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & _N);
-}
-
-int Curl_isalnum(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_N|_U|_L));
-}
-
-int Curl_isxdigit(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_N|_X));
-}
-
-int Curl_isgraph(int c)
-{
- if((c < 0) || (c >= 0x80) || (c == ' '))
- return FALSE;
- return (ascii[c] & (_N|_X|_U|_L|_P|_S));
-}
-
-int Curl_isprint(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_N|_X|_U|_L|_P|_S));
-}
-
-int Curl_isalpha(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_U|_L));
-}
-
-int Curl_isupper(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_U));
-}
-
-int Curl_islower(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_L));
-}
-
-int Curl_iscntrl(int c)
-{
- if((c < 0) || (c >= 0x80))
- return FALSE;
- return (ascii[c] & (_C));
-}
-
diff --git a/lib/curl_ctype.h b/lib/curl_ctype.h
index c70945a..1d1d60c 100644
--- a/lib/curl_ctype.h
+++ b/lib/curl_ctype.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,32 +24,24 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#define ISLOWHEXALHA(x) (((x) >= 'a') && ((x) <= 'f'))
+#define ISUPHEXALHA(x) (((x) >= 'A') && ((x) <= 'F'))
-int Curl_isspace(int c);
-int Curl_isdigit(int c);
-int Curl_isalnum(int c);
-int Curl_isxdigit(int c);
-int Curl_isgraph(int c);
-int Curl_isprint(int c);
-int Curl_isalpha(int c);
-int Curl_isupper(int c);
-int Curl_islower(int c);
-int Curl_iscntrl(int c);
+#define ISLOWCNTRL(x) ((unsigned char)(x) <= 0x1f)
+#define IS7F(x) ((x) == 0x7f)
-#define ISSPACE(x) (Curl_isspace((int) ((unsigned char)x)))
-#define ISDIGIT(x) (Curl_isdigit((int) ((unsigned char)x)))
-#define ISALNUM(x) (Curl_isalnum((int) ((unsigned char)x)))
-#define ISXDIGIT(x) (Curl_isxdigit((int) ((unsigned char)x)))
-#define ISGRAPH(x) (Curl_isgraph((int) ((unsigned char)x)))
-#define ISALPHA(x) (Curl_isalpha((int) ((unsigned char)x)))
-#define ISPRINT(x) (Curl_isprint((int) ((unsigned char)x)))
-#define ISUPPER(x) (Curl_isupper((int) ((unsigned char)x)))
-#define ISLOWER(x) (Curl_islower((int) ((unsigned char)x)))
-#define ISCNTRL(x) (Curl_iscntrl((int) ((unsigned char)x)))
-#define ISASCII(x) (((x) >= 0) && ((x) <= 0x80))
+#define ISLOWPRINT(x) (((x) >= 9) && ((x) <= 0x0d))
-#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
- (((unsigned char)x) == '\t'))
+#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 ISXDIGIT(x) (ISDIGIT(x) || ISLOWHEXALHA(x) || ISUPHEXALHA(x))
+#define ISALNUM(x) (ISDIGIT(x) || ISLOWER(x) || ISUPPER(x))
+#define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
+#define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
+#define ISDIGIT(x) (((x) >= '0') && ((x) <= '9'))
+#define ISBLANK(x) (((x) == ' ') || ((x) == '\t'))
+#define ISSPACE(x) (ISBLANK(x) || (((x) >= 0xa) && ((x) <= 0x0d)))
#endif /* HEADER_CURL_CTYPE_H */
diff --git a/lib/curl_des.c b/lib/curl_des.c
index 6d52cd3..5c623b3 100644
--- a/lib/curl_des.c
+++ b/lib/curl_des.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2015 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -41,7 +41,7 @@
*
* The function is a port of the Java based oddParity() function over at:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
*
* Parameters:
*
diff --git a/lib/curl_des.h b/lib/curl_des.h
index c1c1674..6ec450a 100644
--- a/lib/curl_des.h
+++ b/lib/curl_des.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2015 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_endian.c b/lib/curl_endian.c
index 3cc7734..11c662a 100644
--- a/lib/curl_endian.c
+++ b/lib/curl_endian.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_endian.h b/lib/curl_endian.h
index 758d55f..fa28321 100644
--- a/lib/curl_endian.h
+++ b/lib/curl_endian.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,13 +33,4 @@
/* Converts a 16-bit integer from big endian */
unsigned short Curl_read16_be(const unsigned char *buf);
-#if (SIZEOF_CURL_OFF_T > 4)
-/* Converts a 64-bit integer to little endian */
-#if defined(HAVE_LONGLONG)
-void Curl_write64_le(const long long value, unsigned char *buffer);
-#else
-void Curl_write64_le(const __int64 value, unsigned char *buffer);
-#endif
-#endif
-
#endif /* HEADER_CURL_ENDIAN_H */
diff --git a/lib/curl_fnmatch.c b/lib/curl_fnmatch.c
index 0dd1eb5..5f9ca4f 100644
--- a/lib/curl_fnmatch.c
+++ b/lib/curl_fnmatch.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -76,9 +76,9 @@
parsekey_state state = CURLFNM_PKW_INIT;
#define KEYLEN 10
char keyword[KEYLEN] = { 0 };
- int found = FALSE;
int i;
unsigned char *p = *pattern;
+ bool found = FALSE;
for(i = 0; !found; i++) {
char c = *p++;
if(i >= KEYLEN)
@@ -368,14 +368,13 @@
*/
int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
{
- int rc;
(void)ptr; /* the argument is specified by the curl_fnmatch_callback
prototype, but not used by Curl_fnmatch() */
if(!pattern || !string) {
return CURL_FNMATCH_FAIL;
}
- rc = fnmatch(pattern, string, 0);
- switch(rc) {
+
+ switch(fnmatch(pattern, string, 0)) {
case 0:
return CURL_FNMATCH_MATCH;
case FNM_NOMATCH:
diff --git a/lib/curl_fnmatch.h b/lib/curl_fnmatch.h
index 8324be5..595646f 100644
--- a/lib/curl_fnmatch.h
+++ b/lib/curl_fnmatch.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_get_line.c b/lib/curl_get_line.c
index 6a26bb2..686abe7 100644
--- a/lib/curl_get_line.c
+++ b/lib/curl_get_line.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,7 +25,7 @@
#include "curl_setup.h"
#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
- !defined(CURL_DISABLE_HSTS)
+ !defined(CURL_DISABLE_HSTS) || !defined(CURL_DISABLE_NETRC)
#include "curl_get_line.h"
#include "curl_memory.h"
@@ -33,25 +33,49 @@
#include "memdebug.h"
/*
- * get_line() makes sure to only return complete whole lines that fit in 'len'
- * bytes and end with a newline.
+ * Curl_get_line() makes sure to only return complete whole lines that fit in
+ * 'len' bytes and end with a newline.
*/
char *Curl_get_line(char *buf, int len, FILE *input)
{
bool partial = FALSE;
while(1) {
char *b = fgets(buf, len, input);
+
if(b) {
size_t rlen = strlen(b);
- if(rlen && (b[rlen-1] == '\n')) {
+
+ if(!rlen)
+ break;
+
+ if(b[rlen-1] == '\n') {
+ /* b is \n terminated */
if(partial) {
partial = FALSE;
continue;
}
return b;
}
- /* read a partial, discard the next piece that ends with newline */
- partial = TRUE;
+ else if(feof(input)) {
+ if(partial)
+ /* Line is already too large to return, ignore rest */
+ break;
+
+ if(rlen + 1 < (size_t) len) {
+ /* b is EOF terminated, insert missing \n */
+ b[rlen] = '\n';
+ b[rlen + 1] = '\0';
+ return b;
+ }
+ else
+ /* Maximum buffersize reached + EOF
+ * This line is impossible to add a \n to so we'll ignore it
+ */
+ break;
+ }
+ else
+ /* Maximum buffersize reached */
+ partial = TRUE;
}
else
break;
diff --git a/lib/curl_get_line.h b/lib/curl_get_line.h
index b2a534d0..0ff32c5 100644
--- a/lib/curl_get_line.h
+++ b/lib/curl_get_line.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_gethostname.c b/lib/curl_gethostname.c
index 4747e93..706b2e6 100644
--- a/lib/curl_gethostname.c
+++ b/lib/curl_gethostname.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_gethostname.h b/lib/curl_gethostname.h
index b736096..9281d9c 100644
--- a/lib/curl_gethostname.h
+++ b/lib/curl_gethostname.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_gssapi.c b/lib/curl_gssapi.c
index 01ab48e..c6fe125 100644
--- a/lib/curl_gssapi.c
+++ b/lib/curl_gssapi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2011 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,10 +34,16 @@
#include "curl_memory.h"
#include "memdebug.h"
-gss_OID_desc Curl_spnego_mech_oid = {
+#if defined(__GNUC__)
+#define CURL_ALIGN8 __attribute__ ((aligned(8)))
+#else
+#define CURL_ALIGN8
+#endif
+
+gss_OID_desc Curl_spnego_mech_oid CURL_ALIGN8 = {
6, (char *)"\x2b\x06\x01\x05\x05\x02"
};
-gss_OID_desc Curl_krb5_mech_oid = {
+gss_OID_desc Curl_krb5_mech_oid CURL_ALIGN8 = {
9, (char *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
};
diff --git a/lib/curl_gssapi.h b/lib/curl_gssapi.h
index b4ed482..7b9a534 100644
--- a/lib/curl_gssapi.h
+++ b/lib/curl_gssapi.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2011 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_hmac.h b/lib/curl_hmac.h
index 77dce0f..11625c0 100644
--- a/lib/curl_hmac.h
+++ b/lib/curl_hmac.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,6 +26,8 @@
#ifndef CURL_DISABLE_CRYPTO_AUTH
+#include <curl/curl.h>
+
#define HMAC_MD5_LENGTH 16
typedef CURLcode (* HMAC_hinit_func)(void *context);
diff --git a/lib/curl_krb5.h b/lib/curl_krb5.h
index ccd6f10..ccf6b96 100644
--- a/lib/curl_krb5.h
+++ b/lib/curl_krb5.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_ldap.h b/lib/curl_ldap.h
index ba3ede4..8a1d807 100644
--- a/lib/curl_ldap.h
+++ b/lib/curl_ldap.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_log.c b/lib/curl_log.c
new file mode 100644
index 0000000..782c35a
--- /dev/null
+++ b/lib/curl_log.c
@@ -0,0 +1,228 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 <curl/curl.h>
+
+#include "curl_log.h"
+#include "urldata.h"
+#include "easyif.h"
+#include "cfilters.h"
+#include "timeval.h"
+#include "multiif.h"
+#include "strcase.h"
+
+#include "cf-socket.h"
+#include "connect.h"
+#include "http2.h"
+#include "http_proxy.h"
+#include "cf-h1-proxy.h"
+#include "cf-h2-proxy.h"
+#include "cf-haproxy.h"
+#include "cf-https-connect.h"
+#include "socks.h"
+#include "strtok.h"
+#include "vtls/vtls.h"
+#include "vquic/vquic.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+
+void Curl_debug(struct Curl_easy *data, curl_infotype type,
+ char *ptr, size_t size)
+{
+ if(data->set.verbose) {
+ static const char s_infotype[CURLINFO_END][3] = {
+ "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
+ if(data->set.fdebug) {
+ bool inCallback = Curl_is_in_callback(data);
+ Curl_set_in_callback(data, true);
+ (void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
+ Curl_set_in_callback(data, inCallback);
+ }
+ else {
+ switch(type) {
+ case CURLINFO_TEXT:
+ case CURLINFO_HEADER_OUT:
+ case CURLINFO_HEADER_IN:
+ fwrite(s_infotype[type], 2, 1, data->set.err);
+ fwrite(ptr, size, 1, data->set.err);
+ break;
+ default: /* nada */
+ break;
+ }
+ }
+ }
+}
+
+
+/* Curl_failf() is for messages stating why we failed.
+ * The message SHALL NOT include any LF or CR.
+ */
+void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
+{
+ DEBUGASSERT(!strchr(fmt, '\n'));
+ if(data->set.verbose || data->set.errorbuffer) {
+ va_list ap;
+ int len;
+ char error[CURL_ERROR_SIZE + 2];
+ va_start(ap, fmt);
+ len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
+
+ if(data->set.errorbuffer && !data->state.errorbuf) {
+ strcpy(data->set.errorbuffer, error);
+ data->state.errorbuf = TRUE; /* wrote error string */
+ }
+ error[len++] = '\n';
+ error[len] = '\0';
+ Curl_debug(data, CURLINFO_TEXT, error, len);
+ va_end(ap);
+ }
+}
+
+/* Curl_infof() is for info message along the way */
+#define MAXINFO 2048
+
+void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
+{
+ DEBUGASSERT(!strchr(fmt, '\n'));
+ if(data && data->set.verbose) {
+ va_list ap;
+ int len;
+ char buffer[MAXINFO + 2];
+ va_start(ap, fmt);
+ len = mvsnprintf(buffer, MAXINFO, fmt, ap);
+ va_end(ap);
+ buffer[len++] = '\n';
+ buffer[len] = '\0';
+ Curl_debug(data, CURLINFO_TEXT, buffer, len);
+ }
+}
+
+#ifdef DEBUGBUILD
+
+void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
+ const char *fmt, ...)
+{
+ DEBUGASSERT(cf);
+ if(data && Curl_log_cf_is_debug(cf, data)) {
+ va_list ap;
+ int len;
+ char buffer[MAXINFO + 2];
+ len = msnprintf(buffer, MAXINFO, "[%s] ", cf->cft->name);
+ va_start(ap, fmt);
+ len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap);
+ va_end(ap);
+ buffer[len++] = '\n';
+ buffer[len] = '\0';
+ Curl_debug(data, CURLINFO_TEXT, buffer, len);
+ }
+}
+
+
+static struct Curl_cftype *cf_types[] = {
+ &Curl_cft_tcp,
+ &Curl_cft_udp,
+ &Curl_cft_unix,
+ &Curl_cft_tcp_accept,
+ &Curl_cft_happy_eyeballs,
+ &Curl_cft_setup,
+#ifdef USE_NGHTTP2
+ &Curl_cft_nghttp2,
+#endif
+#ifdef USE_SSL
+ &Curl_cft_ssl,
+ &Curl_cft_ssl_proxy,
+#endif
+#if !defined(CURL_DISABLE_PROXY)
+#if !defined(CURL_DISABLE_HTTP)
+ &Curl_cft_h1_proxy,
+#ifdef USE_NGHTTP2
+ &Curl_cft_h2_proxy,
+#endif
+ &Curl_cft_http_proxy,
+#endif /* !CURL_DISABLE_HTTP */
+ &Curl_cft_haproxy,
+ &Curl_cft_socks_proxy,
+#endif /* !CURL_DISABLE_PROXY */
+#ifdef ENABLE_QUIC
+ &Curl_cft_http3,
+#endif
+#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
+ &Curl_cft_http_connect,
+#endif
+ NULL,
+};
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
+
+CURLcode Curl_log_init(void)
+{
+ const char *setting = getenv("CURL_DEBUG");
+ if(setting) {
+ char *token, *tok_buf, *tmp;
+ size_t i;
+
+ tmp = strdup(setting);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+
+ token = strtok_r(tmp, ", ", &tok_buf);
+ while(token) {
+ for(i = 0; cf_types[i]; ++i) {
+ if(strcasecompare(token, cf_types[i]->name)) {
+ cf_types[i]->log_level = CURL_LOG_DEBUG;
+ break;
+ }
+ }
+ token = strtok_r(NULL, ", ", &tok_buf);
+ }
+ free(tmp);
+ }
+ return CURLE_OK;
+}
+#else /* DEBUGBUILD */
+
+CURLcode Curl_log_init(void)
+{
+ return CURLE_OK;
+}
+
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
+void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
+ const char *fmt, ...)
+{
+ (void)data;
+ (void)cf;
+ (void)fmt;
+}
+#endif
+
+#endif /* !DEBUGBUILD */
diff --git a/lib/curl_log.h b/lib/curl_log.h
new file mode 100644
index 0000000..ebfa5a0
--- /dev/null
+++ b/lib/curl_log.h
@@ -0,0 +1,121 @@
+#ifndef HEADER_CURL_LOG_H
+#define HEADER_CURL_LOG_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+struct Curl_easy;
+struct Curl_cfilter;
+
+/**
+ * Init logging, return != 0 on failure.
+ */
+CURLcode Curl_log_init(void);
+
+
+void Curl_infof(struct Curl_easy *, const char *fmt, ...);
+void Curl_failf(struct Curl_easy *, const char *fmt, ...);
+
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+
+#if defined(HAVE_VARIADIC_MACROS_C99)
+#define infof(...) Curl_nop_stmt
+#elif defined(HAVE_VARIADIC_MACROS_GCC)
+#define infof(x...) Curl_nop_stmt
+#else
+#error "missing VARIADIC macro define, fix and rebuild!"
+#endif
+
+#else /* CURL_DISABLE_VERBOSE_STRINGS */
+
+#define infof Curl_infof
+
+#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+
+#define failf Curl_failf
+
+
+#define CURL_LOG_DEFAULT 0
+#define CURL_LOG_DEBUG 1
+#define CURL_LOG_TRACE 2
+
+
+/* the function used to output verbose information */
+void Curl_debug(struct Curl_easy *data, curl_infotype type,
+ char *ptr, size_t size);
+
+#ifdef DEBUGBUILD
+
+/* explainer: we have some mix configuration and werror settings
+ * that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced
+ * on gnuc and some other compiler. Need to treat carefully.
+ */
+#if defined(HAVE_VARIADIC_MACROS_C99) && \
+ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+
+#define LOG_CF(data, cf, ...) \
+ do { if(Curl_log_cf_is_debug(cf, data)) \
+ Curl_log_cf_debug(data, cf, __VA_ARGS__); } while(0)
+#else
+#define LOG_CF Curl_log_cf_debug
+#endif
+
+void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
+#if defined(__GNUC__) && !defined(printf) && \
+ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+ !defined(__MINGW32__)
+ const char *fmt, ...)
+ __attribute__((format(printf, 3, 4)));
+#else
+ const char *fmt, ...);
+#endif
+
+#define Curl_log_cf_is_debug(cf, data) \
+ ((data) && (data)->set.verbose && \
+ (cf) && (cf)->cft->log_level >= CURL_LOG_DEBUG)
+
+
+#else /* !DEBUGBUILD */
+
+#if defined(HAVE_VARIADIC_MACROS_C99) && \
+ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#define LOG_CF(...) Curl_nop_stmt
+#define Curl_log_cf_debug(...) Curl_nop_stmt
+#elif defined(HAVE_VARIADIC_MACROS_GCC) && \
+ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#define LOG_CF(x...) Curl_nop_stmt
+#define Curl_log_cf_debug(x...) Curl_nop_stmt
+#else
+#define LOG_CF Curl_log_cf_debug
+/* without c99, we seem unable to completely define away this function. */
+void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
+ const char *fmt, ...);
+#endif
+
+#define Curl_log_cf_is_debug(x,y) ((void)(x), (void)(y), FALSE)
+
+#endif /* !DEBUGBUILD */
+
+#define LOG_CF_IS_DEBUG(cf, data) Curl_log_cf_is_debug(cf, data)
+
+#endif /* HEADER_CURL_LOG_H */
diff --git a/lib/curl_md4.h b/lib/curl_md4.h
index 8049355..03567b9 100644
--- a/lib/curl_md4.h
+++ b/lib/curl_md4.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_md5.h b/lib/curl_md5.h
index 7893296..ec2512f 100644
--- a/lib/curl_md5.h
+++ b/lib/curl_md5.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_memory.h b/lib/curl_memory.h
index 092fc9f..b8c46d7 100644
--- a/lib/curl_memory.h
+++ b/lib/curl_memory.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -52,38 +52,67 @@
* mentioned above will compile without any indication, but it will
* trigger weird memory related issues at runtime.
*
- * OTOH some source files from 'lib' subdirectory may additionally be
- * used directly as source code when using some curlx_ functions by
- * third party programs that don't even use libcurl at all. When using
- * these source files in this way it is necessary these are compiled
- * with CURLX_NO_MEMORY_CALLBACKS defined, in order to ensure that no
- * attempt of calling libcurl's memory callbacks is done from code
- * which can not use this machinery.
- *
- * Notice that libcurl's 'memory tracking' system works chaining into
- * the memory callback machinery. This implies that when compiling
- * 'lib' source files with CURLX_NO_MEMORY_CALLBACKS defined this file
- * disengages usage of libcurl's 'memory tracking' system, defining
- * MEMDEBUG_NODEFINES and overriding CURLDEBUG purpose.
- *
- * CURLX_NO_MEMORY_CALLBACKS takes precedence over CURLDEBUG. This is
- * done in order to allow building a 'memory tracking' enabled libcurl
- * and at the same time allow building programs which do not use it.
- *
- * Programs and libraries in 'tests' subdirectories have specific
- * purposes and needs, and as such each one will use whatever fits
- * best, depending additionally whether it links with libcurl or not.
- *
- * Caveat emptor. Proper curlx_* separation is a work in progress
- * the same as CURLX_NO_MEMORY_CALLBACKS usage, some adjustments may
- * still be required. IOW don't use them yet, there are sharp edges.
*/
#ifdef HEADER_CURL_MEMDEBUG_H
-#error "Header memdebug.h shall not be included before curl_memory.h"
+/* cleanup after memdebug.h */
+
+#ifdef MEMDEBUG_NODEFINES
+#ifdef CURLDEBUG
+
+#undef strdup
+#undef malloc
+#undef calloc
+#undef realloc
+#undef free
+#undef send
+#undef recv
+
+#ifdef WIN32
+# ifdef UNICODE
+# undef wcsdup
+# undef _wcsdup
+# undef _tcsdup
+# else
+# undef _tcsdup
+# endif
#endif
-#ifndef CURLX_NO_MEMORY_CALLBACKS
+#undef socket
+#undef accept
+#ifdef HAVE_SOCKETPAIR
+#undef socketpair
+#endif
+
+#ifdef HAVE_GETADDRINFO
+#if defined(getaddrinfo) && defined(__osf__)
+#undef ogetaddrinfo
+#else
+#undef getaddrinfo
+#endif
+#endif /* HAVE_GETADDRINFO */
+
+#ifdef HAVE_FREEADDRINFO
+#undef freeaddrinfo
+#endif /* HAVE_FREEADDRINFO */
+
+/* sclose is probably already defined, redefine it! */
+#undef sclose
+#undef fopen
+#undef fdopen
+#undef fclose
+
+#endif /* MEMDEBUG_NODEFINES */
+#endif /* CURLDEBUG */
+
+#undef HEADER_CURL_MEMDEBUG_H
+#endif /* HEADER_CURL_MEMDEBUG_H */
+
+/*
+** Following section applies even when CURLDEBUG is not defined.
+*/
+
+#undef fake_sclose
#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS /* only if not already done */
/*
@@ -146,13 +175,4 @@
#endif
#endif /* CURLDEBUG */
-
-#else /* CURLX_NO_MEMORY_CALLBACKS */
-
-#ifndef MEMDEBUG_NODEFINES
-#define MEMDEBUG_NODEFINES
-#endif
-
-#endif /* CURLX_NO_MEMORY_CALLBACKS */
-
#endif /* HEADER_CURL_MEMORY_H */
diff --git a/lib/curl_memrchr.c b/lib/curl_memrchr.c
index c329a61..3f3dc6d 100644
--- a/lib/curl_memrchr.c
+++ b/lib/curl_memrchr.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_memrchr.h b/lib/curl_memrchr.h
index e7654e1..a1a4ba0 100644
--- a/lib/curl_memrchr.h
+++ b/lib/curl_memrchr.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_multibyte.c b/lib/curl_multibyte.c
index 309dccb..522ea34 100644
--- a/lib/curl_multibyte.c
+++ b/lib/curl_multibyte.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_multibyte.h b/lib/curl_multibyte.h
index 9297148..ddac1f6 100644
--- a/lib/curl_multibyte.h
+++ b/lib/curl_multibyte.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
index eabb000..ba8457d 100644
--- a/lib/curl_ntlm_core.c
+++ b/lib/curl_ntlm_core.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,19 +29,20 @@
/*
* NTLM details:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
/* Please keep the SSL backend-specific #if branches in this order:
1. USE_OPENSSL
- 2. USE_GNUTLS
- 3. USE_NSS
- 4. USE_MBEDTLS
- 5. USE_SECTRANSP
- 6. USE_OS400CRYPTO
- 7. USE_WIN32_CRYPTO
+ 2. USE_WOLFSSL
+ 3. USE_GNUTLS
+ 4. USE_NSS
+ 5. USE_MBEDTLS
+ 6. USE_SECTRANSP
+ 7. USE_OS400CRYPTO
+ 8. USE_WIN32_CRYPTO
This ensures that:
- the same SSL branch gets activated throughout this source
@@ -60,17 +61,17 @@
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
-#ifdef USE_WOLFSSL
+#if defined(USE_OPENSSL)
+# include <openssl/des.h>
+# include <openssl/md5.h>
+# include <openssl/ssl.h>
+# include <openssl/rand.h>
+#else
# include <wolfssl/options.h>
# include <wolfssl/openssl/des.h>
# include <wolfssl/openssl/md5.h>
# include <wolfssl/openssl/ssl.h>
# include <wolfssl/openssl/rand.h>
-#else
-# include <openssl/des.h>
-# include <openssl/md5.h>
-# include <openssl/ssl.h>
-# include <openssl/rand.h>
#endif
# if (defined(OPENSSL_VERSION_NUMBER) && \
@@ -82,6 +83,10 @@
# define DES_ecb_encrypt des_ecb_encrypt
# define DESKEY(x) x
# define DESKEYARG(x) x
+# elif defined(OPENSSL_IS_AWSLC)
+# define DES_set_key_unchecked (void)DES_set_key
+# define DESKEYARG(x) *x
+# define DESKEY(x) &x
# else
# define DESKEYARG(x) *x
# define DESKEY(x) &x
@@ -186,9 +191,9 @@
#elif defined(USE_NSS)
/*
- * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using
- * the expanded key. The caller is responsible for giving 64 bit of valid
- * data is IN and (at least) 64 bit large buffer as OUT.
+ * encrypt_des() expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of
+ * data, using the expanded key. IN should point to 64 bits of source data,
+ * OUT to a 64 bit output buffer.
*/
static bool encrypt_des(const unsigned char *in, unsigned char *out,
const unsigned char *key_56)
@@ -658,7 +663,8 @@
LONGQUARTET(tw.dwLowDateTime), LONGQUARTET(tw.dwHighDateTime));
memcpy(ptr + 32, challenge_client, 8);
- memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
+ if(ntlm->target_info_len)
+ memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
/* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
memcpy(ptr + 8, &ntlm->nonce[0], 8);
diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h
index 60444c9..33b651f 100644
--- a/lib/curl_ntlm_core.h
+++ b/lib/curl_ntlm_core.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,11 +37,11 @@
#define NTLM_NEEDS_NSS_INIT
#endif
-#ifdef USE_WOLFSSL
+#if defined(USE_OPENSSL)
+# include <openssl/ssl.h>
+#elif defined(USE_WOLFSSL)
# include <wolfssl/options.h>
# include <wolfssl/openssl/ssl.h>
-#elif defined(USE_OPENSSL)
-# include <openssl/ssl.h>
#endif
/* Helpers to generate function byte arguments in little endian order */
diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c
index f1eb9c6..a10e2a1 100644
--- a/lib/curl_ntlm_wb.c
+++ b/lib/curl_ntlm_wb.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,7 +30,7 @@
/*
* NTLM details:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
@@ -385,7 +385,7 @@
bool proxy)
{
/* point to the address of the pointer that holds the string to send to the
- server, which is for a plain host or for a HTTP proxy */
+ server, which is for a plain host or for an HTTP proxy */
char **allocuserpwd;
/* point to the name and password for this */
const char *userp;
diff --git a/lib/curl_ntlm_wb.h b/lib/curl_ntlm_wb.h
index 1f04db8..37704c0 100644
--- a/lib/curl_ntlm_wb.h
+++ b/lib/curl_ntlm_wb.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_path.c b/lib/curl_path.c
index ba1b717..856423d 100644
--- a/lib/curl_path.c
+++ b/lib/curl_path.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -18,7 +18,7 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
- * SPDX-License-Identifier: curl
+ * SPDX-License-Identifier: curl AND ISC
*
***************************************************************************/
@@ -32,66 +32,68 @@
#include "escape.h"
#include "memdebug.h"
+#define MAX_SSHPATH_LEN 100000 /* arbitrary */
+
/* figure out the path to work with in this particular request */
CURLcode Curl_getworkingpath(struct Curl_easy *data,
char *homedir, /* when SFTP is used */
char **path) /* returns the allocated
real path to work with */
{
- char *real_path = NULL;
char *working_path;
size_t working_path_len;
+ struct dynbuf npath;
CURLcode result =
Curl_urldecode(data->state.up.path, 0, &working_path,
&working_path_len, REJECT_ZERO);
if(result)
return result;
+ /* new path to switch to in case we need to */
+ Curl_dyn_init(&npath, MAX_SSHPATH_LEN);
+
/* Check for /~/, indicating relative to the user's home directory */
- if(data->conn->handler->protocol & CURLPROTO_SCP) {
- real_path = malloc(working_path_len + 1);
- if(!real_path) {
+ if((data->conn->handler->protocol & CURLPROTO_SCP) &&
+ (working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) {
+ /* It is referenced to the home directory, so strip the leading '/~/' */
+ if(Curl_dyn_addn(&npath, &working_path[3], working_path_len - 3)) {
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
- if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3)))
- /* It is referenced to the home directory, so strip the leading '/~/' */
- memcpy(real_path, working_path + 3, working_path_len - 2);
- else
- memcpy(real_path, working_path, 1 + working_path_len);
}
- else if(data->conn->handler->protocol & CURLPROTO_SFTP) {
- if((working_path_len > 1) && (working_path[1] == '~')) {
- size_t homelen = strlen(homedir);
- real_path = malloc(homelen + working_path_len + 1);
- if(!real_path) {
+ else if((data->conn->handler->protocol & CURLPROTO_SFTP) &&
+ (!strcmp("/~", working_path) ||
+ ((working_path_len > 2) && !memcmp(working_path, "/~/", 3)))) {
+ if(Curl_dyn_add(&npath, homedir)) {
+ free(working_path);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(working_path_len > 2) {
+ size_t len;
+ const char *p;
+ int copyfrom = 3;
+ /* Copy a separating '/' if homedir does not end with one */
+ len = Curl_dyn_len(&npath);
+ p = Curl_dyn_ptr(&npath);
+ if(len && (p[len-1] != '/'))
+ copyfrom = 2;
+
+ if(Curl_dyn_addn(&npath,
+ &working_path[copyfrom], working_path_len - copyfrom)) {
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
- /* It is referenced to the home directory, so strip the
- leading '/' */
- memcpy(real_path, homedir, homelen);
- real_path[homelen] = '/';
- real_path[homelen + 1] = '\0';
- if(working_path_len > 3) {
- memcpy(real_path + homelen + 1, working_path + 3,
- 1 + working_path_len -3);
- }
- }
- else {
- real_path = malloc(working_path_len + 1);
- if(!real_path) {
- free(working_path);
- return CURLE_OUT_OF_MEMORY;
- }
- memcpy(real_path, working_path, 1 + working_path_len);
}
}
- free(working_path);
+ if(Curl_dyn_len(&npath)) {
+ free(working_path);
- /* store the pointer for the caller to receive */
- *path = real_path;
+ /* store the pointer for the caller to receive */
+ *path = Curl_dyn_ptr(&npath);
+ }
+ else
+ *path = working_path;
return CURLE_OK;
}
@@ -122,7 +124,8 @@
bool relativePath = false;
static const char WHITESPACE[] = " \t\r\n";
- if(!*cp) {
+ DEBUGASSERT(homedir);
+ if(!*cp || !homedir) {
*cpp = NULL;
*path = NULL;
return CURLE_QUOTE_ERROR;
@@ -147,15 +150,12 @@
break;
}
if(cp[i] == '\0') { /* End of string */
- /*error("Unterminated quote");*/
goto fail;
}
if(cp[i] == '\\') { /* Escaped characters */
i++;
if(cp[i] != '\'' && cp[i] != '\"' &&
cp[i] != '\\') {
- /*error("Bad escaped character '\\%c'",
- cp[i]);*/
goto fail;
}
}
@@ -163,7 +163,6 @@
}
if(j == 0) {
- /*error("Empty quotes");*/
goto fail;
}
*cpp = cp + i + strspn(cp + i, WHITESPACE);
@@ -192,7 +191,7 @@
}
return CURLE_OK;
- fail:
+fail:
Curl_safefree(*path);
return CURLE_QUOTE_ERROR;
}
diff --git a/lib/curl_path.h b/lib/curl_path.h
index 98e56ea..9ed09de 100644
--- a/lib/curl_path.h
+++ b/lib/curl_path.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_printf.h b/lib/curl_printf.h
index 3823828..46ef344 100644
--- a/lib/curl_printf.h
+++ b/lib/curl_printf.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,6 +37,7 @@
# undef vprintf
# undef vfprintf
# undef vsnprintf
+# undef mvsnprintf
# undef aprintf
# undef vaprintf
# define printf curl_mprintf
diff --git a/lib/curl_range.c b/lib/curl_range.c
index 9e03c3d..d499953 100644
--- a/lib/curl_range.c
+++ b/lib/curl_range.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,12 +44,12 @@
if(data->state.use_range && data->state.range) {
CURLofft from_t;
CURLofft to_t;
- from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
+ from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from);
if(from_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+ while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
ptr++;
- to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
+ to_t = curlx_strtoofft(ptr, &ptr2, 10, &to);
if(to_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
if((to_t == CURL_OFFT_INVAL) && !from_t) {
diff --git a/lib/curl_range.h b/lib/curl_range.h
index 33570ab..77679e2 100644
--- a/lib/curl_range.h
+++ b/lib/curl_range.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c
index b0c3710..406fb42 100644
--- a/lib/curl_rtmp.c
+++ b/lib/curl_rtmp.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2012, Howard Chu, <hyc@highlandsun.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Howard Chu, <hyc@highlandsun.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -85,7 +85,7 @@
PORT_RTMP, /* defport */
CURLPROTO_RTMP, /* protocol */
CURLPROTO_RTMP, /* family */
- PROTOPT_NONE /* flags*/
+ PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmpt = {
@@ -108,7 +108,7 @@
PORT_RTMPT, /* defport */
CURLPROTO_RTMPT, /* protocol */
CURLPROTO_RTMPT, /* family */
- PROTOPT_NONE /* flags*/
+ PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmpe = {
@@ -131,7 +131,7 @@
PORT_RTMP, /* defport */
CURLPROTO_RTMPE, /* protocol */
CURLPROTO_RTMPE, /* family */
- PROTOPT_NONE /* flags*/
+ PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmpte = {
@@ -154,7 +154,7 @@
PORT_RTMPT, /* defport */
CURLPROTO_RTMPTE, /* protocol */
CURLPROTO_RTMPTE, /* family */
- PROTOPT_NONE /* flags*/
+ PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmps = {
@@ -177,7 +177,7 @@
PORT_RTMPS, /* defport */
CURLPROTO_RTMPS, /* protocol */
CURLPROTO_RTMP, /* family */
- PROTOPT_NONE /* flags*/
+ PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmpts = {
@@ -200,7 +200,7 @@
PORT_RTMPS, /* defport */
CURLPROTO_RTMPTS, /* protocol */
CURLPROTO_RTMPT, /* family */
- PROTOPT_NONE /* flags*/
+ PROTOPT_NONE /* flags */
};
static CURLcode rtmp_setup_connection(struct Curl_easy *data,
@@ -231,7 +231,7 @@
/* We have to know if it's a write before we send the
* connect request packet
*/
- if(data->set.upload)
+ if(data->state.upload)
r->Link.protocol |= RTMP_FEATURE_WRITE;
/* For plain streams, use the buffer toggle trick to keep data flowing */
@@ -263,7 +263,7 @@
if(!RTMP_ConnectStream(r, 0))
return CURLE_FAILED_INIT;
- if(data->set.upload) {
+ if(data->state.upload) {
Curl_pgrsSetUploadSize(data, data->state.infilesize);
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
}
diff --git a/lib/curl_rtmp.h b/lib/curl_rtmp.h
index f856085..9b93ee0 100644
--- a/lib/curl_rtmp.h
+++ b/lib/curl_rtmp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2022, Howard Chu, <hyc@highlandsun.com>
+ * Copyright (C) Howard Chu, <hyc@highlandsun.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index 9684ee4..1cb0e54 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,7 +36,8 @@
#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 <curl/curl.h>
#include "urldata.h"
@@ -44,6 +45,7 @@
#include "curl_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"
@@ -219,12 +221,12 @@
}
/*
- * state()
+ * sasl_state()
*
* This is the ONLY way to change SASL state!
*/
-static void state(struct SASL *sasl, struct Curl_easy *data,
- saslstate newstate)
+static void sasl_state(struct SASL *sasl, struct Curl_easy *data,
+ saslstate newstate)
{
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
@@ -340,8 +342,8 @@
struct bufref resp;
saslstate state1 = SASL_STOP;
saslstate state2 = SASL_FINAL;
- const char * const hostname = SSL_HOST_NAME();
- const long int port = SSL_HOST_PORT();
+ const char *hostname, *disp_hostname;
+ int port;
#if defined(USE_KERBEROS5) || defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
@@ -350,6 +352,7 @@
const char *oauth_bearer = data->set.str[STRING_BEARER];
struct bufref nullmsg;
+ Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port);
Curl_bufref_init(&nullmsg);
Curl_bufref_init(&resp);
sasl->force_ir = force_ir; /* Latch for future use */
@@ -505,7 +508,7 @@
if(!result) {
*progress = SASL_INPROGRESS;
- state(sasl, data, Curl_bufref_ptr(&resp) ? state2 : state1);
+ sasl_state(sasl, data, Curl_bufref_ptr(&resp) ? state2 : state1);
}
}
@@ -525,8 +528,8 @@
struct connectdata *conn = data->conn;
saslstate newstate = SASL_FINAL;
struct bufref resp;
- const char * const hostname = SSL_HOST_NAME();
- const long int port = SSL_HOST_PORT();
+ const char *hostname, *disp_hostname;
+ int port;
#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
@@ -536,6 +539,7 @@
const char *oauth_bearer = data->set.str[STRING_BEARER];
struct bufref serverdata;
+ Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port);
Curl_bufref_init(&serverdata);
Curl_bufref_init(&resp);
*progress = SASL_INPROGRESS;
@@ -544,14 +548,14 @@
if(code != sasl->params->finalcode)
result = CURLE_LOGIN_DENIED;
*progress = SASL_DONE;
- state(sasl, data, SASL_STOP);
+ sasl_state(sasl, data, SASL_STOP);
return result;
}
if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP &&
code != sasl->params->contcode) {
*progress = SASL_DONE;
- state(sasl, data, SASL_STOP);
+ sasl_state(sasl, data, SASL_STOP);
return CURLE_LOGIN_DENIED;
}
@@ -694,7 +698,7 @@
if(code == sasl->params->finalcode) {
/* Final response was received so we are done */
*progress = SASL_DONE;
- state(sasl, data, SASL_STOP);
+ sasl_state(sasl, data, SASL_STOP);
return result;
}
else if(code == sasl->params->contcode) {
@@ -704,7 +708,7 @@
}
else {
*progress = SASL_DONE;
- state(sasl, data, SASL_STOP);
+ sasl_state(sasl, data, SASL_STOP);
return CURLE_LOGIN_DENIED;
}
@@ -741,7 +745,7 @@
Curl_bufref_free(&resp);
- state(sasl, data, newstate);
+ sasl_state(sasl, data, newstate);
return result;
}
diff --git a/lib/curl_sasl.h b/lib/curl_sasl.h
index c709d56..e94e643 100644
--- a/lib/curl_sasl.h
+++ b/lib/curl_sasl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -125,9 +125,9 @@
unsigned short authmechs; /* Accepted authentication mechanisms */
unsigned short prefmech; /* Preferred authentication mechanism */
unsigned short authused; /* Auth mechanism used for the connection */
- bool resetprefs; /* For URL auth option parsing. */
- bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */
- bool force_ir; /* Protocol always supports initial response */
+ BIT(resetprefs); /* For URL auth option parsing. */
+ BIT(mutual_auth); /* Mutual authentication enabled (GSSAPI only) */
+ BIT(force_ir); /* Protocol always supports initial response */
};
/* This is used to test whether the line starts with the given mechanism */
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index 4bc8aea..81c4bd1 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -92,7 +92,7 @@
# endif
#endif
-#if defined(macintosh) && defined(__MRC__)
+#ifdef macintosh
# include "config-mac.h"
#endif
@@ -112,6 +112,10 @@
# include "config-plan9.h"
#endif
+#ifdef MSDOS
+# include "config-dos.h"
+#endif
+
#endif /* HAVE_CONFIG_H */
/* ================================================================ */
@@ -158,8 +162,6 @@
/* please, do it beyond the point further indicated in this file. */
/* ================================================================ */
-#include <curl/curl.h>
-
/*
* Disable other protocols when http is the only one desired.
*/
@@ -219,7 +221,7 @@
/* ================================================================ */
/* No system header file shall be included in this file before this */
-/* point. The only allowed ones are those included from curl/system.h */
+/* point. */
/* ================================================================ */
/*
@@ -246,6 +248,8 @@
# include "setup-win32.h"
#endif
+#include <curl/system.h>
+
/*
* Use getaddrinfo to resolve the IPv4 address literal. If the current network
* interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
@@ -254,7 +258,7 @@
#if defined(__APPLE__) && !defined(USE_ARES)
#include <TargetConditionals.h>
#define USE_RESOLVE_ON_IPS 1
-# if defined(TARGET_OS_OSX) && TARGET_OS_OSX
+# if !defined(TARGET_OS_OSX) || TARGET_OS_OSX
# define CURL_OSX_CALL_COPYPROXIES 1
# endif
#endif
@@ -274,14 +278,42 @@
#endif
#ifdef __AMIGA__
+# ifdef __amigaos4__
+# define __USE_INLINE__
+ /* use our own resolver which uses runtime feature detection */
+# define CURLRES_AMIGA
+ /* getaddrinfo() currently crashes bsdsocket.library, so disable */
+# undef HAVE_GETADDRINFO
+# if !(defined(__NEWLIB__) || \
+ (defined(__CLIB2__) && defined(__THREAD_SAFE)))
+ /* disable threaded resolver with clib2 - requires newlib or clib-ts */
+# undef USE_THREADS_POSIX
+# endif
+# endif
# include <exec/types.h>
# include <exec/execbase.h>
# include <proto/exec.h>
# include <proto/dos.h>
# include <unistd.h>
-# ifdef HAVE_PROTO_BSDSOCKET_H
-# include <proto/bsdsocket.h> /* ensure bsdsocket.library use */
-# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
+# if defined(HAVE_PROTO_BSDSOCKET_H) && \
+ (!defined(__amigaos4__) || defined(USE_AMISSL))
+ /* use bsdsocket.library directly, instead of libc networking functions */
+# define _SYS_MBUF_H /* m_len define clashes with curl */
+# include <proto/bsdsocket.h>
+# 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)
+# else
+# 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
+# undef HAVE_FCNTL_O_NONBLOCK
+# else
+ /* use libc networking and hence close() and fnctl() */
+# undef HAVE_CLOSESOCKET_CAMEL
+# undef HAVE_IOCTLSOCKET_CAMEL
# endif
/*
* In clib2 arpa/inet.h warns that some prototypes may clash
@@ -291,12 +323,12 @@
#endif
#include <stdio.h>
-#ifdef HAVE_ASSERT_H
#include <assert.h>
-#endif
-#ifdef __TANDEM /* for nsr-tandem-nsk systems */
-#include <floss.h>
+#ifdef __TANDEM /* for ns*-tandem-nsk systems */
+# if ! defined __LP64
+# include <floss.h> /* FLOSS is only used for 32-bit builds. */
+# endif
#endif
#ifndef STDC_HEADERS /* no standard C headers! */
@@ -410,8 +442,8 @@
# endif
#endif
-#if (SIZEOF_CURL_OFF_T == 4)
-# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF)
+#if (SIZEOF_CURL_OFF_T < 8)
+#error "too small curl_off_t"
#else
/* assume SIZEOF_CURL_OFF_T == 8 */
# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
@@ -563,7 +595,6 @@
/* now undef the stock libc functions just to avoid them being used */
# undef HAVE_GETADDRINFO
# undef HAVE_FREEADDRINFO
-# undef HAVE_GETHOSTBYNAME
#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
# define CURLRES_ASYNCH
# define CURLRES_THREADED
@@ -665,7 +696,7 @@
# define UNUSED_PARAM __attribute__((__unused__))
# define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
-# define UNUSED_PARAM /*NOTHING*/
+# define UNUSED_PARAM /* NOTHING */
# define WARN_UNUSED_RESULT
#endif
@@ -714,12 +745,12 @@
#define SHUT_RDWR 0x02
#endif
-/* Define S_ISREG if not defined by system headers, f.e. MSVC */
+/* Define S_ISREG if not defined by system headers, e.g. MSVC */
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
-/* Define S_ISDIR if not defined by system headers, f.e. MSVC */
+/* Define S_ISDIR if not defined by system headers, e.g. MSVC */
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
@@ -747,21 +778,6 @@
#define FOPEN_APPENDTEXT "a"
#endif
-/* WinSock destroys recv() buffer when send() failed.
- * Enabled automatically for Windows and for Cygwin as Cygwin sockets are
- * wrappers for WinSock sockets. https://github.com/curl/curl/issues/657
- * Define DONT_USE_RECV_BEFORE_SEND_WORKAROUND to force disable workaround.
- */
-#if !defined(DONT_USE_RECV_BEFORE_SEND_WORKAROUND)
-# if defined(WIN32) || defined(__CYGWIN__)
-# define USE_RECV_BEFORE_SEND_WORKAROUND
-# endif
-#else /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */
-# ifdef USE_RECV_BEFORE_SEND_WORKAROUND
-# undef USE_RECV_BEFORE_SEND_WORKAROUND
-# endif
-#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */
-
/* for systems that don't detect this in configure */
#ifndef CURL_SA_FAMILY_T
# if defined(HAVE_SA_FAMILY_T)
@@ -801,11 +817,19 @@
#define USE_HTTP2
#endif
-#if defined(USE_NGTCP2) || defined(USE_QUICHE) || defined(USE_MSH3)
+#if (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
+ defined(USE_QUICHE) || defined(USE_MSH3)
#define ENABLE_QUIC
#define USE_HTTP3
#endif
+/* Certain Windows implementations are not aligned with what curl expects,
+ so always use the local one on this platform. E.g. the mingw-w64
+ implementation can return wrong results for non-ASCII inputs. */
+#if defined(HAVE_BASENAME) && defined(WIN32)
+#undef HAVE_BASENAME
+#endif
+
#if defined(USE_UNIX_SOCKETS) && defined(WIN32)
# if defined(__MINGW32__) && !defined(LUP_SECURE)
typedef u_short ADDRESS_FAMILY; /* Classic mingw, 11y+ old mingw-w64 */
@@ -823,4 +847,10 @@
# endif
#endif
+/* OpenSSLv3 marks DES, MD5 and ENGINE functions deprecated but we have no
+ replacements (yet) so tell the compiler to not warn for them. */
+#ifdef USE_OPENSSL
+#define OPENSSL_SUPPRESS_DEPRECATED
+#endif
+
#endif /* HEADER_CURL_SETUP_H */
diff --git a/lib/curl_setup_once.h b/lib/curl_setup_once.h
index 656dc08..c1ed059 100644
--- a/lib/curl_setup_once.h
+++ b/lib/curl_setup_once.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,12 +33,8 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
-#include <ctype.h>
#include <time.h>
-
-#ifdef HAVE_ERRNO_H
#include <errno.h>
-#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -73,6 +69,20 @@
#include <unistd.h>
#endif
+#ifdef USE_WOLFSSL
+# if defined(HAVE_STDINT_H)
+# include <stdint.h>
+# elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+# endif
+#endif
+
+#ifdef USE_SCHANNEL
+/* Must set this before <schannel.h> is included directly or indirectly by
+ another Windows header. */
+# define SCHANNEL_USE_BLACKLISTS 1
+#endif
+
#ifdef __hpux
# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
# ifdef _APP32_64BIT_OFF_T
@@ -88,6 +98,8 @@
#include <sys/socket.h>
#endif
+#include "functypes.h"
+
#ifdef __hpux
# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
# ifdef OLD_APP32_64BIT_OFF_T
@@ -150,20 +162,10 @@
* SEND_TYPE_RETV must also be defined.
*/
-#if !defined(RECV_TYPE_ARG1) || \
- !defined(RECV_TYPE_ARG2) || \
- !defined(RECV_TYPE_ARG3) || \
- !defined(RECV_TYPE_ARG4) || \
- !defined(RECV_TYPE_RETV)
- /* */
- Error Missing_definition_of_return_and_arguments_types_of_recv
- /* */
-#else
#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \
(RECV_TYPE_ARG2)(y), \
(RECV_TYPE_ARG3)(z), \
(RECV_TYPE_ARG4)(0))
-#endif
#else /* HAVE_RECV */
#ifndef sread
/* */
@@ -180,21 +182,10 @@
(SEND_TYPE_ARG3)(z))
#elif defined(HAVE_SEND)
-#if !defined(SEND_TYPE_ARG1) || \
- !defined(SEND_QUAL_ARG2) || \
- !defined(SEND_TYPE_ARG2) || \
- !defined(SEND_TYPE_ARG3) || \
- !defined(SEND_TYPE_ARG4) || \
- !defined(SEND_TYPE_RETV)
- /* */
- Error Missing_definition_of_return_and_arguments_types_of_send
- /* */
-#else
#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \
(SEND_QUAL_ARG2 SEND_TYPE_ARG2)(y), \
(SEND_TYPE_ARG3)(z), \
(SEND_TYPE_ARG4)(SEND_4TH_ARG))
-#endif
#else /* HAVE_SEND */
#ifndef swrite
/* */
@@ -204,46 +195,6 @@
#endif /* HAVE_SEND */
-#if 0
-#if defined(HAVE_RECVFROM)
-/*
- * Currently recvfrom is only used on udp sockets.
- */
-#if !defined(RECVFROM_TYPE_ARG1) || \
- !defined(RECVFROM_TYPE_ARG2) || \
- !defined(RECVFROM_TYPE_ARG3) || \
- !defined(RECVFROM_TYPE_ARG4) || \
- !defined(RECVFROM_TYPE_ARG5) || \
- !defined(RECVFROM_TYPE_ARG6) || \
- !defined(RECVFROM_TYPE_RETV)
- /* */
- Error Missing_definition_of_return_and_arguments_types_of_recvfrom
- /* */
-#else
-#define sreadfrom(s,b,bl,f,fl) (ssize_t)recvfrom((RECVFROM_TYPE_ARG1) (s), \
- (RECVFROM_TYPE_ARG2 *)(b), \
- (RECVFROM_TYPE_ARG3) (bl), \
- (RECVFROM_TYPE_ARG4) (0), \
- (RECVFROM_TYPE_ARG5 *)(f), \
- (RECVFROM_TYPE_ARG6 *)(fl))
-#endif
-#else /* HAVE_RECVFROM */
-#ifndef sreadfrom
- /* */
- Error Missing_definition_of_macro_sreadfrom
- /* */
-#endif
-#endif /* HAVE_RECVFROM */
-
-
-#ifdef RECVFROM_TYPE_ARG6_IS_VOID
-# define RECVFROM_ARG6_T int
-#else
-# define RECVFROM_ARG6_T RECVFROM_TYPE_ARG6
-#endif
-#endif /* if 0 */
-
-
/*
* Function-like macro definition used to close a socket.
*/
@@ -269,9 +220,6 @@
# define sfcntl fcntl
#endif
-#define TOLOWER(x) (tolower((int) ((unsigned char)x)))
-
-
/*
* 'bool' stuff compatible with HP-UX headers.
*/
@@ -350,7 +298,7 @@
*/
#undef DEBUGASSERT
-#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H)
+#if defined(DEBUGBUILD)
#define DEBUGASSERT(x) assert(x)
#else
#define DEBUGASSERT(x) do { } while(0)
diff --git a/lib/curl_sha256.h b/lib/curl_sha256.h
index 82fcdff..c5e157b 100644
--- a/lib/curl_sha256.h
+++ b/lib/curl_sha256.h
@@ -7,8 +7,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017, Florin Petriuc, <petriuc.florin@gmail.com>
- * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Florin Petriuc, <petriuc.florin@gmail.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,13 +26,14 @@
***************************************************************************/
#ifndef CURL_DISABLE_CRYPTO_AUTH
+#include <curl/curl.h>
#include "curl_hmac.h"
extern const struct HMAC_params Curl_HMAC_SHA256[1];
#ifdef USE_WOLFSSL
/* SHA256_DIGEST_LENGTH is an enum value in wolfSSL. Need to import it from
- * sha.h*/
+ * sha.h */
#include <wolfssl/options.h>
#include <wolfssl/openssl/sha.h>
#else
diff --git a/lib/curl_sspi.c b/lib/curl_sspi.c
index 33108c4..eb21e7e 100644
--- a/lib/curl_sspi.c
+++ b/lib/curl_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_sspi.h b/lib/curl_sspi.h
index ad11130..9816d59 100644
--- a/lib/curl_sspi.h
+++ b/lib/curl_sspi.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curl_threads.c b/lib/curl_threads.c
index eb8e136..e13e294 100644
--- a/lib/curl_threads.c
+++ b/lib/curl_threads.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,9 +31,7 @@
# include <pthread.h>
# endif
#elif defined(USE_THREADS_WIN32)
-# ifdef HAVE_PROCESS_H
-# include <process.h>
-# endif
+# include <process.h>
#endif
#include "curl_threads.h"
diff --git a/lib/curl_threads.h b/lib/curl_threads.h
index 63392f6..facbc73 100644
--- a/lib/curl_threads.h
+++ b/lib/curl_threads.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/curlx.h b/lib/curlx.h
index 1796afa..7a753d6 100644
--- a/lib/curlx.h
+++ b/lib/curlx.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/dict.c b/lib/dict.c
index 6f7678f..3172b38 100644
--- a/lib/dict.c
+++ b/lib/dict.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -98,37 +98,27 @@
PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
};
-static char *unescape_word(const char *inputbuff)
+#define DYN_DICT_WORD 10000
+static char *unescape_word(const char *input)
{
- char *newp = NULL;
- char *dictp;
- size_t len;
+ struct dynbuf out;
+ const char *ptr;
+ CURLcode result = CURLE_OK;
+ Curl_dyn_init(&out, DYN_DICT_WORD);
- CURLcode result = Curl_urldecode(inputbuff, 0, &newp, &len,
- REJECT_NADA);
- if(!newp || result)
- return NULL;
-
- dictp = malloc(len*2 + 1); /* add one for terminating zero */
- if(dictp) {
- char *ptr;
- char ch;
- int olen = 0;
- /* According to RFC2229 section 2.2, these letters need to be escaped with
- \[letter] */
- for(ptr = newp;
- (ch = *ptr) != 0;
- ptr++) {
- if((ch <= 32) || (ch == 127) ||
- (ch == '\'') || (ch == '\"') || (ch == '\\')) {
- dictp[olen++] = '\\';
- }
- dictp[olen++] = ch;
- }
- dictp[olen] = 0;
+ /* According to RFC2229 section 2.2, these letters need to be escaped with
+ \[letter] */
+ for(ptr = input; *ptr; ptr++) {
+ char ch = *ptr;
+ if((ch <= 32) || (ch == 127) ||
+ (ch == '\'') || (ch == '\"') || (ch == '\\'))
+ result = Curl_dyn_addn(&out, "\\", 1);
+ if(!result)
+ result = Curl_dyn_addn(&out, ptr, 1);
+ if(result)
+ return NULL;
}
- free(newp);
- return dictp;
+ return Curl_dyn_ptr(&out);
}
/* sendf() sends formatted data to the server */
@@ -178,20 +168,25 @@
static CURLcode dict_do(struct Curl_easy *data, bool *done)
{
char *word;
- char *eword;
+ char *eword = NULL;
char *ppath;
char *database = NULL;
char *strategy = NULL;
char *nthdef = NULL; /* This is not part of the protocol, but required
by RFC 2229 */
- CURLcode result = CURLE_OK;
+ CURLcode result;
struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- char *path = data->state.up.path;
+ char *path;
*done = TRUE; /* unconditionally */
+ /* url-decode path before further evaluation */
+ result = Curl_urldecode(data->state.up.path, 0, &path, NULL, REJECT_CTRL);
+ if(result)
+ return result;
+
if(strncasecompare(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
strncasecompare(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
strncasecompare(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
@@ -225,8 +220,10 @@
}
eword = unescape_word(word);
- if(!eword)
- return CURLE_OUT_OF_MEMORY;
+ if(!eword) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
result = sendf(sockfd, data,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
@@ -239,11 +236,9 @@
strategy,
eword);
- free(eword);
-
if(result) {
failf(data, "Failed sending DICT request");
- return result;
+ goto error;
}
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */
}
@@ -273,8 +268,10 @@
}
eword = unescape_word(word);
- if(!eword)
- return CURLE_OUT_OF_MEMORY;
+ if(!eword) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
result = sendf(sockfd, data,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
@@ -285,11 +282,9 @@
database,
eword);
- free(eword);
-
if(result) {
failf(data, "Failed sending DICT request");
- return result;
+ goto error;
}
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
}
@@ -310,13 +305,16 @@
"QUIT\r\n", ppath);
if(result) {
failf(data, "Failed sending DICT request");
- return result;
+ goto error;
}
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
}
}
- return CURLE_OK;
+error:
+ free(eword);
+ free(path);
+ return result;
}
-#endif /*CURL_DISABLE_DICT*/
+#endif /* CURL_DISABLE_DICT */
diff --git a/lib/dict.h b/lib/dict.h
index b283a0d..ba9a927 100644
--- a/lib/dict.h
+++ b/lib/dict.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/doh.c b/lib/doh.c
index a21c94f..7a38eab 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -243,6 +243,7 @@
the gcc typecheck helpers */
struct dynbuf *resp = &p->serverdoh;
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
+ ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp);
ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, p->dohbuffer);
@@ -346,7 +347,7 @@
free(nurl);
return CURLE_OK;
- error:
+error:
free(nurl);
Curl_close(&doh);
return result;
@@ -395,7 +396,8 @@
goto error;
dohp->pending++;
- if(Curl_ipv6works(data)) {
+#ifdef ENABLE_IPV6
+ if((conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* create IPv6 DoH request */
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
@@ -404,9 +406,10 @@
goto error;
dohp->pending++;
}
+#endif
return NULL;
- error:
+error:
curl_slist_free_all(dohp->headers);
data->req.doh->headers = NULL;
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
@@ -791,7 +794,7 @@
#endif
CURLcode result = CURLE_OK;
int i;
- size_t hostlen = strlen(hostname) + 1; /* include zero terminator */
+ size_t hostlen = strlen(hostname) + 1; /* include null-terminator */
if(!de)
/* no input == no output! */
@@ -949,7 +952,7 @@
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
/* we got a response, store it in the cache */
- dns = Curl_cache_addr(data, ai, dohp->host, dohp->port);
+ dns = Curl_cache_addr(data, ai, dohp->host, 0, dohp->port);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
diff --git a/lib/doh.h b/lib/doh.h
index f8b6435..7d7b694 100644
--- a/lib/doh.h
+++ b/lib/doh.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,21 +29,6 @@
#ifndef CURL_DISABLE_DOH
-/*
- * Curl_doh() resolve a name 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 *waitp);
-
-CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
- struct Curl_dns_entry **dns);
-
-int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks);
-
typedef enum {
DOH_OK,
DOH_DNS_BAD_LABEL, /* 1 */
@@ -69,6 +54,38 @@
DNS_TYPE_DNAME = 39 /* RFC6672 */
} DNStype;
+/* one of these for each DoH request */
+struct dnsprobe {
+ CURL *easy;
+ DNStype dnstype;
+ unsigned char dohbuffer[512];
+ size_t dohlen;
+ struct dynbuf serverdoh;
+};
+
+struct dohdata {
+ struct curl_slist *headers;
+ struct dnsprobe probe[DOH_PROBE_SLOTS];
+ unsigned int pending; /* still outstanding requests */
+ int port;
+ const char *host;
+};
+
+/*
+ * Curl_doh() resolve a name 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 *waitp);
+
+CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
+ struct Curl_dns_entry **dns);
+
+int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks);
+
#define DOH_MAX_ADDR 24
#define DOH_MAX_CNAME 4
diff --git a/lib/dotdot.c b/lib/dotdot.c
deleted file mode 100644
index 0b04531..0000000
--- a/lib/dotdot.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the 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 <curl/curl.h>
-
-#include "dotdot.h"
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
-/*
- * "Remove Dot Segments"
- * https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4
- */
-
-/*
- * Curl_dedotdotify()
- * @unittest: 1395
- *
- * This function gets a null-terminated path with dot and dotdot sequences
- * passed in and strips them off according to the rules in RFC 3986 section
- * 5.2.4.
- *
- * The function handles a query part ('?' + stuff) appended but it expects
- * that fragments ('#' + stuff) have already been cut off.
- *
- * RETURNS
- *
- * an allocated dedotdotified output string
- */
-char *Curl_dedotdotify(const char *input)
-{
- size_t inlen = strlen(input);
- char *clone;
- size_t clen = inlen; /* the length of the cloned input */
- char *out = malloc(inlen + 1);
- char *outptr;
- char *orgclone;
- char *queryp;
- if(!out)
- return NULL; /* out of memory */
-
- *out = 0; /* null-terminates, for inputs like "./" */
-
- /* get a cloned copy of the input */
- clone = strdup(input);
- if(!clone) {
- free(out);
- return NULL;
- }
- orgclone = clone;
- outptr = out;
-
- if(!*clone) {
- /* zero length string, return that */
- free(out);
- return clone;
- }
-
- /*
- * To handle query-parts properly, we must find it and remove it during the
- * dotdot-operation and then append it again at the end to the output
- * string.
- */
- queryp = strchr(clone, '?');
- if(queryp)
- *queryp = 0;
-
- do {
-
- /* A. If the input buffer begins with a prefix of "../" or "./", then
- remove that prefix from the input buffer; otherwise, */
-
- if(!strncmp("./", clone, 2)) {
- clone += 2;
- clen -= 2;
- }
- else if(!strncmp("../", clone, 3)) {
- clone += 3;
- clen -= 3;
- }
-
- /* B. if the input buffer begins with a prefix of "/./" or "/.", where
- "." is a complete path segment, then replace that prefix with "/" in
- the input buffer; otherwise, */
- else if(!strncmp("/./", clone, 3)) {
- clone += 2;
- clen -= 2;
- }
- else if(!strcmp("/.", clone)) {
- clone[1]='/';
- clone++;
- clen -= 1;
- }
-
- /* C. if the input buffer begins with a prefix of "/../" or "/..", where
- ".." is a complete path segment, then replace that prefix with "/" in
- the input buffer and remove the last segment and its preceding "/" (if
- any) from the output buffer; otherwise, */
-
- else if(!strncmp("/../", clone, 4)) {
- clone += 3;
- clen -= 3;
- /* remove the last segment from the output buffer */
- while(outptr > out) {
- outptr--;
- if(*outptr == '/')
- break;
- }
- *outptr = 0; /* null-terminate where it stops */
- }
- else if(!strcmp("/..", clone)) {
- clone[2]='/';
- clone += 2;
- clen -= 2;
- /* remove the last segment from the output buffer */
- while(outptr > out) {
- outptr--;
- if(*outptr == '/')
- break;
- }
- *outptr = 0; /* null-terminate where it stops */
- }
-
- /* D. if the input buffer consists only of "." or "..", then remove
- that from the input buffer; otherwise, */
-
- else if(!strcmp(".", clone) || !strcmp("..", clone)) {
- *clone = 0;
- *out = 0;
- }
-
- else {
- /* E. move the first path segment in the input buffer to the end of
- the output buffer, including the initial "/" character (if any) and
- any subsequent characters up to, but not including, the next "/"
- character or the end of the input buffer. */
-
- do {
- *outptr++ = *clone++;
- clen--;
- } while(*clone && (*clone != '/'));
- *outptr = 0;
- }
-
- } while(*clone);
-
- if(queryp) {
- size_t qlen;
- /* There was a query part, append that to the output. The 'clone' string
- may now have been altered so we copy from the original input string
- from the correct index. */
- size_t oindex = queryp - orgclone;
- qlen = strlen(&input[oindex]);
- memcpy(outptr, &input[oindex], qlen + 1); /* include the end zero byte */
- }
-
- free(orgclone);
- return out;
-}
diff --git a/lib/dotdot.h b/lib/dotdot.h
deleted file mode 100644
index 4ffe72d..0000000
--- a/lib/dotdot.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef HEADER_CURL_DOTDOT_H
-#define HEADER_CURL_DOTDOT_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-char *Curl_dedotdotify(const char *input);
-#endif /* HEADER_CURL_DOTDOT_H */
diff --git a/lib/dynbuf.c b/lib/dynbuf.c
index 3b907db..0c9c491 100644
--- a/lib/dynbuf.c
+++ b/lib/dynbuf.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -76,6 +76,7 @@
DEBUGASSERT(s->toobig);
DEBUGASSERT(indx < s->toobig);
DEBUGASSERT(!s->leng || s->bufr);
+ DEBUGASSERT(a <= s->toobig);
if(fit > s->toobig) {
Curl_dyn_free(s);
@@ -84,7 +85,9 @@
else if(!a) {
DEBUGASSERT(!indx);
/* first invoke */
- if(fit < MIN_FIRST_ALLOC)
+ if(MIN_FIRST_ALLOC > s->toobig)
+ a = s->toobig;
+ else if(fit < MIN_FIRST_ALLOC)
a = MIN_FIRST_ALLOC;
else
a = fit;
@@ -92,6 +95,9 @@
else {
while(a < fit)
a *= 2;
+ if(a > s->toobig)
+ /* no point in allocating a larger buffer than this is allowed to use */
+ a = s->toobig;
}
if(a != s->allc) {
@@ -99,8 +105,7 @@
include that as well when it uses this code */
void *p = realloc(s->bufr, a);
if(!p) {
- Curl_safefree(s->bufr);
- s->leng = s->allc = 0;
+ Curl_dyn_free(s);
return CURLE_OUT_OF_MEMORY;
}
s->bufr = p;
@@ -128,7 +133,6 @@
s->leng = 0;
}
-#ifdef USE_NGTCP2
/*
* Specify the size of the tail to keep (number of bytes from the end of the
* buffer). The rest will be dropped.
@@ -153,7 +157,6 @@
return CURLE_OK;
}
-#endif
/*
* Appends a buffer with length.
@@ -255,3 +258,18 @@
DEBUGASSERT(!s->leng || s->bufr);
return s->leng;
}
+
+/*
+ * Set a new (smaller) length.
+ */
+CURLcode Curl_dyn_setlen(struct dynbuf *s, size_t set)
+{
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ if(set > s->leng)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ s->leng = set;
+ s->bufr[s->leng] = 0;
+ return CURLE_OK;
+}
diff --git a/lib/dynbuf.h b/lib/dynbuf.h
index c1e9723..6291eab 100644
--- a/lib/dynbuf.h
+++ b/lib/dynbuf.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,6 +24,8 @@
*
***************************************************************************/
+#include <curl/curl.h>
+
#ifndef BUILDING_LIBCURL
/* this renames the functions so that the tool code can use the same code
without getting symbol collisions */
@@ -38,12 +40,13 @@
#define Curl_dyn_len(a) curlx_dyn_len(a)
#define Curl_dyn_reset(a) curlx_dyn_reset(a)
#define Curl_dyn_tail(a,b) curlx_dyn_tail(a,b)
+#define Curl_dyn_setlen(a,b) curlx_dyn_setlen(a,b)
#define curlx_dynbuf dynbuf /* for the struct name */
#endif
struct dynbuf {
char *bufr; /* point to a null-terminated allocated buffer */
- size_t leng; /* number of bytes *EXCLUDING* the zero terminator */
+ 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
@@ -63,6 +66,7 @@
WARN_UNUSED_RESULT;
void Curl_dyn_reset(struct dynbuf *s);
CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail);
+CURLcode Curl_dyn_setlen(struct dynbuf *s, size_t set);
char *Curl_dyn_ptr(const struct dynbuf *s);
unsigned char *Curl_dyn_uptr(const struct dynbuf *s);
size_t Curl_dyn_len(const struct dynbuf *s);
@@ -77,8 +81,6 @@
#define DYN_PAUSE_BUFFER (64 * 1024 * 1024)
#define DYN_HAXPROXY 2048
#define DYN_HTTP_REQUEST (1024*1024)
-#define DYN_H2_HEADERS (128*1024)
-#define DYN_H2_TRAILERS (128*1024)
#define DYN_APRINTF 8000000
#define DYN_RTSP_REQ_HEADER (64*1024)
#define DYN_TRAILERS (64*1024)
diff --git a/lib/dynhds.c b/lib/dynhds.c
new file mode 100644
index 0000000..007dfc5
--- /dev/null
+++ b/lib/dynhds.c
@@ -0,0 +1,366 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 "dynhds.h"
+#include "strcase.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+
+static struct dynhds_entry *
+entry_new(const char *name, size_t namelen,
+ const char *value, size_t valuelen, int opts)
+{
+ struct dynhds_entry *e;
+ char *p;
+
+ DEBUGASSERT(name);
+ DEBUGASSERT(value);
+ e = calloc(1, sizeof(*e) + namelen + valuelen + 2);
+ if(!e)
+ return NULL;
+ e->name = p = ((char *)e) + sizeof(*e);
+ memcpy(p, name, namelen);
+ e->namelen = namelen;
+ e->value = p += namelen + 1; /* leave a \0 at the end of name */
+ memcpy(p, value, valuelen);
+ e->valuelen = valuelen;
+ if(opts & DYNHDS_OPT_LOWERCASE)
+ Curl_strntolower(e->name, e->name, e->namelen);
+ return e;
+}
+
+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);
+ if(!e2)
+ return NULL;
+ e2->name = p = ((char *)e2) + sizeof(*e2);
+ memcpy(p, e->name, e->namelen);
+ e2->namelen = e->namelen;
+ e2->value = p += e->namelen + 1; /* leave a \0 at the end of name */
+ memcpy(p, e->value, e->valuelen);
+ p += e->valuelen;
+ p[0] = ' ';
+ memcpy(p + 1, value, valuelen);
+ e2->valuelen = valuelen2;
+ return e2;
+}
+
+static void entry_free(struct dynhds_entry *e)
+{
+ free(e);
+}
+
+void Curl_dynhds_init(struct dynhds *dynhds, size_t max_entries,
+ size_t max_strs_size)
+{
+ DEBUGASSERT(dynhds);
+ DEBUGASSERT(max_strs_size);
+ dynhds->hds = NULL;
+ dynhds->hds_len = dynhds->hds_allc = dynhds->strs_len = 0;
+ dynhds->max_entries = max_entries;
+ dynhds->max_strs_size = max_strs_size;
+ dynhds->opts = 0;
+}
+
+void Curl_dynhds_free(struct dynhds *dynhds)
+{
+ DEBUGASSERT(dynhds);
+ if(dynhds->hds && dynhds->hds_len) {
+ size_t i;
+ DEBUGASSERT(dynhds->hds);
+ for(i = 0; i < dynhds->hds_len; ++i) {
+ entry_free(dynhds->hds[i]);
+ }
+ }
+ Curl_safefree(dynhds->hds);
+ dynhds->hds_len = dynhds->hds_allc = dynhds->strs_len = 0;
+}
+
+void Curl_dynhds_reset(struct dynhds *dynhds)
+{
+ DEBUGASSERT(dynhds);
+ if(dynhds->hds_len) {
+ size_t i;
+ DEBUGASSERT(dynhds->hds);
+ for(i = 0; i < dynhds->hds_len; ++i) {
+ entry_free(dynhds->hds[i]);
+ dynhds->hds[i] = NULL;
+ }
+ }
+ dynhds->hds_len = dynhds->strs_len = 0;
+}
+
+size_t Curl_dynhds_count(struct dynhds *dynhds)
+{
+ return dynhds->hds_len;
+}
+
+void Curl_dynhds_set_opts(struct dynhds *dynhds, int opts)
+{
+ dynhds->opts = opts;
+}
+
+struct dynhds_entry *Curl_dynhds_getn(struct dynhds *dynhds, size_t n)
+{
+ DEBUGASSERT(dynhds);
+ return (n < dynhds->hds_len)? dynhds->hds[n] : NULL;
+}
+
+struct dynhds_entry *Curl_dynhds_get(struct dynhds *dynhds, const char *name,
+ size_t namelen)
+{
+ size_t i;
+ for(i = 0; i < dynhds->hds_len; ++i) {
+ if(dynhds->hds[i]->namelen == namelen &&
+ strncasecompare(dynhds->hds[i]->name, name, namelen)) {
+ return dynhds->hds[i];
+ }
+ }
+ return NULL;
+}
+
+struct dynhds_entry *Curl_dynhds_cget(struct dynhds *dynhds, const char *name)
+{
+ return Curl_dynhds_get(dynhds, name, strlen(name));
+}
+
+CURLcode Curl_dynhds_add(struct dynhds *dynhds,
+ const char *name, size_t namelen,
+ const char *value, size_t valuelen)
+{
+ struct dynhds_entry *entry = NULL;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+
+ DEBUGASSERT(dynhds);
+ if(dynhds->max_entries && dynhds->hds_len >= dynhds->max_entries)
+ return CURLE_OUT_OF_MEMORY;
+ if(dynhds->strs_len + namelen + valuelen > dynhds->max_strs_size)
+ return CURLE_OUT_OF_MEMORY;
+
+entry = entry_new(name, namelen, value, valuelen, dynhds->opts);
+ if(!entry)
+ goto out;
+
+ if(dynhds->hds_len + 1 >= dynhds->hds_allc) {
+ size_t nallc = dynhds->hds_len + 16;
+ struct dynhds_entry **nhds;
+
+ if(dynhds->max_entries && nallc > dynhds->max_entries)
+ nallc = dynhds->max_entries;
+
+ nhds = calloc(nallc, sizeof(struct dynhds_entry *));
+ if(!nhds)
+ goto out;
+ if(dynhds->hds) {
+ memcpy(nhds, dynhds->hds,
+ dynhds->hds_len * sizeof(struct dynhds_entry *));
+ Curl_safefree(dynhds->hds);
+ }
+ dynhds->hds = nhds;
+ dynhds->hds_allc = nallc;
+ }
+ dynhds->hds[dynhds->hds_len++] = entry;
+ entry = NULL;
+ dynhds->strs_len += namelen + valuelen;
+ result = CURLE_OK;
+
+out:
+ if(entry)
+ entry_free(entry);
+ return result;
+}
+
+CURLcode Curl_dynhds_cadd(struct dynhds *dynhds,
+ const char *name, const char *value)
+{
+ return Curl_dynhds_add(dynhds, name, strlen(name), value, strlen(value));
+}
+
+CURLcode Curl_dynhds_h1_add_line(struct dynhds *dynhds,
+ const char *line, size_t line_len)
+{
+ const char *p;
+ const char *name;
+ size_t namelen;
+ const char *value;
+ size_t valuelen, i;
+
+ if(!line || !line_len)
+ return CURLE_OK;
+
+ if((line[0] == ' ') || (line[0] == '\t')) {
+ struct dynhds_entry *e, *e2;
+ /* header continuation, yikes! */
+ if(!dynhds->hds_len)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ while(line_len && ISBLANK(line[0])) {
+ ++line;
+ --line_len;
+ }
+ if(!line_len)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ 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;
+ entry_free(e);
+ return CURLE_OK;
+ }
+ else {
+ p = memchr(line, ':', line_len);
+ if(!p)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ name = line;
+ namelen = p - line;
+ p++; /* move past the colon */
+ for(i = namelen + 1; i < line_len; ++i, ++p) {
+ if(!ISBLANK(*p))
+ break;
+ }
+ value = p;
+ valuelen = line_len - i;
+
+ p = memchr(value, '\r', valuelen);
+ if(!p)
+ p = memchr(value, '\n', valuelen);
+ if(p)
+ valuelen = (size_t)(p - value);
+
+ return Curl_dynhds_add(dynhds, name, namelen, value, valuelen);
+ }
+}
+
+CURLcode Curl_dynhds_h1_cadd_line(struct dynhds *dynhds, const char *line)
+{
+ return Curl_dynhds_h1_add_line(dynhds, line, line? strlen(line) : 0);
+}
+
+#ifdef DEBUGBUILD
+/* used by unit2602.c */
+
+bool Curl_dynhds_contains(struct dynhds *dynhds,
+ const char *name, size_t namelen)
+{
+ return !!Curl_dynhds_get(dynhds, name, namelen);
+}
+
+bool Curl_dynhds_ccontains(struct dynhds *dynhds, const char *name)
+{
+ return Curl_dynhds_contains(dynhds, name, strlen(name));
+}
+
+size_t Curl_dynhds_count_name(struct dynhds *dynhds,
+ const char *name, size_t namelen)
+{
+ size_t n = 0;
+ if(dynhds->hds_len) {
+ size_t i;
+ for(i = 0; i < dynhds->hds_len; ++i) {
+ if((namelen == dynhds->hds[i]->namelen) &&
+ strncasecompare(name, dynhds->hds[i]->name, namelen))
+ ++n;
+ }
+ }
+ return n;
+}
+
+size_t Curl_dynhds_ccount_name(struct dynhds *dynhds, const char *name)
+{
+ return Curl_dynhds_count_name(dynhds, name, strlen(name));
+}
+
+CURLcode Curl_dynhds_set(struct dynhds *dynhds,
+ const char *name, size_t namelen,
+ const char *value, size_t valuelen)
+{
+ Curl_dynhds_remove(dynhds, name, namelen);
+ return Curl_dynhds_add(dynhds, name, namelen, value, valuelen);
+}
+
+size_t Curl_dynhds_remove(struct dynhds *dynhds,
+ const char *name, size_t namelen)
+{
+ size_t n = 0;
+ if(dynhds->hds_len) {
+ size_t i, len;
+ for(i = 0; i < dynhds->hds_len; ++i) {
+ if((namelen == dynhds->hds[i]->namelen) &&
+ strncasecompare(name, dynhds->hds[i]->name, namelen)) {
+ ++n;
+ --dynhds->hds_len;
+ dynhds->strs_len -= (dynhds->hds[i]->namelen +
+ dynhds->hds[i]->valuelen);
+ entry_free(dynhds->hds[i]);
+ len = dynhds->hds_len - i; /* remaining entries */
+ if(len) {
+ memmove(&dynhds->hds[i], &dynhds->hds[i + 1],
+ len * sizeof(dynhds->hds[i]));
+ }
+ --i; /* do this index again */
+ }
+ }
+ }
+ return n;
+}
+
+size_t Curl_dynhds_cremove(struct dynhds *dynhds, const char *name)
+{
+ return Curl_dynhds_remove(dynhds, name, strlen(name));
+}
+
+CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf)
+{
+ CURLcode result = CURLE_OK;
+ size_t i;
+
+ if(!dynhds->hds_len)
+ return result;
+
+ for(i = 0; i < dynhds->hds_len; ++i) {
+ result = Curl_dyn_addf(dbuf, "%.*s: %.*s\r\n",
+ (int)dynhds->hds[i]->namelen, dynhds->hds[i]->name,
+ (int)dynhds->hds[i]->valuelen, dynhds->hds[i]->value);
+ if(result)
+ break;
+ }
+
+ return result;
+}
+
+#endif
diff --git a/lib/dynhds.h b/lib/dynhds.h
new file mode 100644
index 0000000..8a05348
--- /dev/null
+++ b/lib/dynhds.h
@@ -0,0 +1,174 @@
+#ifndef HEADER_CURL_DYNHDS_H
+#define HEADER_CURL_DYNHDS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+#include "dynbuf.h"
+
+struct dynbuf;
+
+/**
+ * A single header entry.
+ * `name` and `value` are non-NULL and always NUL terminated.
+ */
+struct dynhds_entry {
+ char *name;
+ char *value;
+ size_t namelen;
+ size_t valuelen;
+};
+
+struct dynhds {
+ struct dynhds_entry **hds;
+ size_t hds_len; /* number of entries in hds */
+ size_t hds_allc; /* size of hds allocation */
+ size_t max_entries; /* size limit number of entries */
+ size_t strs_len; /* length of all strings */
+ size_t max_strs_size; /* max length of all strings */
+ int opts;
+};
+
+#define DYNHDS_OPT_NONE (0)
+#define DYNHDS_OPT_LOWERCASE (1 << 0)
+
+/**
+ * Init for use on first time or after a reset.
+ * Allow `max_entries` headers to be added, 0 for unlimited.
+ * Allow size of all name and values added to not exceed `max_strs_size``
+ */
+void Curl_dynhds_init(struct dynhds *dynhds, size_t max_entries,
+ size_t max_strs_size);
+/**
+ * Frees all data held in `dynhds`, but not the struct itself.
+ */
+void Curl_dynhds_free(struct dynhds *dynhds);
+
+/**
+ * Reset `dyndns` to the initial init state. May keep allocations
+ * around.
+ */
+void Curl_dynhds_reset(struct dynhds *dynhds);
+
+/**
+ * Return the number of header entries.
+ */
+size_t Curl_dynhds_count(struct dynhds *dynhds);
+
+/**
+ * Set the options to use, replacing any existing ones.
+ * This will not have an effect on already existing headers.
+ */
+void Curl_dynhds_set_opts(struct dynhds *dynhds, int opts);
+
+/**
+ * Return the n-th header entry or NULL if it does not exist.
+ */
+struct dynhds_entry *Curl_dynhds_getn(struct dynhds *dynhds, size_t n);
+
+/**
+ * Return the 1st header entry of the name or NULL if none exists.
+ */
+struct dynhds_entry *Curl_dynhds_get(struct dynhds *dynhds,
+ const char *name, size_t namelen);
+struct dynhds_entry *Curl_dynhds_cget(struct dynhds *dynhds, const char *name);
+
+/**
+ * Return TRUE iff one or more headers with the given name exist.
+ */
+bool Curl_dynhds_contains(struct dynhds *dynhds,
+ const char *name, size_t namelen);
+bool Curl_dynhds_ccontains(struct dynhds *dynhds, const char *name);
+
+/**
+ * Return how often the given name appears in `dynhds`.
+ * Names are case-insensitive.
+ */
+size_t Curl_dynhds_count_name(struct dynhds *dynhds,
+ const char *name, size_t namelen);
+
+/**
+ * Return how often the given 0-terminated name appears in `dynhds`.
+ * Names are case-insensitive.
+ */
+size_t Curl_dynhds_ccount_name(struct dynhds *dynhds, const char *name);
+
+/**
+ * Add a header, name + value, to `dynhds` at the end. Does *not*
+ * check for duplicate names.
+ */
+CURLcode Curl_dynhds_add(struct dynhds *dynhds,
+ const char *name, size_t namelen,
+ const char *value, size_t valuelen);
+
+/**
+ * Add a header, c-string name + value, to `dynhds` at the end.
+ */
+CURLcode Curl_dynhds_cadd(struct dynhds *dynhds,
+ const char *name, const char *value);
+
+/**
+ * Remove all entries with the given name.
+ * Returns number of entries removed.
+ */
+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)
+ * entries.
+ */
+CURLcode Curl_dynhds_set(struct dynhds *dynhds,
+ const char *name, size_t namelen,
+ const char *value, size_t valuelen);
+
+CURLcode Curl_dynhds_cset(struct dynhds *dynhds,
+ const char *name, const char *value);
+
+/**
+ * Add a single header from a HTTP/1.1 formatted line at the end. Line
+ * may contain a delimiting \r\n or just \n. Any characters after
+ * that will be ignored.
+ */
+CURLcode Curl_dynhds_h1_cadd_line(struct dynhds *dynhds, const char *line);
+
+/**
+ * Add a single header from a HTTP/1.1 formatted line at the end. Line
+ * may contain a delimiting \r\n or just \n. Any characters after
+ * that will be ignored.
+ */
+CURLcode Curl_dynhds_h1_add_line(struct dynhds *dynhds,
+ const char *line, size_t line_len);
+
+/**
+ * Add the headers to the given `dynbuf` in HTTP/1.1 format with
+ * cr+lf line endings. Will NOT output a last empty line.
+ */
+CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf);
+
+#endif /* HEADER_CURL_DYNHDS_H */
diff --git a/lib/easy.c b/lib/easy.c
index 704a59d..d034629 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,14 +24,6 @@
#include "curl_setup.h"
-/*
- * See comment in curl_memory.h for the explanation of this sanity check.
- */
-
-#ifdef CURLX_NO_MEMORY_CALLBACKS
-#error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined"
-#endif
-
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
@@ -65,13 +57,14 @@
#include "easyif.h"
#include "multiif.h"
#include "select.h"
+#include "cfilters.h"
#include "sendf.h" /* for failf function prototype */
#include "connect.h" /* for Curl_getconnectinfo */
#include "slist.h"
#include "mime.h"
#include "amigaos.h"
+#include "macos.h"
#include "warnless.h"
-#include "multiif.h"
#include "sigpipe.h"
#include "vssh/ssh.h"
#include "setopt.h"
@@ -82,15 +75,16 @@
#include "altsvc.h"
#include "hsts.h"
+#include "easy_lock.h"
+
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-#include "easy_lock.h"
/* true globals -- for curl_global_init() and curl_global_cleanup() */
static unsigned int initialized;
-static long init_flags;
+static long easy_init_flags;
#ifdef GLOBAL_INIT_IS_THREADSAFE
@@ -113,7 +107,7 @@
#if defined(_WIN32_WCE)
#define system_strdup _strdup
#elif !defined(HAVE_STRDUP)
-#define system_strdup curlx_strdup
+#define system_strdup Curl_strdup
#else
#define system_strdup strdup
#endif
@@ -164,6 +158,11 @@
#endif
}
+ if(Curl_log_init()) {
+ DEBUGF(fprintf(stderr, "Error: Curl_log_init failed\n"));
+ goto fail;
+ }
+
if(!Curl_ssl_init()) {
DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
goto fail;
@@ -177,12 +176,17 @@
#endif
#ifdef __AMIGA__
- if(!Curl_amiga_init()) {
+ if(Curl_amiga_init()) {
DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
goto fail;
}
#endif
+ if(Curl_macos_init()) {
+ DEBUGF(fprintf(stderr, "Error: Curl_macos_init failed\n"));
+ goto fail;
+ }
+
if(Curl_resolver_global_init()) {
DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
goto fail;
@@ -201,7 +205,7 @@
}
#endif
- init_flags = flags;
+ easy_init_flags = flags;
#ifdef DEBUGBUILD
if(getenv("CURL_GLOBAL_INIT"))
@@ -211,7 +215,7 @@
return CURLE_OK;
- fail:
+fail:
initialized--; /* undo the increase */
return CURLE_FAILED_INIT;
}
@@ -276,7 +280,7 @@
/**
* curl_global_cleanup() globally cleanups curl, uses the value of
- * "init_flags" to determine what needs to be cleaned up and what doesn't.
+ * "easy_init_flags" to determine what needs to be cleaned up and what doesn't.
*/
void curl_global_cleanup(void)
{
@@ -296,7 +300,7 @@
Curl_resolver_global_cleanup();
#ifdef WIN32
- Curl_win32_cleanup(init_flags);
+ Curl_win32_cleanup(easy_init_flags);
#endif
Curl_amiga_cleanup();
@@ -310,7 +314,7 @@
free(leakpointer);
#endif
- init_flags = 0;
+ easy_init_flags = 0;
global_init_unlock();
}
@@ -725,7 +729,7 @@
else {
/* this multi handle will only ever have a single easy handled attached
to it, so make it use minimal hashes */
- multi = Curl_multi_handle(1, 3);
+ multi = Curl_multi_handle(1, 3, 7);
if(!multi)
return CURLE_OUT_OF_MEMORY;
data->multi_easy = multi;
@@ -789,14 +793,12 @@
*/
void curl_easy_cleanup(struct Curl_easy *data)
{
- SIGPIPE_VARIABLE(pipe_st);
-
- if(!data)
- return;
-
- sigpipe_ignore(data, &pipe_st);
- Curl_close(&data);
- sigpipe_restore(&pipe_st);
+ if(GOOD_EASY_HANDLE(data)) {
+ SIGPIPE_VARIABLE(pipe_st);
+ sigpipe_ignore(data, &pipe_st);
+ Curl_close(&data);
+ sigpipe_restore(&pipe_st);
+ }
}
/*
@@ -828,7 +830,7 @@
/* Copy src->set into dst->set first, then deal with the strings
afterwards */
dst->set = src->set;
- Curl_mime_initpart(&dst->set.mimepost, dst);
+ Curl_mime_initpart(&dst->set.mimepost);
/* clear all string pointers first */
memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
@@ -862,7 +864,7 @@
}
/* Duplicate mime data. */
- result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost);
+ result = Curl_mime_duppart(dst, &dst->set.mimepost, &src->set.mimepost);
if(src->set.resolve)
dst->state.resolve = dst->set.resolve;
@@ -897,6 +899,8 @@
/* the connection cache is setup on demand */
outcurl->state.conn_cache = NULL;
outcurl->state.lastconnect_id = -1;
+ outcurl->state.recent_conn_id = -1;
+ outcurl->id = -1;
outcurl->progress.flags = data->progress.flags;
outcurl->progress.callback = data->progress.callback;
@@ -913,11 +917,9 @@
goto fail;
}
- /* duplicate all values in 'change' */
- if(data->state.cookielist) {
- outcurl->state.cookielist =
- Curl_slist_duplicate(data->state.cookielist);
- if(!outcurl->state.cookielist)
+ if(data->set.cookielist) {
+ outcurl->set.cookielist = Curl_slist_duplicate(data->set.cookielist);
+ if(!outcurl->set.cookielist)
goto fail;
}
#endif
@@ -943,7 +945,7 @@
goto fail;
}
-#ifdef USE_ALTSVC
+#ifndef CURL_DISABLE_ALTSVC
if(data->asi) {
outcurl->asi = Curl_altsvc_init();
if(!outcurl->asi)
@@ -999,12 +1001,12 @@
return outcurl;
- fail:
+fail:
if(outcurl) {
#ifndef CURL_DISABLE_COOKIES
- curl_slist_free_all(outcurl->state.cookielist);
- outcurl->state.cookielist = NULL;
+ curl_slist_free_all(outcurl->set.cookielist);
+ outcurl->set.cookielist = NULL;
#endif
Curl_safefree(outcurl->state.buffer);
Curl_dyn_free(&outcurl->state.headerb);
@@ -1101,7 +1103,7 @@
k->keepon = newstate;
if(!(newstate & KEEP_RECV_PAUSE)) {
- Curl_http2_stream_pause(data, FALSE);
+ Curl_conn_ev_data_pause(data, FALSE);
if(data->state.tempcount) {
/* there are buffers for sending that can be delivered as the receive
@@ -1132,6 +1134,16 @@
}
}
+#ifdef USE_HYPER
+ if(!(newstate & KEEP_SEND_PAUSE)) {
+ /* need to wake the send body waker */
+ if(data->hyp.send_body_waker) {
+ hyper_waker_wake(data->hyp.send_body_waker);
+ data->hyp.send_body_waker = NULL;
+ }
+ }
+#endif
+
/* if there's no error and we're not pausing both directions, we want
to have this handle checked soon */
if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
@@ -1160,8 +1172,7 @@
}
-static CURLcode easy_connection(struct Curl_easy *data,
- curl_socket_t *sfd,
+static CURLcode easy_connection(struct Curl_easy *data, curl_socket_t *sfd,
struct connectdata **connp)
{
if(!data)
@@ -1215,16 +1226,36 @@
return result;
*n = (size_t)n1;
-
return CURLE_OK;
}
+#ifdef USE_WEBSOCKETS
+CURLcode Curl_connect_only_attach(struct Curl_easy *data)
+{
+ curl_socket_t sfd;
+ CURLcode result;
+ struct connectdata *c = NULL;
+
+ result = easy_connection(data, &sfd, &c);
+ if(result)
+ return result;
+
+ if(!data->conn)
+ /* on first invoke, the transfer has been detached from the connection and
+ needs to be reattached */
+ Curl_attach_connection(data, c);
+
+ return CURLE_OK;
+}
+#endif /* USE_WEBSOCKETS */
+
/*
- * Sends data over the connected socket. Use after successful
- * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ * Sends data over the connected socket.
+ *
+ * This is the private internal version of curl_easy_send()
*/
-CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
- size_t buflen, size_t *n)
+CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
+ size_t buflen, ssize_t *n)
{
curl_socket_t sfd;
CURLcode result;
@@ -1232,9 +1263,6 @@
struct connectdata *c = NULL;
SIGPIPE_VARIABLE(pipe_st);
- if(Curl_is_in_callback(data))
- return CURLE_RECURSIVE_API_CALL;
-
result = easy_connection(data, &sfd, &c);
if(result)
return result;
@@ -1256,12 +1284,29 @@
if(!result && !n1)
return CURLE_AGAIN;
- *n = (size_t)n1;
+ *n = n1;
return result;
}
/*
+ * Sends data over the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
+ size_t buflen, size_t *n)
+{
+ ssize_t written = 0;
+ CURLcode result;
+ if(Curl_is_in_callback(data))
+ return CURLE_RECURSIVE_API_CALL;
+
+ result = Curl_senddata(data, buffer, buflen, &written);
+ *n = (size_t)written;
+ return result;
+}
+
+/*
* Wrapper to call functions in Curl_conncache_foreach()
*
* Returns always 0.
@@ -1270,29 +1315,34 @@
struct connectdata *conn,
void *param)
{
- /* Param is unused. */
- (void)param;
+ struct curltime *now = param;
+ if(Curl_timediff(*now, conn->keepalive) <= data->set.upkeep_interval_ms)
+ return 0;
+
+ /* briefly attach for action */
+ Curl_attach_connection(data, conn);
if(conn->handler->connection_check) {
- /* briefly attach the connection to this transfer for the purpose of
- checking it */
- Curl_attach_connection(data, conn);
-
/* Do a protocol-specific keepalive check on the connection. */
conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE);
- /* detach the connection again */
- Curl_detach_connection(data);
}
+ else {
+ /* Do the generic action on the FIRSTSOCKE filter chain */
+ Curl_conn_keep_alive(data, conn, FIRSTSOCKET);
+ }
+ Curl_detach_connection(data);
+ conn->keepalive = *now;
return 0; /* continue iteration */
}
static CURLcode upkeep(struct conncache *conn_cache, void *data)
{
+ struct curltime now = Curl_now();
/* Loop over every connection and make connection alive. */
Curl_conncache_foreach(data,
conn_cache,
- data,
+ &now,
conn_upkeep);
return CURLE_OK;
}
diff --git a/lib/easy_lock.h b/lib/easy_lock.h
index 819f50c..6399a39 100644
--- a/lib/easy_lock.h
+++ b/lib/easy_lock.h
@@ -1,3 +1,5 @@
+#ifndef HEADER_CURL_EASY_LOCK_H
+#define HEADER_CURL_EASY_LOCK_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -5,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,17 +30,51 @@
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
+#ifdef __MINGW32__
+#ifndef __MINGW64_VERSION_MAJOR
+#if (__MINGW32_MAJOR_VERSION < 5) || \
+ (__MINGW32_MAJOR_VERSION == 5 && __MINGW32_MINOR_VERSION == 0)
+/* mingw >= 5.0.1 defines SRWLOCK, and slightly different from MS define */
+typedef PVOID SRWLOCK, *PSRWLOCK;
+#endif
+#endif
+#ifndef SRWLOCK_INIT
+#define SRWLOCK_INIT NULL
+#endif
+#endif /* __MINGW32__ */
+
#define curl_simple_lock SRWLOCK
#define CURL_SIMPLE_LOCK_INIT SRWLOCK_INIT
#define curl_simple_lock_lock(m) AcquireSRWLockExclusive(m)
#define curl_simple_lock_unlock(m) ReleaseSRWLockExclusive(m)
-#elif defined (HAVE_ATOMIC)
+#elif defined(HAVE_ATOMIC) && defined(HAVE_STDATOMIC_H)
#include <stdatomic.h>
+#if defined(HAVE_SCHED_YIELD)
+#include <sched.h>
+#endif
-#define curl_simple_lock atomic_bool
-#define CURL_SIMPLE_LOCK_INIT false
+#define curl_simple_lock atomic_int
+#define CURL_SIMPLE_LOCK_INIT 0
+
+/* a clang-thing */
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+
+#ifndef __INTEL_COMPILER
+/* The Intel compiler tries to look like GCC *and* clang *and* lies in its
+ __has_builtin() function, so override it. */
+
+/* if GCC on i386/x86_64 or if the built-in is present */
+#if ( (defined(__GNUC__) && !defined(__clang__)) && \
+ (defined(__i386__) || defined(__x86_64__))) || \
+ __has_builtin(__builtin_ia32_pause)
+#define HAVE_BUILTIN_IA32_PAUSE
+#endif
+
+#endif
static inline void curl_simple_lock_lock(curl_simple_lock *lock)
{
@@ -48,10 +84,10 @@
/* Reduce cache coherency traffic */
while(atomic_load_explicit(lock, memory_order_relaxed)) {
/* Reduce load (not mandatory) */
-#if defined(__i386__) || defined(__x86_64__)
+#ifdef HAVE_BUILTIN_IA32_PAUSE
__builtin_ia32_pause();
#elif defined(__aarch64__)
- asm volatile("yield" ::: "memory");
+ __asm__ volatile("yield" ::: "memory");
#elif defined(HAVE_SCHED_YIELD)
sched_yield();
#endif
@@ -69,3 +105,5 @@
#undef GLOBAL_INIT_IS_THREADSAFE
#endif
+
+#endif /* HEADER_CURL_EASY_LOCK_H */
diff --git a/lib/easygetopt.c b/lib/easygetopt.c
index a639bb3..2b8a521 100644
--- a/lib/easygetopt.c
+++ b/lib/easygetopt.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* ___|___/|_| ______|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/easyif.h b/lib/easyif.h
index 615df3f..6448952 100644
--- a/lib/easyif.h
+++ b/lib/easyif.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,6 +27,13 @@
/*
* Prototypes for library-wide functions provided by easy.c
*/
+CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
+ size_t buflen, ssize_t *n);
+
+#ifdef USE_WEBSOCKETS
+CURLcode Curl_connect_only_attach(struct Curl_easy *data);
+#endif
+
#ifdef CURLDEBUG
CURL_EXTERN CURLcode curl_easy_perform_ev(struct Curl_easy *easy);
#endif
diff --git a/lib/easyoptions.c b/lib/easyoptions.c
index c99f135..e69c658 100644
--- a/lib/easyoptions.c
+++ b/lib/easyoptions.c
@@ -1,11 +1,11 @@
/***************************************************************************
* _ _ ____ _
- * Project ___| | | | _ | |
+ * Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
- * ___|___/|_| ______|
+ * \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,6 +42,7 @@
{"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},
@@ -107,7 +108,8 @@
{"FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS,
CURLOT_LONG, 0},
{"FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD, CURLOT_VALUES, 0},
- {"FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOT_LONG, 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},
@@ -118,6 +120,7 @@
{"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},
@@ -162,7 +165,9 @@
{"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_ALLLOWFAILS, CURLOT_LONG, 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},
@@ -203,6 +208,7 @@
{"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},
@@ -239,12 +245,14 @@
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},
@@ -264,8 +272,8 @@
{"SASL_IR", CURLOPT_SASL_IR, CURLOT_LONG, 0},
{"SEEKDATA", CURLOPT_SEEKDATA, CURLOT_CBPTR, 0},
{"SEEKFUNCTION", CURLOPT_SEEKFUNCTION, CURLOT_FUNCTION, 0},
- {"SERVER_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT,
- CURLOT_LONG, CURLOT_FLAG_ALIAS},
+ {"SERVER_RESPONSE_TIMEOUT", CURLOPT_SERVER_RESPONSE_TIMEOUT,
+ CURLOT_LONG, 0},
{"SERVICE_NAME", CURLOPT_SERVICE_NAME, CURLOT_STRING, 0},
{"SHARE", CURLOPT_SHARE, CURLOT_OBJECT, 0},
{"SOCKOPTDATA", CURLOPT_SOCKOPTDATA, CURLOT_CBPTR, 0},
@@ -275,14 +283,14 @@
{"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_HOSTKEYDATA", CURLOPT_SSH_HOSTKEYDATA, CURLOT_CBPTR, 0},
- {"SSH_HOSTKEYFUNCTION", CURLOPT_SSH_HOSTKEYFUNCTION, 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},
@@ -351,10 +359,11 @@
{"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, 0, 0} /* end of table */
+ {NULL, CURLOPT_LASTENTRY, CURLOT_LONG, 0} /* end of table */
};
#ifdef DEBUGBUILD
@@ -364,6 +373,6 @@
*/
int Curl_easyopts_check(void)
{
- return ((CURLOPT_LASTENTRY%10000) != (317 + 1));
+ return ((CURLOPT_LASTENTRY%10000) != (323 + 1));
}
#endif
diff --git a/lib/easyoptions.h b/lib/easyoptions.h
index 33f816d..24b4cd9 100644
--- a/lib/easyoptions.h
+++ b/lib/easyoptions.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/escape.c b/lib/escape.c
index 650e409..56aa2b3 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -77,6 +77,9 @@
return curl_easy_unescape(NULL, string, length, NULL);
}
+/* Escapes for URL the given unescaped string of given length.
+ * 'data' is ignored since 7.82.0.
+ */
char *curl_easy_escape(struct Curl_easy *data, const char *string,
int inlength)
{
@@ -94,7 +97,7 @@
return strdup("");
while(length--) {
- unsigned char in = *string; /* we need to treat the characters unsigned */
+ unsigned char in = *string++; /* treat the characters unsigned */
if(Curl_isunreserved(in)) {
/* append this */
@@ -103,23 +106,34 @@
}
else {
/* encode it */
- if(Curl_dyn_addf(&d, "%%%02X", in))
+ const char hex[] = "0123456789ABCDEF";
+ char out[3]={'%'};
+ out[1] = hex[in>>4];
+ out[2] = hex[in & 0xf];
+ if(Curl_dyn_addn(&d, out, 3))
return NULL;
}
- string++;
}
return Curl_dyn_ptr(&d);
}
+static const unsigned char hextable[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
+ 0, 10, 11, 12, 13, 14, 15 /* 0x60 - 0x66 */
+};
+
+/* the input is a single hex digit */
+#define onehex2dec(x) hextable[x - '0']
+
/*
* Curl_urldecode() URL decodes the given string.
*
* Returns a pointer to a malloced string in *ostring with length given in
* *olen. If length == 0, the length is assumed to be strlen(string).
*
- * 'data' can be set to NULL
- *
* ctrl options:
* - REJECT_NADA: accept everything
* - REJECT_CTRL: rejects control characters (byte codes lower than 32) in
@@ -136,54 +150,47 @@
{
size_t alloc;
char *ns;
- size_t strindex = 0;
- unsigned long hex;
DEBUGASSERT(string);
DEBUGASSERT(ctrl >= REJECT_NADA); /* crash on TRUE/FALSE */
- alloc = (length?length:strlen(string)) + 1;
- ns = malloc(alloc);
+ alloc = (length?length:strlen(string));
+ ns = malloc(alloc + 1);
if(!ns)
return CURLE_OUT_OF_MEMORY;
- while(--alloc > 0) {
+ /* store output string */
+ *ostring = ns;
+
+ while(alloc) {
unsigned char in = *string;
if(('%' == in) && (alloc > 2) &&
ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
/* this is two hexadecimal digits following a '%' */
- char hexstr[3];
- char *ptr;
- hexstr[0] = string[1];
- hexstr[1] = string[2];
- hexstr[2] = 0;
+ in = (unsigned char)(onehex2dec(string[1]) << 4) | onehex2dec(string[2]);
- hex = strtoul(hexstr, &ptr, 16);
-
- in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */
-
- string += 2;
- alloc -= 2;
+ string += 3;
+ alloc -= 3;
+ }
+ else {
+ string++;
+ alloc--;
}
if(((ctrl == REJECT_CTRL) && (in < 0x20)) ||
((ctrl == REJECT_ZERO) && (in == 0))) {
- free(ns);
+ Curl_safefree(*ostring);
return CURLE_URL_MALFORMAT;
}
- ns[strindex++] = in;
- string++;
+ *ns++ = in;
}
- ns[strindex] = 0; /* terminate it */
+ *ns = 0; /* terminate it */
if(olen)
/* store output size */
- *olen = strindex;
-
- /* store output string */
- *ostring = ns;
+ *olen = ns - *ostring;
return CURLE_OK;
}
@@ -193,6 +200,7 @@
* pointer to a malloced string with length given in *olen.
* If length == 0, the length is assumed to be strlen(string).
* If olen == NULL, no output length is stored.
+ * 'data' is ignored since 7.82.0.
*/
char *curl_easy_unescape(struct Curl_easy *data, const char *string,
int length, int *olen)
@@ -200,7 +208,7 @@
char *str = NULL;
(void)data;
if(length >= 0) {
- size_t inputlen = length;
+ size_t inputlen = (size_t)length;
size_t outputlen;
CURLcode res = Curl_urldecode(string, inputlen, &str, &outputlen,
REJECT_NADA);
diff --git a/lib/escape.h b/lib/escape.h
index 61d4611..cdbb712 100644
--- a/lib/escape.h
+++ b/lib/escape.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/file.c b/lib/file.c
index 40a5e42..c751e88 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -71,6 +71,8 @@
#if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
#define DOS_FILESYSTEM 1
+#elif defined(__amigaos4__)
+#define AMIGA_FILESYSTEM 1
#endif
#ifdef OPEN_NEEDS_ARG3
@@ -148,9 +150,19 @@
char *actual_path;
#endif
size_t real_path_len;
+ CURLcode result;
- CURLcode result = Curl_urldecode(data->state.up.path, 0, &real_path,
- &real_path_len, REJECT_ZERO);
+ if(file->path) {
+ /* already connected.
+ * the handler->connect_it() is normally only called once, but
+ * FILE does a special check on setting up the connection which
+ * calls this explicitly. */
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ result = Curl_urldecode(data->state.up.path, 0, &real_path,
+ &real_path_len, REJECT_ZERO);
if(result)
return result;
@@ -196,13 +208,39 @@
return CURLE_URL_MALFORMAT;
}
+ #ifdef AMIGA_FILESYSTEM
+ /*
+ * A leading slash in an AmigaDOS path denotes the parent
+ * directory, and hence we block this as it is relative.
+ * Absolute paths start with 'volumename:', so we check for
+ * this first. Failing that, we treat the path as a real unix
+ * path, but only if the application was compiled with -lunix.
+ */
+ fd = -1;
+ file->path = real_path;
+
+ if(real_path[0] == '/') {
+ extern int __unix_path_semantics;
+ if(strchr(real_path + 1, ':')) {
+ /* Amiga absolute path */
+ fd = open_readonly(real_path + 1, O_RDONLY);
+ file->path++;
+ }
+ else if(__unix_path_semantics) {
+ /* -lunix fallback */
+ fd = open_readonly(real_path, O_RDONLY);
+ }
+ }
+ #else
fd = open_readonly(real_path, O_RDONLY);
file->path = real_path;
+ #endif
#endif
+ Curl_safefree(file->freepath);
file->freepath = real_path; /* free this when done */
file->fd = fd;
- if(!data->set.upload && (fd == -1)) {
+ if(!data->state.upload && (fd == -1)) {
failf(data, "Couldn't open file %s", data->state.up.path);
file_done(data, CURLE_FILE_COULDNT_READ_FILE, FALSE);
return CURLE_FILE_COULDNT_READ_FILE;
@@ -236,7 +274,7 @@
{
(void)dead_connection; /* not used */
(void)conn;
- return file_done(data, 0, 0);
+ return file_done(data, CURLE_OK, FALSE);
}
#ifdef DOS_FILESYSTEM
@@ -302,7 +340,7 @@
while(!result) {
size_t nread;
- size_t nwrite;
+ ssize_t nwrite;
size_t readcount;
result = Curl_fillreadbuffer(data, data->set.buffer_size, &readcount);
if(result)
@@ -313,7 +351,7 @@
nread = readcount;
- /*skip bytes before resume point*/
+ /* skip bytes before resume point */
if(data->state.resume_from) {
if((curl_off_t)nread <= data->state.resume_from) {
data->state.resume_from -= nread;
@@ -331,7 +369,7 @@
/* write the data to the target */
nwrite = write(fd, buf2, nread);
- if(nwrite != nread) {
+ if((size_t)nwrite != nread) {
result = CURLE_SEND_ERROR;
break;
}
@@ -384,7 +422,7 @@
Curl_pgrsStartNow(data);
- if(data->set.upload)
+ if(data->state.upload)
return file_upload(data);
file = data->req.p.file;
@@ -444,13 +482,13 @@
tm->tm_hour,
tm->tm_min,
tm->tm_sec,
- data->set.opt_no_body ? "": "\r\n");
+ data->req.no_body ? "": "\r\n");
result = Curl_client_write(data, CLIENTWRITE_HEADER, header, headerlen);
if(result)
return result;
/* set the file size to make it available post transfer */
Curl_pgrsSetDownloadSize(data, expected_size);
- if(data->set.opt_no_body)
+ if(data->req.no_body)
return result;
}
diff --git a/lib/file.h b/lib/file.h
index 826d453..4565525 100644
--- a/lib/file.h
+++ b/lib/file.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/fileinfo.c b/lib/fileinfo.c
index 7bbf24b..2be3b32 100644
--- a/lib/fileinfo.c
+++ b/lib/fileinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,7 +40,7 @@
if(!finfo)
return;
- Curl_safefree(finfo->info.b_data);
+ Curl_dyn_free(&finfo->buf);
free(finfo);
}
#endif
diff --git a/lib/fileinfo.h b/lib/fileinfo.h
index 5bad718..ce009da 100644
--- a/lib/fileinfo.h
+++ b/lib/fileinfo.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,10 +26,12 @@
#include <curl/curl.h>
#include "llist.h"
+#include "dynbuf.h"
struct fileinfo {
struct curl_fileinfo info;
struct Curl_llist_element list;
+ struct dynbuf buf;
};
struct fileinfo *Curl_fileinfo_alloc(void);
diff --git a/lib/fopen.c b/lib/fopen.c
index ad3691b..b6e3cad 100644
--- a/lib/fopen.c
+++ b/lib/fopen.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -56,13 +56,13 @@
int fd = -1;
*tempname = NULL;
- if(stat(filename, &sb) == -1 || !S_ISREG(sb.st_mode)) {
- /* a non-regular file, fallback to direct fopen() */
- *fh = fopen(filename, FOPEN_WRITETEXT);
- if(*fh)
- return CURLE_OK;
+ *fh = fopen(filename, FOPEN_WRITETEXT);
+ if(!*fh)
goto fail;
- }
+ if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode))
+ return CURLE_OK;
+ fclose(*fh);
+ *fh = NULL;
result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix));
if(result)
@@ -85,7 +85,7 @@
if((fstat(fd, &nsb) != -1) &&
(nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) {
/* if the user and group are the same, clone the original mode */
- if(fchmod(fd, sb.st_mode) == -1)
+ if(fchmod(fd, (mode_t)sb.st_mode) == -1)
goto fail;
}
}
@@ -106,7 +106,6 @@
free(tempstore);
- *tempname = NULL;
return result;
}
diff --git a/lib/fopen.h b/lib/fopen.h
index 289e55f..e3a919d 100644
--- a/lib/fopen.h
+++ b/lib/fopen.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/formdata.c b/lib/formdata.c
index f5ed365..2bdb9f2 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -59,7 +59,7 @@
*
* AddHttpPost()
*
- * Adds a HttpPost structure to the list, if parent_post is given becomes
+ * Adds an HttpPost structure to the list, if parent_post is given becomes
* a subpost of parent_post instead of a direct list element.
*
* Returns newly allocated HttpPost on success and NULL if malloc failed.
@@ -135,15 +135,13 @@
{
struct FormInfo *form_info;
form_info = calloc(1, sizeof(struct FormInfo));
- if(form_info) {
- if(value)
- form_info->value = value;
- if(contenttype)
- form_info->contenttype = contenttype;
- form_info->flags = HTTPPOST_FILENAME;
- }
- else
+ if(!form_info)
return NULL;
+ if(value)
+ form_info->value = value;
+ if(contenttype)
+ form_info->contenttype = contenttype;
+ form_info->flags = HTTPPOST_FILENAME;
if(parent_form_info) {
/* now, point our 'more' to the original 'more' */
@@ -199,7 +197,7 @@
* CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
* CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
* CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
- * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
+ * CURL_FORMADD_MEMORY if an HttpPost struct cannot be allocated
* CURL_FORMADD_MEMORY if some allocation for string copying failed.
* CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
*
@@ -251,8 +249,10 @@
}
}
else {
- /* This is not array-state, get next option */
- option = va_arg(params, CURLformoption);
+ /* This is not array-state, get next option. This gets an 'int' with
+ va_arg() because CURLformoption might be a smaller type than int and
+ might cause compiler warnings and wrong behavior. */
+ option = (CURLformoption)va_arg(params, int);
if(CURLFORM_END == option)
break;
}
@@ -715,10 +715,10 @@
CURLcode result;
curl_mimepart toppart;
- Curl_mime_initpart(&toppart, NULL); /* default form is empty */
+ Curl_mime_initpart(&toppart); /* default form is empty */
result = Curl_getformdata(NULL, &toppart, form, NULL);
if(!result)
- result = Curl_mime_prepare_headers(&toppart, "multipart/form-data",
+ result = Curl_mime_prepare_headers(NULL, &toppart, "multipart/form-data",
NULL, MIMESTRATEGY_FORM);
while(!result) {
diff --git a/lib/formdata.h b/lib/formdata.h
index c6c6397..caabb63 100644
--- a/lib/formdata.h
+++ b/lib/formdata.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/ftp.c b/lib/ftp.c
index e6e9821..c04daa8 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -43,11 +43,6 @@
#include <inet.h>
#endif
-#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
-#undef in_addr_t
-#define in_addr_t unsigned long
-#endif
-
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
@@ -65,6 +60,8 @@
#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
+#include "cfilters.h"
+#include "cf-socket.h"
#include "connect.h"
#include "strerror.h"
#include "inet_ntop.h"
@@ -74,7 +71,6 @@
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "url.h"
-#include "strcase.h"
#include "speedcheck.h"
#include "warnless.h"
#include "http_proxy.h"
@@ -97,14 +93,14 @@
/* Local API functions */
#ifndef DEBUGBUILD
-static void _state(struct Curl_easy *data,
- ftpstate newstate);
-#define state(x,y) _state(x,y)
+static void _ftp_state(struct Curl_easy *data,
+ ftpstate newstate);
+#define ftp_state(x,y) _ftp_state(x,y)
#else
-static void _state(struct Curl_easy *data,
- ftpstate newstate,
- int lineno);
-#define state(x,y) _state(x,y,__LINE__)
+static void _ftp_state(struct Curl_easy *data,
+ ftpstate newstate,
+ int lineno);
+#define ftp_state(x,y) _ftp_state(x,y,__LINE__)
#endif
static CURLcode ftp_sendquote(struct Curl_easy *data,
@@ -219,14 +215,8 @@
static void close_secondarysocket(struct Curl_easy *data,
struct connectdata *conn)
{
- if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
- Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
- conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
- }
- conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
-#ifndef CURL_DISABLE_PROXY
- conn->bits.proxy_ssl_connected[SECONDARYSOCKET] = FALSE;
-#endif
+ Curl_conn_close(data, SECONDARYSOCKET);
+ Curl_conn_cf_discard_all(data, conn, SECONDARYSOCKET);
}
/*
@@ -278,13 +268,13 @@
struct sockaddr_in add;
#endif
curl_socklen_t size = (curl_socklen_t) sizeof(add);
+ CURLcode result;
if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) {
size = sizeof(add);
s = accept(sock, (struct sockaddr *) &add, &size);
}
- Curl_closesocket(data, conn, sock); /* close the first socket */
if(CURL_SOCKET_BAD == s) {
failf(data, "Error accept()ing server connect");
@@ -295,9 +285,11 @@
not needing DO_MORE anymore */
conn->bits.do_more = FALSE;
- conn->sock[SECONDARYSOCKET] = s;
(void)curlx_nonblock(s, TRUE); /* enable non-blocking */
- conn->bits.sock_accepted = TRUE;
+ /* Replace any filter on SECONDARY with one listening on this socket */
+ result = Curl_conn_tcp_accepted_set(data, conn, SECONDARYSOCKET, &s);
+ if(result)
+ return result;
if(data->set.fsockopt) {
int error = 0;
@@ -441,15 +433,18 @@
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
+ bool connected;
- if(conn->bits.ftp_use_data_ssl) {
- /* since we only have a plaintext TCP connection here, we must now
- * do the TLS stuff */
- infof(data, "Doing the SSL/TLS handshake on the data stream");
- result = Curl_ssl_connect(data, conn, SECONDARYSOCKET);
+ DEBUGF(infof(data, "ftp InitiateTransfer()"));
+ if(conn->bits.ftp_use_data_ssl && data->set.ftp_use_port &&
+ !Curl_conn_is_ssl(conn, SECONDARYSOCKET)) {
+ result = Curl_ssl_cfilter_add(data, conn, SECONDARYSOCKET);
if(result)
return result;
}
+ result = Curl_conn_connect(data, SECONDARYSOCKET, TRUE, &connected);
+ if(result || !connected)
+ return result;
if(conn->proto.ftpc.state_saved == FTP_STOR) {
/* When we know we're uploading a specified file, we can get the file
@@ -468,7 +463,7 @@
}
conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return CURLE_OK;
}
@@ -497,31 +492,33 @@
if(timeout_ms < 0) {
/* if a timeout was already reached, bail out */
failf(data, "Accept timeout occurred while waiting server connect");
- return CURLE_FTP_ACCEPT_TIMEOUT;
+ result = CURLE_FTP_ACCEPT_TIMEOUT;
+ goto out;
}
/* see if the connection request is already here */
result = ReceivedServerConnect(data, connected);
if(result)
- return result;
+ goto out;
if(*connected) {
result = AcceptServerConnect(data);
if(result)
- return result;
+ goto out;
result = InitiateTransfer(data);
if(result)
- return result;
+ goto out;
}
else {
/* Add timeout to multi handle and break out of the loop */
- if(*connected == FALSE) {
- Curl_expire(data, data->set.accepttimeout > 0 ?
- data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT, 0);
- }
+ Curl_expire(data, data->set.accepttimeout ?
+ data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT,
+ EXPIRE_FTP_ACCEPT);
}
+out:
+ DEBUGF(infof(data, "ftp AllowServerConnect() -> %d", result));
return result;
}
@@ -594,7 +591,7 @@
* generically is a good idea.
*/
infof(data, "We got a 421 - timeout");
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return CURLE_OPERATION_TIMEDOUT;
}
@@ -673,7 +670,7 @@
* wait for more data anyway.
*/
}
- else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) {
+ else if(!Curl_conn_data_pending(data, FIRSTSOCKET)) {
switch(SOCKET_READABLE(sockfd, interval_ms)) {
case -1: /* select() error, stop reading */
failf(data, "FTP response aborted due to select/poll error: %d",
@@ -753,10 +750,10 @@
#endif
/* This is the ONLY way to change FTP state! */
-static void _state(struct Curl_easy *data,
- ftpstate newstate
+static void _ftp_state(struct Curl_easy *data,
+ ftpstate newstate
#ifdef DEBUGBUILD
- , int lineno
+ , int lineno
#endif
)
{
@@ -787,7 +784,7 @@
if(!result) {
struct ftp_conn *ftpc = &conn->proto.ftpc;
ftpc->ftp_trying_alternative = FALSE;
- state(data, FTP_USER);
+ ftp_state(data, FTP_USER);
}
return result;
}
@@ -797,7 +794,7 @@
{
CURLcode result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PWD");
if(!result)
- state(data, FTP_PWD);
+ ftp_state(data, FTP_PWD);
return result;
}
@@ -822,31 +819,18 @@
* handle ordinary commands.
*/
- if(SOCKS_STATE(conn->cnnct.state))
- return Curl_SOCKS_getsock(conn, socks, SECONDARYSOCKET);
+ DEBUGF(infof(data, "ftp_domore_getsock()"));
+ if(conn->cfilter[SECONDARYSOCKET]
+ && !Curl_conn_is_connected(conn, SECONDARYSOCKET))
+ return Curl_conn_get_select_socks(data, SECONDARYSOCKET, socks);
if(FTP_STOP == ftpc->state) {
int bits = GETSOCK_READSOCK(0);
- bool any = FALSE;
/* if stopped and still in this state, then we're also waiting for a
connect on the secondary connection */
socks[0] = conn->sock[FIRSTSOCKET];
-
- if(!data->set.ftp_use_port) {
- int s;
- int i;
- /* PORT is used to tell the server to connect to us, and during that we
- don't do happy eyeballs, but we do if we connect to the server */
- for(s = 1, i = 0; i<2; i++) {
- if(conn->tempsock[i] != CURL_SOCKET_BAD) {
- socks[s] = conn->tempsock[i];
- bits |= GETSOCK_WRITESOCK(s++);
- any = TRUE;
- }
- }
- }
- if(!any) {
+ if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
socks[1] = conn->sock[SECONDARYSOCKET];
bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1);
}
@@ -888,7 +872,7 @@
for all upcoming ones in the ftp->dirs[] array */
result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->entrypath);
if(!result)
- state(data, FTP_CWD);
+ ftp_state(data, FTP_CWD);
}
else {
if(ftpc->dirdepth) {
@@ -898,7 +882,7 @@
result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
ftpc->dirs[ftpc->cwdcount -1]);
if(!result)
- state(data, FTP_CWD);
+ ftp_state(data, FTP_CWD);
}
else {
/* No CWD necessary */
@@ -918,7 +902,7 @@
static CURLcode ftp_state_use_port(struct Curl_easy *data,
ftpport fcmd) /* start with this */
{
- CURLcode result = CURLE_OK;
+ CURLcode result = CURLE_FTP_PORT_FAILED;
struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
curl_socket_t portsock = CURL_SOCKET_BAD;
@@ -967,8 +951,10 @@
char *port_sep = NULL;
addr = calloc(addrlen + 1, 1);
- if(!addr)
- return CURLE_OUT_OF_MEMORY;
+ if(!addr) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
#ifdef ENABLE_IPV6
if(*string_ftpport == '[') {
@@ -1028,12 +1014,11 @@
if(port_min > port_max)
port_min = port_max = 0;
-
if(*addr != '\0') {
/* attempt to get the address of the given interface name */
- switch(Curl_if2ip(conn->ip_addr->ai_family,
+ switch(Curl_if2ip(conn->remote_addr->family,
#ifdef ENABLE_IPV6
- Curl_ipv6_scope(conn->ip_addr->ai_addr),
+ Curl_ipv6_scope(&conn->remote_addr->sa_addr),
conn->scope_id,
#endif
addr, hbuf, sizeof(hbuf))) {
@@ -1042,7 +1027,7 @@
host = addr;
break;
case IF2IP_AF_NOT_SUPPORTED:
- return CURLE_FTP_PORT_FAILED;
+ goto out;
case IF2IP_FOUND:
host = hbuf; /* use the hbuf for host name */
}
@@ -1060,8 +1045,7 @@
if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
failf(data, "getsockname() failed: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- free(addr);
- return CURLE_FTP_PORT_FAILED;
+ goto out;
}
switch(sa->sa_family) {
#ifdef ENABLE_IPV6
@@ -1073,8 +1057,9 @@
r = Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
break;
}
- if(!r)
- return CURLE_FTP_PORT_FAILED;
+ if(!r) {
+ goto out;
+ }
host = hbuf; /* use this host name */
possibly_non_local = FALSE; /* we know it is local now */
}
@@ -1094,20 +1079,15 @@
if(!res) {
failf(data, "failed to resolve the address provided to PORT: %s", host);
- free(addr);
- return CURLE_FTP_PORT_FAILED;
+ goto out;
}
- free(addr);
host = NULL;
/* step 2, create a socket for the requested address */
-
- portsock = CURL_SOCKET_BAD;
error = 0;
for(ai = res; ai; ai = ai->ai_next) {
- result = Curl_socket(data, ai, NULL, &portsock);
- if(result) {
+ if(Curl_socket_open(data, ai, NULL, conn->transport, &portsock)) {
error = SOCKERRNO;
continue;
}
@@ -1116,8 +1096,9 @@
if(!ai) {
failf(data, "socket failure: %s",
Curl_strerror(error, buffer, sizeof(buffer)));
- return CURLE_FTP_PORT_FAILED;
+ goto out;
}
+ DEBUGF(infof(data, "ftp_state_use_port(), opened socket"));
/* step 3, bind to a suitable local address */
@@ -1146,8 +1127,7 @@
if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
failf(data, "getsockname() failed: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- Curl_closesocket(data, conn, portsock);
- return CURLE_FTP_PORT_FAILED;
+ goto out;
}
port = port_min;
possibly_non_local = FALSE; /* don't try this again */
@@ -1156,8 +1136,7 @@
if(error != EADDRINUSE && error != EACCES) {
failf(data, "bind(port=%hu) failed: %s", port,
Curl_strerror(error, buffer, sizeof(buffer)));
- Curl_closesocket(data, conn, portsock);
- return CURLE_FTP_PORT_FAILED;
+ goto out;
}
}
else
@@ -1166,31 +1145,30 @@
port++;
}
- /* maybe all ports were in use already*/
+ /* maybe all ports were in use already */
if(port > port_max) {
failf(data, "bind() failed, we ran out of ports");
- Curl_closesocket(data, conn, portsock);
- return CURLE_FTP_PORT_FAILED;
+ goto out;
}
/* get the name again after the bind() so that we can extract the
port number it uses now */
sslen = sizeof(ss);
- if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
+ if(getsockname(portsock, sa, &sslen)) {
failf(data, "getsockname() failed: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- Curl_closesocket(data, conn, portsock);
- return CURLE_FTP_PORT_FAILED;
+ goto out;
}
+ DEBUGF(infof(data, "ftp_state_use_port(), socket bound to port %d", port));
/* step 4, listen on the socket */
if(listen(portsock, 1)) {
failf(data, "socket failure: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- Curl_closesocket(data, conn, portsock);
- return CURLE_FTP_PORT_FAILED;
+ goto out;
}
+ DEBUGF(infof(data, "ftp_state_use_port(), listening on %d", port));
/* step 5, send the proper FTP command */
@@ -1243,12 +1221,7 @@
if(result) {
failf(data, "Failure sending EPRT command: %s",
curl_easy_strerror(result));
- Curl_closesocket(data, conn, portsock);
- /* don't retry using PORT */
- ftpc->count1 = PORT;
- /* bail out */
- state(data, FTP_STOP);
- return result;
+ goto out;
}
break;
}
@@ -1274,10 +1247,7 @@
if(result) {
failf(data, "Failure sending PORT command: %s",
curl_easy_strerror(result));
- Curl_closesocket(data, conn, portsock);
- /* bail out */
- state(data, FTP_STOP);
- return result;
+ goto out;
}
break;
}
@@ -1286,23 +1256,20 @@
/* store which command was sent */
ftpc->count1 = fcmd;
- close_secondarysocket(data, conn);
+ /* Replace any filter on SECONDARY with one listening on this socket */
+ result = Curl_conn_tcp_listen_set(data, conn, SECONDARYSOCKET, &portsock);
+ if(result)
+ goto out;
+ portsock = CURL_SOCKET_BAD; /* now held in filter */
+ ftp_state(data, FTP_PORT);
- /* we set the secondary socket variable to this for now, it is only so that
- the cleanup function will close it in case we fail before the true
- secondary stuff is made */
- conn->sock[SECONDARYSOCKET] = portsock;
-
- /* this tcpconnect assignment below is a hackish work-around to make the
- multi interface with active FTP work - as it will not wait for a
- (passive) connect in Curl_is_connected().
-
- The *proper* fix is to make sure that the active connection from the
- server is done in a non-blocking way. Currently, it is still BLOCKING.
- */
- conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
-
- state(data, FTP_PORT);
+out:
+ if(result) {
+ ftp_state(data, FTP_STOP);
+ }
+ if(portsock != CURL_SOCKET_BAD)
+ Curl_socket_close(data, conn, portsock);
+ free(addr);
return result;
}
@@ -1340,7 +1307,7 @@
result = Curl_pp_sendf(data, &ftpc->pp, "%s", mode[modeoff]);
if(!result) {
ftpc->count1 = modeoff;
- state(data, FTP_PASV);
+ ftp_state(data, FTP_PASV);
infof(data, "Connect data stream passively");
}
return result;
@@ -1363,7 +1330,7 @@
/* doesn't transfer any data */
/* still possibly do PRE QUOTE jobs */
- state(data, FTP_RETR_PREQUOTE);
+ ftp_state(data, FTP_RETR_PREQUOTE);
result = ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE);
}
else if(data->set.ftp_use_port) {
@@ -1381,14 +1348,14 @@
data->set.str[STRING_CUSTOMREQUEST]?
data->set.str[STRING_CUSTOMREQUEST]:
(data->state.list_only?"NLST":"LIST"));
- else if(data->set.upload)
+ else if(data->state.upload)
result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s",
conn->proto.ftpc.file);
else
result = Curl_pp_sendf(data, &ftpc->pp, "PRET RETR %s",
conn->proto.ftpc.file);
if(!result)
- state(data, FTP_PRET);
+ ftp_state(data, FTP_PRET);
}
else
result = ftp_state_use_pasv(data, conn);
@@ -1410,7 +1377,7 @@
whether it supports range */
result = Curl_pp_sendf(data, &ftpc->pp, "REST %d", 0);
if(!result)
- state(data, FTP_REST);
+ ftp_state(data, FTP_REST);
}
else
result = ftp_state_prepare_transfer(data);
@@ -1431,7 +1398,7 @@
/* we know ftpc->file is a valid pointer to a file name */
result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
if(!result)
- state(data, FTP_SIZE);
+ ftp_state(data, FTP_SIZE);
}
else
result = ftp_state_rest(data, conn);
@@ -1499,7 +1466,7 @@
free(cmd);
if(!result)
- state(data, FTP_LIST);
+ ftp_state(data, FTP_LIST);
return result;
}
@@ -1526,7 +1493,7 @@
/* If we have selected NOBODY and HEADER, it means that we only want file
information. Which in FTP can't be much more than the file size and
date. */
- if(data->set.opt_no_body && ftpc->file &&
+ if(data->req.no_body && ftpc->file &&
ftp_need_type(conn, data->state.prefer_ascii)) {
/* The SIZE command is _not_ RFC 959 specified, and therefore many servers
may not support it! It is however the only way we have to get a file's
@@ -1563,7 +1530,7 @@
result = Curl_pp_sendf(data, &ftpc->pp, "MDTM %s", ftpc->file);
if(!result)
- state(data, FTP_MDTM);
+ ftp_state(data, FTP_MDTM);
}
else
result = ftp_state_type(data);
@@ -1602,7 +1569,7 @@
/* Got no given size to start from, figure it out */
result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
if(!result)
- state(data, FTP_STOR_SIZE);
+ ftp_state(data, FTP_STOR_SIZE);
return result;
}
@@ -1657,7 +1624,7 @@
* ftp_done() because we didn't transfer anything! */
ftp->transfer = PPTRANSFER_NONE;
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return CURLE_OK;
}
}
@@ -1667,7 +1634,7 @@
result = Curl_pp_sendf(data, &ftpc->pp, append?"APPE %s":"STOR %s",
ftpc->file);
if(!result)
- state(data, FTP_STOR);
+ ftp_state(data, FTP_STOR);
return result;
}
@@ -1728,7 +1695,7 @@
result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
if(result)
return result;
- state(data, instate);
+ ftp_state(data, instate);
quote = TRUE;
}
}
@@ -1742,7 +1709,7 @@
break;
case FTP_RETR_PREQUOTE:
if(ftp->transfer != PPTRANSFER_BODY)
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
else {
if(ftpc->known_filesize != -1) {
Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
@@ -1764,12 +1731,12 @@
*/
result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
if(!result)
- state(data, FTP_RETR);
+ ftp_state(data, FTP_RETR);
}
else {
result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
if(!result)
- state(data, FTP_RETR_SIZE);
+ ftp_state(data, FTP_RETR_SIZE);
}
}
}
@@ -1805,13 +1772,15 @@
infof(data, "Failed EPSV attempt. Disabling EPSV");
/* disable it for next transfer */
conn->bits.ftp_use_epsv = FALSE;
+ Curl_conn_close(data, SECONDARYSOCKET);
+ Curl_conn_cf_discard_all(data, conn, SECONDARYSOCKET);
data->state.errorbuf = FALSE; /* allow error message to get
rewritten */
result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PASV");
if(!result) {
conn->proto.ftpc.count1++;
/* remain in/go to the FTP_PASV state */
- state(data, FTP_PASV);
+ ftp_state(data, FTP_PASV);
}
return result;
}
@@ -1830,6 +1799,29 @@
return conn->primary_ip;
}
+static bool match_pasv_6nums(const char *p,
+ unsigned int *array) /* 6 numbers */
+{
+ int i;
+ for(i = 0; i < 6; i++) {
+ unsigned long num;
+ char *endp;
+ if(i) {
+ if(*p != ',')
+ return FALSE;
+ p++;
+ }
+ if(!ISDIGIT(*p))
+ return FALSE;
+ num = strtoul(p, &endp, 10);
+ if(num > 255)
+ return FALSE;
+ array[i] = (unsigned int)num;
+ p = endp;
+ }
+ return TRUE;
+}
+
static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
int ftpcode)
{
@@ -1849,27 +1841,18 @@
/* positive EPSV response */
char *ptr = strchr(str, '(');
if(ptr) {
- unsigned int num;
- char separator[4];
+ char sep;
ptr++;
- if(5 == sscanf(ptr, "%c%c%c%u%c",
- &separator[0],
- &separator[1],
- &separator[2],
- &num,
- &separator[3])) {
- const char sep1 = separator[0];
- int i;
-
- /* The four separators should be identical, or else this is an oddly
- formatted reply and we bail out immediately. */
- for(i = 1; i<4; i++) {
- if(separator[i] != sep1) {
- ptr = NULL; /* set to NULL to signal error */
- break;
- }
- }
- if(num > 0xffff) {
+ /* |||12345| */
+ sep = ptr[0];
+ /* the ISDIGIT() check here is because strtoul() accepts leading minus
+ etc */
+ if((ptr[1] == sep) && (ptr[2] == sep) && ISDIGIT(ptr[3])) {
+ char *endp;
+ unsigned long num = strtoul(&ptr[3], &endp, 10);
+ if(*endp != sep)
+ ptr = NULL;
+ else if(num > 0xffff) {
failf(data, "Illegal port number in EPSV reply");
return CURLE_FTP_WEIRD_PASV_REPLY;
}
@@ -1891,8 +1874,7 @@
else if((ftpc->count1 == 1) &&
(ftpcode == 227)) {
/* positive PASV response */
- unsigned int ip[4] = {0, 0, 0, 0};
- unsigned int port[2] = {0, 0};
+ unsigned int ip[6];
/*
* Scan for a sequence of six comma-separated numbers and use them as
@@ -1904,15 +1886,12 @@
* "227 Entering passive mode. 127,0,0,1,4,51"
*/
while(*str) {
- if(6 == sscanf(str, "%u,%u,%u,%u,%u,%u",
- &ip[0], &ip[1], &ip[2], &ip[3],
- &port[0], &port[1]))
+ if(match_pasv_6nums(str, ip))
break;
str++;
}
- if(!*str || (ip[0] > 255) || (ip[1] > 255) || (ip[2] > 255) ||
- (ip[3] > 255) || (port[0] > 255) || (port[1] > 255) ) {
+ if(!*str) {
failf(data, "Couldn't interpret the 227-response");
return CURLE_FTP_WEIRD_227_FORMAT;
}
@@ -1932,7 +1911,7 @@
if(!ftpc->newhost)
return CURLE_OUT_OF_MEMORY;
- ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff);
+ ftpc->newport = (unsigned short)(((ip[4]<<8) + ip[5]) & 0xffff);
}
else if(ftpc->count1 == 0) {
/* EPSV failed, move on to PASV */
@@ -1952,7 +1931,7 @@
*/
const char * const host_name = conn->bits.socksproxy ?
conn->socks_proxy.host.name : conn->http_proxy.host.name;
- rc = Curl_resolv(data, host_name, (int)conn->port, FALSE, &addr);
+ rc = Curl_resolv(data, host_name, conn->port, FALSE, &addr);
if(rc == CURLRESOLV_PENDING)
/* BLOCKING, ignores the return code but 'addr' will be NULL in
case of failure */
@@ -1974,7 +1953,7 @@
/* postponed address resolution in case of tcp fastopen */
if(conn->bits.tcp_fastopen && !conn->bits.reuse && !ftpc->newhost[0]) {
- Curl_conninfo_remote(data, conn, conn->sock[FIRSTSOCKET]);
+ Curl_conn_ev_update_info(data, conn);
Curl_safefree(ftpc->newhost);
ftpc->newhost = strdup(control_address(conn));
if(!ftpc->newhost)
@@ -1994,8 +1973,9 @@
}
}
- conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
- result = Curl_connecthost(data, conn, addr);
+ result = Curl_conn_setup(data, conn, SECONDARYSOCKET, addr,
+ conn->bits.ftp_use_data_ssl?
+ CURL_CF_SSL_ENABLE : CURL_CF_SSL_DISABLE);
if(result) {
Curl_resolv_unlock(data, addr); /* we're done using this address */
@@ -2025,7 +2005,7 @@
return CURLE_OUT_OF_MEMORY;
conn->bits.do_more = TRUE;
- state(data, FTP_STOP); /* this phase is completed */
+ ftp_state(data, FTP_STOP); /* this phase is completed */
return result;
}
@@ -2059,13 +2039,37 @@
}
else {
infof(data, "Connect data stream actively");
- state(data, FTP_STOP); /* end of DO phase */
+ ftp_state(data, FTP_STOP); /* end of DO phase */
result = ftp_dophase_done(data, FALSE);
}
return result;
}
+static int twodigit(const char *p)
+{
+ return (p[0]-'0') * 10 + (p[1]-'0');
+}
+
+static bool ftp_213_date(const char *p, int *year, int *month, int *day,
+ int *hour, int *minute, int *second)
+{
+ size_t len = strlen(p);
+ if(len < 14)
+ return FALSE;
+ *year = twodigit(&p[0]) * 100 + twodigit(&p[2]);
+ *month = twodigit(&p[4]);
+ *day = twodigit(&p[6]);
+ *hour = twodigit(&p[8]);
+ *minute = twodigit(&p[10]);
+ *second = twodigit(&p[12]);
+
+ if((*month > 12) || (*day > 31) || (*hour > 23) || (*minute > 59) ||
+ (*second > 60))
+ return FALSE;
+ return TRUE;
+}
+
static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
int ftpcode)
{
@@ -2080,8 +2084,8 @@
/* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
last .sss part is optional and means fractions of a second */
int year, month, day, hour, minute, second;
- if(6 == sscanf(&data->state.buffer[4], "%04d%02d%02d%02d%02d%02d",
- &year, &month, &day, &hour, &minute, &second)) {
+ if(ftp_213_date(&data->state.buffer[4],
+ &year, &month, &day, &hour, &minute, &second)) {
/* we have a time, reformat it */
char timebuf[24];
msnprintf(timebuf, sizeof(timebuf),
@@ -2093,9 +2097,9 @@
#ifdef CURL_FTP_HTTPSTYLE_HEAD
/* If we asked for a time of the file and we actually got one as well,
- we "emulate" a HTTP-style header in our output. */
+ we "emulate" an HTTP-style header in our output. */
- if(data->set.opt_no_body &&
+ if(data->req.no_body &&
ftpc->file &&
data->set.get_filetime &&
(data->info.filetime >= 0) ) {
@@ -2130,9 +2134,11 @@
default:
infof(data, "unsupported MDTM reply format");
break;
- case 550: /* "No such file or directory" */
- failf(data, "Given file does not exist");
- result = CURLE_REMOTE_FILE_NOT_FOUND;
+ case 550: /* 550 is used for several different problems, e.g.
+ "No such file or directory" or "Permission denied".
+ It does not mean that the file does not exist at all. */
+ infof(data, "MDTM failed: file does not exist or permission problem,"
+ " continuing");
break;
}
@@ -2145,7 +2151,7 @@
infof(data, "The requested document is not new enough");
ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
data->info.timecond = TRUE;
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return CURLE_OK;
}
break;
@@ -2154,7 +2160,7 @@
infof(data, "The requested document is not old enough");
ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
data->info.timecond = TRUE;
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return CURLE_OK;
}
break;
@@ -2209,6 +2215,7 @@
struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
+ DEBUGF(infof(data, "ftp_state_retr()"));
if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
failf(data, "Maximum file size exceeded");
return CURLE_FILESIZE_EXCEEDED;
@@ -2261,7 +2268,7 @@
/* Set ->transfer so that we won't get any error in ftp_done()
* because we didn't transfer the any file */
ftp->transfer = PPTRANSFER_NONE;
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return CURLE_OK;
}
@@ -2272,13 +2279,13 @@
result = Curl_pp_sendf(data, &ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
data->state.resume_from);
if(!result)
- state(data, FTP_RETR_REST);
+ ftp_state(data, FTP_RETR_REST);
}
else {
/* no resume */
result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
if(!result)
- state(data, FTP_RETR);
+ ftp_state(data, FTP_RETR);
}
return result;
@@ -2309,7 +2316,7 @@
else
fdigit = start;
/* ignores parsing errors, which will make the size remain unknown */
- (void)curlx_strtoofft(fdigit, NULL, 0, &filesize);
+ (void)curlx_strtoofft(fdigit, NULL, 10, &filesize);
}
else if(ftpcode == 550) { /* "No such file or directory" */
@@ -2378,7 +2385,7 @@
else {
result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
if(!result)
- state(data, FTP_RETR);
+ ftp_state(data, FTP_RETR);
}
break;
}
@@ -2394,7 +2401,7 @@
if(ftpcode >= 400) {
failf(data, "Failed FTP upload: %0d", ftpcode);
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
/* oops, we never close the sockets! */
return CURLE_UPLOAD_FAILED;
}
@@ -2405,7 +2412,7 @@
if(data->set.ftp_use_port) {
bool connected;
- state(data, FTP_STOP); /* no longer in STOR state */
+ ftp_state(data, FTP_STOP); /* no longer in STOR state */
result = AllowServerConnect(data, &connected);
if(result)
@@ -2464,6 +2471,7 @@
if((instate != FTP_LIST) &&
!data->state.prefer_ascii &&
+ !data->set.ignorecl &&
(ftp->downloadsize < 1)) {
/*
* It seems directory listings either don't show the size or very
@@ -2494,7 +2502,7 @@
if(bytes) {
++bytes;
/* get the number! */
- (void)curlx_strtoofft(bytes, NULL, 0, &size);
+ (void)curlx_strtoofft(bytes, NULL, 10, &size);
}
}
}
@@ -2527,7 +2535,7 @@
if(!connected) {
struct ftp_conn *ftpc = &conn->proto.ftpc;
infof(data, "Data conn was not available immediately");
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
ftpc->wait_data_conn = TRUE;
}
}
@@ -2538,7 +2546,7 @@
if((instate == FTP_LIST) && (ftpcode == 450)) {
/* simply no matching files in the dir listing */
ftp->transfer = PPTRANSFER_NONE; /* don't download anything */
- state(data, FTP_STOP); /* this phase is over */
+ ftp_state(data, FTP_STOP); /* this phase is over */
}
else {
failf(data, "RETR response: %03d", ftpcode);
@@ -2574,7 +2582,7 @@
*/
result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "PBSZ %d", 0);
if(!result)
- state(data, FTP_PBSZ);
+ ftp_state(data, FTP_PBSZ);
}
else {
result = ftp_state_pwd(data, conn);
@@ -2584,13 +2592,11 @@
/* for USER and PASS responses */
static CURLcode ftp_state_user_resp(struct Curl_easy *data,
- int ftpcode,
- ftpstate instate)
+ int ftpcode)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- (void)instate; /* no use for this yet */
/* some need password anyway, and others just return 2xx ignored */
if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
@@ -2599,7 +2605,7 @@
result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s",
conn->passwd?conn->passwd:"");
if(!result)
- state(data, FTP_PASS);
+ ftp_state(data, FTP_PASS);
}
else if(ftpcode/100 == 2) {
/* 230 User ... logged in.
@@ -2611,7 +2617,7 @@
result = Curl_pp_sendf(data, &ftpc->pp, "ACCT %s",
data->set.str[STRING_FTP_ACCOUNT]);
if(!result)
- state(data, FTP_ACCT);
+ ftp_state(data, FTP_ACCT);
}
else {
failf(data, "ACCT requested but none available");
@@ -2632,7 +2638,7 @@
data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
if(!result) {
ftpc->ftp_trying_alternative = TRUE;
- state(data, FTP_USER);
+ ftp_state(data, FTP_USER);
}
}
else {
@@ -2667,7 +2673,7 @@
int ftpcode;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
- static const char ftpauth[][4] = { "SSL", "TLS" };
+ static const char * const ftpauth[] = { "SSL", "TLS" };
size_t nread = 0;
if(pp->sendleft)
@@ -2685,7 +2691,7 @@
/* 230 User logged in - already! Take as 220 if TLS required. */
if(data->set.use_ssl <= CURLUSESSL_TRY ||
conn->bits.ftp_use_control_ssl)
- return ftp_state_user_resp(data, ftpcode, ftpc->state);
+ return ftp_state_user_resp(data, ftpcode);
}
else if(ftpcode != 220) {
failf(data, "Got a %03d ftp-server response when 220 was expected",
@@ -2735,7 +2741,7 @@
result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
ftpauth[ftpc->count1]);
if(!result)
- state(data, FTP_AUTH);
+ ftp_state(data, FTP_AUTH);
}
else
result = ftp_state_user(data, conn);
@@ -2755,8 +2761,16 @@
*/
if((ftpcode == 234) || (ftpcode == 334)) {
- /* Curl_ssl_connect is BLOCKING */
- result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
+ /* this was BLOCKING, keep it so for now */
+ bool done;
+ if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
+ result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
+ if(result) {
+ /* we failed and bail out */
+ return CURLE_USE_SSL_FAILED;
+ }
+ }
+ result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, &done);
if(!result) {
conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
conn->bits.ftp_use_control_ssl = TRUE; /* SSL on control */
@@ -2782,7 +2796,7 @@
case FTP_USER:
case FTP_PASS:
- result = ftp_state_user_resp(data, ftpcode, ftpc->state);
+ result = ftp_state_user_resp(data, ftpcode);
break;
case FTP_ACCT:
@@ -2794,7 +2808,7 @@
Curl_pp_sendf(data, &ftpc->pp, "PROT %c",
data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
if(!result)
- state(data, FTP_PROT);
+ ftp_state(data, FTP_PROT);
break;
case FTP_PROT:
@@ -2813,7 +2827,7 @@
*/
result = Curl_pp_sendf(data, &ftpc->pp, "%s", "CCC");
if(!result)
- state(data, FTP_CCC);
+ ftp_state(data, FTP_CCC);
}
else
result = ftp_state_pwd(data, conn);
@@ -2822,7 +2836,7 @@
case FTP_CCC:
if(ftpcode < 500) {
/* First shut down the SSL layer (note: this call will block) */
- result = Curl_ssl_shutdown(data, conn, FIRSTSOCKET);
+ result = Curl_ssl_cfilter_remove(data, FIRSTSOCKET);
if(result)
failf(data, "Failed to clear the command channel (CCC)");
@@ -2905,7 +2919,7 @@
infof(data, "Entry path is '%s'", ftpc->entrypath);
/* also save it where getinfo can access it: */
data->state.most_recent_ftp_entrypath = ftpc->entrypath;
- state(data, FTP_SYST);
+ ftp_state(data, FTP_SYST);
break;
}
@@ -2921,7 +2935,7 @@
infof(data, "Failed to figure out path");
}
}
- state(data, FTP_STOP); /* we are done with the CONNECT phase! */
+ ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
DEBUGF(infof(data, "protocol connect phase DONE"));
break;
@@ -2956,7 +2970,7 @@
/* remember target server OS */
Curl_safefree(ftpc->server_os);
ftpc->server_os = os;
- state(data, FTP_NAMEFMT);
+ ftp_state(data, FTP_NAMEFMT);
break;
}
/* Nothing special for the target server. */
@@ -2968,7 +2982,7 @@
/* Cannot identify server OS. Continue anyway and cross fingers. */
}
- state(data, FTP_STOP); /* we are done with the CONNECT phase! */
+ ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
DEBUGF(infof(data, "protocol connect phase DONE"));
break;
@@ -2979,7 +2993,7 @@
break;
}
- state(data, FTP_STOP); /* we are done with the CONNECT phase! */
+ ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
DEBUGF(infof(data, "protocol connect phase DONE"));
break;
@@ -3012,7 +3026,7 @@
result = Curl_pp_sendf(data, &ftpc->pp, "MKD %s",
ftpc->dirs[ftpc->cwdcount - 1]);
if(!result)
- state(data, FTP_MKD);
+ ftp_state(data, FTP_MKD);
}
else {
/* return failure */
@@ -3041,7 +3055,7 @@
result = CURLE_REMOTE_ACCESS_DENIED;
}
else {
- state(data, FTP_CWD);
+ ftp_state(data, FTP_CWD);
/* send CWD */
result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
ftpc->dirs[ftpc->cwdcount - 1]);
@@ -3100,7 +3114,7 @@
/* fallthrough, just stop! */
default:
/* internal error */
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
break;
}
} /* if(ftpcode) */
@@ -3166,7 +3180,7 @@
if(conn->handler->flags & PROTOPT_SSL) {
/* BLOCKING */
- result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
+ result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, done);
if(result)
return result;
conn->bits.ftp_use_control_ssl = TRUE;
@@ -3177,7 +3191,7 @@
/* When we connect, we start in the state where we await the 220
response */
- state(data, FTP_WAIT220);
+ ftp_state(data, FTP_WAIT220);
result = ftp_multi_statemach(data, done);
@@ -3245,7 +3259,7 @@
if(data->state.wildcardmatch) {
if(data->set.chunk_end && ftpc->file) {
Curl_set_in_callback(data, true);
- data->set.chunk_end(data->wildcard.customptr);
+ data->set.chunk_end(data->set.wildcardptr);
Curl_set_in_callback(data, false);
}
ftpc->known_filesize = -1;
@@ -3309,14 +3323,6 @@
}
}
- if(conn->ssl[SECONDARYSOCKET].use) {
- /* The secondary socket is using SSL so we must close down that part
- first before we close the socket for real */
- Curl_ssl_close(data, conn, SECONDARYSOCKET);
-
- /* Note that we keep "use" set to TRUE since that (next) connection is
- still requested to use SSL */
- }
close_secondarysocket(data, conn);
}
@@ -3378,7 +3384,7 @@
/* the response code from the transfer showed an error already so no
use checking further */
;
- else if(data->set.upload) {
+ else if(data->state.upload) {
if((-1 != data->state.infilesize) &&
(data->state.infilesize != data->req.writebytecount) &&
!data->set.crlf &&
@@ -3510,13 +3516,13 @@
char want = (char)(ascii?'A':'I');
if(ftpc->transfertype == want) {
- state(data, newstate);
+ ftp_state(data, newstate);
return ftp_state_type_resp(data, 200, newstate);
}
result = Curl_pp_sendf(data, &ftpc->pp, "TYPE %c", want);
if(!result) {
- state(data, newstate);
+ ftp_state(data, newstate);
/* keep track of our current transfer type */
ftpc->transfertype = want;
@@ -3570,23 +3576,15 @@
* complete */
struct FTP *ftp = NULL;
- /* if the second connection isn't done yet, wait for it */
- if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
- if(Curl_connect_ongoing(conn)) {
- /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
- aren't used so we blank their arguments. */
- result = Curl_proxyCONNECT(data, SECONDARYSOCKET, NULL, 0);
-
- return result;
- }
-
- result = Curl_is_connected(data, conn, SECONDARYSOCKET, &connected);
-
- /* Ready to do more? */
- if(connected) {
- DEBUGF(infof(data, "DO-MORE connected phase starts"));
- }
- else {
+ /* if the second connection isn't done yet, wait for it to have
+ * connected to the remote host. When using proxy tunneling, this
+ * means the tunnel needs to have been establish. However, we
+ * can not expect the remote host to talk to us in any way yet.
+ * So, when using ftps: the SSL handshake will not start until we
+ * tell the remote server that we are there. */
+ if(conn->cfilter[SECONDARYSOCKET]) {
+ result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &connected);
+ if(result || !Curl_conn_is_ip_connected(data, SECONDARYSOCKET)) {
if(result && (ftpc->count1 == 0)) {
*completep = -1; /* go back to DOING please */
/* this is a EPSV connect failing, try PASV instead */
@@ -3596,19 +3594,6 @@
}
}
-#ifndef CURL_DISABLE_PROXY
- result = Curl_proxy_connect(data, SECONDARYSOCKET);
- if(result)
- return result;
-
- if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
- return result;
-
- if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
- Curl_connect_ongoing(conn))
- return result;
-#endif
-
/* Curl_proxy_connect might have moved the protocol state */
ftp = data->req.p.ftp;
@@ -3634,7 +3619,7 @@
/* a transfer is about to take place, or if not a file name was given
so we'll do a SIZE on it later and then we need the right TYPE first */
- if(ftpc->wait_data_conn == TRUE) {
+ if(ftpc->wait_data_conn) {
bool serv_conned;
result = ReceivedServerConnect(data, &serv_conned);
@@ -3655,20 +3640,14 @@
connected back to us */
}
}
- else if(data->set.upload) {
+ else if(data->state.upload) {
result = ftp_nb_type(data, conn, data->state.prefer_ascii,
FTP_STOR_TYPE);
if(result)
return result;
result = ftp_multi_statemach(data, &complete);
- if(ftpc->wait_data_conn)
- /* if we reach the end of the FTP state machine here, *complete will be
- TRUE but so is ftpc->wait_data_conn, which says we need to wait for
- the data connection and therefore we're not actually complete */
- *completep = 0;
- else
- *completep = (int)complete;
+ *completep = (int)complete;
}
else {
/* download */
@@ -3738,11 +3717,10 @@
{
/* this is FTP and no proxy */
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
DEBUGF(infof(data, "DO phase starts"));
- if(data->set.opt_no_body) {
+ if(data->req.no_body) {
/* requested no body means no transfer... */
struct FTP *ftp = data->req.p.ftp;
ftp->transfer = PPTRANSFER_INFO;
@@ -3758,7 +3736,7 @@
/* run the state-machine */
result = ftp_multi_statemach(data, dophase_done);
- *connected = conn->bits.tcpconnect[SECONDARYSOCKET];
+ *connected = Curl_conn_is_connected(data->conn, SECONDARYSOCKET);
infof(data, "ftp_perform ends with SECONDARY: %d", *connected);
@@ -3781,7 +3759,7 @@
char *last_slash;
struct FTP *ftp = data->req.p.ftp;
char *path = ftp->path;
- struct WildcardData *wildcard = &(data->wildcard);
+ struct WildcardData *wildcard = data->wildcard;
CURLcode result = CURLE_OK;
struct ftp_wc *ftpwc = NULL;
@@ -3829,7 +3807,7 @@
goto fail;
}
- wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */
+ wildcard->ftpwc = ftpwc; /* put it to the WildcardData tmp pointer */
wildcard->dtor = wc_data_dtor;
/* wildcard does not support NOCWD option (assert it?) */
@@ -3860,20 +3838,20 @@
infof(data, "Wildcard - Parsing started");
return CURLE_OK;
- fail:
+fail:
if(ftpwc) {
Curl_ftp_parselist_data_free(&ftpwc->parser);
free(ftpwc);
}
Curl_safefree(wildcard->pattern);
wildcard->dtor = ZERO_NULL;
- wildcard->protdata = NULL;
+ wildcard->ftpwc = NULL;
return result;
}
static CURLcode wc_statemach(struct Curl_easy *data)
{
- struct WildcardData * const wildcard = &(data->wildcard);
+ struct WildcardData * const wildcard = data->wildcard;
struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
@@ -3890,7 +3868,7 @@
case CURLWC_MATCHING: {
/* In this state is LIST response successfully parsed, so lets restore
previous WRITEFUNCTION callback and WRITEDATA pointer */
- struct ftp_wc *ftpwc = wildcard->protdata;
+ struct ftp_wc *ftpwc = wildcard->ftpwc;
data->set.fwrite_func = ftpwc->backup.write_function;
data->set.out = ftpwc->backup.file_descriptor;
ftpwc->backup.write_function = ZERO_NULL;
@@ -3929,7 +3907,7 @@
long userresponse;
Curl_set_in_callback(data, true);
userresponse = data->set.chunk_bgn(
- finfo, wildcard->customptr, (int)wildcard->filelist.size);
+ finfo, data->set.wildcardptr, (int)wildcard->filelist.size);
Curl_set_in_callback(data, false);
switch(userresponse) {
case CURL_CHUNK_BGN_FUNC_SKIP:
@@ -3969,7 +3947,7 @@
case CURLWC_SKIP: {
if(data->set.chunk_end) {
Curl_set_in_callback(data, true);
- data->set.chunk_end(data->wildcard.customptr);
+ data->set.chunk_end(data->set.wildcardptr);
Curl_set_in_callback(data, false);
}
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
@@ -3979,7 +3957,7 @@
}
case CURLWC_CLEAN: {
- struct ftp_wc *ftpwc = wildcard->protdata;
+ struct ftp_wc *ftpwc = wildcard->ftpwc;
result = CURLE_OK;
if(ftpwc)
result = Curl_ftp_parselist_geterror(ftpwc->parser);
@@ -3991,8 +3969,10 @@
case CURLWC_DONE:
case CURLWC_ERROR:
case CURLWC_CLEAR:
- if(wildcard->dtor)
- wildcard->dtor(wildcard->protdata);
+ if(wildcard->dtor) {
+ wildcard->dtor(wildcard->ftpwc);
+ wildcard->ftpwc = NULL;
+ }
return result;
}
}
@@ -4019,8 +3999,8 @@
if(data->state.wildcardmatch) {
result = wc_statemach(data);
- if(data->wildcard.state == CURLWC_SKIP ||
- data->wildcard.state == CURLWC_DONE) {
+ if(data->wildcard->state == CURLWC_SKIP ||
+ data->wildcard->state == CURLWC_DONE) {
/* do not call ftp_regular_transfer */
return CURLE_OK;
}
@@ -4059,11 +4039,11 @@
curl_easy_strerror(result));
conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */
connclose(conn, "QUIT command failed"); /* mark for connection closure */
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return result;
}
- state(data, FTP_QUIT);
+ ftp_state(data, FTP_QUIT);
result = ftp_block_statemach(data, conn);
}
@@ -4106,6 +4086,8 @@
}
freedirs(ftpc);
+ Curl_safefree(ftpc->account);
+ Curl_safefree(ftpc->alternative_to_user);
Curl_safefree(ftpc->prevpath);
Curl_safefree(ftpc->server_os);
Curl_pp_disconnect(pp);
@@ -4152,7 +4134,7 @@
case FTPFILE_NOCWD: /* fastest, but less standard-compliant */
if((pathLen > 0) && (rawPath[pathLen - 1] != '/'))
- fileName = rawPath; /* this is a full file path */
+ 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.
@@ -4167,7 +4149,7 @@
/* get path before last slash, except for / */
size_t dirlen = slashPos - rawPath;
if(dirlen == 0)
- dirlen++;
+ dirlen = 1;
ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
if(!ftpc->dirs) {
@@ -4194,13 +4176,14 @@
/* current position: begin of next path component */
const char *curPos = rawPath;
- int dirAlloc = 0; /* number of entries allocated for the 'dirs' array */
+ /* number of entries allocated for the 'dirs' array */
+ size_t dirAlloc = 0;
const char *str = rawPath;
for(; *str != 0; ++str)
- if (*str == '/')
+ if(*str == '/')
++dirAlloc;
- if(dirAlloc > 0) {
+ if(dirAlloc) {
ftpc->dirs = calloc(dirAlloc, sizeof(ftpc->dirs[0]));
if(!ftpc->dirs) {
free(rawPath);
@@ -4230,7 +4213,7 @@
curPos = slashPos + 1;
}
}
- DEBUGASSERT(ftpc->dirdepth <= dirAlloc);
+ DEBUGASSERT((size_t)ftpc->dirdepth <= dirAlloc);
fileName = curPos; /* the rest is the file name (or empty) */
}
break;
@@ -4242,7 +4225,7 @@
ftpc->file = NULL; /* instead of point to a zero byte,
we make it a NULL pointer */
- if(data->set.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) {
+ if(data->state.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) {
/* We need a file name when uploading. Return error! */
failf(data, "Uploading to a URL without a file name");
free(rawPath);
@@ -4373,11 +4356,32 @@
{
char *type;
struct FTP *ftp;
+ CURLcode result = CURLE_OK;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
- data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1);
+ ftp = calloc(sizeof(struct FTP), 1);
if(!ftp)
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]);
+ if(!ftpc->account) {
+ free(ftp);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]) {
+ ftpc->alternative_to_user =
+ strdup(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
+ if(!ftpc->alternative_to_user) {
+ Curl_safefree(ftpc->account);
+ free(ftp);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ data->req.p.ftp = ftp;
+
ftp->path = &data->state.up.path[1]; /* don't include the initial slash */
/* FTP URLs support an extension like ";type=<typecode>" that
@@ -4412,9 +4416,11 @@
/* get some initial data into the ftp struct */
ftp->transfer = PPTRANSFER_BODY;
ftp->downloadsize = 0;
- conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
+ ftpc->known_filesize = -1; /* unknown size for now */
+ ftpc->use_ssl = data->set.use_ssl;
+ ftpc->ccc = data->set.ftp_ccc;
- return CURLE_OK;
+ return result;
}
#endif /* CURL_DISABLE_FTP */
diff --git a/lib/ftp.h b/lib/ftp.h
index 7f6f432..977fc88 100644
--- a/lib/ftp.h
+++ b/lib/ftp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,7 +42,7 @@
/****************************************************************************
* FTP unique setup
***************************************************************************/
-typedef enum {
+enum {
FTP_STOP, /* do nothing state, stops the state machine */
FTP_WAIT220, /* waiting for the initial 220 response immediately after
a connect */
@@ -80,7 +80,8 @@
FTP_STOR, /* generic state for STOR and APPE */
FTP_QUIT,
FTP_LAST /* never used */
-} ftpstate;
+};
+typedef unsigned char ftpstate; /* use the enum values */
struct ftp_parselist_data; /* defined later in ftplistparser.c */
@@ -119,41 +120,46 @@
struct */
struct ftp_conn {
struct pingpong pp;
+ char *account;
+ char *alternative_to_user;
char *entrypath; /* the PWD reply when we logged on */
char *file; /* url-decoded file name (or path) */
char **dirs; /* realloc()ed array for path components */
- int dirdepth; /* number of entries used in the 'dirs' array */
- bool dont_check; /* Set to TRUE to prevent the final (post-transfer)
- file size and 226/250 status check. It should still
- read the line, just ignore the result. */
- bool ctl_valid; /* Tells Curl_ftp_quit() whether or not to do anything. If
- the connection has timed out or been closed, this
- should be FALSE when it gets to Curl_ftp_quit() */
- bool cwddone; /* if it has been determined that the proper CWD combo
- already has been done */
- int cwdcount; /* number of CWD commands issued */
- bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent
- caching the current directory */
- bool wait_data_conn; /* this is set TRUE if data connection is waited */
- /* newhost is the (allocated) IP addr or host name to connect the data
- connection to */
- unsigned short newport;
char *newhost;
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) */
- 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 */
- ftpstate state; /* always use ftp.c:state() to change state! */
- ftpstate state_saved; /* transfer type saved to be reloaded after
- data connection is established */
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 */
+ /* newhost is the (allocated) IP addr or host name to connect the data
+ connection to */
+ unsigned short newport;
+ 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 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 */
BIT(ftp_trying_alternative);
+ BIT(dont_check); /* Set to TRUE to prevent the final (post-transfer)
+ file size and 226/250 status check. It should still
+ read the line, just ignore the result. */
+ BIT(ctl_valid); /* Tells Curl_ftp_quit() whether or not to do anything. If
+ the connection has timed out or been closed, this
+ should be FALSE when it gets to Curl_ftp_quit() */
+ BIT(cwddone); /* if it has been determined that the proper CWD combo
+ already has been done */
+ BIT(cwdfail); /* set TRUE if a CWD command fails, as then we must prevent
+ caching the current directory */
+ BIT(wait_data_conn); /* this is set TRUE if data connection is waited */
};
#define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */
diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c
index 09476e5..226d9bc 100644
--- a/lib/ftplistparser.c
+++ b/lib/ftplistparser.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -181,6 +181,43 @@
} offsets;
};
+static void fileinfo_dtor(void *user, void *element)
+{
+ (void)user;
+ Curl_fileinfo_cleanup(element);
+}
+
+CURLcode 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)
+{
+ struct WildcardData *wc = *wcp;
+ if(!wc)
+ return;
+
+ if(wc->dtor) {
+ wc->dtor(wc->ftpwc);
+ wc->dtor = ZERO_NULL;
+ wc->ftpwc = NULL;
+ }
+ DEBUGASSERT(wc->ftpwc == NULL);
+
+ Curl_llist_destroy(&wc->filelist, NULL);
+ free(wc->path);
+ wc->path = NULL;
+ free(wc->pattern);
+ wc->pattern = NULL;
+ wc->state = CURLWC_INIT;
+ free(wc);
+ *wcp = NULL;
+}
+
struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void)
{
return calloc(1, sizeof(struct ftp_parselist_data));
@@ -205,9 +242,9 @@
#define FTP_LP_MALFORMATED_PERM 0x01000000
-static int ftp_pl_get_permission(const char *str)
+static unsigned int ftp_pl_get_permission(const char *str)
{
- int permissions = 0;
+ unsigned int permissions = 0;
/* USER */
if(str[0] == 'r')
permissions |= 1 << 8;
@@ -274,15 +311,15 @@
struct fileinfo *infop)
{
curl_fnmatch_callback compare;
- struct WildcardData *wc = &data->wildcard;
- struct ftp_wc *ftpwc = wc->protdata;
+ struct WildcardData *wc = data->wildcard;
+ struct ftp_wc *ftpwc = wc->ftpwc;
struct Curl_llist *llist = &wc->filelist;
struct ftp_parselist_data *parser = ftpwc->parser;
bool add = TRUE;
struct curl_fileinfo *finfo = &infop->info;
- /* move finfo pointers to b_data */
- char *str = finfo->b_data;
+ /* set the finfo pointers */
+ char *str = Curl_dyn_ptr(&infop->buf);
finfo->filename = str + parser->offsets.filename;
finfo->strings.group = parser->offsets.group ?
str + parser->offsets.group : NULL;
@@ -325,16 +362,16 @@
return CURLE_OK;
}
+#define MAX_FTPLIST_BUFFER 10000 /* arbitrarily set */
+
size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
void *connptr)
{
size_t bufflen = size*nmemb;
struct Curl_easy *data = (struct Curl_easy *)connptr;
- struct ftp_wc *ftpwc = data->wildcard.protdata;
+ struct ftp_wc *ftpwc = data->wildcard->ftpwc;
struct ftp_parselist_data *parser = ftpwc->parser;
- struct fileinfo *infop;
- struct curl_fileinfo *finfo;
- unsigned long i = 0;
+ size_t i = 0;
CURLcode result;
size_t retsize = bufflen;
@@ -350,48 +387,35 @@
if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) {
/* considering info about FILE response format */
- parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ?
- OS_TYPE_WIN_NT : OS_TYPE_UNIX;
+ parser->os_type = ISDIGIT(buffer[0]) ? OS_TYPE_WIN_NT : OS_TYPE_UNIX;
}
while(i < bufflen) { /* FSM */
-
+ char *mem;
+ size_t len; /* number of bytes of data in the dynbuf */
char c = buffer[i];
+ struct fileinfo *infop;
+ struct curl_fileinfo *finfo;
if(!parser->file_data) { /* tmp file data is not allocated yet */
parser->file_data = Curl_fileinfo_alloc();
if(!parser->file_data) {
parser->error = CURLE_OUT_OF_MEMORY;
goto fail;
}
- parser->file_data->info.b_data = malloc(FTP_BUFFER_ALLOCSIZE);
- if(!parser->file_data->info.b_data) {
- parser->error = CURLE_OUT_OF_MEMORY;
- goto fail;
- }
- parser->file_data->info.b_size = FTP_BUFFER_ALLOCSIZE;
parser->item_offset = 0;
parser->item_length = 0;
+ Curl_dyn_init(&parser->file_data->buf, MAX_FTPLIST_BUFFER);
}
infop = parser->file_data;
finfo = &infop->info;
- finfo->b_data[finfo->b_used++] = c;
- if(finfo->b_used >= finfo->b_size - 1) {
- /* if it is important, extend buffer space for file data */
- char *tmp = realloc(finfo->b_data,
- finfo->b_size + FTP_BUFFER_ALLOCSIZE);
- if(tmp) {
- finfo->b_size += FTP_BUFFER_ALLOCSIZE;
- finfo->b_data = tmp;
- }
- else {
- Curl_fileinfo_cleanup(parser->file_data);
- parser->file_data = NULL;
- parser->error = CURLE_OUT_OF_MEMORY;
- goto fail;
- }
+ if(Curl_dyn_addn(&infop->buf, &c, 1)) {
+ parser->error = CURLE_OUT_OF_MEMORY;
+ goto fail;
}
+ len = Curl_dyn_len(&infop->buf);
+ mem = Curl_dyn_ptr(&infop->buf);
switch(parser->os_type) {
case OS_TYPE_UNIX:
@@ -406,7 +430,7 @@
else {
parser->state.UNIX.main = PL_UNIX_FILETYPE;
/* start FSM again not considering size of directory */
- finfo->b_used = 0;
+ Curl_dyn_reset(&infop->buf);
continue;
}
break;
@@ -414,15 +438,15 @@
parser->item_length++;
if(c == '\r') {
parser->item_length--;
- finfo->b_used--;
+ Curl_dyn_setlen(&infop->buf, --len);
}
else if(c == '\n') {
- finfo->b_data[parser->item_length - 1] = 0;
- if(strncmp("total ", finfo->b_data, 6) == 0) {
- char *endptr = finfo->b_data + 6;
+ mem[parser->item_length - 1] = 0;
+ if(!strncmp("total ", mem, 6)) {
+ char *endptr = mem + 6;
/* here we can deal with directory size, pass the leading
whitespace and then the digits */
- while(ISSPACE(*endptr))
+ while(ISBLANK(*endptr))
endptr++;
while(ISDIGIT(*endptr))
endptr++;
@@ -431,7 +455,7 @@
goto fail;
}
parser->state.UNIX.main = PL_UNIX_FILETYPE;
- finfo->b_used = 0;
+ Curl_dyn_reset(&infop->buf);
}
else {
parser->error = CURLE_FTP_BAD_FILE_LIST;
@@ -489,8 +513,8 @@
parser->error = CURLE_FTP_BAD_FILE_LIST;
goto fail;
}
- finfo->b_data[10] = 0; /* terminate permissions */
- perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset);
+ mem[10] = 0; /* terminate permissions */
+ perm = ftp_pl_get_permission(mem + parser->item_offset);
if(perm & FTP_LP_MALFORMATED_PERM) {
parser->error = CURLE_FTP_BAD_FILE_LIST;
goto fail;
@@ -508,8 +532,8 @@
switch(parser->state.UNIX.sub.hlinks) {
case PL_UNIX_HLINKS_PRESPACE:
if(c != ' ') {
- if(c >= '0' && c <= '9') {
- parser->item_offset = finfo->b_used - 1;
+ if(ISDIGIT(c)) {
+ parser->item_offset = len - 1;
parser->item_length = 1;
parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
}
@@ -524,8 +548,8 @@
if(c == ' ') {
char *p;
long int hlinks;
- finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
- hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10);
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ hlinks = strtol(mem + parser->item_offset, &p, 10);
if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
parser->file_data->info.hardlinks = hlinks;
@@ -535,7 +559,7 @@
parser->state.UNIX.main = PL_UNIX_USER;
parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE;
}
- else if(c < '0' || c > '9') {
+ else if(!ISDIGIT(c)) {
parser->error = CURLE_FTP_BAD_FILE_LIST;
goto fail;
}
@@ -546,7 +570,7 @@
switch(parser->state.UNIX.sub.user) {
case PL_UNIX_USER_PRESPACE:
if(c != ' ') {
- parser->item_offset = finfo->b_used - 1;
+ parser->item_offset = len - 1;
parser->item_length = 1;
parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING;
}
@@ -554,7 +578,7 @@
case PL_UNIX_USER_PARSING:
parser->item_length++;
if(c == ' ') {
- finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ mem[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.user = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_GROUP;
parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE;
@@ -568,7 +592,7 @@
switch(parser->state.UNIX.sub.group) {
case PL_UNIX_GROUP_PRESPACE:
if(c != ' ') {
- parser->item_offset = finfo->b_used - 1;
+ parser->item_offset = len - 1;
parser->item_length = 1;
parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME;
}
@@ -576,7 +600,7 @@
case PL_UNIX_GROUP_NAME:
parser->item_length++;
if(c == ' ') {
- finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ mem[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.group = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_SIZE;
parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE;
@@ -590,8 +614,8 @@
switch(parser->state.UNIX.sub.size) {
case PL_UNIX_SIZE_PRESPACE:
if(c != ' ') {
- if(c >= '0' && c <= '9') {
- parser->item_offset = finfo->b_used - 1;
+ if(ISDIGIT(c)) {
+ parser->item_offset = len - 1;
parser->item_length = 1;
parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
}
@@ -606,8 +630,8 @@
if(c == ' ') {
char *p;
curl_off_t fsize;
- finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
- if(!curlx_strtoofft(finfo->b_data + parser->item_offset,
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ if(!curlx_strtoofft(mem + parser->item_offset,
&p, 10, &fsize)) {
if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
fsize != CURL_OFF_T_MIN) {
@@ -632,7 +656,7 @@
case PL_UNIX_TIME_PREPART1:
if(c != ' ') {
if(ISALNUM(c)) {
- parser->item_offset = finfo->b_used -1;
+ parser->item_offset = len -1;
parser->item_length = 1;
parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
}
@@ -689,10 +713,10 @@
case PL_UNIX_TIME_PART3:
parser->item_length++;
if(c == ' ') {
- finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
+ mem[parser->item_offset + parser->item_length -1] = 0;
parser->offsets.time = parser->item_offset;
/*
- if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) {
+ if(ftp_pl_gettime(parser, finfo->mem + parser->item_offset)) {
parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME;
}
*/
@@ -716,7 +740,7 @@
switch(parser->state.UNIX.sub.filename) {
case PL_UNIX_FILENAME_PRESPACE:
if(c != ' ') {
- parser->item_offset = finfo->b_used - 1;
+ parser->item_offset = len - 1;
parser->item_length = 1;
parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME;
}
@@ -727,7 +751,7 @@
parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL;
}
else if(c == '\n') {
- finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ mem[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.filename = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_FILETYPE;
result = ftp_pl_insert_finfo(data, infop);
@@ -739,7 +763,7 @@
break;
case PL_UNIX_FILENAME_WINDOWSEOL:
if(c == '\n') {
- finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ mem[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.filename = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_FILETYPE;
result = ftp_pl_insert_finfo(data, infop);
@@ -759,7 +783,7 @@
switch(parser->state.UNIX.sub.symlink) {
case PL_UNIX_SYMLINK_PRESPACE:
if(c != ' ') {
- parser->item_offset = finfo->b_used - 1;
+ parser->item_offset = len - 1;
parser->item_length = 1;
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
}
@@ -805,7 +829,7 @@
if(c == ' ') {
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4;
/* now place where is symlink following */
- finfo->b_data[parser->item_offset + parser->item_length - 4] = 0;
+ mem[parser->item_offset + parser->item_length - 4] = 0;
parser->offsets.filename = parser->item_offset;
parser->item_length = 0;
parser->item_offset = 0;
@@ -821,7 +845,7 @@
case PL_UNIX_SYMLINK_PRETARGET4:
if(c != '\r' && c != '\n') {
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET;
- parser->item_offset = finfo->b_used - 1;
+ parser->item_offset = len - 1;
parser->item_length = 1;
}
else {
@@ -835,7 +859,7 @@
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL;
}
else if(c == '\n') {
- finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ mem[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset;
result = ftp_pl_insert_finfo(data, infop);
if(result) {
@@ -847,7 +871,7 @@
break;
case PL_UNIX_SYMLINK_WINDOWSEOL:
if(c == '\n') {
- finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ mem[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset;
result = ftp_pl_insert_finfo(data, infop);
if(result) {
@@ -894,14 +918,14 @@
parser->item_length++;
switch(parser->state.NT.sub.time) {
case PL_WINNT_TIME_PRESPACE:
- if(!ISSPACE(c)) {
+ if(!ISBLANK(c)) {
parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
}
break;
case PL_WINNT_TIME_TIME:
if(c == ' ') {
parser->offsets.time = parser->item_offset;
- finfo->b_data[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;
@@ -917,7 +941,7 @@
switch(parser->state.NT.sub.dirorsize) {
case PL_WINNT_DIRORSIZE_PRESPACE:
if(c != ' ') {
- parser->item_offset = finfo->b_used - 1;
+ parser->item_offset = len - 1;
parser->item_length = 1;
parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;
}
@@ -925,14 +949,14 @@
case PL_WINNT_DIRORSIZE_CONTENT:
parser->item_length ++;
if(c == ' ') {
- finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
- if(strcmp("<DIR>", finfo->b_data + parser->item_offset) == 0) {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ if(strcmp("<DIR>", mem + parser->item_offset) == 0) {
finfo->filetype = CURLFILETYPE_DIRECTORY;
finfo->size = 0;
}
else {
char *endptr;
- if(curlx_strtoofft(finfo->b_data +
+ if(curlx_strtoofft(mem +
parser->item_offset,
&endptr, 10, &finfo->size)) {
parser->error = CURLE_FTP_BAD_FILE_LIST;
@@ -954,7 +978,7 @@
switch(parser->state.NT.sub.filename) {
case PL_WINNT_FILENAME_PRESPACE:
if(c != ' ') {
- parser->item_offset = finfo->b_used -1;
+ parser->item_offset = len -1;
parser->item_length = 1;
parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT;
}
@@ -963,11 +987,11 @@
parser->item_length++;
if(c == '\r') {
parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL;
- finfo->b_data[finfo->b_used - 1] = 0;
+ mem[len - 1] = 0;
}
else if(c == '\n') {
parser->offsets.filename = parser->item_offset;
- finfo->b_data[finfo->b_used - 1] = 0;
+ mem[len - 1] = 0;
result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
diff --git a/lib/ftplistparser.h b/lib/ftplistparser.h
index 0a80543..5ba1f6a 100644
--- a/lib/ftplistparser.h
+++ b/lib/ftplistparser.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -39,5 +39,39 @@
void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data);
+/* list of wildcard process states */
+typedef enum {
+ CURLWC_CLEAR = 0,
+ CURLWC_INIT = 1,
+ CURLWC_MATCHING, /* library is trying to get list of addresses for
+ downloading */
+ CURLWC_DOWNLOADING,
+ CURLWC_CLEAN, /* deallocate resources and reset settings */
+ CURLWC_SKIP, /* skip over concrete file */
+ CURLWC_ERROR, /* error cases */
+ CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop
+ will end */
+} wildcard_states;
+
+typedef void (*wildcard_dtor)(void *ptr);
+
+/* struct keeping information about wildcard download process */
+struct WildcardData {
+ char *path; /* path to the directory, where we trying wildcard-match */
+ char *pattern; /* wildcard pattern */
+ struct Curl_llist filelist; /* llist with struct Curl_fileinfo */
+ struct ftp_wc *ftpwc; /* pointer to FTP wildcard data */
+ wildcard_dtor dtor;
+ unsigned char state; /* wildcard_states */
+};
+
+CURLcode Curl_wildcard_init(struct WildcardData *wc);
+void Curl_wildcard_dtor(struct WildcardData **wcp);
+
+struct Curl_easy;
+
+#else
+/* FTP is disabled */
+#define Curl_wildcard_dtor(x)
#endif /* CURL_DISABLE_FTP */
#endif /* HEADER_CURL_FTPLISTPARSER_H */
diff --git a/lib/functypes.h b/lib/functypes.h
new file mode 100644
index 0000000..075c02e
--- /dev/null
+++ b/lib/functypes.h
@@ -0,0 +1,115 @@
+#ifndef HEADER_CURL_FUNCTYPES_H
+#define HEADER_CURL_FUNCTYPES_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+/* defaults:
+
+ ssize_t recv(int, void *, size_t, int);
+ ssize_t send(int, const void *, size_t, int);
+
+ If other argument or return types are needed:
+
+ 1. For systems that run configure or cmake, the alternatives are provided
+ here.
+ 2. For systems with config-*.h files, define them there.
+*/
+
+#ifdef WIN32
+/* int recv(SOCKET, char *, int, int) */
+#define RECV_TYPE_ARG1 SOCKET
+#define RECV_TYPE_ARG2 char *
+#define RECV_TYPE_ARG3 int
+#define RECV_TYPE_RETV int
+
+/* int send(SOCKET, const char *, int, int); */
+#define SEND_TYPE_ARG1 SOCKET
+#define SEND_TYPE_ARG2 char *
+#define SEND_TYPE_ARG3 int
+#define SEND_TYPE_RETV int
+
+#elif defined(__AMIGA__) /* Any AmigaOS flavour */
+
+/* long recv(long, char *, long, long); */
+#define RECV_TYPE_ARG1 long
+#define RECV_TYPE_ARG2 char *
+#define RECV_TYPE_ARG3 long
+#define RECV_TYPE_ARG4 long
+#define RECV_TYPE_RETV long
+
+/* int send(int, const char *, int, int); */
+#define SEND_TYPE_ARG1 int
+#define SEND_TYPE_ARG2 char *
+#define SEND_TYPE_ARG3 int
+#define SEND_TYPE_RETV int
+#endif
+
+
+#ifndef RECV_TYPE_ARG1
+#define RECV_TYPE_ARG1 int
+#endif
+
+#ifndef RECV_TYPE_ARG2
+#define RECV_TYPE_ARG2 void *
+#endif
+
+#ifndef RECV_TYPE_ARG3
+#define RECV_TYPE_ARG3 size_t
+#endif
+
+#ifndef RECV_TYPE_ARG4
+#define RECV_TYPE_ARG4 int
+#endif
+
+#ifndef RECV_TYPE_RETV
+#define RECV_TYPE_RETV ssize_t
+#endif
+
+#ifndef SEND_QUAL_ARG2
+#define SEND_QUAL_ARG2 const
+#endif
+
+#ifndef SEND_TYPE_ARG1
+#define SEND_TYPE_ARG1 int
+#endif
+
+#ifndef SEND_TYPE_ARG2
+#define SEND_TYPE_ARG2 void *
+#endif
+
+#ifndef SEND_TYPE_ARG3
+#define SEND_TYPE_ARG3 size_t
+#endif
+
+#ifndef SEND_TYPE_ARG4
+#define SEND_TYPE_ARG4 int
+#endif
+
+#ifndef SEND_TYPE_RETV
+#define SEND_TYPE_RETV ssize_t
+#endif
+
+#endif /* HEADER_CURL_FUNCTYPES_H */
diff --git a/lib/getenv.c b/lib/getenv.c
index 5f00fd1..8069784 100644
--- a/lib/getenv.c
+++ b/lib/getenv.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/getinfo.c b/lib/getinfo.c
index 758cf54..f1574e0 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -415,6 +415,13 @@
case CURLINFO_RETRY_AFTER:
*param_offt = data->info.retry_after;
break;
+ case CURLINFO_XFER_ID:
+ *param_offt = data->id;
+ break;
+ case CURLINFO_CONN_ID:
+ *param_offt = data->conn?
+ data->conn->connection_id : data->state.recent_conn_id;
+ break;
default:
return CURLE_UNKNOWN_OPTION;
}
@@ -533,13 +540,7 @@
#ifdef USE_SSL
if(conn && tsi->backend != CURLSSLBACKEND_NONE) {
- unsigned int i;
- for(i = 0; i < (sizeof(conn->ssl) / sizeof(conn->ssl[0])); ++i) {
- if(conn->ssl[i].use) {
- tsi->internals = Curl_ssl->get_internals(&conn->ssl[i], info);
- break;
- }
- }
+ tsi->internals = Curl_ssl_get_internals(data, FIRSTSOCKET, info, 0);
}
#endif
}
@@ -578,7 +579,7 @@
CURLcode result = CURLE_UNKNOWN_OPTION;
if(!data)
- return result;
+ return CURLE_BAD_FUNCTION_ARGUMENT;
va_start(arg, info);
diff --git a/lib/getinfo.h b/lib/getinfo.h
index 1b5e8c2..56bb440 100644
--- a/lib/getinfo.h
+++ b/lib/getinfo.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/gopher.c b/lib/gopher.c
index 01f4bde..4a11d93 100644
--- a/lib/gopher.c
+++ b/lib/gopher.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,6 +30,7 @@
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
+#include "cfilters.h"
#include "connect.h"
#include "progress.h"
#include "gopher.h"
@@ -117,7 +118,9 @@
static CURLcode gopher_connecting(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- CURLcode result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
+ CURLcode result;
+
+ result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, done);
if(result)
connclose(conn, "Failed TLS connection");
*done = TRUE;
@@ -236,4 +239,4 @@
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
return CURLE_OK;
}
-#endif /*CURL_DISABLE_GOPHER*/
+#endif /* CURL_DISABLE_GOPHER */
diff --git a/lib/gopher.h b/lib/gopher.h
index 4ea269d..9e3365b 100644
--- a/lib/gopher.h
+++ b/lib/gopher.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/h2h3.c b/lib/h2h3.c
deleted file mode 100644
index 9453cf5..0000000
--- a/lib/h2h3.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the 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 "urldata.h"
-#include "h2h3.h"
-#include "transfer.h"
-#include "sendf.h"
-#include "strcase.h"
-
-/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
-
-/*
- * Curl_pseudo_headers() creates the array with pseudo headers to be
- * used in a HTTP/2 or HTTP/3 request.
- */
-
-#if defined(USE_NGHTTP2) || defined(ENABLE_QUIC)
-
-/* Index where :authority header field will appear in request header
- field list. */
-#define AUTHORITY_DST_IDX 3
-
-/* USHRT_MAX is 65535 == 0xffff */
-#define HEADER_OVERFLOW(x) \
- (x.namelen > 0xffff || x.valuelen > 0xffff - x.namelen)
-
-/*
- * Check header memory for the token "trailers".
- * Parse the tokens as separated by comma and surrounded by whitespace.
- * Returns TRUE if found or FALSE if not.
- */
-static bool contains_trailers(const char *p, size_t len)
-{
- const char *end = p + len;
- for(;;) {
- for(; p != end && (*p == ' ' || *p == '\t'); ++p)
- ;
- if(p == end || (size_t)(end - p) < sizeof("trailers") - 1)
- return FALSE;
- if(strncasecompare("trailers", p, sizeof("trailers") - 1)) {
- p += sizeof("trailers") - 1;
- for(; p != end && (*p == ' ' || *p == '\t'); ++p)
- ;
- if(p == end || *p == ',')
- return TRUE;
- }
- /* skip to next token */
- for(; p != end && *p != ','; ++p)
- ;
- if(p == end)
- return FALSE;
- ++p;
- }
-}
-
-typedef enum {
- /* Send header to server */
- HEADERINST_FORWARD,
- /* Don't send header to server */
- HEADERINST_IGNORE,
- /* Discard header, and replace it with "te: trailers" */
- HEADERINST_TE_TRAILERS
-} header_instruction;
-
-/* Decides how to treat given header field. */
-static header_instruction inspect_header(const char *name, size_t namelen,
- const char *value, size_t valuelen) {
- switch(namelen) {
- case 2:
- if(!strncasecompare("te", name, namelen))
- return HEADERINST_FORWARD;
-
- return contains_trailers(value, valuelen) ?
- HEADERINST_TE_TRAILERS : HEADERINST_IGNORE;
- case 7:
- return strncasecompare("upgrade", name, namelen) ?
- HEADERINST_IGNORE : HEADERINST_FORWARD;
- case 10:
- return (strncasecompare("connection", name, namelen) ||
- strncasecompare("keep-alive", name, namelen)) ?
- HEADERINST_IGNORE : HEADERINST_FORWARD;
- case 16:
- return strncasecompare("proxy-connection", name, namelen) ?
- HEADERINST_IGNORE : HEADERINST_FORWARD;
- case 17:
- return strncasecompare("transfer-encoding", name, namelen) ?
- HEADERINST_IGNORE : HEADERINST_FORWARD;
- default:
- return HEADERINST_FORWARD;
- }
-}
-
-CURLcode Curl_pseudo_headers(struct Curl_easy *data,
- const char *mem, /* the request */
- const size_t len /* size of request */,
- struct h2h3req **hp)
-{
- struct connectdata *conn = data->conn;
- size_t nheader = 0;
- size_t i;
- size_t authority_idx;
- char *hdbuf = (char *)mem;
- char *end, *line_end;
- struct h2h3pseudo *nva = NULL;
- struct h2h3req *hreq = NULL;
- char *vptr;
-
- /* Calculate number of headers contained in [mem, mem + len). Assumes a
- correctly generated HTTP header field block. */
- for(i = 1; i < len; ++i) {
- if(hdbuf[i] == '\n' && hdbuf[i - 1] == '\r') {
- ++nheader;
- ++i;
- }
- }
- if(nheader < 2) {
- goto fail;
- }
- /* We counted additional 2 \r\n in the first and last line. We need 3
- new headers: :method, :path and :scheme. Therefore we need one
- more space. */
- nheader += 1;
- hreq = malloc(sizeof(struct h2h3req) +
- sizeof(struct h2h3pseudo) * (nheader - 1));
- if(!hreq) {
- goto fail;
- }
-
- nva = &hreq->header[0];
-
- /* Extract :method, :path from request line
- We do line endings with CRLF so checking for CR is enough */
- line_end = memchr(hdbuf, '\r', len);
- if(!line_end) {
- goto fail;
- }
-
- /* Method does not contain spaces */
- end = memchr(hdbuf, ' ', line_end - hdbuf);
- if(!end || end == hdbuf)
- goto fail;
- nva[0].name = H2H3_PSEUDO_METHOD;
- nva[0].namelen = sizeof(H2H3_PSEUDO_METHOD) - 1;
- nva[0].value = hdbuf;
- nva[0].valuelen = (size_t)(end - hdbuf);
-
- hdbuf = end + 1;
-
- /* Path may contain spaces so scan backwards */
- end = NULL;
- for(i = (size_t)(line_end - hdbuf); i; --i) {
- if(hdbuf[i - 1] == ' ') {
- end = &hdbuf[i - 1];
- break;
- }
- }
- if(!end || end == hdbuf)
- goto fail;
- nva[1].name = H2H3_PSEUDO_PATH;
- nva[1].namelen = sizeof(H2H3_PSEUDO_PATH) - 1;
- nva[1].value = hdbuf;
- nva[1].valuelen = (end - hdbuf);
-
- nva[2].name = H2H3_PSEUDO_SCHEME;
- nva[2].namelen = sizeof(H2H3_PSEUDO_SCHEME) - 1;
- vptr = Curl_checkheaders(data, STRCONST(H2H3_PSEUDO_SCHEME));
- if(vptr) {
- vptr += sizeof(H2H3_PSEUDO_SCHEME);
- while(*vptr && ISSPACE(*vptr))
- vptr++;
- nva[2].value = vptr;
- infof(data, "set pseudo header %s to %s", H2H3_PSEUDO_SCHEME, vptr);
- }
- else {
- if(conn->handler->flags & PROTOPT_SSL)
- nva[2].value = "https";
- else
- nva[2].value = "http";
- }
- nva[2].valuelen = strlen((char *)nva[2].value);
-
- authority_idx = 0;
- i = 3;
- while(i < nheader) {
- size_t hlen;
-
- hdbuf = line_end + 2;
-
- /* check for next CR, but only within the piece of data left in the given
- buffer */
- line_end = memchr(hdbuf, '\r', len - (hdbuf - (char *)mem));
- if(!line_end || (line_end == hdbuf))
- goto fail;
-
- /* header continuation lines are not supported */
- if(*hdbuf == ' ' || *hdbuf == '\t')
- goto fail;
-
- for(end = hdbuf; end < line_end && *end != ':'; ++end)
- ;
- if(end == hdbuf || end == line_end)
- goto fail;
- hlen = end - hdbuf;
-
- if(hlen == 4 && strncasecompare("host", hdbuf, 4)) {
- authority_idx = i;
- nva[i].name = H2H3_PSEUDO_AUTHORITY;
- nva[i].namelen = sizeof(H2H3_PSEUDO_AUTHORITY) - 1;
- }
- else {
- nva[i].namelen = (size_t)(end - hdbuf);
- /* Lower case the header name for HTTP/3 */
- Curl_strntolower((char *)hdbuf, hdbuf, nva[i].namelen);
- nva[i].name = hdbuf;
- }
- hdbuf = end + 1;
- while(*hdbuf == ' ' || *hdbuf == '\t')
- ++hdbuf;
- end = line_end;
-
- switch(inspect_header((const char *)nva[i].name, nva[i].namelen, hdbuf,
- end - hdbuf)) {
- case HEADERINST_IGNORE:
- /* skip header fields prohibited by HTTP/2 specification. */
- --nheader;
- continue;
- case HEADERINST_TE_TRAILERS:
- nva[i].value = "trailers";
- nva[i].valuelen = sizeof("trailers") - 1;
- break;
- default:
- nva[i].value = hdbuf;
- nva[i].valuelen = (end - hdbuf);
- }
-
- nva[i].value = hdbuf;
- nva[i].valuelen = (end - hdbuf);
-
- ++i;
- }
-
- /* :authority must come before non-pseudo header fields */
- if(authority_idx && authority_idx != AUTHORITY_DST_IDX) {
- struct h2h3pseudo authority = nva[authority_idx];
- for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) {
- nva[i] = nva[i - 1];
- }
- nva[i] = authority;
- }
-
- /* Warn stream may be rejected if cumulative length of headers is too
- large. */
-#define MAX_ACC 60000 /* <64KB to account for some overhead */
- {
- size_t acc = 0;
-
- for(i = 0; i < nheader; ++i) {
- acc += nva[i].namelen + nva[i].valuelen;
-
- infof(data, "h2h3 [%.*s: %.*s]",
- (int)nva[i].namelen, nva[i].name,
- (int)nva[i].valuelen, nva[i].value);
- }
-
- if(acc > MAX_ACC) {
- infof(data, "http_request: Warning: The cumulative length of all "
- "headers exceeds %d bytes and that could cause the "
- "stream to be rejected.", MAX_ACC);
- }
- }
-
- hreq->entries = nheader;
- *hp = hreq;
-
- return CURLE_OK;
-
- fail:
- free(hreq);
- return CURLE_OUT_OF_MEMORY;
-}
-
-void Curl_pseudo_free(struct h2h3req *hp)
-{
- free(hp);
-}
-
-#endif /* USE_NGHTTP2 or HTTP/3 enabled */
diff --git a/lib/h2h3.h b/lib/h2h3.h
deleted file mode 100644
index 84caec5..0000000
--- a/lib/h2h3.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef HEADER_CURL_H2H3_H
-#define HEADER_CURL_H2H3_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the 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"
-
-#define H2H3_PSEUDO_METHOD ":method"
-#define H2H3_PSEUDO_SCHEME ":scheme"
-#define H2H3_PSEUDO_AUTHORITY ":authority"
-#define H2H3_PSEUDO_PATH ":path"
-#define H2H3_PSEUDO_STATUS ":status"
-
-struct h2h3pseudo {
- const char *name;
- size_t namelen;
- const char *value;
- size_t valuelen;
-};
-
-struct h2h3req {
- size_t entries;
- struct h2h3pseudo header[1]; /* the array is allocated to contain entries */
-};
-
-/*
- * Curl_pseudo_headers() creates the array with pseudo headers to be
- * used in a HTTP/2 or HTTP/3 request. Returns an allocated struct.
- * Free it with Curl_pseudo_free().
- */
-CURLcode Curl_pseudo_headers(struct Curl_easy *data,
- const char *request,
- const size_t len,
- struct h2h3req **hp);
-
-/*
- * Curl_pseudo_free() frees a h2h3req struct.
- */
-void Curl_pseudo_free(struct h2h3req *hp);
-
-#endif /* HEADER_CURL_H2H3_H */
diff --git a/lib/hash.c b/lib/hash.c
index b6a2a33..30f28e2 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -330,7 +330,6 @@
struct Curl_hash_element *he = iter->current_element->ptr;
return he;
}
- iter->current_element = NULL;
return NULL;
}
diff --git a/lib/hash.h b/lib/hash.h
index 5b59bf1..9cfffc2 100644
--- a/lib/hash.h
+++ b/lib/hash.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/headers.c b/lib/headers.c
index 1546237..4367ce7 100644
--- a/lib/headers.c
+++ b/lib/headers.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -38,14 +38,13 @@
/* Generate the curl_header struct for the user. This function MUST assign all
struct fields in the output struct. */
-static void copy_header_external(struct Curl_easy *data,
- struct Curl_header_store *hs,
+static void copy_header_external(struct Curl_header_store *hs,
size_t index,
size_t amount,
struct Curl_llist_element *e,
- struct curl_header **hout)
+ struct curl_header *hout)
{
- struct curl_header *h = *hout = &data->state.headerout;
+ struct curl_header *h = hout;
h->name = hs->name;
h->value = hs->value;
h->amount = amount;
@@ -74,8 +73,8 @@
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 || (request < -1))
+ (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))
return CURLHE_NOHEADERS; /* no headers available */
@@ -118,7 +117,9 @@
return CURLHE_MISSING;
}
/* this is the name we want */
- copy_header_external(data, hs, nameindex, amount, e_pick, hout);
+ copy_header_external(hs, nameindex, amount, e_pick,
+ &data->state.headerout[0]);
+ *hout = &data->state.headerout[0];
return CURLHE_OK;
}
@@ -132,7 +133,6 @@
struct Curl_llist_element *pick;
struct Curl_llist_element *e;
struct Curl_header_store *hs;
- struct curl_header *hout;
size_t amount = 0;
size_t index = 0;
@@ -179,8 +179,9 @@
index = amount - 1;
}
- copy_header_external(data, hs, index, amount, pick, &hout);
- return hout;
+ copy_header_external(hs, index, amount, pick,
+ &data->state.headerout[1]);
+ return &data->state.headerout[1];
}
static CURLcode namevalue(char *header, size_t hlen, unsigned int type,
@@ -207,7 +208,7 @@
return CURLE_BAD_FUNCTION_ARGUMENT;
/* skip all leading space letters */
- while(*header && ISSPACE(*header))
+ while(*header && ISBLANK(*header))
header++;
*value = header;
@@ -237,7 +238,7 @@
vlen--;
/* save only one leading space */
- while((vlen > 1) && ISSPACE(value[0]) && ISSPACE(value[1])) {
+ while((vlen > 1) && ISBLANK(value[0]) && ISBLANK(value[1])) {
vlen--;
value++;
}
@@ -259,7 +260,7 @@
/* put the data at the end of the previous data, not the newline */
memcpy(&newhs->value[olen], value, vlen);
- newhs->value[olen + vlen] = 0; /* zero terminate at newline */
+ newhs->value[olen + vlen] = 0; /* null-terminate at newline */
/* insert this node into the list of headers */
Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail,
@@ -324,7 +325,7 @@
hs, &hs->node);
data->state.prevhead = hs;
return CURLE_OK;
- fail:
+fail:
free(hs);
return result;
}
@@ -335,6 +336,7 @@
static void headers_init(struct Curl_easy *data)
{
Curl_llist_init(&data->state.httphdrs, NULL);
+ data->state.prevhead = NULL;
}
/*
diff --git a/lib/headers.h b/lib/headers.h
index 96332db..a5229ea 100644
--- a/lib/headers.h
+++ b/lib/headers.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/hmac.c b/lib/hmac.c
index dfb0db5..8d8de17 100644
--- a/lib/hmac.c
+++ b/lib/hmac.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/hostasyn.c b/lib/hostasyn.c
index 0bfbe2e..2f6762c 100644
--- a/lib/hostasyn.c
+++ b/lib/hostasyn.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -43,10 +43,6 @@
#include <inet.h>
#endif
-#ifdef HAVE_PROCESS_H
-#include <process.h>
-#endif
-
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
@@ -82,7 +78,7 @@
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = Curl_cache_addr(data, ai,
- data->state.async.hostname,
+ data->state.async.hostname, 0,
data->state.async.port);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
diff --git a/lib/hostip.c b/lib/hostip.c
index 1ced9d2..1a289de 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,10 +48,6 @@
#include <signal.h>
#endif
-#ifdef HAVE_PROCESS_H
-#include <process.h>
-#endif
-
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
@@ -65,23 +61,25 @@
#include "doh.h"
#include "warnless.h"
#include "strcase.h"
+#include "easy_lock.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
-#include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
-#endif
-
-#if defined(CURLRES_SYNCH) && \
- defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP)
+#if defined(CURLRES_SYNCH) && \
+ defined(HAVE_ALARM) && \
+ defined(SIGALRM) && \
+ defined(HAVE_SIGSETJMP) && \
+ defined(GLOBAL_INIT_IS_THREADSAFE)
/* alarm-based timeouts can only be used with all the dependencies satisfied */
#define USE_ALARM_TIMEOUT
#endif
#define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */
+#define MAX_DNS_CACHE_SIZE 29999
+
/*
* hostip.c explained
* ==================
@@ -126,7 +124,7 @@
/*
* Return # of addresses in a Curl_addrinfo struct
*/
-int Curl_num_addresses(const struct Curl_addrinfo *addr)
+static int num_addresses(const struct Curl_addrinfo *addr)
{
int i = 0;
while(addr) {
@@ -171,23 +169,31 @@
/*
* Create a hostcache id string for the provided host + port, to be used by
- * the DNS caching. Without alloc.
+ * the DNS caching. Without alloc. Return length of the id string.
*/
-static void
-create_hostcache_id(const char *name, int port, char *ptr, size_t buflen)
+static size_t
+create_hostcache_id(const char *name,
+ size_t nlen, /* 0 or actual name length */
+ int port, char *ptr, size_t buflen)
{
- size_t len = strlen(name);
+ size_t len = nlen ? nlen : strlen(name);
+ size_t olen = 0;
+ DEBUGASSERT(buflen >= MAX_HOSTCACHE_LEN);
if(len > (buflen - 7))
len = buflen - 7;
/* store and lower case the name */
- while(len--)
- *ptr++ = (char)TOLOWER(*name++);
- msnprintf(ptr, 7, ":%u", port);
+ while(len--) {
+ *ptr++ = Curl_raw_tolower(*name++);
+ olen++;
+ }
+ olen += msnprintf(ptr, 7, ":%u", port);
+ return olen;
}
struct hostcache_prune_data {
- long cache_timeout;
time_t now;
+ time_t oldest; /* oldest time in cache not pruned. */
+ int cache_timeout;
};
/*
@@ -200,28 +206,40 @@
static int
hostcache_timestamp_remove(void *datap, void *hc)
{
- struct hostcache_prune_data *data =
+ struct hostcache_prune_data *prune =
(struct hostcache_prune_data *) datap;
struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc;
- return (0 != c->timestamp)
- && (data->now - c->timestamp >= data->cache_timeout);
+ if(c->timestamp) {
+ /* age in seconds */
+ time_t age = prune->now - c->timestamp;
+ if(age >= prune->cache_timeout)
+ return TRUE;
+ if(age > prune->oldest)
+ prune->oldest = age;
+ }
+ return FALSE;
}
/*
* Prune the DNS cache. This assumes that a lock has already been taken.
+ * Returns the 'age' of the oldest still kept entry.
*/
-static void
-hostcache_prune(struct Curl_hash *hostcache, long cache_timeout, time_t now)
+static time_t
+hostcache_prune(struct Curl_hash *hostcache, int cache_timeout,
+ time_t now)
{
struct hostcache_prune_data user;
user.cache_timeout = cache_timeout;
user.now = now;
+ user.oldest = 0;
Curl_hash_clean_with_criterium(hostcache,
(void *) &user,
hostcache_timestamp_remove);
+
+ return user.oldest;
}
/*
@@ -231,10 +249,11 @@
void Curl_hostcache_prune(struct Curl_easy *data)
{
time_t now;
+ /* the timeout may be set -1 (forever) */
+ int timeout = data->set.dns_cache_timeout;
- if((data->set.dns_cache_timeout == -1) || !data->dns.hostcache)
- /* cache forever means never prune, and NULL hostcache means
- we can't do it */
+ if(!data->dns.hostcache)
+ /* NULL hostcache means we can't do it */
return;
if(data->share)
@@ -242,20 +261,29 @@
time(&now);
- /* Remove outdated and unused entries from the hostcache */
- hostcache_prune(data->dns.hostcache,
- data->set.dns_cache_timeout,
- now);
+ do {
+ /* Remove outdated and unused entries from the hostcache */
+ time_t oldest = hostcache_prune(data->dns.hostcache, timeout, now);
+
+ if(oldest < INT_MAX)
+ timeout = (int)oldest; /* we know it fits */
+ else
+ timeout = INT_MAX - 1;
+
+ /* if the cache size is still too big, use the oldest age as new
+ prune limit */
+ } while(timeout && (data->dns.hostcache->size > MAX_DNS_CACHE_SIZE));
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
}
-#ifdef HAVE_SIGSETJMP
+#ifdef USE_ALARM_TIMEOUT
/* Beware this is a global and unique instance. This is used to store the
return address that we can jump back to from inside a signal handler. This
is not thread-safe stuff. */
-sigjmp_buf curl_jmpenv;
+static sigjmp_buf curl_jmpenv;
+static curl_simple_lock curl_jmpenv_lock;
#endif
/* lookup address, returns entry if found and not stale */
@@ -264,20 +292,18 @@
int port)
{
struct Curl_dns_entry *dns = NULL;
- size_t entry_len;
char entry_id[MAX_HOSTCACHE_LEN];
/* Create an entry id, based upon the hostname and port */
- create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
- entry_len = strlen(entry_id);
+ size_t entry_len = create_hostcache_id(hostname, 0, port,
+ entry_id, sizeof(entry_id));
/* See if its already in our dns cache */
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
/* No entry found in cache, check if we might have a wildcard entry */
if(!dns && data->state.wildcard_resolve) {
- create_hostcache_id("*", port, entry_id, sizeof(entry_id));
- entry_len = strlen(entry_id);
+ entry_len = create_hostcache_id("*", 1, port, entry_id, sizeof(entry_id));
/* See if it's already in our dns cache */
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
@@ -289,6 +315,7 @@
time(&user.now);
user.cache_timeout = data->set.dns_cache_timeout;
+ user.oldest = 0;
if(hostcache_timestamp_remove(&user, dns)) {
infof(data, "Hostname in DNS cache was stale, zapped");
@@ -297,6 +324,31 @@
}
}
+ /* See if the returned entry matches the required resolve mode */
+ if(dns && data->conn->ip_version != CURL_IPRESOLVE_WHATEVER) {
+ int pf = PF_INET;
+ bool found = false;
+ struct Curl_addrinfo *addr = dns->addr;
+
+#ifdef PF_INET6
+ if(data->conn->ip_version == CURL_IPRESOLVE_V6)
+ pf = PF_INET6;
+#endif
+
+ while(addr) {
+ if(addr->ai_family == pf) {
+ found = true;
+ break;
+ }
+ addr = addr->ai_next;
+ }
+
+ if(!found) {
+ infof(data, "Hostname in DNS cache doesn't have needed family, zapped");
+ dns = NULL; /* the memory deallocation is being handled by the hash */
+ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
+ }
+ }
return dns;
}
@@ -354,7 +406,7 @@
struct Curl_addrinfo **addr)
{
CURLcode result = CURLE_OK;
- const int num_addrs = Curl_num_addresses(*addr);
+ const int num_addrs = num_addresses(*addr);
if(num_addrs > 1) {
struct Curl_addrinfo **nodes;
@@ -417,6 +469,7 @@
Curl_cache_addr(struct Curl_easy *data,
struct Curl_addrinfo *addr,
const char *hostname,
+ size_t hostlen, /* length or zero */
int port)
{
char entry_id[MAX_HOSTCACHE_LEN];
@@ -440,8 +493,8 @@
}
/* Create an entry id, based upon the hostname and port */
- create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
- entry_len = strlen(entry_id);
+ entry_len = create_hostcache_id(hostname, hostlen, port,
+ entry_id, sizeof(entry_id));
dns->inuse = 1; /* the cache has the first reference */
dns->addr = addr; /* this is the address(es) */
@@ -463,12 +516,12 @@
}
#ifdef ENABLE_IPV6
-/* return a static IPv6 resolve for 'localhost' */
-static struct Curl_addrinfo *get_localhost6(int port)
+/* return a static IPv6 ::1 for the name */
+static struct Curl_addrinfo *get_localhost6(int port, const char *name)
{
struct Curl_addrinfo *ca;
const size_t ss_size = sizeof(struct sockaddr_in6);
- const size_t hostlen = strlen("localhost");
+ const size_t hostlen = strlen(name);
struct sockaddr_in6 sa6;
unsigned char ipv6[16];
unsigned short port16 = (unsigned short)(port & 0xffff);
@@ -493,19 +546,20 @@
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, "localhost");
+ strcpy(ca->ai_canonname, name);
return ca;
}
#else
-#define get_localhost6(x) NULL
+#define get_localhost6(x,y) NULL
#endif
-/* return a static IPv4 resolve for 'localhost' */
-static struct Curl_addrinfo *get_localhost(int port)
+/* return a static IPv4 127.0.0.1 for the given name */
+static struct Curl_addrinfo *get_localhost(int port, const char *name)
{
struct Curl_addrinfo *ca;
+ struct Curl_addrinfo *ca6;
const size_t ss_size = sizeof(struct sockaddr_in);
- const size_t hostlen = strlen("localhost");
+ const size_t hostlen = strlen(name);
struct sockaddr_in sa;
unsigned int ipv4;
unsigned short port16 = (unsigned short)(port & 0xffff);
@@ -529,9 +583,13 @@
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, "localhost");
- ca->ai_next = get_localhost6(port);
- return ca;
+ strcpy(ca->ai_canonname, name);
+
+ ca6 = get_localhost6(port, name);
+ if(!ca6)
+ return ca;
+ ca6->ai_next = ca;
+ return ca6;
}
#ifdef ENABLE_IPV6
@@ -546,7 +604,11 @@
have the info kept for fast re-use */
DEBUGASSERT(data);
DEBUGASSERT(data->multi);
- return data->multi->ipv6_works;
+ if(data->multi->ipv6_up == IPV6_UNKNOWN) {
+ bool works = Curl_ipv6works(NULL);
+ data->multi->ipv6_up = works ? IPV6_WORKS : IPV6_DEAD;
+ }
+ return data->multi->ipv6_up == IPV6_WORKS;
}
else {
int ipv6_works = -1;
@@ -583,6 +645,17 @@
return FALSE;
}
+
+/* return TRUE if 'part' is a case insensitive tail of 'full' */
+static bool tailmatch(const char *full, const char *part)
+{
+ size_t plen = strlen(part);
+ size_t flen = strlen(full);
+ if(plen > flen)
+ return FALSE;
+ return strncasecompare(part, &full[flen - plen], plen);
+}
+
/*
* Curl_resolv() is the main name resolve function within libcurl. It resolves
* a name and returns a pointer to the entry in the 'entry' argument (if one
@@ -610,6 +683,14 @@
CURLcode result;
enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
struct connectdata *conn = data->conn;
+ /* We should intentionally error and not resolve .onion TLDs */
+ size_t hostname_len = strlen(hostname);
+ if(hostname_len >= 7 &&
+ (curl_strequal(&hostname[hostname_len - 6], ".onion") ||
+ curl_strequal(&hostname[hostname_len - 7], ".onion."))) {
+ failf(data, "Not resolving .onion address (RFC 7686)");
+ return CURLRESOLV_ERROR;
+ }
*entry = NULL;
#ifndef CURL_DISABLE_DOH
conn->bits.doh = FALSE; /* default is not */
@@ -663,23 +744,6 @@
return CURLRESOLV_ERROR;
}
-#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
- {
- /*
- * The automagic conversion from IPv4 literals to IPv6 literals only
- * works if the SCDynamicStoreCopyProxies system function gets called
- * first. As Curl currently doesn't support system-wide HTTP proxies, we
- * therefore don't use any value this function might return.
- *
- * This function is only available on a macOS and is not needed for
- * IPv4-only builds, hence the conditions above.
- */
- CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);
- if(dict)
- CFRelease(dict);
- }
-#endif
-
#ifndef USE_RESOLVE_ON_IPS
/* First check if this is an IPv4 address string */
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
@@ -718,8 +782,9 @@
if(conn->ip_version == CURL_IPRESOLVE_V6 && !Curl_ipv6works(data))
return CURLRESOLV_ERROR;
- if(strcasecompare(hostname, "localhost"))
- addr = get_localhost(port);
+ if(strcasecompare(hostname, "localhost") ||
+ tailmatch(hostname, ".localhost"))
+ addr = get_localhost(port, hostname);
#ifndef CURL_DISABLE_DOH
else if(allowDOH && data->set.doh && !ipnum)
addr = Curl_doh(data, hostname, port, &respwait);
@@ -754,7 +819,7 @@
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
/* we got a response, store it in the cache */
- dns = Curl_cache_addr(data, addr, hostname, port);
+ dns = Curl_cache_addr(data, addr, hostname, 0, port);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
@@ -781,7 +846,6 @@
static
void alarmfunc(int sig)
{
- /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
(void)sig;
siglongjmp(curl_jmpenv, 1);
}
@@ -861,6 +925,8 @@
This should be the last thing we do before calling Curl_resolv(),
as otherwise we'd have to worry about variables that get modified
before we invoke Curl_resolv() (and thus use "volatile"). */
+ curl_simple_lock_lock(&curl_jmpenv_lock);
+
if(sigsetjmp(curl_jmpenv, 1)) {
/* this is coming from a siglongjmp() after an alarm signal */
failf(data, "name lookup timed out");
@@ -929,6 +995,8 @@
#endif
#endif /* HAVE_SIGACTION */
+ curl_simple_lock_unlock(&curl_jmpenv_lock);
+
/* switch back the alarm() to either zero or to what it was before minus
the time we spent until now! */
if(prev_alarm) {
@@ -993,9 +1061,9 @@
/*
* Curl_init_dnscache() inits a new DNS cache.
*/
-void Curl_init_dnscache(struct Curl_hash *hash)
+void Curl_init_dnscache(struct Curl_hash *hash, int size)
{
- Curl_hash_init(hash, 7, Curl_hash_str, Curl_str_key_compare,
+ Curl_hash_init(hash, size, Curl_hash_str, Curl_str_key_compare,
freednsentry);
}
@@ -1022,8 +1090,7 @@
CURLcode Curl_loadhostpairs(struct Curl_easy *data)
{
struct curl_slist *hostp;
- char hostname[256];
- int port = 0;
+ char *host_end;
/* Default is no wildcard found */
data->state.wildcard_resolve = false;
@@ -1033,18 +1100,25 @@
if(!hostp->data)
continue;
if(hostp->data[0] == '-') {
+ unsigned long num = 0;
size_t entry_len;
+ size_t hlen = 0;
+ host_end = strchr(&hostp->data[1], ':');
- if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) {
- infof(data, "Couldn't parse CURLOPT_RESOLVE removal entry '%s'",
+ if(host_end) {
+ hlen = host_end - &hostp->data[1];
+ num = strtoul(++host_end, NULL, 10);
+ if(!hlen || (num > 0xffff))
+ host_end = NULL;
+ }
+ if(!host_end) {
+ infof(data, "Bad syntax CURLOPT_RESOLVE removal entry '%s'",
hostp->data);
continue;
}
-
/* Create an entry id, based upon the hostname and port */
- create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
- entry_len = strlen(entry_id);
-
+ entry_len = create_hostcache_id(&hostp->data[1], hlen, (int)num,
+ entry_id, sizeof(entry_id));
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
@@ -1065,25 +1139,22 @@
char *addr_begin;
char *addr_end;
char *port_ptr;
+ int port = 0;
char *end_ptr;
bool permanent = TRUE;
- char *host_begin;
- char *host_end;
unsigned long tmp_port;
bool error = true;
+ char *host_begin = hostp->data;
+ size_t hlen = 0;
- host_begin = hostp->data;
if(host_begin[0] == '+') {
host_begin++;
permanent = FALSE;
}
host_end = strchr(host_begin, ':');
- if(!host_end ||
- ((host_end - host_begin) >= (ptrdiff_t)sizeof(hostname)))
+ if(!host_end)
goto err;
-
- memcpy(hostname, host_begin, host_end - host_begin);
- hostname[host_end - host_begin] = '\0';
+ hlen = host_end - host_begin;
port_ptr = host_end + 1;
tmp_port = strtoul(port_ptr, &end_ptr, 10);
@@ -1150,7 +1221,7 @@
goto err;
error = false;
- err:
+err:
if(error) {
failf(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'",
hostp->data);
@@ -1159,8 +1230,8 @@
}
/* Create an entry id, based upon the hostname and port */
- create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
- entry_len = strlen(entry_id);
+ entry_len = create_hostcache_id(host_begin, hlen, port,
+ entry_id, sizeof(entry_id));
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
@@ -1169,8 +1240,8 @@
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
if(dns) {
- infof(data, "RESOLVE %s:%d is - old addresses discarded",
- hostname, port);
+ infof(data, "RESOLVE %.*s:%d is - old addresses discarded",
+ (int)hlen, host_begin, port);
/* delete old entry, there are two reasons for this
1. old entry may have different addresses.
2. even if entry with correct addresses is already in the cache,
@@ -1186,7 +1257,7 @@
}
/* put this new host in the cache */
- dns = Curl_cache_addr(data, head, hostname, port);
+ dns = Curl_cache_addr(data, head, host_begin, hlen, port);
if(dns) {
if(permanent)
dns->timestamp = 0; /* mark as permanent */
@@ -1202,13 +1273,13 @@
Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
- infof(data, "Added %s:%d:%s to DNS cache%s",
- hostname, port, addresses, permanent ? "" : " (non-permanent)");
+ infof(data, "Added %.*s:%d:%s to DNS cache%s",
+ (int)hlen, host_begin, port, addresses,
+ permanent ? "" : " (non-permanent)");
/* Wildcard hostname */
- if(hostname[0] == '*' && hostname[1] == '\0') {
- infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks",
- hostname, port);
+ if((hlen == 1) && (host_begin[0] == '*')) {
+ infof(data, "RESOLVE *:%d using wildcard", port);
data->state.wildcard_resolve = true;
}
}
diff --git a/lib/hostip.h b/lib/hostip.h
index 4b60337..06d0867 100644
--- a/lib/hostip.h
+++ b/lib/hostip.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,11 +34,6 @@
#include <setjmp.h>
#endif
-#ifdef NETWARE
-#undef in_addr_t
-#define in_addr_t unsigned long
-#endif
-
/* Allocate enough memory to hold the full name information structs and
* everything. OSF1 is known to require at least 8872 bytes. The buffer
* required for storing all possible aliases and IP numbers is according to
@@ -132,14 +127,11 @@
struct Curl_dns_entry *dns);
/* init a new dns cache */
-void Curl_init_dnscache(struct Curl_hash *hash);
+void Curl_init_dnscache(struct Curl_hash *hash, int hashsize);
/* prune old entries from the DNS cache */
void Curl_hostcache_prune(struct Curl_easy *data);
-/* Return # of addresses in a Curl_addrinfo struct */
-int Curl_num_addresses(const struct Curl_addrinfo *addr);
-
/* IPv4 threadsafe resolve function used for synch and asynch builds */
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
@@ -183,7 +175,7 @@
*/
struct Curl_dns_entry *
Curl_cache_addr(struct Curl_easy *data, struct Curl_addrinfo *addr,
- const char *hostname, int port);
+ const char *hostname, size_t hostlen, int port);
#ifndef INADDR_NONE
#define CURL_INADDR_NONE (in_addr_t) ~0
@@ -191,15 +183,6 @@
#define CURL_INADDR_NONE INADDR_NONE
#endif
-#ifdef HAVE_SIGSETJMP
-/* Forward-declaration of variable defined in hostip.c. Beware this
- * is a global and unique instance. This is used to store the return
- * address that we can jump back to from inside a signal handler.
- * This is not thread-safe stuff.
- */
-extern sigjmp_buf curl_jmpenv;
-#endif
-
/*
* Function provided by the resolver backend to set DNS servers to use.
*/
diff --git a/lib/hostip4.c b/lib/hostip4.c
index 47da605..9140180 100644
--- a/lib/hostip4.c
+++ b/lib/hostip4.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -43,10 +43,6 @@
#include <inet.h>
#endif
-#ifdef HAVE_PROCESS_H
-#include <process.h>
-#endif
-
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
@@ -112,7 +108,8 @@
#endif /* CURLRES_SYNCH */
#endif /* CURLRES_IPV4 */
-#if defined(CURLRES_IPV4) && !defined(CURLRES_ARES)
+#if defined(CURLRES_IPV4) && \
+ !defined(CURLRES_ARES) && !defined(CURLRES_AMIGA)
/*
* Curl_ipv4_resolve_r() - ipv4 threadsafe resolver function.
@@ -124,14 +121,15 @@
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
int port)
{
-#if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3)
+#if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE)) && \
+ defined(HAVE_GETHOSTBYNAME_R_3)
int res;
#endif
struct Curl_addrinfo *ai = NULL;
struct hostent *h = NULL;
struct hostent *buf = NULL;
-#if defined(HAVE_GETADDRINFO_THREADSAFE)
+#if defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE)
struct addrinfo hints;
char sbuf[12];
char *sbufptr = NULL;
@@ -279,14 +277,16 @@
h = NULL; /* set return code to NULL */
free(buf);
}
-#else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
+#else /* (HAVE_GETADDRINFO && HAVE_GETADDRINFO_THREADSAFE) ||
+ HAVE_GETHOSTBYNAME_R */
/*
* Here is code for platforms that don't have a thread safe
* getaddrinfo() nor gethostbyname_r() function or for which
* gethostbyname() is the preferred one.
*/
h = gethostbyname((void *)hostname);
-#endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
+#endif /* (HAVE_GETADDRINFO && HAVE_GETADDRINFO_THREADSAFE) ||
+ HAVE_GETHOSTBYNAME_R */
if(h) {
ai = Curl_he2ai(h, port);
@@ -297,4 +297,5 @@
return ai;
}
-#endif /* defined(CURLRES_IPV4) && !defined(CURLRES_ARES) */
+#endif /* defined(CURLRES_IPV4) && !defined(CURLRES_ARES) &&
+ !defined(CURLRES_AMIGA) */
diff --git a/lib/hostip6.c b/lib/hostip6.c
index d986862..6b0ba55 100644
--- a/lib/hostip6.c
+++ b/lib/hostip6.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -43,10 +43,6 @@
#include <inet.h>
#endif
-#ifdef HAVE_PROCESS_H
-#include <process.h>
-#endif
-
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
@@ -96,8 +92,8 @@
* non-ares version).
*
* Returns name information about the given hostname and port number. If
- * successful, the 'addrinfo' is returned and the forth argument will point to
- * memory we need to free after use. That memory *MUST* be freed with
+ * successful, the 'addrinfo' 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.
*/
struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
@@ -117,7 +113,7 @@
*waitp = 0; /* synchronous response only */
- if(Curl_ipv6works(data))
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
diff --git a/lib/hostsyn.c b/lib/hostsyn.c
index ee54363..ca8b075 100644
--- a/lib/hostsyn.c
+++ b/lib/hostsyn.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -43,10 +43,6 @@
#include <inet.h>
#endif
-#ifdef HAVE_PROCESS_H
-#include <process.h>
-#endif
-
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
diff --git a/lib/hsts.c b/lib/hsts.c
index 4ba0f30..7ecf004 100644
--- a/lib/hsts.c
+++ b/lib/hsts.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -39,7 +39,7 @@
#include "parsedate.h"
#include "fopen.h"
#include "rename.h"
-#include "strtoofft.h"
+#include "share.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -57,7 +57,7 @@
/* to play well with debug builds, we can *set* a fixed time this will
return */
time_t deltatime; /* allow for "adjustments" for unit test purposes */
-static time_t debugtime(void *unused)
+static time_t hsts_debugtime(void *unused)
{
char *timestr = getenv("CURL_TIME");
(void)unused;
@@ -70,7 +70,8 @@
}
return time(NULL);
}
-#define time(x) debugtime(x)
+#undef time
+#define time(x) hsts_debugtime(x)
#endif
struct hsts *Curl_hsts_init(void)
@@ -156,9 +157,9 @@
return CURLE_OK;
do {
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
- if(Curl_strncasecompare("max-age=", p, 8)) {
+ if(strncasecompare("max-age=", p, 8)) {
bool quoted = FALSE;
CURLofft offt;
char *endp;
@@ -167,7 +168,7 @@
return CURLE_BAD_FUNCTION_ARGUMENT;
p += 8;
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(*p == '\"') {
p++;
@@ -187,7 +188,7 @@
}
gotma = TRUE;
}
- else if(Curl_strncasecompare("includesubdomains", p, 17)) {
+ else if(strncasecompare("includesubdomains", p, 17)) {
if(gotinc)
return CURLE_BAD_FUNCTION_ARGUMENT;
subdomains = TRUE;
@@ -200,11 +201,11 @@
p++;
}
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(*p == ';')
p++;
- } while (*p);
+ } while(*p);
if(!gotma)
/* max-age is mandatory */
@@ -278,11 +279,11 @@
if(ntail < hlen) {
size_t offs = hlen - ntail;
if((hostname[offs-1] == '.') &&
- Curl_strncasecompare(&hostname[offs], sts->host, ntail))
+ strncasecompare(&hostname[offs], sts->host, ntail))
return sts;
}
}
- if(Curl_strcasecompare(hostname, sts->host))
+ if(strcasecompare(hostname, sts->host))
return sts;
}
}
@@ -390,7 +391,7 @@
unlink(tempstore);
}
free(tempstore);
- skipsave:
+skipsave:
if(data->set.hsts_write) {
/* if there's a write callback */
struct curl_index i; /* count */
@@ -426,14 +427,23 @@
if(2 == rc) {
time_t expires = strcmp(date, UNLIMITED) ? Curl_getdate_capped(date) :
TIME_T_MAX;
- CURLcode result;
+ CURLcode result = CURLE_OK;
char *p = host;
bool subdomain = FALSE;
+ struct stsentry *e;
if(p[0] == '.') {
p++;
subdomain = TRUE;
}
- result = hsts_create(h, p, subdomain, expires);
+ /* only add it if not already present */
+ e = Curl_hsts(h, p, subdomain);
+ if(!e)
+ result = hsts_create(h, p, subdomain, expires);
+ else {
+ /* the same host name, use the largest expire time */
+ if(expires > e->expires)
+ e->expires = expires;
+ }
if(result)
return result;
}
@@ -525,7 +535,7 @@
}
return result;
- fail:
+fail:
Curl_safefree(h->filename);
fclose(fp);
return CURLE_OUT_OF_MEMORY;
@@ -552,4 +562,18 @@
return CURLE_OK;
}
+void Curl_hsts_loadfiles(struct Curl_easy *data)
+{
+ struct curl_slist *l = data->set.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);
+ l = l->next;
+ }
+ Curl_share_unlock(data, CURL_LOCK_DATA_HSTS);
+ }
+}
+
#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */
diff --git a/lib/hsts.h b/lib/hsts.h
index 0e36a77..d3431a5 100644
--- a/lib/hsts.h
+++ b/lib/hsts.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -59,9 +59,11 @@
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);
#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)
#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */
#endif /* HEADER_CURL_HSTS_H */
diff --git a/lib/http.c b/lib/http.c
index 258722a..e611d27 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -62,6 +62,7 @@
#include "cookie.h"
#include "vauth/vauth.h"
#include "vtls/vtls.h"
+#include "vquic/vquic.h"
#include "http_digest.h"
#include "http_ntlm.h"
#include "curl_ntlm_wb.h"
@@ -70,6 +71,7 @@
#include "url.h"
#include "share.h"
#include "hostip.h"
+#include "dynhds.h"
#include "http.h"
#include "select.h"
#include "parsedate.h" /* for the week day and month names */
@@ -80,11 +82,14 @@
#include "http_proxy.h"
#include "warnless.h"
#include "http2.h"
+#include "cfilters.h"
#include "connect.h"
#include "strdup.h"
#include "altsvc.h"
#include "hsts.h"
+#include "ws.h"
#include "c-hyper.h"
+#include "curl_ctype.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -100,20 +105,12 @@
curl_socket_t *socks);
static bool http_should_fail(struct Curl_easy *data);
-#ifndef CURL_DISABLE_PROXY
-static CURLcode add_haproxy_protocol_header(struct Curl_easy *data);
-#endif
-
-#ifdef USE_SSL
-static CURLcode https_connecting(struct Curl_easy *data, bool *done);
-static int https_getsock(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *socks);
-#else
-#define https_connecting(x,y) CURLE_COULDNT_CONNECT
-#endif
static CURLcode http_setup_conn(struct Curl_easy *data,
struct connectdata *conn);
+#ifdef USE_WEBSOCKETS
+static CURLcode ws_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn);
+#endif
/*
* HTTP handler interface.
@@ -142,6 +139,32 @@
PROTOPT_USERPWDCTRL
};
+#ifdef USE_WEBSOCKETS
+const struct Curl_handler Curl_handler_ws = {
+ "WS", /* scheme */
+ ws_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ Curl_http_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ Curl_ws_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
+ PORT_HTTP, /* defport */
+ CURLPROTO_WS, /* protocol */
+ CURLPROTO_HTTP, /* family */
+ PROTOPT_CREDSPERREQUEST | /* flags */
+ PROTOPT_USERPWDCTRL
+};
+#endif
+
#ifdef USE_SSL
/*
* HTTPS handler interface.
@@ -153,9 +176,9 @@
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
Curl_http_connect, /* connect_it */
- https_connecting, /* connecting */
+ NULL, /* connecting */
ZERO_NULL, /* doing */
- https_getsock, /* proto_getsock */
+ NULL, /* proto_getsock */
http_getsock_do, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
@@ -166,9 +189,36 @@
PORT_HTTPS, /* defport */
CURLPROTO_HTTPS, /* protocol */
CURLPROTO_HTTP, /* family */
- PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */
+ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN | /* flags */
PROTOPT_USERPWDCTRL
};
+
+#ifdef USE_WEBSOCKETS
+const struct Curl_handler Curl_handler_wss = {
+ "WSS", /* scheme */
+ ws_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ Curl_http_connect, /* connect_it */
+ NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ NULL, /* proto_getsock */
+ http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ Curl_ws_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
+ PORT_HTTPS, /* defport */
+ CURLPROTO_WSS, /* protocol */
+ CURLPROTO_HTTP, /* family */
+ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */
+ PROTOPT_USERPWDCTRL
+};
+#endif
+
#endif
static CURLcode http_setup_conn(struct Curl_easy *data,
@@ -183,28 +233,29 @@
if(!http)
return CURLE_OUT_OF_MEMORY;
- Curl_mime_initpart(&http->form, data);
+ Curl_mime_initpart(&http->form);
data->req.p.http = http;
+ connkeep(conn, "HTTP default");
- if(data->state.httpwant == CURL_HTTP_VERSION_3) {
- if(conn->handler->flags & PROTOPT_SSL)
- /* Only go HTTP/3 directly on HTTPS URLs. It needs a UDP socket and does
- the QUIC dance. */
- conn->transport = TRNSPRT_QUIC;
- else {
- failf(data, "HTTP/3 requested for non-HTTPS URL");
- return CURLE_URL_MALFORMAT;
- }
+ if(data->state.httpwant == CURL_HTTP_VERSION_3ONLY) {
+ CURLcode result = Curl_conn_may_http3(data, conn);
+ if(result)
+ return result;
}
- else {
- if(!CONN_INUSE(conn))
- /* if not already multi-using, setup connection details */
- Curl_http2_setup_conn(conn);
- Curl_http2_setup_req(data);
- }
+
return CURLE_OK;
}
+#ifdef USE_WEBSOCKETS
+static CURLcode ws_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ /* websockets is 1.1 only (for now) */
+ data->state.httpwant = CURL_HTTP_VERSION_1_1;
+ return http_setup_conn(data, conn);
+}
+#endif
+
#ifndef CURL_DISABLE_PROXY
/*
* checkProxyHeaders() checks the linked list of custom proxy headers
@@ -347,7 +398,7 @@
goto fail;
}
- fail:
+fail:
free(out);
return result;
}
@@ -373,7 +424,7 @@
goto fail;
}
- fail:
+fail:
return result;
}
@@ -487,7 +538,7 @@
}
}
- conn->bits.rewindaftersend = FALSE; /* default */
+ data->state.rewindbeforesend = FALSE; /* default */
if((expectsend == -1) || (expectsend > bytessent)) {
#if defined(USE_NTLM)
@@ -504,8 +555,8 @@
/* rewind data when completely done sending! */
if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
- conn->bits.rewindaftersend = TRUE;
- infof(data, "Rewind stream after send");
+ data->state.rewindbeforesend = TRUE;
+ infof(data, "Rewind stream before next send");
}
return CURLE_OK;
@@ -532,8 +583,8 @@
/* rewind data when completely done sending! */
if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
- conn->bits.rewindaftersend = TRUE;
- infof(data, "Rewind stream after send");
+ data->state.rewindbeforesend = TRUE;
+ infof(data, "Rewind stream before next send");
}
return CURLE_OK;
@@ -557,9 +608,11 @@
closure so we can safely do the rewind right now */
}
- if(bytessent)
- /* we rewind now at once since if we already sent something */
- return Curl_readrewind(data);
+ if(bytessent) {
+ /* mark for rewind since if we already sent something */
+ data->state.rewindbeforesend = TRUE;
+ infof(data, "Please rewind output before next send");
+ }
return CURLE_OK;
}
@@ -582,7 +635,7 @@
if(!data->set.str[STRING_BEARER])
authmask &= (unsigned long)~CURLAUTH_BEARER;
- if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
+ if(100 <= data->req.httpcode && data->req.httpcode <= 199)
/* this is a transient response code, ignore */
return CURLE_OK;
@@ -616,7 +669,7 @@
if(pickhost || pickproxy) {
if((data->state.httpreq != HTTPREQ_GET) &&
(data->state.httpreq != HTTPREQ_HEAD) &&
- !conn->bits.rewindaftersend) {
+ !data->state.rewindbeforesend) {
result = http_perhapsrewind(data, conn);
if(result)
return result;
@@ -653,21 +706,6 @@
return result;
}
-/*
- * Curl_allow_auth_to_host() tells if authentication, cookies or other
- * "sensitive data" can (still) be sent to this host.
- */
-bool Curl_allow_auth_to_host(struct Curl_easy *data)
-{
- struct connectdata *conn = data->conn;
- return (!data->state.this_is_a_follow ||
- data->set.allow_auth_to_other_hosts ||
- (data->state.first_host &&
- strcasecompare(data->state.first_host, conn->host.name) &&
- (data->state.first_remote_port == conn->remote_port) &&
- (data->state.first_remote_protocol == conn->handler->protocol)));
-}
-
#ifndef CURL_DISABLE_HTTP_AUTH
/*
* Output the correct authentication header depending on the auth type
@@ -866,7 +904,7 @@
/* To prevent the user+password to get sent to other than the original host
due to a location-follow */
- if(Curl_allow_auth_to_host(data)
+ if(Curl_auth_allowed_to_host(data)
#ifndef CURL_DISABLE_NETRC
|| conn->bits.netrc
#endif
@@ -972,7 +1010,7 @@
if(authp->picked == CURLAUTH_NEGOTIATE) {
CURLcode result = Curl_input_negotiate(data, conn, proxy, auth);
if(!result) {
- DEBUGASSERT(!data->req.newurl);
+ free(data->req.newurl);
data->req.newurl = strdup(data->state.url);
if(!data->req.newurl)
return CURLE_OUT_OF_MEMORY;
@@ -1180,15 +1218,15 @@
size_t nitems,
void *userp)
{
- struct Curl_easy *data = (struct Curl_easy *)userp;
- struct HTTP *http = data->req.p.http;
+ struct HTTP *http = (struct HTTP *)userp;
+ struct Curl_easy *data = http->backup.data;
size_t fullsize = size * nitems;
if(!http->postsize)
/* nothing to return */
return 0;
- /* make sure that a HTTP request is never sent away chunked! */
+ /* make sure that an HTTP request is never sent away chunked! */
data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
if(data->set.max_send_speed &&
@@ -1233,6 +1271,7 @@
*/
CURLcode Curl_buffer_send(struct dynbuf *in,
struct Curl_easy *data,
+ struct HTTP *http,
/* add the number of sent bytes to this
counter */
curl_off_t *bytes_written,
@@ -1245,14 +1284,13 @@
char *ptr;
size_t size;
struct connectdata *conn = data->conn;
- struct HTTP *http = data->req.p.http;
size_t sendsize;
curl_socket_t sockfd;
size_t headersize;
DEBUGASSERT(socketindex <= SECONDARYSOCKET);
- sockfd = conn->sock[socketindex];
+ sockfd = Curl_conn_get_socket(data, socketindex);
/* The looping below is required since we use non-blocking sockets, but due
to the circumstances we will just loop and try again and again etc */
@@ -1267,10 +1305,10 @@
if((conn->handler->flags & PROTOPT_SSL
#ifndef CURL_DISABLE_PROXY
- || conn->http_proxy.proxytype == CURLPROXY_HTTPS
+ || IS_HTTPS_PROXY(conn->http_proxy.proxytype)
#endif
)
- && conn->httpversion != 20) {
+ && conn->httpversion < 20) {
/* Make sure this doesn't send more body bytes than what the max send
speed says. The request bytes do not count to the max speed.
*/
@@ -1380,10 +1418,11 @@
http->backup.fread_in = data->state.in;
http->backup.postdata = http->postdata;
http->backup.postsize = http->postsize;
+ http->backup.data = data;
/* set the new pointers for the request-sending */
data->state.fread_func = (curl_read_callback)readmoredata;
- data->state.in = (void *)data;
+ data->state.in = (void *)http;
http->postdata = ptr;
http->postsize = (curl_off_t)size;
@@ -1392,7 +1431,6 @@
http->send_buffer = *in; /* copy the whole struct */
http->sending = HTTPSEND_REQUEST;
-
return CURLE_OK;
}
http->sending = HTTPSEND_BODY;
@@ -1486,48 +1524,13 @@
*/
CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
{
- CURLcode result;
struct connectdata *conn = data->conn;
/* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */
connkeep(conn, "HTTP default");
-#ifndef CURL_DISABLE_PROXY
- /* the CONNECT procedure might not have been completed */
- result = Curl_proxy_connect(data, FIRSTSOCKET);
- if(result)
- return result;
-
- if(conn->bits.proxy_connect_closed)
- /* this is not an error, just part of the connection negotiation */
- return CURLE_OK;
-
- if(CONNECT_FIRSTSOCKET_PROXY_SSL())
- return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */
-
- if(Curl_connect_ongoing(conn))
- /* nothing else to do except wait right now - we're not done here. */
- return CURLE_OK;
-
- if(data->set.haproxyprotocol) {
- /* add HAProxy PROXY protocol header */
- result = add_haproxy_protocol_header(data);
- if(result)
- return result;
- }
-#endif
-
- if(conn->given->protocol & CURLPROTO_HTTPS) {
- /* perform SSL initialization */
- result = https_connecting(data, done);
- if(result)
- return result;
- }
- else
- *done = TRUE;
-
- return CURLE_OK;
+ return Curl_conn_connect(data, FIRSTSOCKET, FALSE, done);
}
/* this returns the socket to wait for in the DO and DOING state for the multi
@@ -1538,80 +1541,11 @@
curl_socket_t *socks)
{
/* write mode */
- (void)data;
- socks[0] = conn->sock[FIRSTSOCKET];
+ (void)conn;
+ socks[0] = Curl_conn_get_socket(data, FIRSTSOCKET);
return GETSOCK_WRITESOCK(0);
}
-#ifndef CURL_DISABLE_PROXY
-static CURLcode add_haproxy_protocol_header(struct Curl_easy *data)
-{
- struct dynbuf req;
- CURLcode result;
- const char *tcp_version;
- DEBUGASSERT(data->conn);
- Curl_dyn_init(&req, DYN_HAXPROXY);
-
-#ifdef USE_UNIX_SOCKETS
- if(data->conn->unix_domain_socket)
- /* the buffer is large enough to hold this! */
- result = Curl_dyn_addn(&req, STRCONST("PROXY UNKNOWN\r\n"));
- else {
-#endif
- /* Emit the correct prefix for IPv6 */
- tcp_version = data->conn->bits.ipv6 ? "TCP6" : "TCP4";
-
- result = Curl_dyn_addf(&req, "PROXY %s %s %s %i %i\r\n",
- tcp_version,
- data->info.conn_local_ip,
- data->info.conn_primary_ip,
- data->info.conn_local_port,
- data->info.conn_primary_port);
-
-#ifdef USE_UNIX_SOCKETS
- }
-#endif
-
- if(!result)
- result = Curl_buffer_send(&req, data, &data->info.request_size,
- 0, FIRSTSOCKET);
- return result;
-}
-#endif
-
-#ifdef USE_SSL
-static CURLcode https_connecting(struct Curl_easy *data, bool *done)
-{
- CURLcode result;
- struct connectdata *conn = data->conn;
- DEBUGASSERT((data) && (data->conn->handler->flags & PROTOPT_SSL));
-
-#ifdef ENABLE_QUIC
- if(conn->transport == TRNSPRT_QUIC) {
- *done = TRUE;
- return CURLE_OK;
- }
-#endif
-
- /* perform SSL initialization for this socket */
- result = Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET, done);
- if(result)
- connclose(conn, "Failed HTTPS connection");
-
- return result;
-}
-
-static int https_getsock(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *socks)
-{
- (void)data;
- if(conn->handler->flags & PROTOPT_SSL)
- return Curl_ssl->getsock(conn, socks);
- return GETSOCK_BLANK;
-}
-#endif /* USE_SSL */
-
/*
* Curl_http_done() gets called after a single HTTP request has been
* performed.
@@ -1638,11 +1572,10 @@
return CURLE_OK;
Curl_dyn_free(&http->send_buffer);
- Curl_http2_done(data, premature);
- Curl_quic_done(data, premature);
Curl_mime_cleanpart(&http->form);
Curl_dyn_reset(&data->state.headerb);
Curl_hyper_done(data);
+ Curl_ws_done(data);
if(status)
return status;
@@ -1691,17 +1624,10 @@
static const char *get_http_string(const struct Curl_easy *data,
const struct connectdata *conn)
{
-#ifdef ENABLE_QUIC
- if((data->state.httpwant == CURL_HTTP_VERSION_3) ||
- (conn->httpversion == 30))
+ if(Curl_conn_is_http3(data, conn, FIRSTSOCKET))
return "3";
-#endif
-
-#ifdef USE_NGHTTP2
- if(conn->proto.httpc.h2)
+ if(Curl_conn_is_http2(data, conn, FIRSTSOCKET))
return "2";
-#endif
-
if(Curl_use_http_1_1plus(data, conn))
return "1.1";
@@ -1788,6 +1714,157 @@
return result;
}
+static bool hd_name_eq(const char *n1, size_t n1len,
+ const char *n2, size_t n2len)
+{
+ if(n1len == n2len) {
+ return strncasecompare(n1, n2, n1len);
+ }
+ return FALSE;
+}
+
+CURLcode Curl_dynhds_add_custom(struct Curl_easy *data,
+ bool is_connect,
+ struct dynhds *hds)
+{
+ struct connectdata *conn = data->conn;
+ char *ptr;
+ struct curl_slist *h[2];
+ struct curl_slist *headers;
+ int numlists = 1; /* by default */
+ int i;
+
+#ifndef CURL_DISABLE_PROXY
+ enum proxy_use proxy;
+
+ if(is_connect)
+ proxy = HEADER_CONNECT;
+ else
+ proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy?
+ HEADER_PROXY:HEADER_SERVER;
+
+ switch(proxy) {
+ case HEADER_SERVER:
+ h[0] = data->set.headers;
+ break;
+ case HEADER_PROXY:
+ h[0] = data->set.headers;
+ if(data->set.sep_headers) {
+ h[1] = data->set.proxyheaders;
+ numlists++;
+ }
+ break;
+ case HEADER_CONNECT:
+ if(data->set.sep_headers)
+ h[0] = data->set.proxyheaders;
+ else
+ h[0] = data->set.headers;
+ break;
+ }
+#else
+ (void)is_connect;
+ h[0] = data->set.headers;
+#endif
+
+ /* loop through one or two lists */
+ for(i = 0; i < numlists; i++) {
+ for(headers = h[i]; headers; headers = headers->next) {
+ const char *name, *value;
+ size_t namelen, valuelen;
+
+ /* 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 */
+ while(*ptr && ISSPACE(*ptr))
+ ptr++;
+ if(*ptr) {
+ value = ptr;
+ valuelen = strlen(value);
+ }
+ else {
+ /* quirk #1, suppress this header */
+ continue;
+ }
+ }
+ else {
+ ptr = strchr(headers->data, ';');
+
+ if(!ptr) {
+ /* neither : nor ; in provided header value. We seem
+ * to ignore this silently */
+ continue;
+ }
+
+ name = headers->data;
+ namelen = ptr - headers->data;
+ ptr++; /* pass the semicolon */
+ while(*ptr && ISSPACE(*ptr))
+ 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;
+ }
+ }
+
+ DEBUGASSERT(name && value);
+ if(data->state.aptr.host &&
+ /* a Host: header was sent already, don't pass on any custom Host:
+ header as that will produce *two* in the same request! */
+ hd_name_eq(name, namelen, STRCONST("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:")))
+ ;
+ else if(data->state.httpreq == HTTPREQ_POST_MIME &&
+ /* this header is sent later */
+ hd_name_eq(name, namelen, STRCONST("Content-Type:")))
+ ;
+ else if(conn->bits.authneg &&
+ /* while doing auth neg, don't allow the custom length since
+ we will force length zero then */
+ hd_name_eq(name, namelen, STRCONST("Content-Length:")))
+ ;
+ else if(data->state.aptr.te &&
+ /* when asking for Transfer-Encoding, don't pass on a custom
+ Connection: */
+ hd_name_eq(name, namelen, STRCONST("Connection:")))
+ ;
+ else if((conn->httpversion >= 20) &&
+ hd_name_eq(name, namelen, STRCONST("Transfer-Encoding:")))
+ /* HTTP/2 doesn't support chunked requests */
+ ;
+ else if((hd_name_eq(name, namelen, STRCONST("Authorization:")) ||
+ hd_name_eq(name, namelen, STRCONST("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);
+ if(result)
+ return result;
+ }
+ }
+ }
+
+ return CURLE_OK;
+}
+
CURLcode Curl_add_custom_headers(struct Curl_easy *data,
bool is_connect,
#ifndef USE_HYPER
@@ -1919,7 +1996,7 @@
checkprefix("Cookie:", compare)) &&
/* be careful of sending this potentially sensitive header to
other hosts */
- !Curl_allow_auth_to_host(data))
+ !Curl_auth_allowed_to_host(data))
;
else {
#ifdef USE_HYPER
@@ -2032,17 +2109,17 @@
void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
const char **method, Curl_HttpReq *reqp)
{
- Curl_HttpReq httpreq = data->state.httpreq;
+ Curl_HttpReq httpreq = (Curl_HttpReq)data->state.httpreq;
const char *request;
if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
- data->set.upload)
+ data->state.upload)
httpreq = HTTPREQ_PUT;
/* Now set the 'request' pointer to the proper request string */
if(data->set.str[STRING_CUSTOMREQUEST])
request = data->set.str[STRING_CUSTOMREQUEST];
else {
- if(data->set.opt_no_body)
+ if(data->req.no_body)
request = "HEAD";
else {
DEBUGASSERT((httpreq >= HTTPREQ_GET) && (httpreq <= HTTPREQ_HEAD));
@@ -2086,8 +2163,9 @@
CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
{
const char *ptr;
+ struct dynamically_allocated_data *aptr = &data->state.aptr;
if(!data->state.this_is_a_follow) {
- /* Free to avoid leaking memory on multiple requests*/
+ /* Free to avoid leaking memory on multiple requests */
free(data->state.first_host);
data->state.first_host = strdup(conn->host.name);
@@ -2097,7 +2175,7 @@
data->state.first_remote_port = conn->remote_port;
data->state.first_remote_protocol = conn->handler->protocol;
}
- Curl_safefree(data->state.aptr.host);
+ Curl_safefree(aptr->host);
ptr = Curl_checkheaders(data, STRCONST("Host"));
if(ptr && (!data->state.this_is_a_follow ||
@@ -2132,43 +2210,36 @@
if(colon)
*colon = 0; /* The host must not include an embedded port number */
}
- Curl_safefree(data->state.aptr.cookiehost);
- data->state.aptr.cookiehost = cookiehost;
+ Curl_safefree(aptr->cookiehost);
+ aptr->cookiehost = cookiehost;
}
#endif
if(strcmp("Host:", ptr)) {
- data->state.aptr.host = aprintf("Host:%s\r\n", &ptr[5]);
- if(!data->state.aptr.host)
+ aptr->host = aprintf("Host:%s\r\n", &ptr[5]);
+ if(!aptr->host)
return CURLE_OUT_OF_MEMORY;
}
- else
- /* when clearing the header */
- data->state.aptr.host = NULL;
}
else {
/* When building Host: headers, we must put the host name within
[brackets] if the host name is a plain IPv6-address. RFC2732-style. */
const char *host = conn->host.name;
- if(((conn->given->protocol&CURLPROTO_HTTPS) &&
+ if(((conn->given->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS)) &&
(conn->remote_port == PORT_HTTPS)) ||
- ((conn->given->protocol&CURLPROTO_HTTP) &&
+ ((conn->given->protocol&(CURLPROTO_HTTP|CURLPROTO_WS)) &&
(conn->remote_port == PORT_HTTP)) )
/* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
the port number in the host string */
- data->state.aptr.host = aprintf("Host: %s%s%s\r\n",
- conn->bits.ipv6_ip?"[":"",
- host,
- conn->bits.ipv6_ip?"]":"");
+ aptr->host = aprintf("Host: %s%s%s\r\n", conn->bits.ipv6_ip?"[":"",
+ host, conn->bits.ipv6_ip?"]":"");
else
- data->state.aptr.host = aprintf("Host: %s%s%s:%d\r\n",
- conn->bits.ipv6_ip?"[":"",
- host,
- conn->bits.ipv6_ip?"]":"",
- conn->remote_port);
+ aptr->host = aprintf("Host: %s%s%s:%d\r\n", conn->bits.ipv6_ip?"[":"",
+ host, conn->bits.ipv6_ip?"]":"",
+ conn->remote_port);
- if(!data->state.aptr.host)
+ if(!aptr->host)
/* without Host: we can't make a nice request */
return CURLE_OUT_OF_MEMORY;
}
@@ -2330,7 +2401,7 @@
cthdr = "multipart/form-data";
curl_mime_headers(http->sendit, data->set.headers, 0);
- result = Curl_mime_prepare_headers(http->sendit, cthdr,
+ result = Curl_mime_prepare_headers(data, http->sendit, cthdr,
NULL, MIMESTRATEGY_FORM);
curl_mime_headers(http->sendit, NULL, 0);
if(!result)
@@ -2352,7 +2423,7 @@
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
(((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
http->postsize < 0) ||
- ((data->set.upload || httpreq == HTTPREQ_POST) &&
+ ((data->state.upload || httpreq == HTTPREQ_POST) &&
data->state.infilesize == -1))) {
if(conn->bits.authneg)
/* don't enable chunked during auth neg */
@@ -2386,7 +2457,7 @@
curl_off_t included_body = 0;
#else
/* from this point down, this function should not be used */
-#define Curl_buffer_send(a,b,c,d,e) CURLE_OK
+#define Curl_buffer_send(a,b,c,d,e,f) CURLE_OK
#endif
CURLcode result = CURLE_OK;
struct HTTP *http = data->req.p.http;
@@ -2415,7 +2486,16 @@
return result;
}
- if(http->postsize) {
+ /* For really small puts we don't use Expect: headers at all, and for
+ the somewhat bigger ones we allow the app to disable it. Just make
+ sure that the expect100header is always set to the preferred value
+ here. */
+ ptr = Curl_checkheaders(data, STRCONST("Expect"));
+ if(ptr) {
+ data->state.expect100header =
+ Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
+ }
+ else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
result = expect100(data, conn, r);
if(result)
return result;
@@ -2430,7 +2510,8 @@
Curl_pgrsSetUploadSize(data, http->postsize);
/* this sends the buffer and frees all the buffer resources */
- result = Curl_buffer_send(r, data, &data->info.request_size, 0,
+ result = Curl_buffer_send(r, data, data->req.p.http,
+ &data->info.request_size, 0,
FIRSTSOCKET);
if(result)
failf(data, "Failed sending PUT request");
@@ -2451,7 +2532,8 @@
if(result)
return result;
- result = Curl_buffer_send(r, data, &data->info.request_size, 0,
+ result = Curl_buffer_send(r, data, data->req.p.http,
+ &data->info.request_size, 0,
FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
@@ -2467,8 +2549,7 @@
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if(http->postsize != -1 && !data->req.upload_chunky &&
- (conn->bits.authneg ||
- !Curl_checkheaders(data, STRCONST("Content-Length")))) {
+ (!Curl_checkheaders(data, STRCONST("Content-Length")))) {
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
result = Curl_dyn_addf(r,
@@ -2522,7 +2603,8 @@
http->sending = HTTPSEND_BODY;
/* this sends the buffer and frees all the buffer resources */
- result = Curl_buffer_send(r, data, &data->info.request_size, 0,
+ result = Curl_buffer_send(r, data, data->req.p.http,
+ &data->info.request_size, 0,
FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
@@ -2585,11 +2667,7 @@
#ifndef USE_HYPER
/* With Hyper the body is always passed on separately */
if(data->set.postfields) {
-
- /* In HTTP2, we send request body in DATA frame regardless of
- its size. */
- if(conn->httpversion != 20 &&
- !data->state.expect100header &&
+ if(!data->state.expect100header &&
(http->postsize < MAX_INITIAL_POST_SIZE)) {
/* if we don't use expect: 100 AND
postsize is less than MAX_INITIAL_POST_SIZE
@@ -2639,11 +2717,10 @@
else {
/* A huge POST coming up, do data separate from the request */
http->postdata = data->set.postfields;
-
http->sending = HTTPSEND_BODY;
-
+ http->backup.data = data;
data->state.fread_func = (curl_read_callback)readmoredata;
- data->state.in = (void *)data;
+ data->state.in = (void *)http;
/* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize);
@@ -2682,7 +2759,8 @@
}
}
/* issue the request */
- result = Curl_buffer_send(r, data, &data->info.request_size, included_body,
+ result = Curl_buffer_send(r, data, data->req.p.http,
+ &data->info.request_size, included_body,
FIRSTSOCKET);
if(result)
@@ -2698,10 +2776,18 @@
return result;
/* issue the request */
- result = Curl_buffer_send(r, data, &data->info.request_size, 0,
+ result = Curl_buffer_send(r, data, data->req.p.http,
+ &data->info.request_size, 0,
FIRSTSOCKET);
if(result)
failf(data, "Failed sending HTTP request");
+#ifdef USE_WEBSOCKETS
+ else if((conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) &&
+ !(data->set.connect_only))
+ /* Set up the transfer for two-way since without CONNECT_ONLY set, this
+ request probably wants to send data too post upgrade */
+ Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, FIRSTSOCKET);
+#endif
else
/* HTTP GET/HEAD download: */
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
@@ -2731,10 +2817,10 @@
const char *host = data->state.aptr.cookiehost ?
data->state.aptr.cookiehost : conn->host.name;
const bool secure_context =
- conn->handler->protocol&CURLPROTO_HTTPS ||
+ conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
strcasecompare("localhost", host) ||
!strcmp(host, "127.0.0.1") ||
- !strcmp(host, "[::1]") ? TRUE : FALSE;
+ !strcmp(host, "::1") ? TRUE : FALSE;
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
co = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path,
secure_context);
@@ -2742,16 +2828,18 @@
}
if(co) {
struct Cookie *store = co;
+ size_t clen = 8; /* hold the size of the generated Cookie: header */
/* now loop through all cookies that matched */
while(co) {
if(co->value) {
- if(0 == count) {
+ size_t add;
+ if(!count) {
result = Curl_dyn_addn(r, STRCONST("Cookie: "));
if(result)
break;
}
- if((Curl_dyn_len(r) + strlen(co->name) + strlen(co->value) + 1) >=
- MAX_COOKIE_HEADER_LEN) {
+ add = strlen(co->name) + strlen(co->value) + 1;
+ if(clen + add >= MAX_COOKIE_HEADER_LEN) {
infof(data, "Restricted outgoing cookies due to header size, "
"'%s' not sent", co->name);
linecap = TRUE;
@@ -2761,6 +2849,7 @@
co->name, co->value);
if(result)
break;
+ clen += add + (count ? 2 : 0);
count++;
}
co = co->next; /* next cookie please */
@@ -2864,8 +2953,8 @@
data->state.resume_from = 0;
}
- if(data->state.resume_from && !data->state.this_is_a_follow) {
- /* do we still game? */
+ if(data->state.resume_from && !data->state.followlocation) {
+ /* only act on the first request */
/* Now, let's read off the proper amount of bytes from the
input. */
@@ -2966,14 +3055,14 @@
if(data->set.timecondition && !data->state.range) {
/* A time condition has been set AND no ranges have been requested. This
seems to be what chapter 13.3.4 of RFC 2616 defines to be the correct
- action for a HTTP/1.1 client */
+ action for an HTTP/1.1 client */
if(!Curl_meets_timecondition(data, k->timeofdoc)) {
*done = TRUE;
- /* We're simulating a http 304 from server so we return
+ /* We're simulating an HTTP 304 from server so we return
what should have been returned from the server */
data->info.httpcode = 304;
- infof(data, "Simulate a HTTP 304 response");
+ infof(data, "Simulate an HTTP 304 response");
/* we abort the transfer before it is completed == we ruin the
re-use ability. Close the connection */
streamclose(conn, "Simulated 304 handling");
@@ -3019,7 +3108,7 @@
#ifndef USE_HYPER
/*
- * Curl_http() gets called from the generic multi_do() function when a HTTP
+ * Curl_http() gets called from the generic multi_do() function when an HTTP
* request is to be performed. This creates and sends a properly constructed
* HTTP request.
*/
@@ -3041,50 +3130,37 @@
the rest of the request in the PERFORM phase. */
*done = TRUE;
- if(conn->transport != TRNSPRT_QUIC) {
- if(conn->httpversion < 20) { /* unless the connection is re-used and
- already http2 */
- switch(conn->negnpn) {
- case CURL_HTTP_VERSION_2:
- conn->httpversion = 20; /* we know we're on HTTP/2 now */
-
- result = Curl_http2_switched(data, NULL, 0);
- if(result)
- return result;
- break;
- case CURL_HTTP_VERSION_1_1:
- /* continue with HTTP/1.1 when explicitly requested */
- break;
- default:
- /* Check if user wants to use HTTP/2 with clear TCP*/
-#ifdef USE_NGHTTP2
- if(data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+ switch(conn->alpn) {
+ case CURL_HTTP_VERSION_3:
+ DEBUGASSERT(Curl_conn_is_http3(data, conn, FIRSTSOCKET));
+ break;
+ case CURL_HTTP_VERSION_2:
#ifndef CURL_DISABLE_PROXY
- if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
- /* We don't support HTTP/2 proxies yet. Also it's debatable
- whether or not this setting should apply to HTTP/2 proxies. */
- infof(data, "Ignoring HTTP/2 prior knowledge due to proxy");
- break;
- }
-#endif
- DEBUGF(infof(data, "HTTP/2 over clean TCP"));
- conn->httpversion = 20;
-
- result = Curl_http2_switched(data, NULL, 0);
- if(result)
- return result;
- }
-#endif
- break;
- }
- }
- else {
- /* prepare for a http2 request */
- result = Curl_http2_setup(data, conn);
+ if(!Curl_conn_is_http2(data, conn, FIRSTSOCKET) &&
+ conn->bits.proxy && !conn->bits.tunnel_proxy
+ ) {
+ result = Curl_http2_switch(data, conn, FIRSTSOCKET);
if(result)
return result;
}
+ else
+#endif
+ DEBUGASSERT(Curl_conn_is_http2(data, conn, FIRSTSOCKET));
+ break;
+ case CURL_HTTP_VERSION_1_1:
+ /* continue with HTTP/1.1 when explicitly requested */
+ break;
+ default:
+ /* Check if user wants to use HTTP/2 with clear TCP */
+ if(Curl_http2_may_switch(data, conn, FIRSTSOCKET)) {
+ DEBUGF(infof(data, "HTTP/2 over clean TCP"));
+ result = Curl_http2_switch(data, conn, FIRSTSOCKET);
+ if(result)
+ return result;
+ }
+ break;
}
+
http = data->req.p.http;
DEBUGASSERT(http);
@@ -3244,7 +3320,7 @@
}
if(!(conn->handler->flags&PROTOPT_SSL) &&
- conn->httpversion != 20 &&
+ conn->httpversion < 20 &&
(data->state.httpwant == CURL_HTTP_VERSION_2)) {
/* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
over SSL */
@@ -3256,6 +3332,10 @@
}
result = Curl_http_cookies(data, conn, &req);
+#ifdef USE_WEBSOCKETS
+ if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
+ result = Curl_ws_request(data, &req);
+#endif
if(!result)
result = Curl_add_timecondition(data, &req);
if(!result)
@@ -3300,7 +3380,10 @@
}
}
- if((conn->httpversion == 20) && data->req.upload_chunky)
+ if(data->req.upload_done)
+ Curl_conn_ev_data_done_send(data);
+
+ if((conn->httpversion >= 20) && data->req.upload_chunky)
/* upload_chunky was set above to set up the request in a chunky fashion,
but is disabled here again to avoid that the chunked encoded version is
actually used when sending the request body over h2 */
@@ -3434,7 +3517,7 @@
STRCONST("Proxy-Connection:"),
STRCONST("keep-alive"))) {
/*
- * When a HTTP/1.0 reply comes when using a proxy, the
+ * When an HTTP/1.0 reply comes when using a proxy, the
* 'Proxy-Connection: keep-alive' line tells us the
* connection will be kept alive for our pleasure.
* Default action for 1.0 is to close.
@@ -3448,7 +3531,7 @@
STRCONST("Proxy-Connection:"),
STRCONST("close"))) {
/*
- * We get a HTTP/1.1 response from a proxy and it says it'll
+ * We get an HTTP/1.1 response from a proxy and it says it'll
* close down after this transfer.
*/
connclose(conn, "Proxy-Connection: asked to close after done");
@@ -3460,7 +3543,7 @@
STRCONST("Connection:"),
STRCONST("keep-alive"))) {
/*
- * A HTTP/1.0 reply with the 'Connection: keep-alive' line
+ * An HTTP/1.0 reply with the 'Connection: keep-alive' line
* tells us the connection will be kept alive for our
* pleasure. Default action for 1.0 is to close.
*
@@ -3495,7 +3578,7 @@
TRUE);
if(result)
return result;
- if(!k->chunk) {
+ if(!k->chunk && data->set.http_transfer_encoding) {
/* if this isn't chunked, only close can signal the end of this transfer
as Content-Length is said not to be trusted for transfer-encoding! */
connclose(conn, "HTTP/1.1 transfer-encoding without chunks");
@@ -3520,15 +3603,15 @@
else if(checkprefix("Retry-After:", headp)) {
/* Retry-After = HTTP-date / delay-seconds */
curl_off_t retry_after = 0; /* zero for unknown or "now" */
- time_t date = Curl_getdate_capped(headp + strlen("Retry-After:"));
- if(-1 == date) {
- /* not a date, try it as a decimal number */
- (void)curlx_strtoofft(headp + strlen("Retry-After:"),
- NULL, 10, &retry_after);
+ /* Try it as a decimal number, if it works it is not a date */
+ (void)curlx_strtoofft(headp + strlen("Retry-After:"),
+ NULL, 10, &retry_after);
+ if(!retry_after) {
+ time_t date = Curl_getdate_capped(headp + strlen("Retry-After:"));
+ if(-1 != date)
+ /* convert date to number of seconds into the future */
+ retry_after = date - time(NULL);
}
- else
- /* convert date to number of seconds into the future */
- retry_after = date - time(NULL);
data->info.retry_after = retry_after; /* store it */
}
else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
@@ -3540,7 +3623,7 @@
The second format was added since Sun's webserver
JavaWebServer/1.1.1 obviously sends the header this way!
The third added since some servers use that!
- The forth means the requested range was unsatisfied.
+ The fourth means the requested range was unsatisfied.
*/
char *ptr = headp + strlen("Content-Range:");
@@ -3568,10 +3651,10 @@
const char *host = data->state.aptr.cookiehost?
data->state.aptr.cookiehost:conn->host.name;
const bool secure_context =
- conn->handler->protocol&CURLPROTO_HTTPS ||
+ conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
strcasecompare("localhost", host) ||
!strcmp(host, "127.0.0.1") ||
- !strcmp(host, "[::1]") ? TRUE : FALSE;
+ !strcmp(host, "::1") ? TRUE : FALSE;
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
CURL_LOCK_ACCESS_SINGLE);
@@ -3645,6 +3728,9 @@
result = http_perhapsrewind(data, conn);
if(result)
return result;
+
+ /* mark the next request as a followed location: */
+ data->state.this_is_a_follow = TRUE;
}
}
}
@@ -3652,9 +3738,16 @@
#ifndef CURL_DISABLE_HSTS
/* If enabled, the header is incoming and this is over HTTPS */
else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) &&
- (conn->handler->flags & PROTOPT_SSL)) {
+ ((conn->handler->flags & PROTOPT_SSL) ||
+#ifdef CURLDEBUG
+ /* allow debug builds to circumvent the HTTPS restriction */
+ getenv("CURL_HSTS_HTTP")
+#else
+ 0
+#endif
+ )) {
CURLcode check =
- Curl_hsts_parse(data->hsts, data->state.up.hostname,
+ Curl_hsts_parse(data->hsts, conn->host.name,
headp + strlen("Strict-Transport-Security:"));
if(check)
infof(data, "Illegal STS header skipped");
@@ -3677,11 +3770,12 @@
#endif
)) {
/* the ALPN of the current request */
- enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
+ enum alpnid id = (conn->httpversion == 30)? ALPN_h3 :
+ (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
result = Curl_altsvc_parse(data, data->asi,
headp + strlen("Alt-Svc:"),
id, conn->host.name,
- curlx_uitous(conn->remote_port));
+ curlx_uitous((unsigned int)conn->remote_port));
if(result)
return result;
}
@@ -3734,7 +3828,7 @@
connclose(conn, "HTTP/1.0 close after body");
}
else if(conn->httpversion == 20 ||
- (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
+ (k->upgr101 == UPGR101_H2 && k->httpcode == 101)) {
DEBUGF(infof(data, "HTTP/2 found, allow multiplexing"));
/* HTTP/2 cannot avoid multiplexing since it is a core functionality
of the protocol */
@@ -3942,7 +4036,7 @@
switch(k->httpcode) {
case 100:
/*
- * We have made a HTTP PUT or POST and this is 1.1-lingo
+ * We have made an HTTP PUT or POST and this is 1.1-lingo
* that tells us that the server is OK with this and ready
* to receive the data.
* However, we'll get more headers now so we must get
@@ -3960,9 +4054,9 @@
break;
case 101:
/* Switching Protocols */
- if(k->upgr101 == UPGR101_REQUESTED) {
+ if(k->upgr101 == UPGR101_H2) {
/* Switching to HTTP/2 */
- infof(data, "Received 101");
+ infof(data, "Received 101, Switching to HTTP/2");
k->upgr101 = UPGR101_RECEIVED;
/* we'll get more headers (HTTP/2 response) */
@@ -3971,13 +4065,27 @@
/* switch to http2 now. The bytes after response headers
are also processed here, otherwise they are lost. */
- result = Curl_http2_switched(data, k->str, *nread);
+ result = Curl_http2_upgrade(data, conn, FIRSTSOCKET,
+ k->str, *nread);
if(result)
return result;
*nread = 0;
}
+#ifdef USE_WEBSOCKETS
+ else if(k->upgr101 == UPGR101_WS) {
+ /* verify the response */
+ result = Curl_ws_accept(data, k->str, *nread);
+ if(result)
+ return result;
+ k->header = FALSE; /* no more header to parse! */
+ if(data->set.connect_only) {
+ k->keepon &= ~KEEP_RECV; /* read no more content */
+ *nread = 0;
+ }
+ }
+#endif
else {
- /* Switching to another protocol (e.g. WebSocket) */
+ /* Not switching to another protocol */
k->header = FALSE; /* no more header to parse! */
}
break;
@@ -4070,6 +4178,16 @@
return CURLE_HTTP_RETURNED_ERROR;
}
+#ifdef USE_WEBSOCKETS
+ /* All non-101 HTTP status codes are bad when wanting to upgrade to
+ websockets */
+ if(data->req.upgr101 == UPGR101_WS) {
+ failf(data, "Refused WebSockets upgrade: %d", k->httpcode);
+ return CURLE_HTTP_RETURNED_ERROR;
+ }
+#endif
+
+
data->req.deductheadercount =
(100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
@@ -4083,7 +4201,7 @@
if(k->httpcode >= 300) {
if((!conn->bits.authneg) && !conn->bits.close &&
- !conn->bits.rewindaftersend) {
+ !data->state.rewindbeforesend) {
/*
* General treatment of errors when about to send data. Including :
* "417 Expectation Failed", while waiting for 100-continue.
@@ -4093,7 +4211,7 @@
* something else should've considered the big picture and we
* avoid this check.
*
- * rewindaftersend indicates that something has told libcurl to
+ * rewindbeforesend indicates that something has told libcurl to
* continue sending even if it gets discarded
*/
@@ -4142,9 +4260,9 @@
}
}
- if(conn->bits.rewindaftersend) {
- /* We rewind after a complete send, so thus we continue
- sending now */
+ if(data->state.rewindbeforesend &&
+ (conn->writesockfd != CURL_SOCKET_BAD)) {
+ /* We rewind before next send, continue sending now */
infof(data, "Keep sending data to get tossed away");
k->keepon |= KEEP_SEND;
}
@@ -4157,7 +4275,7 @@
* If we requested a "no body", this is a good time to get
* out and return home.
*/
- if(data->set.opt_no_body)
+ if(data->req.no_body)
*stop_reading = TRUE;
#ifndef CURL_DISABLE_RTSP
else if((conn->handler->protocol & CURLPROTO_RTSP) &&
@@ -4176,11 +4294,8 @@
stream. In order to do this, we keep reading until we
close the stream. */
if(0 == k->maxdownload
-#if defined(USE_NGHTTP2)
- && !((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
- conn->httpversion == 20)
-#endif
- )
+ && !Curl_conn_is_http2(data, conn, FIRSTSOCKET)
+ && !Curl_conn_is_http3(data, conn, FIRSTSOCKET))
*stop_reading = TRUE;
if(*stop_reading) {
@@ -4205,11 +4320,7 @@
if(!k->headerline++) {
/* This is the first header, it MUST be the error code line
or else we consider this to be the body right away! */
- int httpversion_major;
- int rtspversion_major;
- int nc = 0;
-#define HEADER1 headp /* no conversion needed, just use headp */
-
+ bool fine_statusline = FALSE;
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
/*
* https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2
@@ -4218,39 +4329,60 @@
* says. We allow any three-digit number here, but we cannot make
* guarantees on future behaviors since it isn't within the protocol.
*/
- char separator;
- char twoorthree[2];
int httpversion = 0;
- char digit4 = 0;
- nc = sscanf(HEADER1,
- " HTTP/%1d.%1d%c%3d%c",
- &httpversion_major,
- &httpversion,
- &separator,
- &k->httpcode,
- &digit4);
+ char *p = headp;
- if(nc == 1 && httpversion_major >= 2 &&
- 2 == sscanf(HEADER1, " HTTP/%1[23] %d", twoorthree, &k->httpcode)) {
- conn->httpversion = 0;
- nc = 4;
- separator = ' ';
+ while(*p && ISBLANK(*p))
+ p++;
+ if(!strncmp(p, "HTTP/", 5)) {
+ p += 5;
+ switch(*p) {
+ case '1':
+ p++;
+ if((p[0] == '.') && (p[1] == '0' || p[1] == '1')) {
+ if(ISBLANK(p[2])) {
+ httpversion = 10 + (p[1] - '0');
+ p += 3;
+ if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
+ k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
+ (p[2] - '0');
+ p += 3;
+ if(ISSPACE(*p))
+ fine_statusline = TRUE;
+ }
+ }
+ }
+ if(!fine_statusline) {
+ failf(data, "Unsupported HTTP/1 subversion in response");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+ break;
+ case '2':
+ case '3':
+ if(!ISBLANK(p[1]))
+ break;
+ httpversion = (*p - '0') * 10;
+ p += 2;
+ if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
+ k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
+ (p[2] - '0');
+ p += 3;
+ if(!ISSPACE(*p))
+ break;
+ fine_statusline = TRUE;
+ }
+ break;
+ default: /* unsupported */
+ failf(data, "Unsupported HTTP version in response");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
}
- /* There can only be a 4th response code digit stored in 'digit4' if
- all the other fields were parsed and stored first, so nc is 5 when
- digit4 a digit.
-
- The sscanf() line above will also allow zero-prefixed and negative
- numbers, so we check for that too here.
- */
- else if(ISDIGIT(digit4) || (nc >= 4 && k->httpcode < 100)) {
- failf(data, "Unsupported response code in HTTP response");
- return CURLE_UNSUPPORTED_PROTOCOL;
- }
-
- if((nc >= 4) && (' ' == separator)) {
- httpversion += 10 * httpversion_major;
+ if(fine_statusline) {
+ if(k->httpcode < 100) {
+ failf(data, "Unsupported response code in HTTP response");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
switch(httpversion) {
case 10:
case 11:
@@ -4275,54 +4407,52 @@
}
if(conn->httpversion < 20) {
conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
- infof(data, "Mark bundle as not supporting multiuse");
}
}
- else if(!nc) {
- /* this is the real world, not a Nirvana
- NCSA 1.5.x returns this crap when asked for HTTP/1.1
- */
- nc = sscanf(HEADER1, " HTTP %3d", &k->httpcode);
- conn->httpversion = 10;
-
+ else {
/* If user has set option HTTP200ALIASES,
compare header line against list of aliases
*/
- if(!nc) {
- statusline check =
- checkhttpprefix(data,
- Curl_dyn_ptr(&data->state.headerb),
- Curl_dyn_len(&data->state.headerb));
- if(check == STATUS_DONE) {
- nc = 1;
- k->httpcode = 200;
- conn->httpversion = 10;
- }
+ statusline check =
+ checkhttpprefix(data,
+ Curl_dyn_ptr(&data->state.headerb),
+ Curl_dyn_len(&data->state.headerb));
+ if(check == STATUS_DONE) {
+ fine_statusline = TRUE;
+ k->httpcode = 200;
+ conn->httpversion = 10;
}
}
- else {
- failf(data, "Unsupported HTTP version in response");
- return CURLE_UNSUPPORTED_PROTOCOL;
- }
}
else if(conn->handler->protocol & CURLPROTO_RTSP) {
- char separator;
- int rtspversion;
- nc = sscanf(HEADER1,
- " RTSP/%1d.%1d%c%3d",
- &rtspversion_major,
- &rtspversion,
- &separator,
- &k->httpcode);
- if((nc == 4) && (' ' == separator)) {
- conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
- }
- else {
- nc = 0;
+ char *p = headp;
+ while(*p && ISBLANK(*p))
+ p++;
+ if(!strncmp(p, "RTSP/", 5)) {
+ p += 5;
+ if(ISDIGIT(*p)) {
+ p++;
+ if((p[0] == '.') && ISDIGIT(p[1])) {
+ if(ISBLANK(p[2])) {
+ p += 3;
+ if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
+ k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
+ (p[2] - '0');
+ p += 3;
+ if(ISSPACE(*p)) {
+ fine_statusline = TRUE;
+ conn->httpversion = 11; /* RTSP acts like HTTP 1.1 */
+ }
+ }
+ }
+ }
+ }
+ if(!fine_statusline)
+ return CURLE_WEIRD_SERVER_REPLY;
}
}
- if(nc) {
+ if(fine_statusline) {
result = Curl_http_statusline(data, conn);
if(result)
return result;
@@ -4372,4 +4502,385 @@
return CURLE_OK;
}
+
+/* Decode HTTP status code string. */
+CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len)
+{
+ CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
+ int status = 0;
+ int i;
+
+ if(len != 3)
+ goto out;
+
+ for(i = 0; i < 3; ++i) {
+ char c = s[i];
+
+ if(c < '0' || c > '9')
+ goto out;
+
+ status *= 10;
+ status += c - '0';
+ }
+ result = CURLE_OK;
+out:
+ *pstatus = result? -1 : status;
+ return result;
+}
+
+/* simple implementation of strndup(), which isn't portable */
+static char *my_strndup(const char *ptr, size_t len)
+{
+ char *copy = malloc(len + 1);
+ if(!copy)
+ return NULL;
+ memcpy(copy, ptr, len);
+ copy[len] = '\0';
+ return copy;
+}
+
+CURLcode Curl_http_req_make(struct httpreq **preq,
+ const char *method, size_t m_len,
+ const char *scheme, size_t s_len,
+ const char *authority, size_t a_len,
+ const char *path, size_t p_len)
+{
+ struct httpreq *req;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+
+ DEBUGASSERT(method);
+ if(m_len + 1 >= sizeof(req->method))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ req = calloc(1, sizeof(*req));
+ if(!req)
+ goto out;
+ memcpy(req->method, method, m_len);
+ if(scheme) {
+ req->scheme = my_strndup(scheme, s_len);
+ if(!req->scheme)
+ goto out;
+ }
+ if(authority) {
+ req->authority = my_strndup(authority, a_len);
+ if(!req->authority)
+ goto out;
+ }
+ if(path) {
+ req->path = my_strndup(path, p_len);
+ if(!req->path)
+ goto out;
+ }
+ Curl_dynhds_init(&req->headers, 0, DYN_HTTP_REQUEST);
+ Curl_dynhds_init(&req->trailers, 0, DYN_HTTP_REQUEST);
+ result = CURLE_OK;
+
+out:
+ if(result && req)
+ Curl_http_req_free(req);
+ *preq = result? NULL : req;
+ return result;
+}
+
+static CURLcode req_assign_url_authority(struct httpreq *req, CURLU *url)
+{
+ char *user, *pass, *host, *port;
+ struct dynbuf buf;
+ CURLUcode uc;
+ CURLcode result = CURLE_URL_MALFORMAT;
+
+ user = pass = host = port = NULL;
+ Curl_dyn_init(&buf, DYN_HTTP_REQUEST);
+
+ uc = curl_url_get(url, CURLUPART_HOST, &host, 0);
+ if(uc && uc != CURLUE_NO_HOST)
+ goto out;
+ if(!host) {
+ req->authority = NULL;
+ result = CURLE_OK;
+ goto out;
+ }
+
+ 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 = Curl_dyn_add(&buf, user);
+ if(result)
+ goto out;
+ if(pass) {
+ result = Curl_dyn_addf(&buf, ":%s", pass);
+ if(result)
+ goto out;
+ }
+ result = Curl_dyn_add(&buf, "@");
+ if(result)
+ goto out;
+ }
+ result = Curl_dyn_add(&buf, host);
+ if(result)
+ goto out;
+ if(port) {
+ result = Curl_dyn_addf(&buf, ":%s", port);
+ if(result)
+ goto out;
+ }
+ req->authority = strdup(Curl_dyn_ptr(&buf));
+ if(!req->authority)
+ goto out;
+ result = CURLE_OK;
+
+out:
+ free(user);
+ free(pass);
+ free(host);
+ free(port);
+ Curl_dyn_free(&buf);
+ return result;
+}
+
+static CURLcode req_assign_url_path(struct httpreq *req, CURLU *url)
+{
+ char *path, *query;
+ struct dynbuf buf;
+ CURLUcode uc;
+ CURLcode result = CURLE_URL_MALFORMAT;
+
+ path = query = NULL;
+ Curl_dyn_init(&buf, DYN_HTTP_REQUEST);
+
+ uc = curl_url_get(url, CURLUPART_PATH, &path, CURLU_PATH_AS_IS);
+ 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) {
+ req->path = path;
+ path = NULL;
+ }
+ else {
+ if(path) {
+ result = Curl_dyn_add(&buf, path);
+ if(result)
+ goto out;
+ }
+ if(query) {
+ result = Curl_dyn_addf(&buf, "?%s", query);
+ if(result)
+ goto out;
+ }
+ req->path = strdup(Curl_dyn_ptr(&buf));
+ if(!req->path)
+ goto out;
+ }
+ result = CURLE_OK;
+
+out:
+ free(path);
+ free(query);
+ Curl_dyn_free(&buf);
+ return result;
+}
+
+CURLcode Curl_http_req_make2(struct httpreq **preq,
+ const char *method, size_t m_len,
+ CURLU *url, const char *scheme_default)
+{
+ struct httpreq *req;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+ CURLUcode uc;
+
+ DEBUGASSERT(method);
+ if(m_len + 1 >= sizeof(req->method))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ req = calloc(1, sizeof(*req));
+ if(!req)
+ goto out;
+ memcpy(req->method, method, m_len);
+
+ uc = curl_url_get(url, CURLUPART_SCHEME, &req->scheme, 0);
+ if(uc && uc != CURLUE_NO_SCHEME)
+ goto out;
+ if(!req->scheme && scheme_default) {
+ req->scheme = strdup(scheme_default);
+ if(!req->scheme)
+ goto out;
+ }
+
+ result = req_assign_url_authority(req, url);
+ if(result)
+ goto out;
+ result = req_assign_url_path(req, url);
+ if(result)
+ goto out;
+
+ Curl_dynhds_init(&req->headers, 0, DYN_HTTP_REQUEST);
+ Curl_dynhds_init(&req->trailers, 0, DYN_HTTP_REQUEST);
+ result = CURLE_OK;
+
+out:
+ if(result && req)
+ Curl_http_req_free(req);
+ *preq = result? NULL : req;
+ return result;
+}
+
+void Curl_http_req_free(struct httpreq *req)
+{
+ if(req) {
+ free(req->scheme);
+ free(req->authority);
+ free(req->path);
+ Curl_dynhds_free(&req->headers);
+ Curl_dynhds_free(&req->trailers);
+ free(req);
+ }
+}
+
+struct name_const {
+ const char *name;
+ size_t namelen;
+};
+
+static struct name_const H2_NON_FIELD[] = {
+ { STRCONST("Host") },
+ { STRCONST("Upgrade") },
+ { STRCONST("Connection") },
+ { STRCONST("Keep-Alive") },
+ { STRCONST("Proxy-Connection") },
+ { STRCONST("Transfer-Encoding") },
+};
+
+static bool h2_non_field(const char *name, size_t namelen)
+{
+ size_t i;
+ for(i = 0; i < sizeof(H2_NON_FIELD)/sizeof(H2_NON_FIELD[0]); ++i) {
+ if(namelen < H2_NON_FIELD[i].namelen)
+ return FALSE;
+ if(namelen == H2_NON_FIELD[i].namelen &&
+ strcasecompare(H2_NON_FIELD[i].name, name))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
+ struct httpreq *req, struct Curl_easy *data)
+{
+ const char *scheme = NULL, *authority = NULL;
+ struct dynhds_entry *e;
+ size_t i;
+ CURLcode result;
+
+ DEBUGASSERT(req);
+ DEBUGASSERT(h2_headers);
+
+ if(req->scheme) {
+ scheme = req->scheme;
+ }
+ else if(strcmp("CONNECT", req->method)) {
+ scheme = Curl_checkheaders(data, STRCONST(HTTP_PSEUDO_SCHEME));
+ if(scheme) {
+ scheme += sizeof(HTTP_PSEUDO_SCHEME);
+ while(*scheme && ISBLANK(*scheme))
+ scheme++;
+ infof(data, "set pseudo header %s to %s", HTTP_PSEUDO_SCHEME, scheme);
+ }
+ else {
+ scheme = (data->conn && data->conn->handler->flags & PROTOPT_SSL)?
+ "https" : "http";
+ }
+ }
+
+ if(req->authority) {
+ authority = req->authority;
+ }
+ else {
+ e = Curl_dynhds_get(&req->headers, STRCONST("Host"));
+ if(e)
+ authority = e->value;
+ }
+
+ Curl_dynhds_reset(h2_headers);
+ Curl_dynhds_set_opts(h2_headers, DYNHDS_OPT_LOWERCASE);
+ result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_METHOD),
+ req->method, strlen(req->method));
+ if(!result && scheme) {
+ result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_SCHEME),
+ scheme, strlen(scheme));
+ }
+ if(!result && authority) {
+ result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_AUTHORITY),
+ authority, strlen(authority));
+ }
+ if(!result && req->path) {
+ result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_PATH),
+ req->path, strlen(req->path));
+ }
+ for(i = 0; !result && i < Curl_dynhds_count(&req->headers); ++i) {
+ e = Curl_dynhds_getn(&req->headers, i);
+ if(!h2_non_field(e->name, e->namelen)) {
+ result = Curl_dynhds_add(h2_headers, e->name, e->namelen,
+ e->value, e->valuelen);
+ }
+ }
+
+ return result;
+}
+
+CURLcode Curl_http_resp_make(struct http_resp **presp,
+ int status,
+ const char *description)
+{
+ struct http_resp *resp;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+
+ resp = calloc(1, sizeof(*resp));
+ if(!resp)
+ goto out;
+
+ resp->status = status;
+ if(description) {
+ resp->description = strdup(description);
+ if(!resp->description)
+ goto out;
+ }
+ Curl_dynhds_init(&resp->headers, 0, DYN_HTTP_REQUEST);
+ Curl_dynhds_init(&resp->trailers, 0, DYN_HTTP_REQUEST);
+ result = CURLE_OK;
+
+out:
+ if(result && resp)
+ Curl_http_resp_free(resp);
+ *presp = result? NULL : resp;
+ return result;
+}
+
+void Curl_http_resp_free(struct http_resp *resp)
+{
+ if(resp) {
+ free(resp->description);
+ Curl_dynhds_free(&resp->headers);
+ Curl_dynhds_free(&resp->trailers);
+ if(resp->prev)
+ Curl_http_resp_free(resp->prev);
+ free(resp);
+ }
+}
+
#endif /* CURL_DISABLE_HTTP */
diff --git a/lib/http.h b/lib/http.h
index 9eff6b1..df3b4e3 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,6 +25,14 @@
***************************************************************************/
#include "curl_setup.h"
+#if defined(USE_MSH3) && !defined(_WIN32)
+#include <pthread.h>
+#endif
+
+#include "bufq.h"
+#include "dynhds.h"
+#include "ws.h"
+
typedef enum {
HTTPREQ_GET,
HTTPREQ_POST,
@@ -36,11 +44,7 @@
#ifndef CURL_DISABLE_HTTP
-#ifdef USE_NGHTTP2
-#include <nghttp2/nghttp2.h>
-#endif
-
-#if defined(_WIN32) && defined(ENABLE_QUIC)
+#if defined(ENABLE_QUIC)
#include <stdint.h>
#endif
@@ -50,6 +54,16 @@
extern const struct Curl_handler Curl_handler_https;
#endif
+#ifdef USE_WEBSOCKETS
+extern const struct Curl_handler Curl_handler_ws;
+
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_wss;
+#endif
+#endif /* websockets */
+
+struct dynhds;
+
/* Header specific functions */
bool Curl_compareheader(const char *headerline, /* line to check */
const char *header, /* header keyword _with_ colon */
@@ -63,8 +77,10 @@
const struct connectdata *conn,
const char *thisheader,
const size_t thislen);
+struct HTTP; /* see below */
CURLcode Curl_buffer_send(struct dynbuf *in,
struct Curl_easy *data,
+ struct HTTP *http,
curl_off_t *bytes_written,
curl_off_t included_body_bytes,
int socketindex);
@@ -84,6 +100,10 @@
void *headers
#endif
);
+CURLcode Curl_dynhds_add_custom(struct Curl_easy *data,
+ bool is_connect,
+ struct dynhds *hds);
+
CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
struct dynbuf *buf,
struct Curl_easy *handle);
@@ -165,33 +185,6 @@
#endif /* CURL_DISABLE_HTTP */
-#ifdef USE_NGHTTP3
-struct h3out; /* see ngtcp2 */
-#endif
-
-#ifdef USE_MSH3
-#ifdef _WIN32
-#define msh3_lock CRITICAL_SECTION
-#define msh3_lock_initialize(lock) InitializeCriticalSection(lock)
-#define msh3_lock_uninitialize(lock) DeleteCriticalSection(lock)
-#define msh3_lock_acquire(lock) EnterCriticalSection(lock)
-#define msh3_lock_release(lock) LeaveCriticalSection(lock)
-#else /* !_WIN32 */
-#include <pthread.h>
-#define msh3_lock pthread_mutex_t
-#define msh3_lock_initialize(lock) { \
- pthread_mutexattr_t attr; \
- pthread_mutexattr_init(&attr); \
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \
- pthread_mutex_init(lock, &attr); \
- pthread_mutexattr_destroy(&attr); \
-}
-#define msh3_lock_uninitialize(lock) pthread_mutex_destroy(lock)
-#define msh3_lock_acquire(lock) pthread_mutex_lock(lock)
-#define msh3_lock_release(lock) pthread_mutex_unlock(lock)
-#endif /* _WIN32 */
-#endif /* USE_MSH3 */
-
/****************************************************************************
* HTTP unique setup
***************************************************************************/
@@ -210,6 +203,7 @@
void *fread_in; /* backup storage for fread_in pointer */
const char *postdata;
curl_off_t postsize;
+ struct Curl_easy *data;
} backup;
enum {
@@ -219,119 +213,12 @@
} sending;
#ifndef CURL_DISABLE_HTTP
+ void *h2_ctx; /* HTTP/2 implementation context */
+ void *h3_ctx; /* HTTP/3 implementation context */
struct dynbuf send_buffer; /* used if the request couldn't be sent in one
chunk, points to an allocated send_buffer
struct */
#endif
-#ifdef USE_NGHTTP2
- /*********** for HTTP/2 we store stream-local data here *************/
- int32_t stream_id; /* stream we are interested in */
-
- bool bodystarted;
- /* We store non-final and final response headers here, per-stream */
- struct dynbuf header_recvbuf;
- size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into
- upper layer */
- struct dynbuf trailer_recvbuf;
- int status_code; /* HTTP status code */
- const uint8_t *pausedata; /* pointer to data received in on_data_chunk */
- size_t pauselen; /* the number of bytes left in data */
- bool close_handled; /* TRUE if stream closure is handled by libcurl */
-
- char **push_headers; /* allocated array */
- size_t push_headers_used; /* number of entries filled in */
- size_t push_headers_alloc; /* number of entries allocated */
- uint32_t error; /* HTTP/2 stream error code */
-#endif
-#if defined(USE_NGHTTP2) || defined(USE_NGHTTP3)
- bool closed; /* TRUE on HTTP2 stream close */
- char *mem; /* points to a buffer in memory to store received data */
- size_t len; /* size of the buffer 'mem' points to */
- size_t memlen; /* size of data copied to mem */
-#endif
-#if defined(USE_NGHTTP2) || defined(ENABLE_QUIC)
- /* fields used by both HTTP/2 and HTTP/3 */
- const uint8_t *upload_mem; /* points to a buffer to read from */
- size_t upload_len; /* size of the buffer 'upload_mem' points to */
- curl_off_t upload_left; /* number of bytes left to upload */
-#endif
-
-#ifdef ENABLE_QUIC
-#ifndef USE_MSH3
- /*********** for HTTP/3 we store stream-local data here *************/
- int64_t stream3_id; /* stream we are interested in */
- bool firstheader; /* FALSE until headers arrive */
- bool firstbody; /* FALSE until body arrives */
- bool h3req; /* FALSE until request is issued */
-#endif
- bool upload_done;
-#endif
-#ifdef USE_NGHTTP3
- size_t unacked_window;
- struct h3out *h3out; /* per-stream buffers for upload */
- struct dynbuf overflow; /* excess data received during a single Curl_read */
-#endif
-#ifdef USE_MSH3
- struct MSH3_REQUEST *req;
- msh3_lock recv_lock;
- /* Receive Buffer (Headers and Data) */
- uint8_t* recv_buf;
- size_t recv_buf_alloc;
- /* Receive Headers */
- size_t recv_header_len;
- bool recv_header_complete;
- /* Receive Data */
- size_t recv_data_len;
- bool recv_data_complete;
- /* General Receive Error */
- CURLcode recv_error;
-#endif
-};
-
-#ifdef USE_NGHTTP2
-/* h2 settings for this connection */
-struct h2settings {
- uint32_t max_concurrent_streams;
- bool enable_push;
-};
-#endif
-
-struct http_conn {
-#ifdef USE_NGHTTP2
-#define H2_BINSETTINGS_LEN 80
- uint8_t binsettings[H2_BINSETTINGS_LEN];
- size_t binlen; /* length of the binsettings data */
-
- /* We associate the connnectdata struct with the connection, but we need to
- make sure we can identify the current "driving" transfer. This is a
- work-around for the lack of nghttp2_session_set_user_data() in older
- nghttp2 versions that we want to support. (Added in 1.31.0) */
- struct Curl_easy *trnsfr;
-
- nghttp2_session *h2;
- Curl_send *send_underlying; /* underlying send Curl_send callback */
- Curl_recv *recv_underlying; /* underlying recv Curl_recv callback */
- char *inbuf; /* buffer to receive data from underlying socket */
- size_t inbuflen; /* number of bytes filled in inbuf */
- size_t nread_inbuf; /* number of bytes read from in inbuf */
- /* We need separate buffer for transmission and reception because we
- may call nghttp2_session_send() after the
- nghttp2_session_mem_recv() but mem buffer is still not full. In
- this case, we wrongly sends the content of mem buffer if we share
- them for both cases. */
- int32_t pause_stream_id; /* stream ID which paused
- nghttp2_session_mem_recv */
- size_t drain_total; /* sum of all stream's UrlState.drain */
-
- /* this is a hash of all individual streams (Curl_easy structs) */
- struct h2settings settings;
-
- /* list of settings that will be sent */
- nghttp2_settings_entry local_settings[3];
- size_t local_settings_num;
-#else
- int unused; /* prevent a compiler warning */
-#endif
};
CURLcode Curl_http_size(struct Curl_easy *data);
@@ -366,10 +253,79 @@
bool proxytunnel); /* TRUE if this is the request setting
up the proxy tunnel */
-/*
- * Curl_allow_auth_to_host() tells if authentication, cookies or other
- * "sensitive data" can (still) be sent to this host.
+/* 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
*/
-bool Curl_allow_auth_to_host(struct Curl_easy *data);
+struct httpreq {
+ char method[12];
+ char *scheme;
+ char *authority;
+ char *path;
+ struct dynhds headers;
+ struct dynhds trailers;
+};
+
+/**
+ * Create a HTTP request struct.
+ */
+CURLcode Curl_http_req_make(struct httpreq **preq,
+ const char *method, size_t m_len,
+ const char *scheme, size_t s_len,
+ const char *authority, size_t a_len,
+ const char *path, size_t p_len);
+
+CURLcode Curl_http_req_make2(struct httpreq **preq,
+ const char *method, size_t m_len,
+ CURLU *url, const char *scheme_default);
+
+void Curl_http_req_free(struct httpreq *req);
+
+#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"
+
+/**
+ * Create the list of HTTP/2 headers which represent the request,
+ * using HTTP/2 pseudo headers preceeding the `req->headers`.
+ *
+ * Applies the following transformations:
+ * - if `authority` is set, any "Host" header is removed.
+ * - if `authority` is unset and a "Host" header is present, use
+ * that as `authority` and remove "Host"
+ * - removes and Connection header fields as defined in rfc9113 ch. 8.2.2
+ * - lower-cases the header field names
+ *
+ * @param h2_headers will contain the HTTP/2 headers on success
+ * @param req the request to transform
+ * @param data the handle to lookup defaults like ' :scheme' from
+ */
+CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
+ struct httpreq *req, struct Curl_easy *data);
+
+/**
+ * All about a core HTTP response, excluding body and trailers
+ */
+struct http_resp {
+ int status;
+ char *description;
+ struct dynhds headers;
+ struct dynhds trailers;
+ struct http_resp *prev;
+};
+
+/**
+ * Create a HTTP response struct.
+ */
+CURLcode Curl_http_resp_make(struct http_resp **presp,
+ int status,
+ const char *description);
+
+void Curl_http_resp_free(struct http_resp *resp);
#endif /* HEADER_CURL_HTTP_H */
diff --git a/lib/http1.c b/lib/http1.c
new file mode 100644
index 0000000..a442d3e
--- /dev/null
+++ b/lib/http1.c
@@ -0,0 +1,322 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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"
+
+#ifndef CURL_DISABLE_HTTP
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "http.h"
+#include "http1.h"
+#include "urlapi-int.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+
+#define H1_MAX_URL_LEN (8*1024)
+
+void Curl_h1_req_parse_init(struct h1_req_parser *parser, size_t max_line_len)
+{
+ memset(parser, 0, sizeof(*parser));
+ parser->max_line_len = max_line_len;
+ Curl_dyn_init(&parser->scratch, max_line_len);
+}
+
+void Curl_h1_req_parse_free(struct h1_req_parser *parser)
+{
+ if(parser) {
+ Curl_http_req_free(parser->req);
+ Curl_dyn_free(&parser->scratch);
+ parser->req = NULL;
+ parser->done = FALSE;
+ }
+}
+
+static CURLcode trim_line(struct h1_req_parser *parser, int options)
+{
+ DEBUGASSERT(parser->line);
+ if(parser->line_len) {
+ if(parser->line[parser->line_len - 1] == '\n')
+ --parser->line_len;
+ if(parser->line_len) {
+ if(parser->line[parser->line_len - 1] == '\r')
+ --parser->line_len;
+ else if(options & H1_PARSE_OPT_STRICT)
+ return CURLE_URL_MALFORMAT;
+ }
+ else if(options & H1_PARSE_OPT_STRICT)
+ return CURLE_URL_MALFORMAT;
+ }
+ else if(options & H1_PARSE_OPT_STRICT)
+ return CURLE_URL_MALFORMAT;
+
+ if(parser->line_len > parser->max_line_len) {
+ return CURLE_URL_MALFORMAT;
+ }
+ return CURLE_OK;
+}
+
+static ssize_t detect_line(struct h1_req_parser *parser,
+ const char *buf, const size_t buflen,
+ CURLcode *err)
+{
+ const char *line_end;
+
+ DEBUGASSERT(!parser->line);
+ 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;
+}
+
+static ssize_t next_line(struct h1_req_parser *parser,
+ const char *buf, const size_t buflen, int options,
+ CURLcode *err)
+{
+ ssize_t nread = 0;
+
+ if(parser->line) {
+ parser->line = NULL;
+ parser->line_len = 0;
+ Curl_dyn_reset(&parser->scratch);
+ }
+
+ nread = detect_line(parser, buf, buflen, err);
+ if(nread >= 0) {
+ if(Curl_dyn_len(&parser->scratch)) {
+ /* append detected line to scratch to have the complete line */
+ *err = Curl_dyn_addn(&parser->scratch, parser->line, parser->line_len);
+ if(*err)
+ return -1;
+ parser->line = Curl_dyn_ptr(&parser->scratch);
+ parser->line_len = Curl_dyn_len(&parser->scratch);
+ }
+ *err = trim_line(parser, options);
+ if(*err)
+ return -1;
+ }
+ else if(*err == CURLE_AGAIN) {
+ /* no line end in `buf`, add it to our scratch */
+ *err = Curl_dyn_addn(&parser->scratch, (const unsigned char *)buf, buflen);
+ nread = (*err)? -1 : (ssize_t)buflen;
+ }
+ return nread;
+}
+
+static CURLcode start_req(struct h1_req_parser *parser,
+ const char *scheme_default, int options)
+{
+ 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;
+ CURLcode result = CURLE_URL_MALFORMAT; /* Use this as default fail */
+
+ DEBUGASSERT(!parser->req);
+ /* line must match: "METHOD TARGET HTTP_VERSION" */
+ p = memchr(parser->line, ' ', parser->line_len);
+ if(!p || p == parser->line)
+ goto out;
+
+ m = parser->line;
+ m_len = p - parser->line;
+ target = p + 1;
+ target_len = hv_len = 0;
+ hv = NULL;
+
+ /* URL may contain spaces so scan backwards */
+ for(i = parser->line_len; i > m_len; --i) {
+ if(parser->line[i] == ' ') {
+ hv = &parser->line[i + 1];
+ hv_len = parser->line_len - i;
+ target_len = (hv - target) - 1;
+ break;
+ }
+ }
+ /* no SPACE found or empty TARGET or empy HTTP_VERSION */
+ if(!target_len || !hv_len)
+ goto out;
+
+ /* TODO: we do not check HTTP_VERSION for conformity, should
+ + do that when STRICT option is supplied. */
+ (void)hv;
+
+ /* The TARGET can be (rfc 9112, ch. 3.2):
+ * origin-form: path + optional query
+ * absolute-form: absolute URI
+ * authority-form: host+port for CONNECT
+ * asterisk-form: '*' for OPTIONS
+ *
+ * from TARGET, we derive `scheme` `authority` `path`
+ * origin-form -- -- TARGET
+ * absolute-form URL* URL* URL*
+ * authority-form -- TARGET --
+ * asterisk-form -- -- TARGET
+ */
+ scheme = authority = path = NULL;
+ scheme_len = authority_len = path_len = 0;
+
+ if(target_len == 1 && target[0] == '*') {
+ /* asterisk-form */
+ path = target;
+ path_len = target_len;
+ }
+ else if(!strncmp("CONNECT", m, m_len)) {
+ /* authority-form */
+ authority = target;
+ authority_len = target_len;
+ }
+ else if(target[0] == '/') {
+ /* origin-form */
+ path = target;
+ path_len = target_len;
+ }
+ else {
+ /* origin-form OR absolute-form */
+ CURLUcode uc;
+ char tmp[H1_MAX_URL_LEN];
+
+ /* default, unless we see an absolute URL */
+ path = target;
+ path_len = target_len;
+
+ /* URL parser wants 0-termination */
+ if(target_len >= sizeof(tmp))
+ goto out;
+ memcpy(tmp, target, target_len);
+ tmp[target_len] = '\0';
+ /* See if treating TARGET as an absolute URL makes sense */
+ if(Curl_is_absolute_url(tmp, NULL, 0, FALSE)) {
+ int url_options;
+
+ url = curl_url();
+ if(!url) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ 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;
+ uc = curl_url_set(url, CURLUPART_URL, tmp, url_options);
+ if(uc) {
+ goto out;
+ }
+ }
+
+ if(!url && (options & H1_PARSE_OPT_STRICT)) {
+ /* we should have an absolute URL or have seen `/` earlier */
+ goto out;
+ }
+ }
+
+ if(url) {
+ result = Curl_http_req_make2(&parser->req, m, m_len, url, scheme_default);
+ }
+ else {
+ if(!scheme && scheme_default) {
+ scheme = scheme_default;
+ scheme_len = strlen(scheme_default);
+ }
+ result = Curl_http_req_make(&parser->req, m, m_len, scheme, scheme_len,
+ authority, authority_len, path, path_len);
+ }
+
+out:
+ curl_url_cleanup(url);
+ 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)
+{
+ ssize_t nread = 0, n;
+
+ *err = CURLE_OK;
+ while(!parser->done) {
+ n = next_line(parser, buf, buflen, options, err);
+ if(n < 0) {
+ if(*err != CURLE_AGAIN) {
+ nread = -1;
+ }
+ *err = CURLE_OK;
+ goto out;
+ }
+
+ /* Consume this line */
+ nread += (size_t)n;
+ buf += (size_t)n;
+ buflen -= (size_t)n;
+
+ if(!parser->line) {
+ /* consumed bytes, but line not complete */
+ if(!buflen)
+ goto out;
+ }
+ else if(!parser->req) {
+ *err = start_req(parser, scheme_default, options);
+ if(*err) {
+ nread = -1;
+ goto out;
+ }
+ }
+ else if(parser->line_len == 0) {
+ /* last, empty line, we are finished */
+ if(!parser->req) {
+ *err = CURLE_URL_MALFORMAT;
+ nread = -1;
+ goto out;
+ }
+ parser->done = TRUE;
+ Curl_dyn_reset(&parser->scratch);
+ /* last chance adjustments */
+ }
+ else {
+ *err = Curl_dynhds_h1_add_line(&parser->req->headers,
+ parser->line, parser->line_len);
+ if(*err) {
+ nread = -1;
+ goto out;
+ }
+ }
+ }
+
+out:
+ return nread;
+}
+
+
+#endif /* !CURL_DISABLE_HTTP */
diff --git a/lib/http1.h b/lib/http1.h
new file mode 100644
index 0000000..b1eaa969
--- /dev/null
+++ b/lib/http1.h
@@ -0,0 +1,61 @@
+#ifndef HEADER_CURL_HTTP1_H
+#define HEADER_CURL_HTTP1_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_HTTP
+#include "bufq.h"
+#include "http.h"
+
+#define H1_PARSE_OPT_NONE (0)
+#define H1_PARSE_OPT_STRICT (1 << 0)
+
+#define H1_PARSE_DEFAULT_MAX_LINE_LEN DYN_HTTP_REQUEST
+
+struct h1_req_parser {
+ struct httpreq *req;
+ struct dynbuf scratch;
+ size_t scratch_skip;
+ const char *line;
+ size_t max_line_len;
+ size_t line_len;
+ bool done;
+};
+
+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_dprint(const struct httpreq *req,
+ struct dynbuf *dbuf);
+
+
+#endif /* !CURL_DISABLE_HTTP */
+#endif /* HEADER_CURL_HTTP1_H */
diff --git a/lib/http2.c b/lib/http2.c
index f6364d0..6c09ec1 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,8 +25,11 @@
#include "curl_setup.h"
#ifdef USE_NGHTTP2
+#include <stdint.h>
#include <nghttp2/nghttp2.h>
#include "urldata.h"
+#include "bufq.h"
+#include "http1.h"
#include "http2.h"
#include "http.h"
#include "sendf.h"
@@ -35,20 +38,19 @@
#include "strcase.h"
#include "multiif.h"
#include "url.h"
+#include "urlapi-int.h"
+#include "cfilters.h"
#include "connect.h"
#include "strtoofft.h"
#include "strdup.h"
#include "transfer.h"
#include "dynbuf.h"
-#include "h2h3.h"
#include "headers.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-#define H2_BUFSIZE 32768
-
#if (NGHTTP2_VERSION_NUM < 0x010c00)
#error too old nghttp2 version, upgrade!
#endif
@@ -61,305 +63,573 @@
#define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1
#endif
-#define HTTP2_HUGE_WINDOW_SIZE (32 * 1024 * 1024) /* 32 MB */
-#ifdef DEBUG_HTTP2
-#define H2BUGF(x) x
-#else
-#define H2BUGF(x) do { } while(0)
-#endif
+/* buffer dimensioning:
+ * use 16K as chunk size, as that fits H2 DATA frames well */
+#define H2_CHUNK_SIZE (16 * 1024)
+/* this is how much we want "in flight" for a stream */
+#define H2_STREAM_WINDOW_SIZE (10 * 1024 * 1024)
+/* on receving from TLS, we prep for holding a full stream window */
+#define H2_NW_RECV_CHUNKS (H2_STREAM_WINDOW_SIZE / H2_CHUNK_SIZE)
+/* on send into TLS, we just want to accumulate small frames */
+#define H2_NW_SEND_CHUNKS 1
+/* stream recv/send chunks are a result of window / chunk sizes */
+#define H2_STREAM_RECV_CHUNKS (H2_STREAM_WINDOW_SIZE / H2_CHUNK_SIZE)
+/* keep smaller stream upload buffer (default h2 window size) to have
+ * our progress bars and "upload done" reporting closer to reality */
+#define H2_STREAM_SEND_CHUNKS ((64 * 1024) / H2_CHUNK_SIZE)
+/* spare chunks we keep for a full window */
+#define H2_STREAM_POOL_SPARES (H2_STREAM_WINDOW_SIZE / H2_CHUNK_SIZE)
-static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
- char *mem, size_t len, CURLcode *err);
-static bool http2_connisdead(struct Curl_easy *data,
- struct connectdata *conn);
-static int h2_session_send(struct Curl_easy *data,
- nghttp2_session *h2);
-static int h2_process_pending_input(struct Curl_easy *data,
- struct http_conn *httpc,
- CURLcode *err);
+/* We need to accommodate the max number of streams with their window
+ * sizes on the overall connection. Streams might become PAUSED which
+ * will block their received QUOTA in the connection window. And if we
+ * run out of space, the server is blocked from sending us any data.
+ * See #10988 for an issue with this. */
+#define HTTP2_HUGE_WINDOW_SIZE (100 * H2_STREAM_WINDOW_SIZE)
-/*
- * Curl_http2_init_state() is called when the easy handle is created and
- * allows for HTTP/2 specific init of state.
- */
-void Curl_http2_init_state(struct UrlState *state)
+#define H2_SETTINGS_IV_LEN 3
+#define H2_BINSETTINGS_LEN 80
+
+static int populate_settings(nghttp2_settings_entry *iv,
+ struct Curl_easy *data)
{
- state->stream_weight = NGHTTP2_DEFAULT_WEIGHT;
+ 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;
+
+ iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
+ iv[2].value = data->multi->push_cb != NULL;
+
+ return 3;
}
-/*
- * Curl_http2_init_userset() is called when the easy handle is created and
- * allows for HTTP/2 specific user-set fields.
- */
-void Curl_http2_init_userset(struct UserDefined *set)
+static size_t populate_binsettings(uint8_t *binsettings,
+ struct Curl_easy *data)
{
- set->stream_weight = NGHTTP2_DEFAULT_WEIGHT;
+ nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN];
+ int ivlen;
+
+ ivlen = populate_settings(iv, data);
+ /* this returns number of bytes it wrote */
+ return nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
+ iv, ivlen);
}
-static int http2_getsock(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *sock)
+struct cf_h2_ctx {
+ nghttp2_session *h2;
+ uint32_t max_concurrent_streams;
+ /* The easy handle used in the current filter call, cleared at return */
+ struct cf_call_data call_data;
+
+ struct bufq inbufq; /* network input */
+ struct bufq outbufq; /* network output */
+ struct bufc_pool stream_bufcp; /* spares for stream buffers */
+
+ size_t drain_total; /* sum of all stream's UrlState drain */
+ int32_t goaway_error;
+ int32_t last_stream_id;
+ BIT(conn_closed);
+ BIT(goaway);
+ BIT(enable_push);
+ BIT(nw_out_blocked);
+};
+
+/* 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
+
+static void cf_h2_ctx_clear(struct cf_h2_ctx *ctx)
{
- const struct http_conn *c = &conn->proto.httpc;
- struct SingleRequest *k = &data->req;
- int bitmap = GETSOCK_BLANK;
- struct HTTP *stream = data->req.p.http;
+ struct cf_call_data save = ctx->call_data;
- sock[0] = conn->sock[FIRSTSOCKET];
-
- if(!(k->keepon & KEEP_RECV_PAUSE))
- /* Unless paused - in a HTTP/2 connection we can basically always get a
- frame so we should always be ready for one */
- bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
-
- /* we're (still uploading OR the HTTP/2 layer wants to send data) AND
- there's a window to send data in */
- if((((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) ||
- nghttp2_session_want_write(c->h2)) &&
- (nghttp2_session_get_remote_window_size(c->h2) &&
- nghttp2_session_get_stream_remote_window_size(c->h2,
- stream->stream_id)))
- bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
-
- return bitmap;
+ if(ctx->h2) {
+ nghttp2_session_del(ctx->h2);
+ }
+ Curl_bufq_free(&ctx->inbufq);
+ Curl_bufq_free(&ctx->outbufq);
+ Curl_bufcp_free(&ctx->stream_bufcp);
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->call_data = save;
}
-/*
- * http2_stream_free() free HTTP2 stream related data
- */
-static void http2_stream_free(struct HTTP *http)
+static void cf_h2_ctx_free(struct cf_h2_ctx *ctx)
{
- if(http) {
- Curl_dyn_free(&http->header_recvbuf);
- for(; http->push_headers_used > 0; --http->push_headers_used) {
- free(http->push_headers[http->push_headers_used - 1]);
- }
- free(http->push_headers);
- http->push_headers = NULL;
+ if(ctx) {
+ cf_h2_ctx_clear(ctx);
+ free(ctx);
}
}
-/*
- * Disconnects *a* connection used for HTTP/2. It might be an old one from the
- * connection cache and not the "main" one. Don't touch the easy handle!
+static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+/**
+ * All about the H3 internals of a stream
*/
+struct stream_ctx {
+ /*********** for HTTP/2 we store stream-local data here *************/
+ int32_t id; /* HTTP/2 protocol identifier for stream */
+ struct bufq recvbuf; /* response buffer */
+ struct bufq sendbuf; /* request buffer */
+ struct dynhds resp_trailers; /* response trailer fields */
+ size_t resp_hds_len; /* amount of response header bytes in recvbuf */
+ size_t upload_blocked_len;
+ curl_off_t upload_left; /* number of request bytes left to upload */
-static CURLcode http2_disconnect(struct Curl_easy *data,
- struct connectdata *conn,
- bool dead_connection)
+ char **push_headers; /* allocated array */
+ size_t push_headers_used; /* number of entries filled in */
+ size_t push_headers_alloc; /* number of entries allocated */
+
+ int status_code; /* HTTP response status code */
+ uint32_t error; /* stream error code */
+ uint32_t local_window_size; /* the local recv window size */
+ bool closed; /* TRUE on stream close */
+ bool reset; /* TRUE on stream reset */
+ bool close_handled; /* TRUE if stream closure is handled by libcurl */
+ bool bodystarted;
+ bool send_closed; /* transfer is done sending, we might have still
+ buffered data in stream->sendbuf to upload. */
+};
+
+#define H2_STREAM_CTX(d) ((struct stream_ctx *)(((d) && (d)->req.p.http)? \
+ ((struct HTTP *)(d)->req.p.http)->h2_ctx \
+ : NULL))
+#define H2_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h2_ctx
+#define H2_STREAM_ID(d) (H2_STREAM_CTX(d)? \
+ H2_STREAM_CTX(d)->id : -2)
+
+/*
+ * Mark this transfer to get "drained".
+ */
+static void drain_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct stream_ctx *stream)
{
- struct http_conn *c = &conn->proto.httpc;
- (void)dead_connection;
-#ifndef DEBUG_HTTP2
- (void)data;
-#endif
+ unsigned char bits;
- H2BUGF(infof(data, "HTTP/2 DISCONNECT starts now"));
+ (void)cf;
+ bits = CURL_CSELECT_IN;
+ if(!stream->send_closed &&
+ (stream->upload_left || stream->upload_blocked_len))
+ bits |= CURL_CSELECT_OUT;
+ if(data->state.dselect_bits != bits) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] DRAIN dselect_bits=%x",
+ stream->id, bits));
+ data->state.dselect_bits = bits;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+}
- nghttp2_session_del(c->h2);
- Curl_safefree(c->inbuf);
+static CURLcode http2_data_setup(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct stream_ctx **pstream)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream;
- H2BUGF(infof(data, "HTTP/2 DISCONNECT done"));
+ (void)cf;
+ DEBUGASSERT(data);
+ if(!data->req.p.http) {
+ failf(data, "initialization failure, transfer not http initialized");
+ return CURLE_FAILED_INIT;
+ }
+ stream = H2_STREAM_CTX(data);
+ if(stream) {
+ *pstream = stream;
+ return CURLE_OK;
+ }
+ stream = calloc(1, sizeof(*stream));
+ if(!stream)
+ return CURLE_OUT_OF_MEMORY;
+
+ stream->id = -1;
+ Curl_bufq_initp(&stream->sendbuf, &ctx->stream_bufcp,
+ H2_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE);
+ Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
+ H2_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
+ Curl_dynhds_init(&stream->resp_trailers, 0, DYN_HTTP_REQUEST);
+ stream->resp_hds_len = 0;
+ stream->bodystarted = FALSE;
+ stream->status_code = -1;
+ stream->closed = FALSE;
+ stream->close_handled = FALSE;
+ stream->error = NGHTTP2_NO_ERROR;
+ stream->local_window_size = H2_STREAM_WINDOW_SIZE;
+ stream->upload_left = 0;
+
+ H2_STREAM_LCTX(data) = stream;
+ *pstream = stream;
return CURLE_OK;
}
+static void http2_data_done(struct Curl_cfilter *cf,
+ struct Curl_easy *data, bool premature)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+
+ DEBUGASSERT(ctx);
+ (void)premature;
+ if(!stream)
+ return;
+
+ if(ctx->h2) {
+ if(!stream->closed && stream->id > 0) {
+ /* RST_STREAM */
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] premature DATA_DONE, RST stream",
+ stream->id));
+ if(!nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
+ stream->id, NGHTTP2_STREAM_CLOSED))
+ (void)nghttp2_session_send(ctx->h2);
+ }
+ if(!Curl_bufq_is_empty(&stream->recvbuf)) {
+ /* Anything in the recvbuf is still being counted
+ * in stream and connection window flow control. Need
+ * to free that space or the connection window might get
+ * exhausted eventually. */
+ nghttp2_session_consume(ctx->h2, stream->id,
+ Curl_bufq_len(&stream->recvbuf));
+ /* give WINDOW_UPATE a chance to be sent, but ignore any error */
+ (void)h2_progress_egress(cf, data);
+ }
+
+ /* -1 means unassigned and 0 means cleared */
+ if(nghttp2_session_get_stream_user_data(ctx->h2, stream->id)) {
+ int rv = nghttp2_session_set_stream_user_data(ctx->h2,
+ stream->id, 0);
+ if(rv) {
+ infof(data, "http/2: failed to clear user_data for stream %u",
+ stream->id);
+ DEBUGASSERT(0);
+ }
+ }
+ }
+
+ Curl_bufq_free(&stream->sendbuf);
+ Curl_bufq_free(&stream->recvbuf);
+ Curl_dynhds_free(&stream->resp_trailers);
+ if(stream->push_headers) {
+ /* if they weren't used and then freed before */
+ for(; stream->push_headers_used > 0; --stream->push_headers_used) {
+ free(stream->push_headers[stream->push_headers_used - 1]);
+ }
+ free(stream->push_headers);
+ stream->push_headers = NULL;
+ }
+
+ free(stream);
+ H2_STREAM_LCTX(data) = NULL;
+}
+
+static int h2_client_new(struct Curl_cfilter *cf,
+ nghttp2_session_callbacks *cbs)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ nghttp2_option *o;
+
+ int rc = nghttp2_option_new(&o);
+ if(rc)
+ return rc;
+ /* We handle window updates ourself to enforce buffer limits */
+ nghttp2_option_set_no_auto_window_update(o, 1);
+#if NGHTTP2_VERSION_NUM >= 0x013200
+ /* with 1.50.0 */
+ /* turn off RFC 9113 leading and trailing white spaces validation against
+ HTTP field value. */
+ nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(o, 1);
+#endif
+ rc = nghttp2_session_client_new2(&ctx->h2, cbs, cf, o);
+ nghttp2_option_del(o);
+ return rc;
+}
+
+static ssize_t nw_in_reader(void *reader_ctx,
+ unsigned char *buf, size_t buflen,
+ CURLcode *err)
+{
+ struct Curl_cfilter *cf = reader_ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+
+ return Curl_conn_cf_recv(cf->next, data, (char *)buf, buflen, err);
+}
+
+static ssize_t nw_out_writer(void *writer_ctx,
+ const unsigned char *buf, size_t buflen,
+ CURLcode *err)
+{
+ struct Curl_cfilter *cf = writer_ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+
+ return Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err);
+}
+
+static ssize_t send_callback(nghttp2_session *h2,
+ const uint8_t *mem, size_t length, int flags,
+ void *userp);
+static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
+ void *userp);
+static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const uint8_t *mem, size_t len, void *userp);
+static int on_stream_close(nghttp2_session *session, int32_t stream_id,
+ uint32_t error_code, void *userp);
+static int on_begin_headers(nghttp2_session *session,
+ const nghttp2_frame *frame, void *userp);
+static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
+ const uint8_t *name, size_t namelen,
+ const uint8_t *value, size_t valuelen,
+ uint8_t flags,
+ void *userp);
+static int error_callback(nghttp2_session *session, const char *msg,
+ size_t len, void *userp);
+
+/*
+ * multi_connchanged() is called to tell that there is a connection in
+ * this multi handle that has changed state (multiplexing become possible, the
+ * number of allowed streams changed or similar), and a subsequent use of this
+ * multi handle should move CONNECT_PEND handles back to CONNECT to have them
+ * retry.
+ */
+static void multi_connchanged(struct Curl_multi *multi)
+{
+ multi->recheckstate = TRUE;
+}
+
+/*
+ * Initialize the cfilter context
+ */
+static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool via_h1_upgrade)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+ int rc;
+ nghttp2_session_callbacks *cbs = NULL;
+
+ DEBUGASSERT(!ctx->h2);
+ Curl_bufcp_init(&ctx->stream_bufcp, H2_CHUNK_SIZE, H2_STREAM_POOL_SPARES);
+ 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);
+ ctx->last_stream_id = 2147483647;
+
+ rc = nghttp2_session_callbacks_new(&cbs);
+ if(rc) {
+ failf(data, "Couldn't initialize nghttp2 callbacks");
+ goto out;
+ }
+
+ nghttp2_session_callbacks_set_send_callback(cbs, send_callback);
+ nghttp2_session_callbacks_set_on_frame_recv_callback(cbs, on_frame_recv);
+ nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
+ cbs, on_data_chunk_recv);
+ nghttp2_session_callbacks_set_on_stream_close_callback(cbs, on_stream_close);
+ nghttp2_session_callbacks_set_on_begin_headers_callback(
+ cbs, on_begin_headers);
+ nghttp2_session_callbacks_set_on_header_callback(cbs, on_header);
+ nghttp2_session_callbacks_set_error_callback(cbs, error_callback);
+
+ /* The nghttp2 session is not yet setup, do it */
+ rc = h2_client_new(cf, cbs);
+ if(rc) {
+ failf(data, "Couldn't initialize nghttp2");
+ goto out;
+ }
+ ctx->max_concurrent_streams = DEFAULT_MAX_CONCURRENT_STREAMS;
+
+ if(via_h1_upgrade) {
+ /* HTTP/1.1 Upgrade issued. H2 Settings have already been submitted
+ * in the H1 request and we upgrade from there. This stream
+ * is opened implicitly as #1. */
+ uint8_t binsettings[H2_BINSETTINGS_LEN];
+ size_t binlen; /* length of the binsettings data */
+
+ binlen = populate_binsettings(binsettings, data);
+
+ result = http2_data_setup(cf, data, &stream);
+ if(result)
+ goto out;
+ DEBUGASSERT(stream);
+ stream->id = 1;
+ /* queue SETTINGS frame (again) */
+ rc = nghttp2_session_upgrade2(ctx->h2, binsettings, binlen,
+ data->state.httpreq == HTTPREQ_HEAD,
+ NULL);
+ if(rc) {
+ failf(data, "nghttp2_session_upgrade2() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ result = CURLE_HTTP2;
+ goto out;
+ }
+
+ rc = nghttp2_session_set_stream_user_data(ctx->h2, stream->id,
+ data);
+ if(rc) {
+ infof(data, "http/2: failed to set user_data for stream %u",
+ stream->id);
+ DEBUGASSERT(0);
+ }
+ }
+ else {
+ nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN];
+ int ivlen;
+
+ ivlen = populate_settings(iv, data);
+ rc = nghttp2_submit_settings(ctx->h2, NGHTTP2_FLAG_NONE,
+ iv, ivlen);
+ if(rc) {
+ failf(data, "nghttp2_submit_settings() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ result = CURLE_HTTP2;
+ goto out;
+ }
+ }
+
+ rc = nghttp2_session_set_local_window_size(ctx->h2, NGHTTP2_FLAG_NONE, 0,
+ HTTP2_HUGE_WINDOW_SIZE);
+ if(rc) {
+ failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ result = CURLE_HTTP2;
+ goto out;
+ }
+
+ /* all set, traffic will be send on connect */
+ result = CURLE_OK;
+
+out:
+ if(cbs)
+ nghttp2_session_callbacks_del(cbs);
+ return result;
+}
+
+/*
+ * Returns nonzero if current HTTP/2 session should be closed.
+ */
+static int should_close_session(struct cf_h2_ctx *ctx)
+{
+ return ctx->drain_total == 0 && !nghttp2_session_want_read(ctx->h2) &&
+ !nghttp2_session_want_write(ctx->h2);
+}
+
+/*
+ * Processes pending input left in network input buffer.
+ * This function returns 0 if it succeeds, or -1 and error code will
+ * be assigned to *err.
+ */
+static int h2_process_pending_input(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ CURLcode *err)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ const unsigned char *buf;
+ size_t blen;
+ 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) {
+ failf(data,
+ "process_pending_input: nghttp2_session_mem_recv() returned "
+ "%zd:%s", rv, nghttp2_strerror((int)rv));
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+ Curl_bufq_skip(&ctx->inbufq, (size_t)rv);
+ if(Curl_bufq_is_empty(&ctx->inbufq)) {
+ break;
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "process_pending_input: %zu bytes left "
+ "in connection buffer", Curl_bufq_len(&ctx->inbufq)));
+ }
+ }
+
+ if(nghttp2_session_check_request_allowed(ctx->h2) == 0) {
+ /* No more requests are allowed in the current session, so
+ the connection may not be reused. This is set when a
+ GOAWAY frame has been received or when the limit of stream
+ identifiers has been reached. */
+ connclose(cf->conn, "http/2: No new requests allowed");
+ }
+
+ return 0;
+}
+
/*
* The server may send us data at any point (e.g. PING frames). Therefore,
* we cannot assume that an HTTP/2 socket is dead just because it is readable.
*
- * Instead, if it is readable, run Curl_connalive() to peek at the socket
+ * Check the lower filters first and, if successful, peek at the socket
* and distinguish between closed and data.
*/
-static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn)
+static bool http2_connisalive(struct Curl_cfilter *cf, struct Curl_easy *data,
+ bool *input_pending)
{
- int sval;
- bool dead = TRUE;
+ struct cf_h2_ctx *ctx = cf->ctx;
+ bool alive = TRUE;
- if(conn->bits.close)
- return TRUE;
+ *input_pending = FALSE;
+ if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
+ return FALSE;
- sval = SOCKET_READABLE(conn->sock[FIRSTSOCKET], 0);
- if(sval == 0) {
- /* timeout */
- dead = FALSE;
- }
- else if(sval & CURL_CSELECT_ERR) {
- /* socket is in an error state */
- dead = TRUE;
- }
- else if(sval & CURL_CSELECT_IN) {
- /* readable with no error. could still be closed */
- dead = !Curl_connalive(conn);
- if(!dead) {
- /* This happens before we've sent off a request and the connection is
- not in use by any other transfer, there shouldn't be any data here,
- only "protocol frames" */
- CURLcode result;
- struct http_conn *httpc = &conn->proto.httpc;
- ssize_t nread = -1;
- if(httpc->recv_underlying)
- /* if called "too early", this pointer isn't setup yet! */
- nread = ((Curl_recv *)httpc->recv_underlying)(
- data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
- if(nread != -1) {
- H2BUGF(infof(data,
- "%d bytes stray data read before trying h2 connection",
- (int)nread));
- httpc->nread_inbuf = 0;
- httpc->inbuflen = nread;
- if(h2_process_pending_input(data, httpc, &result) < 0)
- /* immediate error, considered dead */
- dead = TRUE;
- }
- else
- /* the read failed so let's say this is dead anyway */
- dead = TRUE;
- }
- }
+ if(*input_pending) {
+ /* This happens before we've sent off a request and the connection is
+ not in use by any other transfer, there shouldn't be any data here,
+ only "protocol frames" */
+ CURLcode result;
+ ssize_t nread = -1;
- return dead;
-}
-
-/*
- * Set the transfer that is currently using this HTTP/2 connection.
- */
-static void set_transfer(struct http_conn *c,
- struct Curl_easy *data)
-{
- c->trnsfr = data;
-}
-
-/*
- * Get the transfer that is currently using this HTTP/2 connection.
- */
-static struct Curl_easy *get_transfer(struct http_conn *c)
-{
- DEBUGASSERT(c && c->trnsfr);
- return c->trnsfr;
-}
-
-static unsigned int http2_conncheck(struct Curl_easy *data,
- struct connectdata *conn,
- unsigned int checks_to_perform)
-{
- unsigned int ret_val = CONNRESULT_NONE;
- struct http_conn *c = &conn->proto.httpc;
- int rc;
- bool send_frames = false;
-
- if(checks_to_perform & CONNCHECK_ISDEAD) {
- if(http2_connisdead(data, conn))
- ret_val |= CONNRESULT_DEAD;
- }
-
- if(checks_to_perform & CONNCHECK_KEEPALIVE) {
- struct curltime now = Curl_now();
- timediff_t elapsed = Curl_timediff(now, conn->keepalive);
-
- if(elapsed > data->set.upkeep_interval_ms) {
- /* Perform an HTTP/2 PING */
- rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL);
- if(!rc) {
- /* Successfully added a PING frame to the session. Need to flag this
- so the frame is sent. */
- send_frames = true;
- }
+ *input_pending = FALSE;
+ nread = Curl_bufq_slurp(&ctx->inbufq, nw_in_reader, cf, &result);
+ if(nread != -1) {
+ DEBUGF(LOG_CF(data, cf, "%zd bytes stray data read before trying "
+ "h2 connection", nread));
+ if(h2_process_pending_input(cf, data, &result) < 0)
+ /* immediate error, considered dead */
+ alive = FALSE;
else {
- failf(data, "nghttp2_submit_ping() failed: %s(%d)",
- nghttp2_strerror(rc), rc);
+ alive = !should_close_session(ctx);
}
-
- conn->keepalive = now;
+ }
+ else if(result != CURLE_AGAIN) {
+ /* the read failed so let's say this is dead anyway */
+ alive = FALSE;
}
}
- if(send_frames) {
- set_transfer(c, data); /* set the transfer */
- rc = nghttp2_session_send(c->h2);
- if(rc)
- failf(data, "nghttp2_session_send() failed: %s(%d)",
- nghttp2_strerror(rc), rc);
+ return alive;
+}
+
+static CURLcode http2_send_ping(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ int rc;
+
+ rc = nghttp2_submit_ping(ctx->h2, 0, ZERO_NULL);
+ if(rc) {
+ failf(data, "nghttp2_submit_ping() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ return CURLE_HTTP2;
}
- return ret_val;
+ rc = nghttp2_session_send(ctx->h2);
+ if(rc) {
+ failf(data, "nghttp2_session_send() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ return CURLE_SEND_ERROR;
+ }
+ return CURLE_OK;
}
-/* called from http_setup_conn */
-void Curl_http2_setup_req(struct Curl_easy *data)
-{
- struct HTTP *http = data->req.p.http;
- http->bodystarted = FALSE;
- http->status_code = -1;
- http->pausedata = NULL;
- http->pauselen = 0;
- http->closed = FALSE;
- http->close_handled = FALSE;
- http->mem = NULL;
- http->len = 0;
- http->memlen = 0;
- http->error = NGHTTP2_NO_ERROR;
-}
-
-/* called from http_setup_conn */
-void Curl_http2_setup_conn(struct connectdata *conn)
-{
- conn->proto.httpc.settings.max_concurrent_streams =
- DEFAULT_MAX_CONCURRENT_STREAMS;
-}
-
-/*
- * HTTP2 handler interface. This isn't added to the general list of protocols
- * but will be used at run-time when the protocol is dynamically switched from
- * HTTP to HTTP2.
- */
-static const struct Curl_handler Curl_handler_http2 = {
- "HTTP", /* scheme */
- ZERO_NULL, /* setup_connection */
- Curl_http, /* do_it */
- Curl_http_done, /* done */
- ZERO_NULL, /* do_more */
- ZERO_NULL, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- http2_getsock, /* proto_getsock */
- http2_getsock, /* doing_getsock */
- ZERO_NULL, /* domore_getsock */
- http2_getsock, /* perform_getsock */
- http2_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
- http2_conncheck, /* connection_check */
- ZERO_NULL, /* attach connection */
- PORT_HTTP, /* defport */
- CURLPROTO_HTTP, /* protocol */
- CURLPROTO_HTTP, /* family */
- PROTOPT_STREAM /* flags */
-};
-
-static const struct Curl_handler Curl_handler_http2_ssl = {
- "HTTPS", /* scheme */
- ZERO_NULL, /* setup_connection */
- Curl_http, /* do_it */
- Curl_http_done, /* done */
- ZERO_NULL, /* do_more */
- ZERO_NULL, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- http2_getsock, /* proto_getsock */
- http2_getsock, /* doing_getsock */
- ZERO_NULL, /* domore_getsock */
- http2_getsock, /* perform_getsock */
- http2_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
- http2_conncheck, /* connection_check */
- ZERO_NULL, /* attach connection */
- PORT_HTTP, /* defport */
- CURLPROTO_HTTPS, /* protocol */
- CURLPROTO_HTTP, /* family */
- PROTOPT_SSL | PROTOPT_STREAM /* flags */
-};
-
/*
* Store nghttp2 version info in this buffer.
*/
@@ -369,44 +639,65 @@
(void)msnprintf(p, len, "nghttp2/%s", h2->version_str);
}
+static CURLcode nw_out_flush(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ ssize_t nwritten;
+ CURLcode result;
+
+ (void)data;
+ if(Curl_bufq_is_empty(&ctx->outbufq))
+ return CURLE_OK;
+
+ nwritten = Curl_bufq_pass(&ctx->outbufq, nw_out_writer, cf, &result);
+ if(nwritten < 0) {
+ if(result == CURLE_AGAIN) {
+ DEBUGF(LOG_CF(data, cf, "flush nw send buffer(%zu) -> EAGAIN",
+ Curl_bufq_len(&ctx->outbufq)));
+ ctx->nw_out_blocked = 1;
+ }
+ return result;
+ }
+ DEBUGF(LOG_CF(data, cf, "nw send buffer flushed"));
+ return Curl_bufq_is_empty(&ctx->outbufq)? CURLE_OK: CURLE_AGAIN;
+}
+
/*
* The implementation of nghttp2_send_callback type. Here we write |data| with
* size |length| to the network and return the number of bytes actually
* written. See the documentation of nghttp2_send_callback for the details.
*/
static ssize_t send_callback(nghttp2_session *h2,
- const uint8_t *mem, size_t length, int flags,
+ const uint8_t *buf, size_t blen, int flags,
void *userp)
{
- struct connectdata *conn = (struct connectdata *)userp;
- struct http_conn *c = &conn->proto.httpc;
- struct Curl_easy *data = get_transfer(c);
- ssize_t written;
+ struct Curl_cfilter *cf = userp;
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nwritten;
CURLcode result = CURLE_OK;
(void)h2;
(void)flags;
+ DEBUGASSERT(data);
- if(!c->send_underlying)
- /* called before setup properly! */
- return NGHTTP2_ERR_CALLBACK_FAILURE;
-
- written = ((Curl_send*)c->send_underlying)(data, FIRSTSOCKET,
- mem, length, &result);
-
- if(result == CURLE_AGAIN) {
- return NGHTTP2_ERR_WOULDBLOCK;
- }
-
- if(written == -1) {
+ nwritten = Curl_bufq_write_pass(&ctx->outbufq, buf, blen,
+ nw_out_writer, cf, &result);
+ if(nwritten < 0) {
+ if(result == CURLE_AGAIN) {
+ ctx->nw_out_blocked = 1;
+ return NGHTTP2_ERR_WOULDBLOCK;
+ }
failf(data, "Failed sending HTTP2 data");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
- if(!written)
+ if(!nwritten) {
+ ctx->nw_out_blocked = 1;
return NGHTTP2_ERR_WOULDBLOCK;
-
- return written;
+ }
+ return nwritten;
}
@@ -427,8 +718,8 @@
if(!h || !GOOD_EASY_HANDLE(h->data))
return NULL;
else {
- struct HTTP *stream = h->data->req.p.http;
- if(num < stream->push_headers_used)
+ struct stream_ctx *stream = H2_STREAM_CTX(h->data);
+ if(stream && num < stream->push_headers_used)
return stream->push_headers[num];
}
return NULL;
@@ -439,6 +730,9 @@
*/
char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
{
+ struct stream_ctx *stream;
+ size_t len;
+ size_t i;
/* Verify that we got a good easy handle in the push header struct,
mostly to detect rubbish input fast(er). Also empty header name
is just a rubbish too. We have to allow ":" at the beginning of
@@ -448,45 +742,25 @@
if(!h || !GOOD_EASY_HANDLE(h->data) || !header || !header[0] ||
!strcmp(header, ":") || strchr(header + 1, ':'))
return NULL;
- else {
- struct HTTP *stream = h->data->req.p.http;
- size_t len = strlen(header);
- size_t i;
- for(i = 0; i<stream->push_headers_used; i++) {
- if(!strncmp(header, stream->push_headers[i], len)) {
- /* sub-match, make sure that it is followed by a colon */
- if(stream->push_headers[i][len] != ':')
- continue;
- return &stream->push_headers[i][len + 1];
- }
+
+ stream = H2_STREAM_CTX(h->data);
+ if(!stream)
+ return NULL;
+
+ len = strlen(header);
+ for(i = 0; i<stream->push_headers_used; i++) {
+ if(!strncmp(header, stream->push_headers[i], len)) {
+ /* sub-match, make sure that it is followed by a colon */
+ if(stream->push_headers[i][len] != ':')
+ continue;
+ return &stream->push_headers[i][len + 1];
}
}
return NULL;
}
-/*
- * This specific transfer on this connection has been "drained".
- */
-static void drained_transfer(struct Curl_easy *data,
- struct http_conn *httpc)
-{
- DEBUGASSERT(httpc->drain_total >= data->state.drain);
- httpc->drain_total -= data->state.drain;
- data->state.drain = 0;
-}
-
-/*
- * Mark this transfer to get "drained".
- */
-static void drain_this(struct Curl_easy *data,
- struct http_conn *httpc)
-{
- data->state.drain++;
- httpc->drain_total++;
- DEBUGASSERT(httpc->drain_total >= data->state.drain);
-}
-
-static struct Curl_easy *duphandle(struct Curl_easy *data)
+static struct Curl_easy *h2_duphandle(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
struct Curl_easy *second = curl_easy_duphandle(data);
if(second) {
@@ -496,10 +770,11 @@
(void)Curl_close(&second);
}
else {
+ struct stream_ctx *second_stream;
+
second->req.p.http = http;
- Curl_dyn_init(&http->header_recvbuf, DYN_H2_HEADERS);
- Curl_http2_setup_req(second);
- second->state.stream_weight = data->state.stream_weight;
+ http2_data_setup(cf, second, &second_stream);
+ second->state.priority.weight = data->state.priority.weight;
}
}
return second;
@@ -517,7 +792,7 @@
if(!u)
return 5;
- v = curl_pushheader_byname(hp, H2H3_PSEUDO_SCHEME);
+ v = curl_pushheader_byname(hp, HTTP_PSEUDO_SCHEME);
if(v) {
uc = curl_url_set(u, CURLUPART_SCHEME, v, 0);
if(uc) {
@@ -526,16 +801,16 @@
}
}
- v = curl_pushheader_byname(hp, H2H3_PSEUDO_AUTHORITY);
+ v = curl_pushheader_byname(hp, HTTP_PSEUDO_AUTHORITY);
if(v) {
- uc = curl_url_set(u, CURLUPART_HOST, v, 0);
+ uc = Curl_url_set_authority(u, v, CURLU_DISALLOW_USER);
if(uc) {
rc = 2;
goto fail;
}
}
- v = curl_pushheader_byname(hp, H2H3_PSEUDO_PATH);
+ v = curl_pushheader_byname(hp, HTTP_PSEUDO_PATH);
if(v) {
uc = curl_url_set(u, CURLUPART_PATH, v, 0);
if(uc) {
@@ -547,7 +822,7 @@
uc = curl_url_get(u, CURLUPART_URL, &url, 0);
if(uc)
rc = 4;
- fail:
+fail:
curl_url_cleanup(u);
if(rc)
return rc;
@@ -559,22 +834,34 @@
return 0;
}
-static int push_promise(struct Curl_easy *data,
- struct connectdata *conn,
+static void discard_newhandle(struct Curl_cfilter *cf,
+ struct Curl_easy *newhandle)
+{
+ if(!newhandle->req.p.http) {
+ http2_data_done(cf, newhandle, TRUE);
+ newhandle->req.p.http = NULL;
+ }
+ (void)Curl_close(&newhandle);
+}
+
+static int push_promise(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
const nghttp2_push_promise *frame)
{
+ struct cf_h2_ctx *ctx = cf->ctx;
int rv; /* one of the CURL_PUSH_* defines */
- H2BUGF(infof(data, "PUSH_PROMISE received, stream %u",
- frame->promised_stream_id));
+
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] PUSH_PROMISE received",
+ frame->promised_stream_id));
if(data->multi->push_cb) {
- struct HTTP *stream;
- struct HTTP *newstream;
+ struct stream_ctx *stream;
+ struct stream_ctx *newstream;
struct curl_pushheaders heads;
CURLMcode rc;
- struct http_conn *httpc;
+ CURLcode result;
size_t i;
/* clone the parent */
- struct Curl_easy *newhandle = duphandle(data);
+ struct Curl_easy *newhandle = h2_duphandle(cf, data);
if(!newhandle) {
infof(data, "failed to duplicate handle");
rv = CURL_PUSH_DENY; /* FAIL HARD */
@@ -584,23 +871,32 @@
heads.data = data;
heads.frame = frame;
/* ask the application */
- H2BUGF(infof(data, "Got PUSH_PROMISE, ask application"));
+ DEBUGF(LOG_CF(data, cf, "Got PUSH_PROMISE, ask application"));
- stream = data->req.p.http;
+ stream = H2_STREAM_CTX(data);
if(!stream) {
failf(data, "Internal NULL stream");
- (void)Curl_close(&newhandle);
+ discard_newhandle(cf, newhandle);
rv = CURL_PUSH_DENY;
goto fail;
}
rv = set_transfer_url(newhandle, &heads);
if(rv) {
- (void)Curl_close(&newhandle);
+ discard_newhandle(cf, newhandle);
rv = CURL_PUSH_DENY;
goto fail;
}
+ result = http2_data_setup(cf, newhandle, &newstream);
+ if(result) {
+ failf(data, "error setting up stream: %d", result);
+ discard_newhandle(cf, newhandle);
+ rv = CURL_PUSH_DENY;
+ goto fail;
+ }
+ DEBUGASSERT(stream);
+
Curl_set_in_callback(data, true);
rv = data->multi->push_cb(data, newhandle,
stream->push_headers_used, &heads,
@@ -617,132 +913,116 @@
if(rv) {
DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
/* denied, kill off the new handle again */
- http2_stream_free(newhandle->req.p.http);
- newhandle->req.p.http = NULL;
- (void)Curl_close(&newhandle);
+ discard_newhandle(cf, newhandle);
goto fail;
}
- newstream = newhandle->req.p.http;
- newstream->stream_id = frame->promised_stream_id;
+ newstream->id = frame->promised_stream_id;
newhandle->req.maxdownload = -1;
newhandle->req.size = -1;
/* approved, add to the multi handle and immediately switch to PERFORM
state with the given connection !*/
- rc = Curl_multi_add_perform(data->multi, newhandle, conn);
+ rc = Curl_multi_add_perform(data->multi, newhandle, cf->conn);
if(rc) {
infof(data, "failed to add handle to multi");
- http2_stream_free(newhandle->req.p.http);
- newhandle->req.p.http = NULL;
- Curl_close(&newhandle);
+ discard_newhandle(cf, newhandle);
rv = CURL_PUSH_DENY;
goto fail;
}
- httpc = &conn->proto.httpc;
- rv = nghttp2_session_set_stream_user_data(httpc->h2,
- frame->promised_stream_id,
+ rv = nghttp2_session_set_stream_user_data(ctx->h2,
+ newstream->id,
newhandle);
if(rv) {
infof(data, "failed to set user_data for stream %u",
- frame->promised_stream_id);
+ newstream->id);
DEBUGASSERT(0);
rv = CURL_PUSH_DENY;
goto fail;
}
- Curl_dyn_init(&newstream->header_recvbuf, DYN_H2_HEADERS);
- Curl_dyn_init(&newstream->trailer_recvbuf, DYN_H2_TRAILERS);
}
else {
- H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it"));
+ DEBUGF(LOG_CF(data, cf, "Got PUSH_PROMISE, ignore it"));
rv = CURL_PUSH_DENY;
}
- fail:
+fail:
return rv;
}
-/*
- * multi_connchanged() is called to tell that there is a connection in
- * this multi handle that has changed state (multiplexing become possible, the
- * number of allowed streams changed or similar), and a subsequent use of this
- * multi handle should move CONNECT_PEND handles back to CONNECT to have them
- * retry.
- */
-static void multi_connchanged(struct Curl_multi *multi)
+static CURLcode recvbuf_write_hds(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *buf, size_t blen)
{
- multi->recheckstate = TRUE;
-}
-
-static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
- void *userp)
-{
- struct connectdata *conn = (struct connectdata *)userp;
- struct http_conn *httpc = &conn->proto.httpc;
- struct Curl_easy *data_s = NULL;
- struct HTTP *stream = NULL;
- struct Curl_easy *data = get_transfer(httpc);
- int rv;
- size_t left, ncopy;
- int32_t stream_id = frame->hd.stream_id;
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ ssize_t nwritten;
CURLcode result;
- if(!stream_id) {
- /* stream ID zero is for connection-oriented stuff */
- if(frame->hd.type == NGHTTP2_SETTINGS) {
- uint32_t max_conn = httpc->settings.max_concurrent_streams;
- H2BUGF(infof(data, "Got SETTINGS"));
- httpc->settings.max_concurrent_streams =
- nghttp2_session_get_remote_settings(
- session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
- httpc->settings.enable_push =
- nghttp2_session_get_remote_settings(
- session, NGHTTP2_SETTINGS_ENABLE_PUSH);
- H2BUGF(infof(data, "MAX_CONCURRENT_STREAMS == %d",
- httpc->settings.max_concurrent_streams));
- H2BUGF(infof(data, "ENABLE_PUSH == %s",
- httpc->settings.enable_push?"TRUE":"false"));
- if(max_conn != httpc->settings.max_concurrent_streams) {
- /* only signal change if the value actually changed */
- infof(data,
- "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!",
- httpc->settings.max_concurrent_streams);
- multi_connchanged(data->multi);
- }
- }
- return 0;
- }
- data_s = nghttp2_session_get_stream_user_data(session, stream_id);
- if(!data_s) {
- H2BUGF(infof(data,
- "No Curl_easy associated with stream: %u",
- stream_id));
- return 0;
- }
+ (void)cf;
+ nwritten = Curl_bufq_write(&stream->recvbuf,
+ (const unsigned char *)buf, blen, &result);
+ if(nwritten < 0)
+ return result;
+ stream->resp_hds_len += (size_t)nwritten;
+ DEBUGASSERT((size_t)nwritten == blen);
+ return CURLE_OK;
+}
- stream = data_s->req.p.http;
+static CURLcode on_stream_frame(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const nghttp2_frame *frame)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ int32_t stream_id = frame->hd.stream_id;
+ CURLcode result;
+ size_t rbuflen;
+ int rv;
+
if(!stream) {
- H2BUGF(infof(data_s, "No proto pointer for stream: %u",
- stream_id));
- return NGHTTP2_ERR_CALLBACK_FAILURE;
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] No proto pointer", stream_id));
+ return CURLE_FAILED_INIT;
}
- H2BUGF(infof(data_s, "on_frame_recv() header %x stream %u",
- frame->hd.type, stream_id));
-
switch(frame->hd.type) {
case NGHTTP2_DATA:
- /* If body started on this stream, then receiving DATA is illegal. */
+ rbuflen = Curl_bufq_len(&stream->recvbuf);
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[DATA len=%zu pad=%zu], "
+ "buffered=%zu, window=%d/%d",
+ stream_id, frame->hd.length, frame->data.padlen, rbuflen,
+ nghttp2_session_get_stream_effective_recv_data_length(
+ ctx->h2, stream->id),
+ nghttp2_session_get_stream_effective_local_window_size(
+ ctx->h2, stream->id)));
+ /* If !body started on this stream, then receiving DATA is illegal. */
if(!stream->bodystarted) {
- rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ rv = nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
stream_id, NGHTTP2_PROTOCOL_ERROR);
if(nghttp2_is_fatal(rv)) {
- return NGHTTP2_ERR_CALLBACK_FAILURE;
+ return CURLE_RECV_ERROR;
+ }
+ }
+ if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
+ drain_stream(cf, data, stream);
+ }
+ else if(rbuflen > stream->local_window_size) {
+ int32_t wsize = nghttp2_session_get_stream_local_window_size(
+ ctx->h2, stream->id);
+ if(wsize > 0 && (uint32_t)wsize != stream->local_window_size) {
+ /* H2 flow control is not absolute, as the server might not have the
+ * same view, yet. When we recieve more than we want, we enforce
+ * the local window size again to make nghttp2 send WINDOW_UPATEs
+ * accordingly. */
+ nghttp2_session_set_local_window_size(ctx->h2,
+ NGHTTP2_FLAG_NONE,
+ stream->id,
+ stream->local_window_size);
}
}
break;
case NGHTTP2_HEADERS:
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[HEADERS]", stream_id));
if(stream->bodystarted) {
/* Only valid HEADERS after body started is trailer HEADERS. We
buffer them in on_header callback. */
@@ -753,7 +1033,7 @@
stream->status_code. Fuzzing has proven this can still be reached
without status code having been set. */
if(stream->status_code == -1)
- return NGHTTP2_ERR_CALLBACK_FAILURE;
+ return CURLE_RECV_ERROR;
/* Only final status code signals the end of header */
if(stream->status_code / 100 != 1) {
@@ -761,69 +1041,148 @@
stream->status_code = -1;
}
- result = Curl_dyn_addn(&stream->header_recvbuf, STRCONST("\r\n"));
+ result = recvbuf_write_hds(cf, data, STRCONST("\r\n"));
if(result)
- return NGHTTP2_ERR_CALLBACK_FAILURE;
+ return result;
- left = Curl_dyn_len(&stream->header_recvbuf) -
- stream->nread_header_recvbuf;
- ncopy = CURLMIN(stream->len, left);
-
- memcpy(&stream->mem[stream->memlen],
- Curl_dyn_ptr(&stream->header_recvbuf) +
- stream->nread_header_recvbuf,
- ncopy);
- stream->nread_header_recvbuf += ncopy;
-
- DEBUGASSERT(stream->mem);
- H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p",
- ncopy, stream_id, stream->mem));
-
- stream->len -= ncopy;
- stream->memlen += ncopy;
-
- drain_this(data_s, httpc);
- /* if we receive data for another handle, wake that up */
- if(get_transfer(httpc) != data_s)
- Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] %zu header bytes",
+ stream_id, Curl_bufq_len(&stream->recvbuf)));
+ drain_stream(cf, data, stream);
break;
case NGHTTP2_PUSH_PROMISE:
- rv = push_promise(data_s, conn, &frame->push_promise);
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[PUSH_PROMISE]", stream_id));
+ rv = push_promise(cf, data, &frame->push_promise);
if(rv) { /* deny! */
- int h2;
DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
- h2 = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ rv = nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
frame->push_promise.promised_stream_id,
NGHTTP2_CANCEL);
- if(nghttp2_is_fatal(h2))
- return NGHTTP2_ERR_CALLBACK_FAILURE;
+ if(nghttp2_is_fatal(rv))
+ return CURLE_SEND_ERROR;
else if(rv == CURL_PUSH_ERROROUT) {
- DEBUGF(infof(data_s, "Fail the parent stream (too)"));
- return NGHTTP2_ERR_CALLBACK_FAILURE;
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] fail in PUSH_PROMISE received",
+ stream_id));
+ return CURLE_RECV_ERROR;
}
}
break;
+ case NGHTTP2_RST_STREAM:
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[RST]", stream_id));
+ stream->closed = TRUE;
+ stream->reset = TRUE;
+ stream->send_closed = TRUE;
+ data->req.keepon &= ~KEEP_SEND_HOLD;
+ drain_stream(cf, data, stream);
+ break;
+ case NGHTTP2_WINDOW_UPDATE:
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[WINDOW_UPDATE]", stream_id));
+ if((data->req.keepon & KEEP_SEND_HOLD) &&
+ (data->req.keepon & KEEP_SEND)) {
+ data->req.keepon &= ~KEEP_SEND_HOLD;
+ drain_stream(cf, data, stream);
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] un-holding after win update",
+ stream_id));
+ }
+ break;
default:
- H2BUGF(infof(data_s, "Got frame type %x for stream %u",
- frame->hd.type, stream_id));
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[%x]",
+ stream_id, frame->hd.type));
break;
}
- return 0;
+ return CURLE_OK;
+}
+
+static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
+ void *userp)
+{
+ struct Curl_cfilter *cf = userp;
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf), *data_s;
+ int32_t stream_id = frame->hd.stream_id;
+
+ DEBUGASSERT(data);
+ if(!stream_id) {
+ /* stream ID zero is for connection-oriented stuff */
+ DEBUGASSERT(data);
+ switch(frame->hd.type) {
+ case NGHTTP2_SETTINGS: {
+ uint32_t max_conn = ctx->max_concurrent_streams;
+ DEBUGF(LOG_CF(data, cf, "FRAME[SETTINGS]"));
+ ctx->max_concurrent_streams = nghttp2_session_get_remote_settings(
+ session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
+ ctx->enable_push = nghttp2_session_get_remote_settings(
+ session, NGHTTP2_SETTINGS_ENABLE_PUSH) != 0;
+ DEBUGF(LOG_CF(data, cf, "MAX_CONCURRENT_STREAMS == %d",
+ ctx->max_concurrent_streams));
+ DEBUGF(LOG_CF(data, cf, "ENABLE_PUSH == %s",
+ ctx->enable_push ? "TRUE" : "false"));
+ if(data && max_conn != ctx->max_concurrent_streams) {
+ /* only signal change if the value actually changed */
+ DEBUGF(LOG_CF(data, cf, "MAX_CONCURRENT_STREAMS now %u",
+ ctx->max_concurrent_streams));
+ multi_connchanged(data->multi);
+ }
+ /* Since the initial stream window is 64K, a request might be on HOLD,
+ * due to exhaustion. The (initial) SETTINGS may announce a much larger
+ * window and *assume* that we treat this like a WINDOW_UPDATE. Some
+ * servers send an explicit WINDOW_UPDATE, but not all seem to do that.
+ * To be safe, we UNHOLD a stream in order not to stall. */
+ if((data->req.keepon & KEEP_SEND_HOLD) &&
+ (data->req.keepon & KEEP_SEND)) {
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ data->req.keepon &= ~KEEP_SEND_HOLD;
+ if(stream) {
+ drain_stream(cf, data, stream);
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] un-holding after SETTINGS",
+ stream_id));
+ }
+ }
+ break;
+ }
+ case NGHTTP2_GOAWAY:
+ ctx->goaway = TRUE;
+ ctx->goaway_error = frame->goaway.error_code;
+ ctx->last_stream_id = frame->goaway.last_stream_id;
+ if(data) {
+ DEBUGF(LOG_CF(data, cf, "FRAME[GOAWAY, error=%d, last_stream=%u]",
+ ctx->goaway_error, ctx->last_stream_id));
+ infof(data, "received GOAWAY, error=%d, last_stream=%u",
+ ctx->goaway_error, ctx->last_stream_id);
+ multi_connchanged(data->multi);
+ }
+ break;
+ case NGHTTP2_WINDOW_UPDATE:
+ DEBUGF(LOG_CF(data, cf, "FRAME[WINDOW_UPDATE]"));
+ break;
+ default:
+ DEBUGF(LOG_CF(data, cf, "recv frame %x on 0", frame->hd.type));
+ }
+ return 0;
+ }
+
+ data_s = nghttp2_session_get_stream_user_data(session, stream_id);
+ if(!data_s) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] No Curl_easy associated",
+ stream_id));
+ return 0;
+ }
+
+ return on_stream_frame(cf, data_s, frame)? NGHTTP2_ERR_CALLBACK_FAILURE : 0;
}
static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
const uint8_t *mem, size_t len, void *userp)
{
- struct HTTP *stream;
+ struct Curl_cfilter *cf = userp;
+ struct stream_ctx *stream;
struct Curl_easy *data_s;
- size_t nread;
- struct connectdata *conn = (struct connectdata *)userp;
- struct http_conn *httpc = &conn->proto.httpc;
- (void)session;
+ ssize_t nwritten;
+ CURLcode result;
(void)flags;
DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
+ DEBUGASSERT(CF_DATA_CURRENT(cf));
/* get the stream from the hash based on Stream ID */
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
@@ -831,123 +1190,93 @@
/* 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. */
- H2BUGF(fprintf(stderr, "Data for stream %u but it doesn't exist\n",
- stream_id));
+ DEBUGF(LOG_CF(CF_DATA_CURRENT(cf), cf, "[h2sid=%d] Data for unknown",
+ stream_id));
+ /* consumed explicitly as no one will read it */
+ nghttp2_session_consume(session, stream_id, len);
return 0;
}
- stream = data_s->req.p.http;
+ stream = H2_STREAM_CTX(data_s);
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- nread = CURLMIN(stream->len, len);
- memcpy(&stream->mem[stream->memlen], mem, nread);
+ nwritten = Curl_bufq_write(&stream->recvbuf, mem, len, &result);
+ if(nwritten < 0) {
+ if(result != CURLE_AGAIN)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream->len -= nread;
- stream->memlen += nread;
-
- drain_this(data_s, &conn->proto.httpc);
+ nwritten = 0;
+ }
/* if we receive data for another handle, wake that up */
- if(get_transfer(httpc) != data_s)
- Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
+ drain_stream(cf, data_s, stream);
- H2BUGF(infof(data_s, "%zu data received for stream %u "
- "(%zu left in buffer %p, total %zu)",
- nread, stream_id,
- stream->len, stream->mem,
- stream->memlen));
-
- if(nread < len) {
- stream->pausedata = mem + nread;
- stream->pauselen = len - nread;
- H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
- ", stream %u",
- len - nread, stream_id));
- data_s->conn->proto.httpc.pause_stream_id = stream_id;
-
- return NGHTTP2_ERR_PAUSE;
- }
-
- /* pause execution of nghttp2 if we received data for another handle
- in order to process them first. */
- if(get_transfer(httpc) != data_s) {
- data_s->conn->proto.httpc.pause_stream_id = stream_id;
-
- return NGHTTP2_ERR_PAUSE;
- }
-
+ DEBUGASSERT((size_t)nwritten == len);
return 0;
}
static int on_stream_close(nghttp2_session *session, int32_t stream_id,
uint32_t error_code, void *userp)
{
+ struct Curl_cfilter *cf = userp;
struct Curl_easy *data_s;
- struct HTTP *stream;
- struct connectdata *conn = (struct connectdata *)userp;
+ struct stream_ctx *stream;
int rv;
(void)session;
- (void)stream_id;
- if(stream_id) {
- struct http_conn *httpc;
- /* get the stream from the hash based on Stream ID, stream ID zero is for
- connection-oriented stuff */
- data_s = nghttp2_session_get_stream_user_data(session, stream_id);
- if(!data_s) {
- /* We could get stream ID not in the hash. For example, if we
- decided to reject stream (e.g., PUSH_PROMISE). */
- return 0;
- }
- H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u",
- nghttp2_http2_strerror(error_code), error_code, stream_id));
- stream = data_s->req.p.http;
- if(!stream)
- return NGHTTP2_ERR_CALLBACK_FAILURE;
-
- stream->closed = TRUE;
- httpc = &conn->proto.httpc;
- drain_this(data_s, httpc);
- Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- stream->error = error_code;
-
- /* remove the entry from the hash as the stream is now gone */
- rv = nghttp2_session_set_stream_user_data(session, stream_id, 0);
- if(rv) {
- infof(data_s, "http/2: failed to clear user_data for stream %u",
- stream_id);
- DEBUGASSERT(0);
- }
- if(stream_id == httpc->pause_stream_id) {
- H2BUGF(infof(data_s, "Stopped the pause stream"));
- httpc->pause_stream_id = 0;
- }
- H2BUGF(infof(data_s, "Removed stream %u hash", stream_id));
- stream->stream_id = 0; /* cleared */
+ /* get the stream from the hash based on Stream ID, stream ID zero is for
+ connection-oriented stuff */
+ data_s = stream_id?
+ nghttp2_session_get_stream_user_data(session, stream_id) : NULL;
+ if(!data_s) {
+ return 0;
}
+ stream = H2_STREAM_CTX(data_s);
+ DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] on_stream_close(), %s (err %d)",
+ stream_id, nghttp2_http2_strerror(error_code), error_code));
+ if(!stream)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+
+ stream->closed = TRUE;
+ stream->error = error_code;
+ if(stream->error)
+ stream->reset = TRUE;
+ data_s->req.keepon &= ~KEEP_SEND_HOLD;
+
+ drain_stream(cf, data_s, stream);
+
+ /* remove `data_s` from the nghttp2 stream */
+ rv = nghttp2_session_set_stream_user_data(session, stream_id, 0);
+ if(rv) {
+ infof(data_s, "http/2: failed to clear user_data for stream %u",
+ stream_id);
+ DEBUGASSERT(0);
+ }
+ DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] closed now", stream_id));
return 0;
}
static int on_begin_headers(nghttp2_session *session,
const nghttp2_frame *frame, void *userp)
{
- struct HTTP *stream;
+ struct Curl_cfilter *cf = userp;
+ struct stream_ctx *stream;
struct Curl_easy *data_s = NULL;
- (void)userp;
+ (void)cf;
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(!data_s) {
return 0;
}
- H2BUGF(infof(data_s, "on_begin_headers() was called"));
+ DEBUGF(LOG_CF(data_s, cf, "on_begin_headers() was called"));
if(frame->hd.type != NGHTTP2_HEADERS) {
return 0;
}
- stream = data_s->req.p.http;
+ stream = H2_STREAM_CTX(data_s);
if(!stream || !stream->bodystarted) {
return 0;
}
@@ -955,33 +1284,6 @@
return 0;
}
-/* Decode HTTP status code. Returns -1 if no valid status code was
- decoded. */
-static int decode_status_code(const uint8_t *value, size_t len)
-{
- int i;
- int res;
-
- if(len != 3) {
- return -1;
- }
-
- res = 0;
-
- for(i = 0; i < 3; ++i) {
- char c = value[i];
-
- if(c < '0' || c > '9') {
- return -1;
- }
-
- res *= 10;
- res += c - '0';
- }
-
- return res;
-}
-
/* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */
static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
@@ -989,11 +1291,10 @@
uint8_t flags,
void *userp)
{
- struct HTTP *stream;
+ struct Curl_cfilter *cf = userp;
+ struct stream_ctx *stream;
struct Curl_easy *data_s;
int32_t stream_id = frame->hd.stream_id;
- struct connectdata *conn = (struct connectdata *)userp;
- struct http_conn *httpc = &conn->proto.httpc;
CURLcode result;
(void)flags;
@@ -1006,7 +1307,7 @@
internal error more than anything else! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream = data_s->req.p.http;
+ stream = H2_STREAM_CTX(data_s);
if(!stream) {
failf(data_s, "Internal NULL stream");
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -1017,16 +1318,17 @@
if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
char *h;
- if(!strcmp(H2H3_PSEUDO_AUTHORITY, (const char *)name)) {
+ if(!strcmp(HTTP_PSEUDO_AUTHORITY, (const char *)name)) {
/* pseudo headers are lower case */
int rc = 0;
- char *check = aprintf("%s:%d", conn->host.name, conn->remote_port);
+ char *check = aprintf("%s:%d", cf->conn->host.name,
+ cf->conn->remote_port);
if(!check)
/* no memory */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- if(!Curl_strcasecompare(check, (const char *)value) &&
- ((conn->remote_port != conn->given->defport) ||
- !Curl_strcasecompare(conn->host.name, (const char *)value))) {
+ if(!strcasecompare(check, (const char *)value) &&
+ ((cf->conn->remote_port != cf->conn->given->defport) ||
+ !strcasecompare(cf->conn->host.name, (const char *)value))) {
/* This is push is not for the same authority that was asked for in
* the URL. RFC 7540 section 8.2 says: "A client MUST treat a
* PUSH_PROMISE for which the server is not authoritative as a stream
@@ -1075,87 +1377,93 @@
if(stream->bodystarted) {
/* This is a trailer */
- H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s", namelen, name, valuelen,
- value));
- result = Curl_dyn_addf(&stream->trailer_recvbuf,
- "%.*s: %.*s\r\n", namelen, name,
- valuelen, value);
+ DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] trailer: %.*s: %.*s",
+ stream->id,
+ (int)namelen, name,
+ (int)valuelen, value));
+ result = Curl_dynhds_add(&stream->resp_trailers,
+ (const char *)name, namelen,
+ (const char *)value, valuelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
return 0;
}
- if(namelen == sizeof(H2H3_PSEUDO_STATUS) - 1 &&
- memcmp(H2H3_PSEUDO_STATUS, name, namelen) == 0) {
- /* nghttp2 guarantees :status is received first and only once, and
- value is 3 digits status code, and decode_status_code always
- succeeds. */
+ if(namelen == sizeof(HTTP_PSEUDO_STATUS) - 1 &&
+ memcmp(HTTP_PSEUDO_STATUS, name, namelen) == 0) {
+ /* nghttp2 guarantees :status is received first and only once. */
char buffer[32];
- stream->status_code = decode_status_code(value, valuelen);
- DEBUGASSERT(stream->status_code != -1);
- msnprintf(buffer, sizeof(buffer), H2H3_PSEUDO_STATUS ":%u\r",
+ result = Curl_http_decode_status(&stream->status_code,
+ (const char *)value, valuelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ msnprintf(buffer, sizeof(buffer), HTTP_PSEUDO_STATUS ":%u\r",
stream->status_code);
result = Curl_headers_push(data_s, buffer, CURLH_PSEUDO);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_dyn_addn(&stream->header_recvbuf, STRCONST("HTTP/2 "));
+ result = recvbuf_write_hds(cf, data_s, STRCONST("HTTP/2 "));
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_dyn_addn(&stream->header_recvbuf, value, valuelen);
+ result = recvbuf_write_hds(cf, data_s, (const char *)value, valuelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* the space character after the status code is mandatory */
- result = Curl_dyn_addn(&stream->header_recvbuf, STRCONST(" \r\n"));
+ result = recvbuf_write_hds(cf, data_s, STRCONST(" \r\n"));
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
- if(get_transfer(httpc) != data_s)
+ if(CF_DATA_CURRENT(cf) != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)",
- stream->status_code, data_s));
+ DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] status: HTTP/2 %03d",
+ stream->id, stream->status_code));
return 0;
}
/* nghttp2 guarantees that namelen > 0, and :status was already
received, and this is not pseudo-header field . */
- /* convert to a HTTP1-style header */
- result = Curl_dyn_addn(&stream->header_recvbuf, name, namelen);
+ /* convert to an HTTP1-style header */
+ result = recvbuf_write_hds(cf, data_s, (const char *)name, namelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_dyn_addn(&stream->header_recvbuf, STRCONST(": "));
+ result = recvbuf_write_hds(cf, data_s, STRCONST(": "));
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_dyn_addn(&stream->header_recvbuf, value, valuelen);
+ result = recvbuf_write_hds(cf, data_s, (const char *)value, valuelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_dyn_addn(&stream->header_recvbuf, STRCONST("\r\n"));
+ result = recvbuf_write_hds(cf, data_s, STRCONST("\r\n"));
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
- if(get_transfer(httpc) != data_s)
+ if(CF_DATA_CURRENT(cf) != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- H2BUGF(infof(data_s, "h2 header: %.*s: %.*s", namelen, name, valuelen,
- value));
+ DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] header: %.*s: %.*s",
+ stream->id,
+ (int)namelen, name,
+ (int)valuelen, value));
return 0; /* 0 is successful */
}
-static ssize_t data_source_read_callback(nghttp2_session *session,
- int32_t stream_id,
- uint8_t *buf, size_t length,
- uint32_t *data_flags,
- nghttp2_data_source *source,
- void *userp)
+static ssize_t req_body_read_callback(nghttp2_session *session,
+ int32_t stream_id,
+ uint8_t *buf, size_t length,
+ uint32_t *data_flags,
+ nghttp2_data_source *source,
+ void *userp)
{
+ struct Curl_cfilter *cf = userp;
struct Curl_easy *data_s;
- struct HTTP *stream = NULL;
- size_t nread;
+ struct stream_ctx *stream = NULL;
+ CURLcode result;
+ ssize_t nread;
(void)source;
- (void)userp;
+ (void)cf;
if(stream_id) {
/* get the stream from the hash based on Stream ID, stream ID zero is for
connection-oriented stuff */
@@ -1165,31 +1473,32 @@
internal error more than anything else! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream = data_s->req.p.http;
+ stream = H2_STREAM_CTX(data_s);
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
else
return NGHTTP2_ERR_INVALID_ARGUMENT;
- nread = CURLMIN(stream->upload_len, length);
- if(nread > 0) {
- memcpy(buf, stream->upload_mem, nread);
- stream->upload_mem += nread;
- stream->upload_len -= nread;
- if(data_s->state.infilesize != -1)
- stream->upload_left -= nread;
+ nread = Curl_bufq_read(&stream->sendbuf, buf, length, &result);
+ if(nread < 0) {
+ if(result != CURLE_AGAIN)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ nread = 0;
}
+ if(nread > 0 && stream->upload_left != -1)
+ stream->upload_left -= nread;
+
+ DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] req_body_read(len=%zu) left=%"
+ CURL_FORMAT_CURL_OFF_T " -> %zd, %d",
+ stream_id, length, stream->upload_left, nread, result));
+
if(stream->upload_left == 0)
*data_flags = NGHTTP2_DATA_FLAG_EOF;
else if(nread == 0)
return NGHTTP2_ERR_DEFERRED;
- H2BUGF(infof(data_s, "data_source_read_callback: "
- "returns %zu bytes stream %u",
- nread, stream_id));
-
return nread;
}
@@ -1207,155 +1516,25 @@
}
#endif
-static void populate_settings(struct Curl_easy *data,
- struct http_conn *httpc)
-{
- nghttp2_settings_entry *iv = httpc->local_settings;
-
- 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 = HTTP2_HUGE_WINDOW_SIZE;
-
- iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
- iv[2].value = data->multi->push_cb != NULL;
-
- httpc->local_settings_num = 3;
-}
-
-void Curl_http2_done(struct Curl_easy *data, bool premature)
-{
- struct HTTP *http = data->req.p.http;
- struct http_conn *httpc = &data->conn->proto.httpc;
-
- /* there might be allocated resources done before this got the 'h2' pointer
- setup */
- Curl_dyn_free(&http->header_recvbuf);
- Curl_dyn_free(&http->trailer_recvbuf);
- if(http->push_headers) {
- /* if they weren't used and then freed before */
- for(; http->push_headers_used > 0; --http->push_headers_used) {
- free(http->push_headers[http->push_headers_used - 1]);
- }
- free(http->push_headers);
- http->push_headers = NULL;
- }
-
- if(!(data->conn->handler->protocol&PROTO_FAMILY_HTTP) ||
- !httpc->h2) /* not HTTP/2 ? */
- return;
-
- /* do this before the reset handling, as that might clear ->stream_id */
- if(http->stream_id == httpc->pause_stream_id) {
- H2BUGF(infof(data, "DONE the pause stream (%u)", http->stream_id));
- httpc->pause_stream_id = 0;
- }
- if(premature || (!http->closed && http->stream_id)) {
- /* RST_STREAM */
- set_transfer(httpc, data); /* set the transfer */
- H2BUGF(infof(data, "RST stream %u", http->stream_id));
- if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE,
- http->stream_id, NGHTTP2_STREAM_CLOSED))
- (void)nghttp2_session_send(httpc->h2);
- }
-
- if(data->state.drain)
- drained_transfer(data, httpc);
-
- /* -1 means unassigned and 0 means cleared */
- if(http->stream_id > 0) {
- int rv = nghttp2_session_set_stream_user_data(httpc->h2,
- http->stream_id, 0);
- if(rv) {
- infof(data, "http/2: failed to clear user_data for stream %u",
- http->stream_id);
- DEBUGASSERT(0);
- }
- set_transfer(httpc, NULL);
- http->stream_id = 0;
- }
-}
-
/*
- * Initialize nghttp2 for a Curl connection
- */
-static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
-{
- if(!conn->proto.httpc.h2) {
- int rc;
- nghttp2_session_callbacks *callbacks;
-
- conn->proto.httpc.inbuf = malloc(H2_BUFSIZE);
- if(!conn->proto.httpc.inbuf)
- return CURLE_OUT_OF_MEMORY;
-
- rc = nghttp2_session_callbacks_new(&callbacks);
-
- if(rc) {
- failf(data, "Couldn't initialize nghttp2 callbacks");
- return CURLE_OUT_OF_MEMORY; /* most likely at least */
- }
-
- /* nghttp2_send_callback */
- nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
- /* nghttp2_on_frame_recv_callback */
- nghttp2_session_callbacks_set_on_frame_recv_callback
- (callbacks, on_frame_recv);
- /* nghttp2_on_data_chunk_recv_callback */
- nghttp2_session_callbacks_set_on_data_chunk_recv_callback
- (callbacks, on_data_chunk_recv);
- /* nghttp2_on_stream_close_callback */
- nghttp2_session_callbacks_set_on_stream_close_callback
- (callbacks, on_stream_close);
- /* nghttp2_on_begin_headers_callback */
- nghttp2_session_callbacks_set_on_begin_headers_callback
- (callbacks, on_begin_headers);
- /* nghttp2_on_header_callback */
- nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);
-
- nghttp2_session_callbacks_set_error_callback(callbacks, error_callback);
-
- /* The nghttp2 session is not yet setup, do it */
- rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn);
-
- nghttp2_session_callbacks_del(callbacks);
-
- if(rc) {
- failf(data, "Couldn't initialize nghttp2");
- return CURLE_OUT_OF_MEMORY; /* most likely at least */
- }
- }
- return CURLE_OK;
-}
-
-/*
- * Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
+ * Append headers to ask for an HTTP1.1 to HTTP2 upgrade.
*/
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
struct Curl_easy *data)
{
CURLcode result;
- ssize_t binlen;
char *base64;
size_t blen;
- struct connectdata *conn = data->conn;
struct SingleRequest *k = &data->req;
- uint8_t *binsettings = conn->proto.httpc.binsettings;
- struct http_conn *httpc = &conn->proto.httpc;
+ uint8_t binsettings[H2_BINSETTINGS_LEN];
+ size_t binlen; /* length of the binsettings data */
- populate_settings(data, httpc);
-
- /* this returns number of bytes it wrote */
- binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
- httpc->local_settings,
- httpc->local_settings_num);
+ binlen = populate_binsettings(binsettings, data);
if(binlen <= 0) {
failf(data, "nghttp2 unexpectedly failed on pack_settings_payload");
Curl_dyn_free(req);
return CURLE_FAILED_INIT;
}
- conn->proto.httpc.binlen = binlen;
result = Curl_base64url_encode((const char *)binsettings, binlen,
&base64, &blen);
@@ -1371,213 +1550,124 @@
NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
free(base64);
- k->upgr101 = UPGR101_REQUESTED;
+ k->upgr101 = UPGR101_H2;
return result;
}
-/*
- * Returns nonzero if current HTTP/2 session should be closed.
- */
-static int should_close_session(struct http_conn *httpc)
+static CURLcode http2_data_done_send(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- return httpc->drain_total == 0 && !nghttp2_session_want_read(httpc->h2) &&
- !nghttp2_session_want_write(httpc->h2);
-}
-
-/*
- * h2_process_pending_input() processes pending input left in
- * httpc->inbuf. Then, call h2_session_send() to send pending data.
- * This function returns 0 if it succeeds, or -1 and error code will
- * be assigned to *err.
- */
-static int h2_process_pending_input(struct Curl_easy *data,
- struct http_conn *httpc,
- CURLcode *err)
-{
- ssize_t nread;
- char *inbuf;
- ssize_t rv;
-
- nread = httpc->inbuflen - httpc->nread_inbuf;
- inbuf = httpc->inbuf + httpc->nread_inbuf;
-
- set_transfer(httpc, data); /* set the transfer */
- rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
- if(rv < 0) {
- failf(data,
- "h2_process_pending_input: nghttp2_session_mem_recv() returned "
- "%zd:%s", rv, nghttp2_strerror((int)rv));
- *err = CURLE_RECV_ERROR;
- return -1;
- }
-
- if(nread == rv) {
- H2BUGF(infof(data,
- "h2_process_pending_input: All data in connection buffer "
- "processed"));
- httpc->inbuflen = 0;
- httpc->nread_inbuf = 0;
- }
- else {
- httpc->nread_inbuf += rv;
- H2BUGF(infof(data,
- "h2_process_pending_input: %zu bytes left in connection "
- "buffer",
- httpc->inbuflen - httpc->nread_inbuf));
- }
-
- rv = h2_session_send(data, httpc->h2);
- if(rv) {
- *err = CURLE_SEND_ERROR;
- return -1;
- }
-
- if(nghttp2_session_check_request_allowed(httpc->h2) == 0) {
- /* No more requests are allowed in the current session, so
- the connection may not be reused. This is set when a
- GOAWAY frame has been received or when the limit of stream
- identifiers has been reached. */
- connclose(data->conn, "http/2: No new requests allowed");
- }
-
- if(should_close_session(httpc)) {
- struct HTTP *stream = data->req.p.http;
- H2BUGF(infof(data,
- "h2_process_pending_input: nothing to do in this session"));
- if(stream->error)
- *err = CURLE_HTTP2;
- else {
- /* not an error per se, but should still close the connection */
- connclose(data->conn, "GOAWAY received");
- *err = CURLE_OK;
- }
- return -1;
- }
- return 0;
-}
-
-/*
- * Called from transfer.c:done_sending when we stop uploading.
- */
-CURLcode Curl_http2_done_sending(struct Curl_easy *data,
- struct connectdata *conn)
-{
+ struct cf_h2_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
- if((conn->handler == &Curl_handler_http2_ssl) ||
- (conn->handler == &Curl_handler_http2)) {
- /* make sure this is only attempted for HTTP/2 transfers */
- struct HTTP *stream = data->req.p.http;
- struct http_conn *httpc = &conn->proto.httpc;
- nghttp2_session *h2 = httpc->h2;
+ if(!ctx || !ctx->h2 || !stream)
+ goto out;
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] data done send", stream->id));
+ if(!stream->send_closed) {
+ stream->send_closed = TRUE;
if(stream->upload_left) {
- /* If the stream still thinks there's data left to upload. */
-
- stream->upload_left = 0; /* DONE! */
-
+ /* we now know that everything that is buffered is all there is. */
+ stream->upload_left = Curl_bufq_len(&stream->sendbuf);
/* resume sending here to trigger the callback to get called again so
that it can signal EOF to nghttp2 */
- (void)nghttp2_session_resume_data(h2, stream->stream_id);
- (void)h2_process_pending_input(data, httpc, &result);
- }
-
- /* If nghttp2 still has pending frames unsent */
- if(nghttp2_session_want_write(h2)) {
- struct SingleRequest *k = &data->req;
- int rv;
-
- H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)", data));
-
- /* and attempt to send the pending frames */
- rv = h2_session_send(data, h2);
- if(rv)
- result = CURLE_SEND_ERROR;
-
- if(nghttp2_session_want_write(h2)) {
- /* re-set KEEP_SEND to make sure we are called again */
- k->keepon |= KEEP_SEND;
- }
+ (void)nghttp2_session_resume_data(ctx->h2, stream->id);
+ drain_stream(cf, data, stream);
}
}
+
+out:
return result;
}
-static ssize_t http2_handle_stream_close(struct connectdata *conn,
+static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
struct Curl_easy *data,
- struct HTTP *stream, CURLcode *err)
+ struct stream_ctx *stream,
+ CURLcode *err)
{
- struct http_conn *httpc = &conn->proto.httpc;
+ ssize_t rv = 0;
- if(httpc->pause_stream_id == stream->stream_id) {
- httpc->pause_stream_id = 0;
- }
-
- drained_transfer(data, httpc);
-
- if(httpc->pause_stream_id == 0) {
- if(h2_process_pending_input(data, httpc, err) != 0) {
- return -1;
- }
- }
-
- DEBUGASSERT(data->state.drain == 0);
-
- /* Reset to FALSE to prevent infinite loop in readwrite_data function. */
- stream->closed = FALSE;
if(stream->error == NGHTTP2_REFUSED_STREAM) {
- H2BUGF(infof(data, "REFUSED_STREAM (%u), try again on a new connection",
- stream->stream_id));
- connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] REFUSED_STREAM, try again on a new "
+ "connection", stream->id));
+ connclose(cf->conn, "REFUSED_STREAM"); /* don't use this anymore */
data->state.refused_stream = TRUE;
- *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
+ *err = CURLE_SEND_ERROR; /* trigger Curl_retry_request() later */
return -1;
}
else if(stream->error != NGHTTP2_NO_ERROR) {
failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %u)",
- stream->stream_id, nghttp2_http2_strerror(stream->error),
+ stream->id, nghttp2_http2_strerror(stream->error),
stream->error);
*err = CURLE_HTTP2_STREAM;
return -1;
}
+ else if(stream->reset) {
+ failf(data, "HTTP/2 stream %u was reset", stream->id);
+ *err = stream->bodystarted? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
+ return -1;
+ }
if(!stream->bodystarted) {
failf(data, "HTTP/2 stream %u was closed cleanly, but before getting "
" all response header fields, treated as error",
- stream->stream_id);
+ stream->id);
*err = CURLE_HTTP2_STREAM;
return -1;
}
- if(Curl_dyn_len(&stream->trailer_recvbuf)) {
- char *trailp = Curl_dyn_ptr(&stream->trailer_recvbuf);
- char *lf;
+ if(Curl_dynhds_count(&stream->resp_trailers)) {
+ struct dynhds_entry *e;
+ struct dynbuf dbuf;
+ size_t i;
- do {
- size_t len = 0;
- CURLcode result;
- /* each trailer line ends with a newline */
- lf = strchr(trailp, '\n');
- if(!lf)
+ *err = CURLE_OK;
+ Curl_dyn_init(&dbuf, DYN_TRAILERS);
+ for(i = 0; i < Curl_dynhds_count(&stream->resp_trailers); ++i) {
+ e = Curl_dynhds_getn(&stream->resp_trailers, i);
+ if(!e)
break;
- len = lf + 1 - trailp;
-
- Curl_debug(data, CURLINFO_HEADER_IN, trailp, len);
- /* pass the trailers one by one to the callback */
- result = Curl_client_write(data, CLIENTWRITE_HEADER, trailp, len);
- if(result) {
- *err = result;
- return -1;
- }
- trailp = ++lf;
- } while(lf);
+ Curl_dyn_reset(&dbuf);
+ *err = Curl_dyn_addf(&dbuf, "%.*s: %.*s\x0d\x0a",
+ (int)e->namelen, e->name,
+ (int)e->valuelen, e->value);
+ if(*err)
+ break;
+ Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&dbuf),
+ Curl_dyn_len(&dbuf));
+ *err = Curl_client_write(data, CLIENTWRITE_HEADER|CLIENTWRITE_TRAILER,
+ Curl_dyn_ptr(&dbuf), Curl_dyn_len(&dbuf));
+ if(*err)
+ break;
+ }
+ Curl_dyn_free(&dbuf);
+ if(*err)
+ goto out;
}
stream->close_handled = TRUE;
+ *err = CURLE_OK;
+ rv = 0;
- H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close"));
- return 0;
+out:
+ DEBUGF(LOG_CF(data, cf, "handle_stream_close -> %zd, %d", rv, *err));
+ return rv;
+}
+
+static int sweight_wanted(const struct Curl_easy *data)
+{
+ /* 0 weight is not set by user and we take the nghttp2 default one */
+ return data->set.priority.weight?
+ data->set.priority.weight : NGHTTP2_DEFAULT_WEIGHT;
+}
+
+static int sweight_in_effect(const struct Curl_easy *data)
+{
+ /* 0 weight is not set by user and we take the nghttp2 default one */
+ return data->state.priority.weight?
+ data->state.priority.weight : NGHTTP2_DEFAULT_WEIGHT;
}
/*
@@ -1589,367 +1679,303 @@
static void h2_pri_spec(struct Curl_easy *data,
nghttp2_priority_spec *pri_spec)
{
- struct HTTP *depstream = (data->set.stream_depends_on?
- data->set.stream_depends_on->req.p.http:NULL);
- int32_t depstream_id = depstream? depstream->stream_id:0;
- nghttp2_priority_spec_init(pri_spec, depstream_id, data->set.stream_weight,
- data->set.stream_depends_e);
- data->state.stream_weight = data->set.stream_weight;
- data->state.stream_depends_e = data->set.stream_depends_e;
- data->state.stream_depends_on = data->set.stream_depends_on;
+ struct Curl_data_priority *prio = &data->set.priority;
+ struct stream_ctx *depstream = H2_STREAM_CTX(prio->parent);
+ int32_t depstream_id = depstream? depstream->id:0;
+ nghttp2_priority_spec_init(pri_spec, depstream_id,
+ sweight_wanted(data),
+ data->set.priority.exclusive);
+ data->state.priority = *prio;
}
/*
- * h2_session_send() checks if there's been an update in the priority /
+ * Check if there's been an update in the priority /
* dependency settings and if so it submits a PRIORITY frame with the updated
* info.
+ * Flush any out data pending in the network buffer.
*/
-static int h2_session_send(struct Curl_easy *data,
- nghttp2_session *h2)
+static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct HTTP *stream = data->req.p.http;
- struct http_conn *httpc = &data->conn->proto.httpc;
- set_transfer(httpc, data);
- if((data->set.stream_weight != data->state.stream_weight) ||
- (data->set.stream_depends_e != data->state.stream_depends_e) ||
- (data->set.stream_depends_on != data->state.stream_depends_on) ) {
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ int rv = 0;
+
+ 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)) ) {
/* send new weight and/or dependency */
nghttp2_priority_spec pri_spec;
- int rv;
h2_pri_spec(data, &pri_spec);
-
- H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)",
- stream->stream_id, data));
- DEBUGASSERT(stream->stream_id != -1);
- rv = nghttp2_submit_priority(h2, NGHTTP2_FLAG_NONE, stream->stream_id,
- &pri_spec);
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] Queuing PRIORITY",
+ stream->id));
+ DEBUGASSERT(stream->id != -1);
+ rv = nghttp2_submit_priority(ctx->h2, NGHTTP2_FLAG_NONE,
+ stream->id, &pri_spec);
if(rv)
- return rv;
+ goto out;
}
- return nghttp2_session_send(h2);
+ ctx->nw_out_blocked = 0;
+ while(!rv && !ctx->nw_out_blocked && nghttp2_session_want_write(ctx->h2))
+ rv = nghttp2_session_send(ctx->h2);
+
+out:
+ if(nghttp2_is_fatal(rv)) {
+ DEBUGF(LOG_CF(data, cf, "nghttp2_session_send error (%s)%d",
+ nghttp2_strerror(rv), rv));
+ return CURLE_SEND_ERROR;
+ }
+ return nw_out_flush(cf, data);
}
-static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
- char *mem, size_t len, CURLcode *err)
+static ssize_t stream_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err)
{
- ssize_t nread;
- struct connectdata *conn = data->conn;
- struct http_conn *httpc = &conn->proto.httpc;
- struct HTTP *stream = data->req.p.http;
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ ssize_t nread = -1;
- (void)sockindex; /* we always do HTTP2 on sockindex 0 */
-
- if(should_close_session(httpc)) {
- H2BUGF(infof(data,
- "http2_recv: nothing to do in this session"));
- if(conn->bits.close) {
- /* already marked for closure, return OK and we're done */
- *err = CURLE_OK;
- return 0;
- }
- *err = CURLE_HTTP2;
- return -1;
+ *err = CURLE_AGAIN;
+ if(!Curl_bufq_is_empty(&stream->recvbuf)) {
+ nread = Curl_bufq_read(&stream->recvbuf,
+ (unsigned char *)buf, len, err);
+ DEBUGF(LOG_CF(data, cf, "recvbuf read(len=%zu) -> %zd, %d",
+ len, nread, *err));
+ if(nread < 0)
+ goto out;
+ DEBUGASSERT(nread > 0);
}
- /* Nullify here because we call nghttp2_session_send() and they
- might refer to the old buffer. */
- stream->upload_mem = NULL;
- stream->upload_len = 0;
-
- /*
- * At this point 'stream' is just in the Curl_easy the connection
- * identifies as its owner at this time.
- */
-
- if(stream->bodystarted &&
- stream->nread_header_recvbuf < Curl_dyn_len(&stream->header_recvbuf)) {
- /* If there is header data pending for this stream to return, do that */
- size_t left =
- Curl_dyn_len(&stream->header_recvbuf) - stream->nread_header_recvbuf;
- size_t ncopy = CURLMIN(len, left);
- memcpy(mem, Curl_dyn_ptr(&stream->header_recvbuf) +
- stream->nread_header_recvbuf, ncopy);
- stream->nread_header_recvbuf += ncopy;
-
- H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf",
- (int)ncopy));
- return ncopy;
- }
-
- H2BUGF(infof(data, "http2_recv: easy %p (stream %u) win %u/%u",
- data, stream->stream_id,
- nghttp2_session_get_local_window_size(httpc->h2),
- nghttp2_session_get_stream_local_window_size(httpc->h2,
- stream->stream_id)
- ));
-
- if((data->state.drain) && stream->memlen) {
- H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u (%p => %p)",
- stream->memlen, stream->stream_id,
- stream->mem, mem));
- if(mem != stream->mem) {
- /* if we didn't get the same buffer this time, we must move the data to
- the beginning */
- memmove(mem, stream->mem, stream->memlen);
- stream->len = len - stream->memlen;
- stream->mem = mem;
+ if(nread < 0) {
+ if(stream->closed) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] returning CLOSE", stream->id));
+ nread = http2_handle_stream_close(cf, data, stream, err);
}
- if(httpc->pause_stream_id == stream->stream_id && !stream->pausedata) {
- /* We have paused nghttp2, but we have no pause data (see
- on_data_chunk_recv). */
- httpc->pause_stream_id = 0;
- if(h2_process_pending_input(data, httpc, err) != 0) {
- return -1;
- }
+ else if(stream->reset ||
+ (ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) ||
+ (ctx->goaway && ctx->last_stream_id < stream->id)) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] returning ERR", stream->id));
+ *err = stream->bodystarted? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
+ nread = -1;
}
}
- else if(stream->pausedata) {
- DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
- nread = CURLMIN(len, stream->pauselen);
- memcpy(mem, stream->pausedata, nread);
-
- stream->pausedata += nread;
- stream->pauselen -= nread;
-
- if(stream->pauselen == 0) {
- H2BUGF(infof(data, "Unpaused by stream %u", stream->stream_id));
- DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
- httpc->pause_stream_id = 0;
-
- stream->pausedata = NULL;
- stream->pauselen = 0;
-
- /* When NGHTTP2_ERR_PAUSE is returned from
- data_source_read_callback, we might not process DATA frame
- fully. Calling nghttp2_session_mem_recv() again will
- continue to process DATA frame, but if there is no incoming
- frames, then we have to call it again with 0-length data.
- Without this, on_stream_close callback will not be called,
- and stream could be hanged. */
- if(h2_process_pending_input(data, httpc, err) != 0) {
- return -1;
- }
- }
- H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u",
- nread, stream->stream_id));
- return nread;
- }
- else if(httpc->pause_stream_id) {
- /* If a stream paused nghttp2_session_mem_recv previously, and has
- not processed all data, it still refers to the buffer in
- nghttp2_session. If we call nghttp2_session_mem_recv(), we may
- overwrite that buffer. To avoid that situation, just return
- here with CURLE_AGAIN. This could be busy loop since data in
- socket is not read. But it seems that usually streams are
- notified with its drain property, and socket is read again
- quickly. */
- if(stream->closed)
- /* closed overrides paused */
- return 0;
- H2BUGF(infof(data, "stream %u is paused, pause id: %u",
- stream->stream_id, httpc->pause_stream_id));
+ else if(nread == 0) {
*err = CURLE_AGAIN;
- return -1;
+ nread = -1;
}
- else {
- /* remember where to store incoming data for this stream and how big the
- buffer is */
- stream->mem = mem;
- stream->len = len;
- stream->memlen = 0;
- if(httpc->inbuflen == 0) {
- nread = ((Curl_recv *)httpc->recv_underlying)(
- data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, err);
+out:
+ DEBUGF(LOG_CF(data, cf, "stream_recv(len=%zu) -> %zd, %d",
+ len, nread, *err));
+ return nread;
+}
- if(nread == -1) {
- if(*err != CURLE_AGAIN)
- failf(data, "Failed receiving HTTP2 data");
- else if(stream->closed)
- /* received when the stream was already closed! */
- return http2_handle_stream_close(conn, data, stream, err);
+static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream;
+ CURLcode result = CURLE_OK;
+ ssize_t nread;
- return -1;
+ /* Process network input buffer fist */
+ if(!Curl_bufq_is_empty(&ctx->inbufq)) {
+ DEBUGF(LOG_CF(data, cf, "Process %zu bytes in connection buffer",
+ Curl_bufq_len(&ctx->inbufq)));
+ if(h2_process_pending_input(cf, data, &result) < 0)
+ return result;
+ }
+
+ /* Receive data from the "lower" filters, e.g. network until
+ * it is time to stop due to connection close or us not processing
+ * all network input */
+ while(!ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) {
+ stream = H2_STREAM_CTX(data);
+ if(stream && (stream->closed || Curl_bufq_is_full(&stream->recvbuf))) {
+ /* We would like to abort here and stop processing, so that
+ * the transfer loop can handle the data/close here. However,
+ * this may leave data in underlying buffers that will not
+ * be consumed. */
+ if(!cf->next || !cf->next->cft->has_data_pending(cf->next, data))
+ break;
+ }
+
+ nread = Curl_bufq_slurp(&ctx->inbufq, nw_in_reader, cf, &result);
+ /* DEBUGF(LOG_CF(data, cf, "read %zu bytes nw data -> %zd, %d",
+ Curl_bufq_len(&ctx->inbufq), nread, result)); */
+ if(nread < 0) {
+ if(result != CURLE_AGAIN) {
+ failf(data, "Failed receiving HTTP2 data: %d(%s)", result,
+ curl_easy_strerror(result));
+ return result;
}
+ break;
+ }
+ else if(nread == 0) {
+ ctx->conn_closed = TRUE;
+ break;
+ }
- if(nread == 0) {
- if(!stream->closed) {
- /* This will happen when the server or proxy server is SIGKILLed
- during data transfer. We should emit an error since our data
- received may be incomplete. */
- failf(data, "HTTP/2 stream %u was not closed cleanly before"
- " end of the underlying stream",
- stream->stream_id);
- *err = CURLE_HTTP2_STREAM;
- return -1;
- }
+ if(h2_process_pending_input(cf, data, &result))
+ return result;
+ }
- H2BUGF(infof(data, "end of stream"));
- *err = CURLE_OK;
- return 0;
- }
+ if(ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) {
+ connclose(cf->conn, "GOAWAY received");
+ }
- H2BUGF(infof(data, "nread=%zd", nread));
+ return CURLE_OK;
+}
- httpc->inbuflen = nread;
+static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ ssize_t nread = -1;
+ CURLcode result;
+ struct cf_call_data save;
- DEBUGASSERT(httpc->nread_inbuf == 0);
+ CF_DATA_SAVE(save, cf, data);
+
+ nread = stream_recv(cf, data, buf, len, err);
+ if(nread < 0 && *err != CURLE_AGAIN)
+ goto out;
+
+ if(nread < 0) {
+ *err = h2_progress_ingress(cf, data);
+ if(*err)
+ goto out;
+
+ nread = stream_recv(cf, data, buf, len, err);
+ }
+
+ if(nread > 0) {
+ size_t data_consumed = (size_t)nread;
+ /* Now that we transferred this to the upper layer, we report
+ * the actual amount of DATA consumed to the H2 session, so
+ * that it adjusts stream flow control */
+ if(stream->resp_hds_len >= data_consumed) {
+ stream->resp_hds_len -= data_consumed; /* no DATA */
}
else {
- nread = httpc->inbuflen - httpc->nread_inbuf;
- (void)nread; /* silence warning, used in debug */
- H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd",
- nread));
+ if(stream->resp_hds_len) {
+ data_consumed -= stream->resp_hds_len;
+ stream->resp_hds_len = 0;
+ }
+ if(data_consumed) {
+ nghttp2_session_consume(ctx->h2, stream->id, data_consumed);
+ }
}
- if(h2_process_pending_input(data, httpc, err))
- return -1;
+ if(stream->closed) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] closed stream, set drain",
+ stream->id));
+ drain_stream(cf, data, stream);
+ }
}
- if(stream->memlen) {
- ssize_t retlen = stream->memlen;
- H2BUGF(infof(data, "http2_recv: returns %zd for stream %u",
- retlen, stream->stream_id));
- stream->memlen = 0;
- if(httpc->pause_stream_id == stream->stream_id) {
- /* data for this stream is returned now, but this stream caused a pause
- already so we need it called again asap */
- H2BUGF(infof(data, "Data returned for PAUSED stream %u",
- stream->stream_id));
- }
- else if(!stream->closed) {
- drained_transfer(data, httpc);
- }
- else
- /* this stream is closed, trigger a another read ASAP to detect that */
- Curl_expire(data, 0, EXPIRE_RUN_NOW);
-
- return retlen;
+out:
+ result = h2_progress_egress(cf, data);
+ if(result && result != CURLE_AGAIN) {
+ *err = result;
+ nread = -1;
}
- if(stream->closed)
- return http2_handle_stream_close(conn, data, stream, err);
- *err = CURLE_AGAIN;
- H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u",
- stream->stream_id));
- return -1;
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_recv(len=%zu) -> %zd %d, "
+ "buffered=%zu, window=%d/%d, connection %d/%d",
+ stream->id, len, nread, *err,
+ Curl_bufq_len(&stream->recvbuf),
+ nghttp2_session_get_stream_effective_recv_data_length(
+ ctx->h2, stream->id),
+ nghttp2_session_get_stream_effective_local_window_size(
+ ctx->h2, stream->id),
+ nghttp2_session_get_local_window_size(ctx->h2),
+ HTTP2_HUGE_WINDOW_SIZE));
+
+ CF_DATA_RESTORE(cf, save);
+ return nread;
}
-static ssize_t http2_send(struct Curl_easy *data, int sockindex,
- const void *mem, size_t len, CURLcode *err)
+static ssize_t h2_submit(struct stream_ctx **pstream,
+ struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err)
{
- /*
- * Currently, we send request in this function, but this function is also
- * used to send request body. It would be nice to add dedicated function for
- * request.
- */
- int rv;
- struct connectdata *conn = data->conn;
- struct http_conn *httpc = &conn->proto.httpc;
- struct HTTP *stream = data->req.p.http;
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = NULL;
+ struct h1_req_parser h1;
+ struct dynhds h2_headers;
nghttp2_nv *nva = NULL;
- size_t nheader;
+ const void *body = NULL;
+ size_t nheader, bodylen, i;
nghttp2_data_provider data_prd;
int32_t stream_id;
- nghttp2_session *h2 = httpc->h2;
nghttp2_priority_spec pri_spec;
- CURLcode result;
- struct h2h3req *hreq;
+ ssize_t nwritten;
- (void)sockindex;
+ Curl_h1_req_parse_init(&h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
+ Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
- H2BUGF(infof(data, "http2_send len=%zu", len));
-
- if(stream->stream_id != -1) {
- if(stream->close_handled) {
- infof(data, "stream %u closed", stream->stream_id);
- *err = CURLE_HTTP2_STREAM;
- return -1;
- }
- else if(stream->closed) {
- return http2_handle_stream_close(conn, data, stream, err);
- }
- /* If stream_id != -1, we have dispatched request HEADERS, and now
- are going to send or sending request body in DATA frame */
- stream->upload_mem = mem;
- stream->upload_len = len;
- rv = nghttp2_session_resume_data(h2, stream->stream_id);
- if(nghttp2_is_fatal(rv)) {
- *err = CURLE_SEND_ERROR;
- return -1;
- }
- rv = h2_session_send(data, h2);
- if(nghttp2_is_fatal(rv)) {
- *err = CURLE_SEND_ERROR;
- return -1;
- }
- len -= stream->upload_len;
-
- /* Nullify here because we call nghttp2_session_send() and they
- might refer to the old buffer. */
- stream->upload_mem = NULL;
- stream->upload_len = 0;
-
- if(should_close_session(httpc)) {
- H2BUGF(infof(data, "http2_send: nothing to do in this session"));
- *err = CURLE_HTTP2;
- return -1;
- }
-
- if(stream->upload_left) {
- /* we are sure that we have more data to send here. Calling the
- following API will make nghttp2_session_want_write() return
- nonzero if remote window allows it, which then libcurl checks
- socket is writable or not. See http2_perform_getsock(). */
- nghttp2_session_resume_data(h2, stream->stream_id);
- }
-
-#ifdef DEBUG_HTTP2
- if(!len) {
- infof(data, "http2_send: easy %p (stream %u) win %u/%u",
- data, stream->stream_id,
- nghttp2_session_get_remote_window_size(httpc->h2),
- nghttp2_session_get_stream_remote_window_size(httpc->h2,
- stream->stream_id)
- );
-
- }
- infof(data, "http2_send returns %zu for stream %u", len,
- stream->stream_id);
-#endif
- return len;
+ *err = http2_data_setup(cf, data, &stream);
+ if(*err) {
+ nwritten = -1;
+ goto out;
}
- result = Curl_pseudo_headers(data, mem, len, &hreq);
- if(result) {
- *err = result;
- return -1;
- }
- nheader = hreq->entries;
+ nwritten = Curl_h1_req_parse_read(&h1, buf, len, NULL, 0, err);
+ if(nwritten < 0)
+ goto out;
+ DEBUGASSERT(h1.done);
+ DEBUGASSERT(h1.req);
+ *err = Curl_http_req_to_h2(&h2_headers, h1.req, data);
+ if(*err) {
+ nwritten = -1;
+ goto out;
+ }
+
+ nheader = Curl_dynhds_count(&h2_headers);
nva = malloc(sizeof(nghttp2_nv) * nheader);
if(!nva) {
- Curl_pseudo_free(hreq);
*err = CURLE_OUT_OF_MEMORY;
- return -1;
+ nwritten = -1;
+ goto out;
}
- else {
- unsigned int i;
- for(i = 0; i < nheader; i++) {
- nva[i].name = (unsigned char *)hreq->header[i].name;
- nva[i].namelen = hreq->header[i].namelen;
- nva[i].value = (unsigned char *)hreq->header[i].value;
- nva[i].valuelen = hreq->header[i].valuelen;
- nva[i].flags = NGHTTP2_NV_FLAG_NONE;
+
+ for(i = 0; i < nheader; ++i) {
+ struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
+ nva[i].name = (unsigned char *)e->name;
+ nva[i].namelen = e->namelen;
+ nva[i].value = (unsigned char *)e->value;
+ nva[i].valuelen = e->valuelen;
+ nva[i].flags = NGHTTP2_NV_FLAG_NONE;
+ }
+
+#define MAX_ACC 60000 /* <64KB to account for some overhead */
+ {
+ size_t acc = 0;
+
+ for(i = 0; i < nheader; ++i) {
+ acc += nva[i].namelen + nva[i].valuelen;
+
+ infof(data, "h2 [%.*s: %.*s]",
+ (int)nva[i].namelen, nva[i].name,
+ (int)nva[i].valuelen, nva[i].value);
}
- Curl_pseudo_free(hreq);
+
+ if(acc > MAX_ACC) {
+ infof(data, "http_request: Warning: The cumulative length of all "
+ "headers exceeds %d bytes and that could cause the "
+ "stream to be rejected.", MAX_ACC);
+ }
}
h2_pri_spec(data, &pri_spec);
- H2BUGF(infof(data, "http2_send request allowed %d (easy handle %p)",
- nghttp2_session_check_request_allowed(h2), (void *)data));
+ DEBUGF(LOG_CF(data, cf, "send request allowed %d",
+ nghttp2_session_check_request_allowed(ctx->h2)));
switch(data->state.httpreq) {
case HTTPREQ_POST:
@@ -1960,220 +1986,345 @@
stream->upload_left = data->state.infilesize;
else
/* data sending without specifying the data amount up front */
- stream->upload_left = -1; /* unknown, but not zero */
+ stream->upload_left = -1; /* unknown */
- data_prd.read_callback = data_source_read_callback;
+ data_prd.read_callback = req_body_read_callback;
data_prd.source.ptr = NULL;
- stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
+ stream_id = nghttp2_submit_request(ctx->h2, &pri_spec, nva, nheader,
&data_prd, data);
break;
default:
- stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
+ stream->upload_left = 0; /* no request body */
+ stream_id = nghttp2_submit_request(ctx->h2, &pri_spec, nva, nheader,
NULL, data);
}
Curl_safefree(nva);
if(stream_id < 0) {
- H2BUGF(infof(data,
- "http2_send() nghttp2_submit_request error (%s)%u",
- nghttp2_strerror(stream_id), stream_id));
+ DEBUGF(LOG_CF(data, cf, "send: nghttp2_submit_request error (%s)%u",
+ nghttp2_strerror(stream_id), stream_id));
*err = CURLE_SEND_ERROR;
- return -1;
+ nwritten = -1;
+ goto out;
}
- infof(data, "Using Stream ID: %u (easy handle %p)",
- stream_id, (void *)data);
- stream->stream_id = stream_id;
-
- rv = h2_session_send(data, h2);
- if(rv) {
- H2BUGF(infof(data,
- "http2_send() nghttp2_session_send error (%s)%d",
- nghttp2_strerror(rv), rv));
-
- *err = CURLE_SEND_ERROR;
- return -1;
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) submit %s",
+ stream_id, len, data->state.url));
+ infof(data, "Using Stream ID: %u", stream_id);
+ stream->id = stream_id;
+ stream->local_window_size = H2_STREAM_WINDOW_SIZE;
+ if(data->set.max_recv_speed) {
+ /* We are asked to only receive `max_recv_speed` bytes per second.
+ * Let's limit our stream window size around that, otherwise the server
+ * will send in large bursts only. We make the window 50% larger to
+ * allow for data in flight and avoid stalling. */
+ curl_off_t n = (((data->set.max_recv_speed - 1) / H2_CHUNK_SIZE) + 1);
+ n += CURLMAX((n/2), 1);
+ if(n < (H2_STREAM_WINDOW_SIZE / H2_CHUNK_SIZE) &&
+ n < (UINT_MAX / H2_CHUNK_SIZE)) {
+ stream->local_window_size = (uint32_t)n * H2_CHUNK_SIZE;
+ }
}
- if(should_close_session(httpc)) {
- H2BUGF(infof(data, "http2_send: nothing to do in this session"));
- *err = CURLE_HTTP2;
- return -1;
+ body = (const char *)buf + nwritten;
+ bodylen = len - nwritten;
+
+ if(bodylen) {
+ /* We have request body to send in DATA frame */
+ ssize_t n = Curl_bufq_write(&stream->sendbuf, body, bodylen, err);
+ if(n < 0) {
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ goto out;
+ }
+ nwritten += n;
}
- /* If whole HEADERS frame was sent off to the underlying socket, the nghttp2
- library calls data_source_read_callback. But only it found that no data
- available, so it deferred the DATA transmission. Which means that
- nghttp2_session_want_write() returns 0 on http2_perform_getsock(), which
- results that no writable socket check is performed. To workaround this,
- we issue nghttp2_session_resume_data() here to bring back DATA
- transmission from deferred state. */
- nghttp2_session_resume_data(h2, stream->stream_id);
-
- return len;
+out:
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] submit -> %zd, %d",
+ stream? stream->id : -1, nwritten, *err));
+ *pstream = stream;
+ Curl_h1_req_parse_free(&h1);
+ Curl_dynhds_free(&h2_headers);
+ return nwritten;
}
-CURLcode Curl_http2_setup(struct Curl_easy *data,
- struct connectdata *conn)
+static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err)
{
- CURLcode result;
- struct http_conn *httpc = &conn->proto.httpc;
- struct HTTP *stream = data->req.p.http;
-
- DEBUGASSERT(data->state.buffer);
-
- stream->stream_id = -1;
-
- Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS);
- Curl_dyn_init(&stream->trailer_recvbuf, DYN_H2_TRAILERS);
-
- stream->upload_left = 0;
- stream->upload_mem = NULL;
- stream->upload_len = 0;
- stream->mem = data->state.buffer;
- stream->len = data->set.buffer_size;
-
- multi_connchanged(data->multi);
- /* below this point only connection related inits are done, which only needs
- to be done once per connection */
-
- if((conn->handler == &Curl_handler_http2_ssl) ||
- (conn->handler == &Curl_handler_http2))
- return CURLE_OK; /* already done */
-
- if(conn->handler->flags & PROTOPT_SSL)
- conn->handler = &Curl_handler_http2_ssl;
- else
- conn->handler = &Curl_handler_http2;
-
- result = http2_init(data, conn);
- if(result) {
- Curl_dyn_free(&stream->header_recvbuf);
- return result;
- }
-
- infof(data, "Using HTTP2, server supports multiplexing");
-
- conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
- conn->httpversion = 20;
- conn->bundle->multiuse = BUNDLE_MULTIPLEX;
-
- httpc->inbuflen = 0;
- httpc->nread_inbuf = 0;
-
- httpc->pause_stream_id = 0;
- httpc->drain_total = 0;
-
- return CURLE_OK;
-}
-
-CURLcode Curl_http2_switched(struct Curl_easy *data,
- const char *mem, size_t nread)
-{
- CURLcode result;
- struct connectdata *conn = data->conn;
- struct http_conn *httpc = &conn->proto.httpc;
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ struct cf_call_data save;
int rv;
- struct HTTP *stream = data->req.p.http;
+ ssize_t nwritten;
+ CURLcode result;
+ int blocked = 0;
- result = Curl_http2_setup(data, conn);
- if(result)
- return result;
+ CF_DATA_SAVE(save, cf, data);
- httpc->recv_underlying = conn->recv[FIRSTSOCKET];
- httpc->send_underlying = conn->send[FIRSTSOCKET];
- conn->recv[FIRSTSOCKET] = http2_recv;
- conn->send[FIRSTSOCKET] = http2_send;
-
- if(data->req.upgr101 == UPGR101_RECEIVED) {
- /* stream 1 is opened implicitly on upgrade */
- stream->stream_id = 1;
- /* queue SETTINGS frame (again) */
- rv = nghttp2_session_upgrade2(httpc->h2, httpc->binsettings, httpc->binlen,
- data->state.httpreq == HTTPREQ_HEAD, NULL);
- if(rv) {
- failf(data, "nghttp2_session_upgrade2() failed: %s(%d)",
- nghttp2_strerror(rv), rv);
- return CURLE_HTTP2;
+ if(stream && stream->id != -1) {
+ if(stream->close_handled) {
+ infof(data, "stream %u closed", stream->id);
+ *err = CURLE_HTTP2_STREAM;
+ nwritten = -1;
+ goto out;
+ }
+ else if(stream->closed) {
+ nwritten = http2_handle_stream_close(cf, data, stream, err);
+ goto out;
+ }
+ else if(stream->upload_blocked_len) {
+ /* the data in `buf` has alread been submitted or added to the
+ * buffers, but have been EAGAINed on the last invocation. */
+ DEBUGASSERT(len >= stream->upload_blocked_len);
+ if(len < stream->upload_blocked_len) {
+ /* Did we get called again with a smaller `len`? This should not
+ * happend. We are not prepared to handle that. */
+ failf(data, "HTTP/2 send again with decreased length");
+ *err = CURLE_HTTP2;
+ nwritten = -1;
+ goto out;
+ }
+ nwritten = (ssize_t)stream->upload_blocked_len;
+ stream->upload_blocked_len = 0;
+ }
+ else {
+ /* If stream_id != -1, we have dispatched request HEADERS and
+ * optionally request body, and now are going to send or sending
+ * more request body in DATA frame */
+ nwritten = Curl_bufq_write(&stream->sendbuf, buf, len, err);
+ if(nwritten < 0) {
+ if(*err != CURLE_AGAIN)
+ goto out;
+ nwritten = 0;
+ }
}
- rv = nghttp2_session_set_stream_user_data(httpc->h2,
- stream->stream_id,
- data);
- if(rv) {
- infof(data, "http/2: failed to set user_data for stream %u",
- stream->stream_id);
- DEBUGASSERT(0);
+ if(!Curl_bufq_is_empty(&stream->sendbuf)) {
+ /* req body data is buffered, resume the potentially suspended stream */
+ rv = nghttp2_session_resume_data(ctx->h2, stream->id);
+ if(nghttp2_is_fatal(rv)) {
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ goto out;
+ }
}
}
else {
- populate_settings(data, httpc);
+ nwritten = h2_submit(&stream, cf, data, buf, len, err);
+ if(nwritten < 0) {
+ goto out;
+ }
+ DEBUGASSERT(stream);
+ }
- /* stream ID is unknown at this point */
- stream->stream_id = -1;
- rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE,
- httpc->local_settings,
- httpc->local_settings_num);
- if(rv) {
- failf(data, "nghttp2_submit_settings() failed: %s(%d)",
- nghttp2_strerror(rv), rv);
- return CURLE_HTTP2;
+ /* Call the nghttp2 send loop and flush to write ALL buffered data,
+ * headers and/or request body completely out to the network */
+ result = h2_progress_egress(cf, data);
+ /* if the stream has been closed in egress handling (nghttp2 does that
+ * when it does not like the headers, for example */
+ if(stream && stream->closed) {
+ nwritten = http2_handle_stream_close(cf, data, stream, err);
+ goto out;
+ }
+ else if(result == CURLE_AGAIN) {
+ blocked = 1;
+ }
+ else if(result) {
+ *err = result;
+ nwritten = -1;
+ goto out;
+ }
+ else if(stream && !Curl_bufq_is_empty(&stream->sendbuf)) {
+ /* although we wrote everything that nghttp2 wants to send now,
+ * there is data left in our stream send buffer unwritten. This may
+ * be due to the stream's HTTP/2 flow window being exhausted. */
+ blocked = 1;
+ }
+
+ if(stream && blocked) {
+ /* Unable to send all data, due to connection blocked or H2 window
+ * exhaustion. Data is left in our stream buffer, or nghttp2's internal
+ * frame buffer or our network out buffer. */
+ size_t rwin = nghttp2_session_get_stream_remote_window_size(ctx->h2,
+ stream->id);
+ if(rwin == 0) {
+ /* H2 flow window exhaustion. We need to HOLD upload until we get
+ * a WINDOW_UPDATE from the server. */
+ data->req.keepon |= KEEP_SEND_HOLD;
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] holding send as remote flow "
+ "window is exhausted", stream->id));
+ }
+
+ /* Whatever the cause, we need to return CURL_EAGAIN for this call.
+ * We have unwritten state that needs us being invoked again and EAGAIN
+ * is the only way to ensure that. */
+ stream->upload_blocked_len = nwritten;
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) BLOCK: win %u/%zu "
+ "blocked_len=%zu",
+ stream->id, len,
+ nghttp2_session_get_remote_window_size(ctx->h2), rwin,
+ nwritten));
+ *err = CURLE_AGAIN;
+ nwritten = -1;
+ goto out;
+ }
+ else if(should_close_session(ctx)) {
+ /* nghttp2 thinks this session is done. If the stream has not been
+ * closed, this is an error state for out transfer */
+ if(stream->closed) {
+ nwritten = http2_handle_stream_close(cf, data, stream, err);
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "send: nothing to do in this session"));
+ *err = CURLE_HTTP2;
+ nwritten = -1;
}
}
- rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0,
- HTTP2_HUGE_WINDOW_SIZE);
- if(rv) {
- failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
- nghttp2_strerror(rv), rv);
- return CURLE_HTTP2;
+out:
+ if(stream) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) -> %zd, %d, "
+ "upload_left=%" CURL_FORMAT_CURL_OFF_T ", "
+ "h2 windows %d-%d (stream-conn), "
+ "buffers %zu-%zu (stream-conn)",
+ stream->id, len, nwritten, *err,
+ (ssize_t)stream->upload_left,
+ nghttp2_session_get_stream_remote_window_size(
+ ctx->h2, stream->id),
+ nghttp2_session_get_remote_window_size(ctx->h2),
+ Curl_bufq_len(&stream->sendbuf),
+ Curl_bufq_len(&ctx->outbufq)));
}
-
- /* we are going to copy mem to httpc->inbuf. This is required since
- mem is part of buffer pointed by stream->mem, and callbacks
- called by nghttp2_session_mem_recv() will write stream specific
- data into stream->mem, overwriting data already there. */
- if(H2_BUFSIZE < nread) {
- failf(data, "connection buffer size is too small to store data following "
- "HTTP Upgrade response header: buflen=%d, datalen=%zu",
- H2_BUFSIZE, nread);
- return CURLE_HTTP2;
+ else {
+ DEBUGF(LOG_CF(data, cf, "cf_send(len=%zu) -> %zd, %d, "
+ "connection-window=%d, nw_send_buffer(%zu)",
+ len, nwritten, *err,
+ nghttp2_session_get_remote_window_size(ctx->h2),
+ Curl_bufq_len(&ctx->outbufq)));
}
-
- infof(data, "Copying HTTP/2 data in stream buffer to connection buffer"
- " after upgrade: len=%zu",
- nread);
-
- if(nread)
- memcpy(httpc->inbuf, mem, nread);
-
- httpc->inbuflen = nread;
-
- DEBUGASSERT(httpc->nread_inbuf == 0);
-
- if(-1 == h2_process_pending_input(data, httpc, &result))
- return CURLE_HTTP2;
-
- return CURLE_OK;
+ CF_DATA_RESTORE(cf, save);
+ return nwritten;
}
-CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause)
+static int cf_h2_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *sock)
{
- DEBUGASSERT(data);
- DEBUGASSERT(data->conn);
- /* if it isn't HTTP/2, we're done */
- if(!(data->conn->handler->protocol & PROTO_FAMILY_HTTP) ||
- !data->conn->proto.httpc.h2)
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct SingleRequest *k = &data->req;
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ int bitmap = GETSOCK_BLANK;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ sock[0] = Curl_conn_cf_get_socket(cf, data);
+
+ if(!(k->keepon & (KEEP_RECV_PAUSE|KEEP_RECV_HOLD)))
+ /* Unless paused - in an HTTP/2 connection we can basically always get a
+ frame so we should always be ready for one */
+ bitmap |= GETSOCK_READSOCK(0);
+
+ /* we're (still uploading OR the HTTP/2 layer wants to send data) AND
+ there's a window to send data in */
+ if((((k->keepon & KEEP_SENDBITS) == KEEP_SEND) ||
+ nghttp2_session_want_write(ctx->h2)) &&
+ (nghttp2_session_get_remote_window_size(ctx->h2) &&
+ nghttp2_session_get_stream_remote_window_size(ctx->h2,
+ stream->id)))
+ bitmap |= GETSOCK_WRITESOCK(0);
+
+ CF_DATA_RESTORE(cf, save);
+ return bitmap;
+}
+
+
+static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+ struct cf_call_data save;
+
+ if(cf->connected) {
+ *done = TRUE;
return CURLE_OK;
+ }
+
+ /* Connect the lower filters first */
+ if(!cf->next->connected) {
+ result = Curl_conn_cf_connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ return result;
+ }
+
+ *done = FALSE;
+
+ CF_DATA_SAVE(save, cf, data);
+ if(!ctx->h2) {
+ result = cf_h2_ctx_init(cf, data, FALSE);
+ if(result)
+ goto out;
+ }
+
+ result = h2_progress_ingress(cf, data);
+ if(result)
+ goto out;
+
+ result = h2_progress_egress(cf, data);
+ if(result)
+ goto out;
+
+ *done = TRUE;
+ cf->connected = TRUE;
+ result = CURLE_OK;
+
+out:
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static void cf_h2_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+
+ if(ctx) {
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ cf_h2_ctx_clear(ctx);
+ CF_DATA_RESTORE(cf, save);
+ }
+}
+
+static void cf_h2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+
+ (void)data;
+ if(ctx) {
+ cf_h2_ctx_free(ctx);
+ cf->ctx = NULL;
+ }
+}
+
+static CURLcode http2_data_pause(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool pause)
+{
#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
- else {
- struct HTTP *stream = data->req.p.http;
- struct http_conn *httpc = &data->conn->proto.httpc;
- uint32_t window = !pause * HTTP2_HUGE_WINDOW_SIZE;
- int rv = nghttp2_session_set_local_window_size(httpc->h2,
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+
+ DEBUGASSERT(data);
+ if(ctx && ctx->h2 && stream) {
+ uint32_t window = pause? 0 : stream->local_window_size;
+
+ int rv = nghttp2_session_set_local_window_size(ctx->h2,
NGHTTP2_FLAG_NONE,
- stream->stream_id,
+ stream->id,
window);
if(rv) {
failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
@@ -2181,22 +2332,32 @@
return CURLE_HTTP2;
}
- /* make sure the window update gets sent */
- rv = h2_session_send(data, httpc->h2);
- if(rv)
- return CURLE_SEND_ERROR;
+ if(!pause)
+ drain_stream(cf, data, stream);
+ /* attempt to send the window update */
+ (void)h2_progress_egress(cf, data);
+
+ if(!pause) {
+ /* Unpausing a h2 transfer, requires it to be run again. The server
+ * may send new DATA on us increasing the flow window, and it may
+ * not. We may have already buffered and exhausted the new window
+ * by operating on things in flight during the handling of other
+ * transfers. */
+ drain_stream(cf, data, stream);
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
DEBUGF(infof(data, "Set HTTP/2 window size to %u for stream %u",
- window, stream->stream_id));
+ window, stream->id));
#ifdef DEBUGBUILD
{
/* read out the stream local window again */
uint32_t window2 =
- nghttp2_session_get_stream_local_window_size(httpc->h2,
- stream->stream_id);
+ nghttp2_session_get_stream_local_window_size(ctx->h2,
+ stream->id);
DEBUGF(infof(data, "HTTP/2 window size is now %u for stream %u",
- window2, stream->stream_id));
+ window2, stream->id));
}
#endif
}
@@ -2204,94 +2365,340 @@
return CURLE_OK;
}
-CURLcode Curl_http2_add_child(struct Curl_easy *parent,
- struct Curl_easy *child,
- bool exclusive)
+static CURLcode cf_h2_cntrl(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
{
- if(parent) {
- struct Curl_http2_dep **tail;
- struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep));
- if(!dep)
- return CURLE_OUT_OF_MEMORY;
- dep->data = child;
+ CURLcode result = CURLE_OK;
+ struct cf_call_data save;
- if(parent->set.stream_dependents && exclusive) {
- struct Curl_http2_dep *node = parent->set.stream_dependents;
- while(node) {
- node->data->set.stream_depends_on = child;
- node = node->next;
- }
+ (void)arg2;
- tail = &child->set.stream_dependents;
- while(*tail)
- tail = &(*tail)->next;
-
- DEBUGASSERT(!*tail);
- *tail = parent->set.stream_dependents;
- parent->set.stream_dependents = 0;
- }
-
- tail = &parent->set.stream_dependents;
- while(*tail) {
- (*tail)->data->set.stream_depends_e = FALSE;
- tail = &(*tail)->next;
- }
-
- DEBUGASSERT(!*tail);
- *tail = dep;
+ CF_DATA_SAVE(save, cf, data);
+ switch(event) {
+ case CF_CTRL_DATA_SETUP:
+ break;
+ case CF_CTRL_DATA_PAUSE:
+ result = http2_data_pause(cf, data, (arg1 != 0));
+ break;
+ case CF_CTRL_DATA_DONE_SEND: {
+ result = http2_data_done_send(cf, data);
+ break;
}
-
- child->set.stream_depends_on = parent;
- child->set.stream_depends_e = exclusive;
- return CURLE_OK;
+ case CF_CTRL_DATA_DONE: {
+ http2_data_done(cf, data, arg1 != 0);
+ break;
+ }
+ default:
+ break;
+ }
+ CF_DATA_RESTORE(cf, save);
+ return result;
}
-void Curl_http2_remove_child(struct Curl_easy *parent, struct Curl_easy *child)
+static bool cf_h2_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
- struct Curl_http2_dep *last = 0;
- struct Curl_http2_dep *data = parent->set.stream_dependents;
- DEBUGASSERT(child->set.stream_depends_on == parent);
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
- while(data && data->data != child) {
- last = data;
- data = data->next;
- }
+ if(ctx && (!Curl_bufq_is_empty(&ctx->inbufq)
+ || (stream && !Curl_bufq_is_empty(&stream->sendbuf))
+ || (stream && !Curl_bufq_is_empty(&stream->recvbuf))))
+ return TRUE;
+ return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
+}
- DEBUGASSERT(data);
+static bool cf_h2_is_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ CURLcode result;
+ struct cf_call_data save;
- if(data) {
- if(last) {
- last->next = data->next;
+ CF_DATA_SAVE(save, cf, data);
+ result = (ctx && ctx->h2 && http2_connisalive(cf, data, input_pending));
+ DEBUGF(LOG_CF(data, cf, "conn alive -> %d, input_pending=%d",
+ result, *input_pending));
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static CURLcode cf_h2_keep_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ CURLcode result;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ result = http2_send_ping(cf, data);
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static CURLcode cf_h2_query(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query, int *pres1, void *pres2)
+{
+ struct cf_h2_ctx *ctx = cf->ctx;
+ struct cf_call_data save;
+ size_t effective_max;
+
+ switch(query) {
+ case CF_QUERY_MAX_CONCURRENT:
+ DEBUGASSERT(pres1);
+
+ CF_DATA_SAVE(save, cf, data);
+ if(nghttp2_session_check_request_allowed(ctx->h2) == 0) {
+ /* the limit is what we have in use right now */
+ effective_max = CONN_INUSE(cf->conn);
}
else {
- parent->set.stream_dependents = data->next;
+ effective_max = ctx->max_concurrent_streams;
}
- free(data);
+ *pres1 = (effective_max > INT_MAX)? INT_MAX : (int)effective_max;
+ CF_DATA_RESTORE(cf, save);
+ return CURLE_OK;
+ default:
+ break;
}
-
- child->set.stream_depends_on = 0;
- child->set.stream_depends_e = FALSE;
+ return cf->next?
+ cf->next->cft->query(cf->next, data, query, pres1, pres2) :
+ CURLE_UNKNOWN_OPTION;
}
-void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
+struct Curl_cftype Curl_cft_nghttp2 = {
+ "HTTP/2",
+ CF_TYPE_MULTIPLEX,
+ CURL_LOG_DEFAULT,
+ cf_h2_destroy,
+ cf_h2_connect,
+ cf_h2_close,
+ Curl_cf_def_get_host,
+ cf_h2_get_select_socks,
+ cf_h2_data_pending,
+ cf_h2_send,
+ cf_h2_recv,
+ cf_h2_cntrl,
+ cf_h2_is_alive,
+ cf_h2_keep_alive,
+ cf_h2_query,
+};
+
+static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
{
- while(data->set.stream_dependents) {
- struct Curl_easy *tmp = data->set.stream_dependents->data;
- Curl_http2_remove_child(data, tmp);
- if(data->set.stream_depends_on)
- Curl_http2_add_child(data->set.stream_depends_on, tmp, FALSE);
- }
+ struct Curl_cfilter *cf = NULL;
+ struct cf_h2_ctx *ctx;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
- if(data->set.stream_depends_on)
- Curl_http2_remove_child(data->set.stream_depends_on, data);
+ DEBUGASSERT(data->conn);
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx)
+ goto out;
+
+ result = Curl_cf_create(&cf, &Curl_cft_nghttp2, ctx);
+ if(result)
+ goto out;
+
+ Curl_conn_cf_add(data, conn, sockindex, cf);
+ result = CURLE_OK;
+
+out:
+ if(result)
+ cf_h2_ctx_free(ctx);
+ *pcf = result? NULL : cf;
+ return result;
}
-/* Only call this function for a transfer that already got a HTTP/2
+static CURLcode http2_cfilter_insert_after(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf_h2 = NULL;
+ struct cf_h2_ctx *ctx;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+
+ (void)data;
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx)
+ goto out;
+
+ result = Curl_cf_create(&cf_h2, &Curl_cft_nghttp2, ctx);
+ if(result)
+ goto out;
+
+ Curl_conn_cf_insert_after(cf, cf_h2);
+ result = CURLE_OK;
+
+out:
+ if(result)
+ cf_h2_ctx_free(ctx);
+ return result;
+}
+
+static bool Curl_cf_is_http2(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ (void)data;
+ for(; cf; cf = cf->next) {
+ if(cf->cft == &Curl_cft_nghttp2)
+ return TRUE;
+ if(cf->cft->flags & CF_TYPE_IP_CONNECT)
+ return FALSE;
+ }
+ return FALSE;
+}
+
+bool Curl_conn_is_http2(const struct Curl_easy *data,
+ const struct connectdata *conn,
+ int sockindex)
+{
+ return conn? Curl_cf_is_http2(conn->cfilter[sockindex], data) : FALSE;
+}
+
+bool Curl_http2_may_switch(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
+{
+ (void)sockindex;
+ if(!Curl_conn_is_http2(data, conn, sockindex) &&
+ data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+#ifndef CURL_DISABLE_PROXY
+ if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
+ /* We don't support HTTP/2 proxies yet. Also it's debatable
+ whether or not this setting should apply to HTTP/2 proxies. */
+ infof(data, "Ignoring HTTP/2 prior knowledge due to proxy");
+ return FALSE;
+ }
+#endif
+ return TRUE;
+ }
+ return FALSE;
+}
+
+CURLcode Curl_http2_switch(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result;
+
+ DEBUGASSERT(!Curl_conn_is_http2(data, conn, sockindex));
+ DEBUGF(infof(data, "switching to HTTP/2"));
+
+ result = http2_cfilter_add(&cf, data, conn, sockindex);
+ if(result)
+ return result;
+
+ result = cf_h2_ctx_init(cf, data, FALSE);
+ if(result)
+ return result;
+
+ conn->httpversion = 20; /* we know we're on HTTP/2 now */
+ conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+ conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+ multi_connchanged(data->multi);
+
+ if(cf->next) {
+ bool done;
+ return Curl_conn_cf_connect(cf, data, FALSE, &done);
+ }
+ return CURLE_OK;
+}
+
+CURLcode Curl_http2_switch_at(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf_h2;
+ CURLcode result;
+
+ DEBUGASSERT(!Curl_cf_is_http2(cf, data));
+
+ result = http2_cfilter_insert_after(cf, data);
+ if(result)
+ return result;
+
+ cf_h2 = cf->next;
+ result = cf_h2_ctx_init(cf_h2, data, FALSE);
+ if(result)
+ return result;
+
+ cf->conn->httpversion = 20; /* we know we're on HTTP/2 now */
+ cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+ cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+ multi_connchanged(data->multi);
+
+ if(cf_h2->next) {
+ bool done;
+ return Curl_conn_cf_connect(cf_h2, data, FALSE, &done);
+ }
+ return CURLE_OK;
+}
+
+CURLcode Curl_http2_upgrade(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
+ const char *mem, size_t nread)
+{
+ struct Curl_cfilter *cf;
+ struct cf_h2_ctx *ctx;
+ CURLcode result;
+
+ DEBUGASSERT(!Curl_conn_is_http2(data, conn, sockindex));
+ DEBUGF(infof(data, "upgrading to HTTP/2"));
+ DEBUGASSERT(data->req.upgr101 == UPGR101_RECEIVED);
+
+ result = http2_cfilter_add(&cf, data, conn, sockindex);
+ if(result)
+ return result;
+
+ DEBUGASSERT(cf->cft == &Curl_cft_nghttp2);
+ ctx = cf->ctx;
+
+ result = cf_h2_ctx_init(cf, data, TRUE);
+ if(result)
+ return result;
+
+ if(nread > 0) {
+ /* Remaining data from the protocol switch reply is already using
+ * the switched protocol, ie. HTTP/2. We add that to the network
+ * inbufq. */
+ ssize_t copied;
+
+ copied = Curl_bufq_write(&ctx->inbufq,
+ (const unsigned char *)mem, nread, &result);
+ if(copied < 0) {
+ failf(data, "error on copying HTTP Upgrade response: %d", result);
+ return CURLE_RECV_ERROR;
+ }
+ if((size_t)copied < nread) {
+ failf(data, "connection buffer size could not take all data "
+ "from HTTP Upgrade response header: copied=%zd, datalen=%zu",
+ copied, nread);
+ return CURLE_HTTP2;
+ }
+ infof(data, "Copied HTTP/2 data in stream buffer to connection buffer"
+ " after upgrade: len=%zu", nread);
+ }
+
+ conn->httpversion = 20; /* we know we're on HTTP/2 now */
+ conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+ conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+ multi_connchanged(data->multi);
+
+ if(cf->next) {
+ bool done;
+ return Curl_conn_cf_connect(cf, data, FALSE, &done);
+ }
+ return CURLE_OK;
+}
+
+/* Only call this function for a transfer that already got an HTTP/2
CURLE_HTTP2_STREAM error! */
bool Curl_h2_http_1_1_error(struct Curl_easy *data)
{
- struct HTTP *stream = data->req.p.http;
- return (stream->error == NGHTTP2_HTTP_1_1_REQUIRED);
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ return (stream && stream->error == NGHTTP2_HTTP_1_1_REQUIRED);
}
#else /* !USE_NGHTTP2 */
diff --git a/lib/http2.h b/lib/http2.h
index f039059..80e1834 100644
--- a/lib/http2.h
+++ b/lib/http2.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -38,46 +38,39 @@
*/
void Curl_http2_ver(char *p, size_t len);
-const char *Curl_http2_strerror(uint32_t err);
-
-CURLcode Curl_http2_init(struct connectdata *conn);
-void Curl_http2_init_state(struct UrlState *state);
-void Curl_http2_init_userset(struct UserDefined *set);
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
struct Curl_easy *data);
-CURLcode Curl_http2_setup(struct Curl_easy *data, struct connectdata *conn);
-CURLcode Curl_http2_switched(struct Curl_easy *data,
- const char *ptr, size_t nread);
-/* called from http_setup_conn */
-void Curl_http2_setup_conn(struct connectdata *conn);
-void Curl_http2_setup_req(struct Curl_easy *data);
-void Curl_http2_done(struct Curl_easy *data, bool premature);
-CURLcode Curl_http2_done_sending(struct Curl_easy *data,
- struct connectdata *conn);
-CURLcode Curl_http2_add_child(struct Curl_easy *parent,
- struct Curl_easy *child,
- bool exclusive);
-void Curl_http2_remove_child(struct Curl_easy *parent,
- struct Curl_easy *child);
-void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
-CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause);
/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */
bool Curl_h2_http_1_1_error(struct Curl_easy *data);
+
+bool Curl_conn_is_http2(const struct Curl_easy *data,
+ const struct connectdata *conn,
+ int sockindex);
+bool Curl_http2_may_switch(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex);
+
+CURLcode Curl_http2_switch(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex);
+
+CURLcode Curl_http2_switch_at(struct Curl_cfilter *cf, struct Curl_easy *data);
+
+CURLcode Curl_http2_upgrade(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
+ const char *ptr, size_t nread);
+
+extern struct Curl_cftype Curl_cft_nghttp2;
+
#else /* USE_NGHTTP2 */
+
+#define Curl_cf_is_http2(a,b) FALSE
+#define Curl_conn_is_http2(a,b,c) FALSE
+#define Curl_http2_may_switch(a,b,c) FALSE
+
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
-#define Curl_http2_setup(x,y) CURLE_UNSUPPORTED_PROTOCOL
-#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL
-#define Curl_http2_setup_conn(x) Curl_nop_stmt
-#define Curl_http2_setup_req(x)
-#define Curl_http2_init_state(x)
-#define Curl_http2_init_userset(x)
-#define Curl_http2_done(x,y)
-#define Curl_http2_done_sending(x,y)
-#define Curl_http2_add_child(x, y, z)
-#define Curl_http2_remove_child(x, y)
-#define Curl_http2_cleanup_dependencies(x)
-#define Curl_http2_stream_pause(x, y)
+#define Curl_http2_switch(a,b,c) 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
diff --git a/lib/http_aws_sigv4.c b/lib/http_aws_sigv4.c
index 390236b..8060162 100644
--- a/lib/http_aws_sigv4.c
+++ b/lib/http_aws_sigv4.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,13 +29,9 @@
#include "urldata.h"
#include "strcase.h"
#include "strdup.h"
-#include "vauth/vauth.h"
-#include "vauth/digest.h"
#include "http_aws_sigv4.h"
#include "curl_sha256.h"
#include "transfer.h"
-
-#include "strcase.h"
#include "parsedate.h"
#include "sendf.h"
@@ -46,67 +42,368 @@
#include "curl_memory.h"
#include "memdebug.h"
+#include "slist.h"
+
#define HMAC_SHA256(k, kl, d, dl, o) \
do { \
ret = Curl_hmacit(Curl_HMAC_SHA256, \
(unsigned char *)k, \
- (unsigned int)kl, \
+ kl, \
(unsigned char *)d, \
- (unsigned int)dl, o); \
- if(ret != CURLE_OK) { \
+ dl, o); \
+ if(ret) { \
goto fail; \
} \
} while(0)
-static void sha256_to_hex(char *dst, unsigned char *sha, size_t dst_l)
+#define TIMESTAMP_SIZE 17
+
+/* hex-encoded with trailing null */
+#define SHA256_HEX_LENGTH (2 * SHA256_DIGEST_LENGTH + 1)
+
+static void sha256_to_hex(char *dst, unsigned char *sha)
{
int i;
- DEBUGASSERT(dst_l >= 65);
- for(i = 0; i < 32; ++i) {
- curl_msnprintf(dst + (i * 2), dst_l - (i * 2), "%02x", sha[i]);
+ for(i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
+ msnprintf(dst + (i * 2), SHA256_HEX_LENGTH - (i * 2), "%02x", sha[i]);
}
}
+static char *find_date_hdr(struct Curl_easy *data, const char *sig_hdr)
+{
+ char *tmp = Curl_checkheaders(data, sig_hdr, strlen(sig_hdr));
+
+ if(tmp)
+ return tmp;
+ return Curl_checkheaders(data, STRCONST("Date"));
+}
+
+/* remove whitespace, and lowercase all headers */
+static void trim_headers(struct curl_slist *head)
+{
+ struct curl_slist *l;
+ for(l = head; l; l = l->next) {
+ char *value; /* to read from */
+ char *store;
+ size_t colon = strcspn(l->data, ":");
+ Curl_strntolower(l->data, l->data, colon);
+
+ value = &l->data[colon];
+ if(!*value)
+ continue;
+ ++value;
+ store = value;
+
+ /* skip leading whitespace */
+ while(*value && ISBLANK(*value))
+ value++;
+
+ while(*value) {
+ int space = 0;
+ while(*value && ISBLANK(*value)) {
+ value++;
+ space++;
+ }
+ if(space) {
+ /* replace any number of consecutive whitespace with a single space,
+ unless at the end of the string, then nothing */
+ if(*value)
+ *store++ = ' ';
+ }
+ else
+ *store++ = *value++;
+ }
+ *store = 0; /* null terminate */
+ }
+}
+
+/* maximum length for the aws sivg4 parts */
+#define MAX_SIGV4_LEN 64
+#define MAX_SIGV4_LEN_TXT "64"
+
+#define DATE_HDR_KEY_LEN (MAX_SIGV4_LEN + sizeof("X--Date"))
+
+#define MAX_HOST_LEN 255
+/* FQDN + host: */
+#define FULL_HOST_LEN (MAX_HOST_LEN + sizeof("host:"))
+
+/* string been x-PROVIDER-date:TIMESTAMP, I need +1 for ':' */
+#define DATE_FULL_HDR_LEN (DATE_HDR_KEY_LEN + TIMESTAMP_SIZE + 1)
+
+/* timestamp should point to a buffer of at last TIMESTAMP_SIZE bytes */
+static CURLcode make_headers(struct Curl_easy *data,
+ const char *hostname,
+ char *timestamp,
+ char *provider1,
+ char **date_header,
+ char *content_sha256_header,
+ struct dynbuf *canonical_headers,
+ struct dynbuf *signed_headers)
+{
+ char date_hdr_key[DATE_HDR_KEY_LEN];
+ char date_full_hdr[DATE_FULL_HDR_LEN];
+ struct curl_slist *head = NULL;
+ struct curl_slist *tmp_head = NULL;
+ CURLcode ret = CURLE_OUT_OF_MEMORY;
+ struct curl_slist *l;
+ int again = 1;
+
+ /* provider1 mid */
+ Curl_strntolower(provider1, provider1, strlen(provider1));
+ provider1[0] = Curl_raw_toupper(provider1[0]);
+
+ msnprintf(date_hdr_key, DATE_HDR_KEY_LEN, "X-%s-Date", provider1);
+
+ /* provider1 lowercase */
+ Curl_strntolower(provider1, provider1, 1); /* first byte only */
+ msnprintf(date_full_hdr, DATE_FULL_HDR_LEN,
+ "x-%s-date:%s", provider1, timestamp);
+
+ if(Curl_checkheaders(data, STRCONST("Host"))) {
+ head = NULL;
+ }
+ else {
+ char full_host[FULL_HOST_LEN + 1];
+
+ if(data->state.aptr.host) {
+ size_t pos;
+
+ if(strlen(data->state.aptr.host) > FULL_HOST_LEN) {
+ ret = CURLE_URL_MALFORMAT;
+ goto fail;
+ }
+ strcpy(full_host, data->state.aptr.host);
+ /* remove /r/n as the separator for canonical request must be '\n' */
+ pos = strcspn(full_host, "\n\r");
+ full_host[pos] = 0;
+ }
+ else {
+ if(strlen(hostname) > MAX_HOST_LEN) {
+ ret = CURLE_URL_MALFORMAT;
+ goto fail;
+ }
+ msnprintf(full_host, FULL_HOST_LEN, "host:%s", hostname);
+ }
+
+ head = curl_slist_append(NULL, full_host);
+ if(!head)
+ goto fail;
+ }
+
+
+ if(*content_sha256_header) {
+ tmp_head = curl_slist_append(head, content_sha256_header);
+ if(!tmp_head)
+ goto fail;
+ head = tmp_head;
+ }
+
+ for(l = data->set.headers; l; l = l->next) {
+ tmp_head = curl_slist_append(head, l->data);
+ if(!tmp_head)
+ goto fail;
+ head = tmp_head;
+ }
+
+ trim_headers(head);
+
+ *date_header = find_date_hdr(data, date_hdr_key);
+ if(!*date_header) {
+ tmp_head = curl_slist_append(head, date_full_hdr);
+ if(!tmp_head)
+ goto fail;
+ head = tmp_head;
+ *date_header = curl_maprintf("%s: %s", date_hdr_key, timestamp);
+ }
+ else {
+ char *value;
+
+ *date_header = strdup(*date_header);
+ if(!*date_header)
+ goto fail;
+
+ value = strchr(*date_header, ':');
+ if(!value)
+ goto fail;
+ ++value;
+ while(ISBLANK(*value))
+ ++value;
+ strncpy(timestamp, value, TIMESTAMP_SIZE - 1);
+ timestamp[TIMESTAMP_SIZE - 1] = 0;
+ }
+
+ /* alpha-sort in a case sensitive manner */
+ do {
+ again = 0;
+ for(l = head; l; l = l->next) {
+ struct curl_slist *next = l->next;
+
+ if(next && strcmp(l->data, next->data) > 0) {
+ char *tmp = l->data;
+
+ l->data = next->data;
+ next->data = tmp;
+ again = 1;
+ }
+ }
+ } while(again);
+
+ for(l = head; l; l = l->next) {
+ char *tmp;
+
+ if(Curl_dyn_add(canonical_headers, l->data))
+ goto fail;
+ if(Curl_dyn_add(canonical_headers, "\n"))
+ goto fail;
+
+ tmp = strchr(l->data, ':');
+ if(tmp)
+ *tmp = 0;
+
+ if(l != head) {
+ if(Curl_dyn_add(signed_headers, ";"))
+ goto fail;
+ }
+ if(Curl_dyn_add(signed_headers, l->data))
+ goto fail;
+ }
+
+ ret = CURLE_OK;
+fail:
+ curl_slist_free_all(head);
+
+ return ret;
+}
+
+#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)
+
+/* try to parse a payload hash from the content-sha256 header */
+static char *parse_content_sha_hdr(struct Curl_easy *data,
+ const char *provider1,
+ size_t *value_len)
+{
+ char key[CONTENT_SHA256_KEY_LEN];
+ size_t key_len;
+ char *value;
+ size_t len;
+
+ key_len = msnprintf(key, sizeof(key), "x-%s-content-sha256", provider1);
+
+ value = Curl_checkheaders(data, key, key_len);
+ if(!value)
+ return NULL;
+
+ value = strchr(value, ':');
+ if(!value)
+ return NULL;
+ ++value;
+
+ while(*value && ISBLANK(*value))
+ ++value;
+
+ len = strlen(value);
+ while(len > 0 && ISBLANK(value[len-1]))
+ --len;
+
+ *value_len = len;
+ return value;
+}
+
+static CURLcode calc_payload_hash(struct Curl_easy *data,
+ unsigned char *sha_hash, char *sha_hex)
+{
+ const char *post_data = data->set.postfields;
+ size_t post_data_len = 0;
+ CURLcode result;
+
+ if(post_data) {
+ if(data->set.postfieldsize < 0)
+ post_data_len = strlen(post_data);
+ else
+ post_data_len = (size_t)data->set.postfieldsize;
+ }
+ result = Curl_sha256it(sha_hash, (const unsigned char *) post_data,
+ post_data_len);
+ if(!result)
+ sha256_to_hex(sha_hex, sha_hash);
+ return result;
+}
+
+#define S3_UNSIGNED_PAYLOAD "UNSIGNED-PAYLOAD"
+
+static CURLcode calc_s3_payload_hash(struct Curl_easy *data,
+ Curl_HttpReq httpreq, char *provider1,
+ unsigned char *sha_hash,
+ char *sha_hex, char *header)
+{
+ bool empty_method = (httpreq == HTTPREQ_GET || httpreq == HTTPREQ_HEAD);
+ /* The request method or filesize indicate no request payload */
+ bool empty_payload = (empty_method || data->set.filesize == 0);
+ /* The POST payload is in memory */
+ bool post_payload = (httpreq == HTTPREQ_POST && data->set.postfields);
+ CURLcode ret = CURLE_OUT_OF_MEMORY;
+
+ if(empty_payload || post_payload) {
+ /* Calculate a real hash when we know the request payload */
+ ret = calc_payload_hash(data, sha_hash, sha_hex);
+ if(ret)
+ goto fail;
+ }
+ else {
+ /* Fall back to s3's UNSIGNED-PAYLOAD */
+ size_t len = sizeof(S3_UNSIGNED_PAYLOAD) - 1;
+ DEBUGASSERT(len < SHA256_HEX_LENGTH); /* 16 < 65 */
+ memcpy(sha_hex, S3_UNSIGNED_PAYLOAD, len);
+ sha_hex[len] = 0;
+ }
+
+ /* format the required content-sha256 header */
+ msnprintf(header, CONTENT_SHA256_HDR_LEN,
+ "x-%s-content-sha256: %s", provider1, sha_hex);
+
+ ret = CURLE_OK;
+fail:
+ return ret;
+}
+
CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
{
CURLcode ret = CURLE_OUT_OF_MEMORY;
struct connectdata *conn = data->conn;
size_t len;
- const char *tmp0;
- const char *tmp1;
- char *provider0_low = NULL;
- char *provider0_up = NULL;
- char *provider1_low = NULL;
- char *provider1_mid = NULL;
- char *region = NULL;
- char *service = NULL;
+ const char *arg;
+ char provider0[MAX_SIGV4_LEN + 1]="";
+ char provider1[MAX_SIGV4_LEN + 1]="";
+ char region[MAX_SIGV4_LEN + 1]="";
+ char service[MAX_SIGV4_LEN + 1]="";
+ bool sign_as_s3 = false;
const char *hostname = conn->host.name;
-#ifdef DEBUGBUILD
- char *force_timestamp;
-#endif
time_t clock;
struct tm tm;
- char timestamp[17];
+ char timestamp[TIMESTAMP_SIZE];
char date[9];
- const char *content_type = Curl_checkheaders(data, STRCONST("Content-Type"));
- char *canonical_headers = NULL;
- char *signed_headers = NULL;
+ struct dynbuf canonical_headers;
+ struct dynbuf signed_headers;
+ char *date_header = NULL;
Curl_HttpReq httpreq;
- const char *method;
- size_t post_data_len;
- const char *post_data = data->set.postfields ? data->set.postfields : "";
- unsigned char sha_hash[32];
- char sha_hex[65];
+ const char *method = NULL;
+ char *payload_hash = NULL;
+ size_t payload_hash_len = 0;
+ unsigned char sha_hash[SHA256_DIGEST_LENGTH];
+ char sha_hex[SHA256_HEX_LENGTH];
+ char content_sha256_hdr[CONTENT_SHA256_HDR_LEN + 2] = ""; /* add \r\n */
char *canonical_request = NULL;
char *request_type = NULL;
char *credential_scope = NULL;
char *str_to_sign = NULL;
const char *user = data->state.aptr.user ? data->state.aptr.user : "";
- const char *passwd = data->state.aptr.passwd ? data->state.aptr.passwd : "";
char *secret = NULL;
- unsigned char tmp_sign0[32] = {0};
- unsigned char tmp_sign1[32] = {0};
+ unsigned char sign0[SHA256_DIGEST_LENGTH] = {0};
+ unsigned char sign1[SHA256_DIGEST_LENGTH] = {0};
char *auth_headers = NULL;
DEBUGASSERT(!proxy);
@@ -117,6 +414,10 @@
return CURLE_OK;
}
+ /* we init those buffers here, so goto fail will free initialized dynbuf */
+ Curl_dyn_init(&canonical_headers, CURL_MAX_HTTP_HEADER);
+ Curl_dyn_init(&signed_headers, CURL_MAX_HTTP_HEADER);
+
/*
* Parameters parsing
* Google and Outscale use the same OSC or GOOG,
@@ -124,223 +425,166 @@
* AWS is the default because most of non-amazon providers
* are still using aws:amz as a prefix.
*/
- tmp0 = data->set.str[STRING_AWS_SIGV4] ?
+ arg = data->set.str[STRING_AWS_SIGV4] ?
data->set.str[STRING_AWS_SIGV4] : "aws:amz";
- tmp1 = strchr(tmp0, ':');
- len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
- if(len < 1) {
- infof(data, "first provider can't be empty");
+
+ /* provider1[:provider2[:region[:service]]]
+
+ No string can be longer than N bytes of non-whitespace
+ */
+ (void)sscanf(arg, "%" MAX_SIGV4_LEN_TXT "[^:]"
+ ":%" MAX_SIGV4_LEN_TXT "[^:]"
+ ":%" MAX_SIGV4_LEN_TXT "[^:]"
+ ":%" MAX_SIGV4_LEN_TXT "s",
+ provider0, provider1, region, service);
+ if(!provider0[0]) {
+ failf(data, "first provider can't be empty");
ret = CURLE_BAD_FUNCTION_ARGUMENT;
goto fail;
}
- provider0_low = malloc(len + 1);
- provider0_up = malloc(len + 1);
- if(!provider0_low || !provider0_up) {
- goto fail;
- }
- Curl_strntolower(provider0_low, tmp0, len);
- provider0_low[len] = '\0';
- Curl_strntoupper(provider0_up, tmp0, len);
- provider0_up[len] = '\0';
+ else if(!provider1[0])
+ strcpy(provider1, provider0);
- if(tmp1) {
- tmp0 = tmp1 + 1;
- tmp1 = strchr(tmp0, ':');
- len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
- if(len < 1) {
- infof(data, "second provider can't be empty");
- ret = CURLE_BAD_FUNCTION_ARGUMENT;
- goto fail;
- }
- provider1_low = malloc(len + 1);
- provider1_mid = malloc(len + 1);
- if(!provider1_low || !provider1_mid) {
- goto fail;
- }
- Curl_strntolower(provider1_low, tmp0, len);
- provider1_low[len] = '\0';
- Curl_strntolower(provider1_mid, tmp0, len);
- provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
- provider1_mid[len] = '\0';
-
- if(tmp1) {
- tmp0 = tmp1 + 1;
- tmp1 = strchr(tmp0, ':');
- len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
- if(len < 1) {
- infof(data, "region can't be empty");
- ret = CURLE_BAD_FUNCTION_ARGUMENT;
- goto fail;
- }
- region = Curl_memdup(tmp0, len + 1);
- if(!region) {
- goto fail;
- }
- region[len] = '\0';
-
- if(tmp1) {
- tmp0 = tmp1 + 1;
- service = strdup(tmp0);
- if(!service) {
- goto fail;
- }
- if(strlen(service) < 1) {
- infof(data, "service can't be empty");
- ret = CURLE_BAD_FUNCTION_ARGUMENT;
- goto fail;
- }
- }
- }
- }
- else {
- provider1_low = Curl_memdup(provider0_low, len + 1);
- provider1_mid = Curl_memdup(provider0_low, len + 1);
- if(!provider1_low || !provider1_mid) {
- goto fail;
- }
- provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
- }
-
- if(!service) {
- tmp0 = hostname;
- tmp1 = strchr(tmp0, '.');
- if(!tmp1) {
- infof(data, "service missing in parameters or hostname");
+ if(!service[0]) {
+ char *hostdot = strchr(hostname, '.');
+ if(!hostdot) {
+ failf(data, "service missing in parameters and hostname");
ret = CURLE_URL_MALFORMAT;
goto fail;
}
- len = tmp1 - tmp0;
- service = Curl_memdup(tmp0, len + 1);
- if(!service) {
+ len = hostdot - hostname;
+ if(len > MAX_SIGV4_LEN) {
+ failf(data, "service too long in hostname");
+ ret = CURLE_URL_MALFORMAT;
goto fail;
}
+ strncpy(service, hostname, len);
service[len] = '\0';
- if(!region) {
- tmp0 = tmp1 + 1;
- tmp1 = strchr(tmp0, '.');
- if(!tmp1) {
- infof(data, "region missing in parameters or hostname");
+ if(!region[0]) {
+ const char *reg = hostdot + 1;
+ const char *hostreg = strchr(reg, '.');
+ if(!hostreg) {
+ failf(data, "region missing in parameters and hostname");
ret = CURLE_URL_MALFORMAT;
goto fail;
}
- len = tmp1 - tmp0;
- region = Curl_memdup(tmp0, len + 1);
- if(!region) {
+ len = hostreg - reg;
+ if(len > MAX_SIGV4_LEN) {
+ failf(data, "region too long in hostname");
+ ret = CURLE_URL_MALFORMAT;
goto fail;
}
+ strncpy(region, reg, len);
region[len] = '\0';
}
}
+ Curl_http_method(data, conn, &method, &httpreq);
+
+ /* AWS S3 requires a x-amz-content-sha256 header, and supports special
+ * values like UNSIGNED-PAYLOAD */
+ sign_as_s3 = (strcasecompare(provider0, "aws") &&
+ strcasecompare(service, "s3"));
+
+ payload_hash = parse_content_sha_hdr(data, provider1, &payload_hash_len);
+
+ if(!payload_hash) {
+ if(sign_as_s3)
+ ret = calc_s3_payload_hash(data, httpreq, provider1, sha_hash,
+ sha_hex, content_sha256_hdr);
+ else
+ ret = calc_payload_hash(data, sha_hash, sha_hex);
+ if(ret)
+ goto fail;
+
+ payload_hash = sha_hex;
+ /* may be shorter than SHA256_HEX_LENGTH, like S3_UNSIGNED_PAYLOAD */
+ payload_hash_len = strlen(sha_hex);
+ }
+
#ifdef DEBUGBUILD
- force_timestamp = getenv("CURL_FORCETIME");
- if(force_timestamp)
- clock = 0;
- else
- time(&clock);
+ {
+ char *force_timestamp = getenv("CURL_FORCETIME");
+ if(force_timestamp)
+ clock = 0;
+ else
+ time(&clock);
+ }
#else
time(&clock);
#endif
ret = Curl_gmtime(clock, &tm);
- if(ret != CURLE_OK) {
+ if(ret) {
goto fail;
}
if(!strftime(timestamp, sizeof(timestamp), "%Y%m%dT%H%M%SZ", &tm)) {
+ ret = CURLE_OUT_OF_MEMORY;
goto fail;
}
+
+ ret = make_headers(data, hostname, timestamp, provider1,
+ &date_header, content_sha256_hdr,
+ &canonical_headers, &signed_headers);
+ if(ret)
+ goto fail;
+ ret = CURLE_OUT_OF_MEMORY;
+
+ if(*content_sha256_hdr) {
+ /* make_headers() needed this without the \r\n for canonicalization */
+ size_t hdrlen = strlen(content_sha256_hdr);
+ DEBUGASSERT(hdrlen + 3 < sizeof(content_sha256_hdr));
+ memcpy(content_sha256_hdr + hdrlen, "\r\n", 3);
+ }
+
memcpy(date, timestamp, sizeof(date));
date[sizeof(date) - 1] = 0;
- if(content_type) {
- content_type = strchr(content_type, ':');
- if(!content_type) {
- ret = CURLE_FAILED_INIT;
- goto fail;
- }
- content_type++;
- /* Skip whitespace now */
- while(*content_type == ' ' || *content_type == '\t')
- ++content_type;
-
- canonical_headers = curl_maprintf("content-type:%s\n"
- "host:%s\n"
- "x-%s-date:%s\n",
- content_type,
- hostname,
- provider1_low, timestamp);
- signed_headers = curl_maprintf("content-type;host;x-%s-date",
- provider1_low);
- }
- else {
- canonical_headers = curl_maprintf("host:%s\n"
- "x-%s-date:%s\n",
- hostname,
- provider1_low, timestamp);
- signed_headers = curl_maprintf("host;x-%s-date", provider1_low);
- }
-
- if(!canonical_headers || !signed_headers) {
- goto fail;
- }
-
- if(data->set.postfieldsize < 0)
- post_data_len = strlen(post_data);
- else
- post_data_len = (size_t)data->set.postfieldsize;
- if(Curl_sha256it(sha_hash, (const unsigned char *) post_data,
- post_data_len)) {
- goto fail;
- }
-
- sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
-
- Curl_http_method(data, conn, &method, &httpreq);
-
canonical_request =
curl_maprintf("%s\n" /* HTTPRequestMethod */
"%s\n" /* CanonicalURI */
"%s\n" /* CanonicalQueryString */
"%s\n" /* CanonicalHeaders */
"%s\n" /* SignedHeaders */
- "%s", /* HashedRequestPayload in hex */
+ "%.*s", /* HashedRequestPayload in hex */
method,
data->state.up.path,
data->state.up.query ? data->state.up.query : "",
- canonical_headers,
- signed_headers,
- sha_hex);
- if(!canonical_request) {
+ Curl_dyn_ptr(&canonical_headers),
+ Curl_dyn_ptr(&signed_headers),
+ (int)payload_hash_len, payload_hash);
+ if(!canonical_request)
goto fail;
- }
- request_type = curl_maprintf("%s4_request", provider0_low);
- if(!request_type) {
+ /* provider 0 lowercase */
+ Curl_strntolower(provider0, provider0, strlen(provider0));
+ request_type = curl_maprintf("%s4_request", provider0);
+ if(!request_type)
goto fail;
- }
credential_scope = curl_maprintf("%s/%s/%s/%s",
date, region, service, request_type);
- if(!credential_scope) {
+ if(!credential_scope)
goto fail;
- }
if(Curl_sha256it(sha_hash, (unsigned char *) canonical_request,
- strlen(canonical_request))) {
+ strlen(canonical_request)))
goto fail;
- }
- sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
+ sha256_to_hex(sha_hex, sha_hash);
+
+ /* provider 0 uppercase */
+ Curl_strntoupper(provider0, provider0, strlen(provider0));
/*
- * Google allow to use rsa key instead of HMAC, so this code might change
- * In the future, but for now we support only HMAC version
+ * Google allows using RSA key instead of HMAC, so this code might change
+ * in the future. For now we only support HMAC.
*/
str_to_sign = curl_maprintf("%s4-HMAC-SHA256\n" /* Algorithm */
"%s\n" /* RequestDateTime */
"%s\n" /* CredentialScope */
"%s", /* HashedCanonicalRequest in hex */
- provider0_up,
+ provider0,
timestamp,
credential_scope,
sha_hex);
@@ -348,36 +592,35 @@
goto fail;
}
- secret = curl_maprintf("%s4%s", provider0_up, passwd);
- if(!secret) {
+ /* provider 0 uppercase */
+ secret = curl_maprintf("%s4%s", provider0,
+ data->state.aptr.passwd ?
+ data->state.aptr.passwd : "");
+ if(!secret)
goto fail;
- }
- HMAC_SHA256(secret, strlen(secret),
- date, strlen(date), tmp_sign0);
- HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
- region, strlen(region), tmp_sign1);
- HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
- service, strlen(service), tmp_sign0);
- HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
- request_type, strlen(request_type), tmp_sign1);
- HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
- str_to_sign, strlen(str_to_sign), tmp_sign0);
+ HMAC_SHA256(secret, strlen(secret), date, strlen(date), sign0);
+ HMAC_SHA256(sign0, sizeof(sign0), region, strlen(region), sign1);
+ HMAC_SHA256(sign1, sizeof(sign1), service, strlen(service), sign0);
+ HMAC_SHA256(sign0, sizeof(sign0), request_type, strlen(request_type), sign1);
+ HMAC_SHA256(sign1, sizeof(sign1), str_to_sign, strlen(str_to_sign), sign0);
- sha256_to_hex(sha_hex, tmp_sign0, sizeof(sha_hex));
+ sha256_to_hex(sha_hex, sign0);
+ /* provider 0 uppercase */
auth_headers = curl_maprintf("Authorization: %s4-HMAC-SHA256 "
"Credential=%s/%s, "
"SignedHeaders=%s, "
"Signature=%s\r\n"
- "X-%s-Date: %s\r\n",
- provider0_up,
+ "%s\r\n"
+ "%s", /* optional sha256 header includes \r\n */
+ provider0,
user,
credential_scope,
- signed_headers,
+ Curl_dyn_ptr(&signed_headers),
sha_hex,
- provider1_mid,
- timestamp);
+ date_header,
+ content_sha256_hdr);
if(!auth_headers) {
goto fail;
}
@@ -388,19 +631,14 @@
ret = CURLE_OK;
fail:
- free(provider0_low);
- free(provider0_up);
- free(provider1_low);
- free(provider1_mid);
- free(region);
- free(service);
- free(canonical_headers);
- free(signed_headers);
+ Curl_dyn_free(&canonical_headers);
+ Curl_dyn_free(&signed_headers);
free(canonical_request);
free(request_type);
free(credential_scope);
free(str_to_sign);
free(secret);
+ free(date_header);
return ret;
}
diff --git a/lib/http_aws_sigv4.h b/lib/http_aws_sigv4.h
index 85755e9..57cc570 100644
--- a/lib/http_aws_sigv4.h
+++ b/lib/http_aws_sigv4.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/http_chunks.c b/lib/http_chunks.c
index 2aeb753..bda00d3 100644
--- a/lib/http_chunks.c
+++ b/lib/http_chunks.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -100,7 +100,7 @@
CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
char *datap,
ssize_t datalen,
- ssize_t *wrotep,
+ ssize_t *wrote,
CURLcode *extrap)
{
CURLcode result = CURLE_OK;
@@ -109,12 +109,11 @@
struct SingleRequest *k = &data->req;
size_t piece;
curl_off_t length = (curl_off_t)datalen;
- size_t *wrote = (size_t *)wrotep;
*wrote = 0; /* nothing's written yet */
/* the original data is written to the client, but we go on with the
- chunk read process, to properly calculate the content length*/
+ chunk read process, to properly calculate the content length */
if(data->set.http_te_skip && !k->ignorebody) {
result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen);
if(result) {
@@ -126,7 +125,7 @@
while(length) {
switch(ch->state) {
case CHUNK_HEX:
- if(isxdigit_ascii(*datap)) {
+ if(ISXDIGIT(*datap)) {
if(ch->hexindex < CHUNK_MAXNUM_LEN) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
diff --git a/lib/http_chunks.h b/lib/http_chunks.h
index 2cf5507..ed50713 100644
--- a/lib/http_chunks.h
+++ b/lib/http_chunks.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/http_digest.c b/lib/http_digest.c
index c2472e1..8daad99 100644
--- a/lib/http_digest.c
+++ b/lib/http_digest.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -58,11 +58,11 @@
digest = &data->state.digest;
}
- if(!checkprefix("Digest", header) || !ISSPACE(header[6]))
+ if(!checkprefix("Digest", header) || !ISBLANK(header[6]))
return CURLE_BAD_CONTENT_ENCODING;
header += strlen("Digest");
- while(*header && ISSPACE(*header))
+ while(*header && ISBLANK(*header))
header++;
return Curl_auth_decode_digest_http_message(header, digest);
@@ -81,7 +81,7 @@
bool have_chlg;
/* Point to the address of the pointer that holds the string to send to the
- server, which is for a plain host or for a HTTP proxy */
+ server, which is for a plain host or for an HTTP proxy */
char **allocuserpwd;
/* Point to the name and password for this */
diff --git a/lib/http_digest.h b/lib/http_digest.h
index eea90b7..7d5cfc1 100644
--- a/lib/http_digest.h
+++ b/lib/http_digest.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c
index 0ac4ead..153e3d4 100644
--- a/lib/http_negotiate.c
+++ b/lib/http_negotiate.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -84,7 +84,7 @@
/* Obtain the input token, if any */
header += strlen("Negotiate");
- while(*header && ISSPACE(*header))
+ while(*header && ISBLANK(*header))
header++;
len = strlen(header);
diff --git a/lib/http_negotiate.h b/lib/http_negotiate.h
index 6e2096c..76d8356 100644
--- a/lib/http_negotiate.h
+++ b/lib/http_negotiate.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c
index a1f0f20..b845ddf 100644
--- a/lib/http_ntlm.c
+++ b/lib/http_ntlm.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,7 +29,7 @@
/*
* NTLM details:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
@@ -134,7 +134,7 @@
struct bufref ntlmmsg;
/* point to the address of the pointer that holds the string to send to the
- server, which is for a plain host or for a HTTP proxy */
+ server, which is for a plain host or for an HTTP proxy */
char **allocuserpwd;
/* point to the username, password, service and host */
diff --git a/lib/http_ntlm.h b/lib/http_ntlm.h
index cec63b8..f37572b 100644
--- a/lib/http_ntlm.h
+++ b/lib/http_ntlm.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index a69cff2..4fd998a 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,7 +26,7 @@
#include "http_proxy.h"
-#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY)
#include <curl/curl.h>
#ifdef USE_HYPER
@@ -37,6 +37,9 @@
#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 "curlx.h"
#include "vtls/vtls.h"
@@ -48,1032 +51,180 @@
#include "curl_memory.h"
#include "memdebug.h"
-/*
- * Perform SSL initialization for HTTPS proxy. Sets
- * proxy_ssl_connected connection bit when complete. Can be
- * called multiple times.
- */
-static CURLcode https_proxy_connect(struct Curl_easy *data, int sockindex)
+
+struct cf_proxy_ctx {
+ /* the protocol specific sub-filter we install during connect */
+ struct Curl_cfilter *cf_protocol;
+};
+
+static CURLcode http_proxy_cf_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
{
-#ifdef USE_SSL
- struct connectdata *conn = data->conn;
- CURLcode result = CURLE_OK;
- DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS);
- if(!conn->bits.proxy_ssl_connected[sockindex]) {
- /* perform SSL initialization for this socket */
- result =
- Curl_ssl_connect_nonblocking(data, conn, TRUE, sockindex,
- &conn->bits.proxy_ssl_connected[sockindex]);
- if(result)
- /* a failed connection is marked for closure to prevent (bad) re-use or
- similar */
- connclose(conn, "TLS handshake failed");
+ struct cf_proxy_ctx *ctx = cf->ctx;
+ CURLcode result;
+
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
}
- return result;
-#else
- (void) data;
- (void) sockindex;
- return CURLE_NOT_BUILT_IN;
+
+ DEBUGF(LOG_CF(data, cf, "connect"));
+connect_sub:
+ result = cf->next->cft->do_connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ return result;
+
+ *done = FALSE;
+ if(!ctx->cf_protocol) {
+ struct Curl_cfilter *cf_protocol = NULL;
+ int alpn = Curl_conn_cf_is_ssl(cf->next)?
+ cf->conn->proxy_alpn : CURL_HTTP_VERSION_1_1;
+
+ /* First time call after the subchain connected */
+ switch(alpn) {
+ case CURL_HTTP_VERSION_NONE:
+ case CURL_HTTP_VERSION_1_0:
+ case CURL_HTTP_VERSION_1_1:
+ DEBUGF(LOG_CF(data, cf, "installing subfilter for HTTP/1.1"));
+ infof(data, "CONNECT tunnel: HTTP/1.%d negotiated",
+ (alpn == CURL_HTTP_VERSION_1_0)? 0 : 1);
+ result = Curl_cf_h1_proxy_insert_after(cf, data);
+ if(result)
+ goto out;
+ cf_protocol = cf->next;
+ break;
+#ifdef USE_NGHTTP2
+ case CURL_HTTP_VERSION_2:
+ DEBUGF(LOG_CF(data, cf, "installing subfilter for HTTP/2"));
+ infof(data, "CONNECT tunnel: HTTP/2 negotiated");
+ result = Curl_cf_h2_proxy_insert_after(cf, data);
+ if(result)
+ goto out;
+ cf_protocol = cf->next;
+ break;
#endif
-}
+ default:
+ DEBUGF(LOG_CF(data, cf, "installing subfilter for default HTTP/1.1"));
+ infof(data, "CONNECT tunnel: unsupported ALPN(%d) negotiated", alpn);
+ result = CURLE_COULDNT_CONNECT;
+ goto out;
+ }
-CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex)
-{
- struct connectdata *conn = data->conn;
- if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
- const CURLcode result = https_proxy_connect(data, sockindex);
- if(result)
- return result;
- if(!conn->bits.proxy_ssl_connected[sockindex])
- return result; /* wait for HTTPS proxy SSL initialization to complete */
- }
-
- if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
-#ifndef CURL_DISABLE_PROXY
- /* for [protocol] tunneled through HTTP proxy */
- const char *hostname;
- int remote_port;
- CURLcode result;
-
- /* We want "seamless" operations through HTTP proxy tunnel */
-
- /* for the secondary socket (FTP), use the "connect to host"
- * but ignore the "connect to port" (use the secondary port)
+ ctx->cf_protocol = cf_protocol;
+ /* after we installed the filter "below" us, we call connect
+ * on out sub-chain again.
*/
-
- if(conn->bits.conn_to_host)
- hostname = conn->conn_to_host.name;
- else if(sockindex == SECONDARYSOCKET)
- hostname = conn->secondaryhostname;
- else
- hostname = conn->host.name;
-
- if(sockindex == SECONDARYSOCKET)
- remote_port = conn->secondary_port;
- else if(conn->bits.conn_to_port)
- remote_port = conn->conn_to_port;
- else
- remote_port = conn->remote_port;
-
- result = Curl_proxyCONNECT(data, sockindex, hostname, remote_port);
- if(CURLE_OK != result)
- return result;
- Curl_safefree(data->state.aptr.proxyuserpwd);
-#else
- return CURLE_NOT_BUILT_IN;
-#endif
- }
- /* no HTTP tunnel proxy, just return */
- return CURLE_OK;
-}
-
-bool Curl_connect_complete(struct connectdata *conn)
-{
- return !conn->connect_state ||
- (conn->connect_state->tunnel_state >= TUNNEL_COMPLETE);
-}
-
-bool Curl_connect_ongoing(struct connectdata *conn)
-{
- return conn->connect_state &&
- (conn->connect_state->tunnel_state <= TUNNEL_COMPLETE);
-}
-
-/* when we've sent a CONNECT to a proxy, we should rather either wait for the
- socket to become readable to be able to get the response headers or if
- we're still sending the request, wait for write. */
-int Curl_connect_getsock(struct connectdata *conn)
-{
- struct HTTP *http;
- DEBUGASSERT(conn);
- DEBUGASSERT(conn->connect_state);
- http = &conn->connect_state->http_proxy;
-
- if(http->sending == HTTPSEND_REQUEST)
- return GETSOCK_WRITESOCK(0);
-
- return GETSOCK_READSOCK(0);
-}
-
-static CURLcode connect_init(struct Curl_easy *data, bool reinit)
-{
- struct http_connect_state *s;
- struct connectdata *conn = data->conn;
- if(conn->handler->flags & PROTOPT_NOTCPPROXY) {
- failf(data, "%s cannot be done over CONNECT", conn->handler->scheme);
- return CURLE_UNSUPPORTED_PROTOCOL;
- }
- if(!reinit) {
- CURLcode result;
- DEBUGASSERT(!conn->connect_state);
- /* we might need the upload buffer for streaming a partial request */
- result = Curl_get_upload_buffer(data);
- if(result)
- return result;
-
- s = calloc(1, sizeof(struct http_connect_state));
- if(!s)
- return CURLE_OUT_OF_MEMORY;
- infof(data, "allocate connect buffer");
- conn->connect_state = s;
- Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
-
- /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
- * member conn->proto.http; we want [protocol] through HTTP and we have
- * to change the member temporarily for connecting to the HTTP
- * proxy. After Curl_proxyCONNECT we have to set back the member to the
- * original pointer
- *
- * This function might be called several times in the multi interface case
- * if the proxy's CONNECT response is not instant.
- */
- s->prot_save = data->req.p.http;
- data->req.p.http = &s->http_proxy;
- connkeep(conn, "HTTP proxy CONNECT");
+ goto connect_sub;
}
else {
- DEBUGASSERT(conn->connect_state);
- s = conn->connect_state;
- Curl_dyn_reset(&s->rcvbuf);
- }
- s->tunnel_state = TUNNEL_INIT;
- s->keepon = KEEPON_CONNECT;
- s->cl = 0;
- s->close_connection = FALSE;
- return CURLE_OK;
-}
-
-void Curl_connect_done(struct Curl_easy *data)
-{
- struct connectdata *conn = data->conn;
- struct http_connect_state *s = conn->connect_state;
- if(s && (s->tunnel_state != TUNNEL_EXIT)) {
- s->tunnel_state = TUNNEL_EXIT;
- Curl_dyn_free(&s->rcvbuf);
- Curl_dyn_free(&s->req);
-
- /* restore the protocol pointer, if not already done */
- if(s->prot_save)
- data->req.p.http = s->prot_save;
- s->prot_save = NULL;
- data->info.httpcode = 0; /* clear it as it might've been used for the
- proxy */
- data->req.ignorebody = FALSE;
-#ifdef USE_HYPER
- data->state.hconnect = FALSE;
-#endif
- infof(data, "CONNECT phase completed");
- }
-}
-
-static CURLcode CONNECT_host(struct Curl_easy *data,
- struct connectdata *conn,
- const char *hostname,
- int remote_port,
- char **connecthostp,
- char **hostp)
-{
- char *hostheader; /* for CONNECT */
- char *host = NULL; /* Host: */
- bool ipv6_ip = conn->bits.ipv6_ip;
-
- /* the hostname may be different */
- if(hostname != conn->host.name)
- ipv6_ip = (strchr(hostname, ':') != NULL);
- hostheader = /* host:port with IPv6 support */
- aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
- remote_port);
- if(!hostheader)
- return CURLE_OUT_OF_MEMORY;
-
- if(!Curl_checkProxyheaders(data, conn, STRCONST("Host"))) {
- host = aprintf("Host: %s\r\n", hostheader);
- if(!host) {
- free(hostheader);
- return CURLE_OUT_OF_MEMORY;
- }
- }
- *connecthostp = hostheader;
- *hostp = host;
- return CURLE_OK;
-}
-
-#ifndef USE_HYPER
-static CURLcode CONNECT(struct Curl_easy *data,
- int sockindex,
- const char *hostname,
- int remote_port)
-{
- int subversion = 0;
- struct SingleRequest *k = &data->req;
- CURLcode result;
- struct connectdata *conn = data->conn;
- curl_socket_t tunnelsocket = conn->sock[sockindex];
- struct http_connect_state *s = conn->connect_state;
- struct HTTP *http = data->req.p.http;
- char *linep;
- size_t perline;
-
-#define SELECT_OK 0
-#define SELECT_ERROR 1
-
- if(Curl_connect_complete(conn))
- return CURLE_OK; /* CONNECT is already completed */
-
- conn->bits.proxy_connect_closed = FALSE;
-
- do {
- timediff_t check;
- if(TUNNEL_INIT == s->tunnel_state) {
- /* BEGIN CONNECT PHASE */
- struct dynbuf *req = &s->req;
- char *hostheader = NULL;
- char *host = NULL;
-
- infof(data, "Establish HTTP proxy tunnel to %s:%d",
- hostname, remote_port);
-
- /* This only happens if we've looped here due to authentication
- reasons, and we don't really use the newly cloned URL here
- then. Just free() it. */
- Curl_safefree(data->req.newurl);
-
- /* initialize send-buffer */
- Curl_dyn_init(req, DYN_HTTP_REQUEST);
-
- result = CONNECT_host(data, conn,
- hostname, remote_port, &hostheader, &host);
- if(result)
- return result;
-
- /* Setup the proxy-authorization header, if any */
- result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
- hostheader, TRUE);
-
- if(!result) {
- const char *httpv =
- (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";
-
- result =
- Curl_dyn_addf(req,
- "CONNECT %s HTTP/%s\r\n"
- "%s" /* Host: */
- "%s", /* Proxy-Authorization */
- hostheader,
- httpv,
- host?host:"",
- data->state.aptr.proxyuserpwd?
- data->state.aptr.proxyuserpwd:"");
-
- if(!result && !Curl_checkProxyheaders(data,
- conn, STRCONST("User-Agent")) &&
- data->set.str[STRING_USERAGENT])
- result = Curl_dyn_addf(req, "User-Agent: %s\r\n",
- data->set.str[STRING_USERAGENT]);
-
- if(!result && !Curl_checkProxyheaders(data, conn,
- STRCONST("Proxy-Connection")))
- result = Curl_dyn_addn(req,
- STRCONST("Proxy-Connection: Keep-Alive\r\n"));
-
- if(!result)
- result = Curl_add_custom_headers(data, TRUE, req);
-
- if(!result)
- /* CRLF terminate the request */
- result = Curl_dyn_addn(req, STRCONST("\r\n"));
-
- if(!result) {
- /* Send the connect request to the proxy */
- result = Curl_buffer_send(req, data, &data->info.request_size, 0,
- sockindex);
- s->headerlines = 0;
- }
- if(result)
- failf(data, "Failed sending CONNECT to proxy");
- }
- free(host);
- free(hostheader);
- if(result)
- return result;
-
- s->tunnel_state = TUNNEL_CONNECT;
- } /* END CONNECT PHASE */
-
- check = Curl_timeleft(data, NULL, TRUE);
- if(check <= 0) {
- failf(data, "Proxy CONNECT aborted due to timeout");
- return CURLE_OPERATION_TIMEDOUT;
- }
-
- if(!Curl_conn_data_pending(conn, sockindex) && !http->sending)
- /* return so we'll be called again polling-style */
- return CURLE_OK;
-
- /* at this point, the tunnel_connecting phase is over. */
-
- if(http->sending == HTTPSEND_REQUEST) {
- if(!s->nsend) {
- size_t fillcount;
- k->upload_fromhere = data->state.ulbuf;
- result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
- &fillcount);
- if(result)
- return result;
- s->nsend = fillcount;
- }
- if(s->nsend) {
- ssize_t bytes_written;
- /* write to socket (send away data) */
- result = Curl_write(data,
- conn->writesockfd, /* socket to send to */
- k->upload_fromhere, /* buffer pointer */
- s->nsend, /* buffer size */
- &bytes_written); /* actually sent */
-
- if(!result)
- /* send to debug callback! */
- result = Curl_debug(data, CURLINFO_HEADER_OUT,
- k->upload_fromhere, bytes_written);
-
- s->nsend -= bytes_written;
- k->upload_fromhere += bytes_written;
- return result;
- }
- http->sending = HTTPSEND_NADA;
- /* if nothing left to send, continue */
- }
- { /* READING RESPONSE PHASE */
- int error = SELECT_OK;
-
- while(s->keepon) {
- ssize_t gotbytes;
- char byte;
-
- /* Read one byte at a time to avoid a race condition. Wait at most one
- second before looping to ensure continuous pgrsUpdates. */
- result = Curl_read(data, tunnelsocket, &byte, 1, &gotbytes);
- if(result == CURLE_AGAIN)
- /* socket buffer drained, return */
- return CURLE_OK;
-
- if(Curl_pgrsUpdate(data))
- return CURLE_ABORTED_BY_CALLBACK;
-
- if(result) {
- s->keepon = KEEPON_DONE;
- break;
- }
- else if(gotbytes <= 0) {
- if(data->set.proxyauth && data->state.authproxy.avail &&
- data->state.aptr.proxyuserpwd) {
- /* proxy auth was requested and there was proxy auth available,
- then deem this as "mere" proxy disconnect */
- conn->bits.proxy_connect_closed = TRUE;
- infof(data, "Proxy CONNECT connection closed");
- }
- else {
- error = SELECT_ERROR;
- failf(data, "Proxy CONNECT aborted");
- }
- s->keepon = KEEPON_DONE;
- break;
- }
-
- if(s->keepon == KEEPON_IGNORE) {
- /* This means we are currently ignoring a response-body */
-
- if(s->cl) {
- /* A Content-Length based body: simply count down the counter
- and make sure to break out of the loop when we're done! */
- s->cl--;
- if(s->cl <= 0) {
- s->keepon = KEEPON_DONE;
- s->tunnel_state = TUNNEL_COMPLETE;
- break;
- }
- }
- else {
- /* chunked-encoded body, so we need to do the chunked dance
- properly to know when the end of the body is reached */
- CHUNKcode r;
- CURLcode extra;
- ssize_t tookcareof = 0;
-
- /* now parse the chunked piece of data so that we can
- properly tell when the stream ends */
- r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra);
- if(r == CHUNKE_STOP) {
- /* we're done reading chunks! */
- infof(data, "chunk reading DONE");
- s->keepon = KEEPON_DONE;
- /* we did the full CONNECT treatment, go COMPLETE */
- s->tunnel_state = TUNNEL_COMPLETE;
- }
- }
- continue;
- }
-
- if(Curl_dyn_addn(&s->rcvbuf, &byte, 1)) {
- failf(data, "CONNECT response too large");
- return CURLE_RECV_ERROR;
- }
-
- /* if this is not the end of a header line then continue */
- if(byte != 0x0a)
- continue;
-
- s->headerlines++;
- linep = Curl_dyn_ptr(&s->rcvbuf);
- perline = Curl_dyn_len(&s->rcvbuf); /* amount of bytes in this line */
-
- /* output debug if that is requested */
- Curl_debug(data, CURLINFO_HEADER_IN, linep, perline);
-
- if(!data->set.suppress_connect_headers) {
- /* send the header to the callback */
- int writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT |
- (data->set.include_header ? CLIENTWRITE_BODY : 0) |
- (s->headerlines == 1 ? CLIENTWRITE_STATUS : 0);
-
- result = Curl_client_write(data, writetype, linep, perline);
- if(result)
- return result;
- }
-
- data->info.header_size += (long)perline;
-
- /* Newlines are CRLF, so the CR is ignored as the line isn't
- really terminated until the LF comes. Treat a following CR
- as end-of-headers as well.*/
-
- if(('\r' == linep[0]) ||
- ('\n' == linep[0])) {
- /* end of response-headers from the proxy */
-
- if((407 == k->httpcode) && !data->state.authproblem) {
- /* If we get a 407 response code with content length
- when we have no auth problem, we must ignore the
- whole response-body */
- s->keepon = KEEPON_IGNORE;
-
- if(s->cl) {
- infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
- " bytes of response-body", s->cl);
- }
- else if(s->chunked_encoding) {
- CHUNKcode r;
- CURLcode extra;
-
- infof(data, "Ignore chunked response-body");
-
- /* We set ignorebody true here since the chunked decoder
- function will acknowledge that. Pay attention so that this is
- cleared again when this function returns! */
- k->ignorebody = TRUE;
-
- if(linep[1] == '\n')
- /* this can only be a LF if the letter at index 0 was a CR */
- linep++;
-
- /* now parse the chunked piece of data so that we can properly
- tell when the stream ends */
- r = Curl_httpchunk_read(data, linep + 1, 1, &gotbytes,
- &extra);
- if(r == CHUNKE_STOP) {
- /* we're done reading chunks! */
- infof(data, "chunk reading DONE");
- s->keepon = KEEPON_DONE;
- /* we did the full CONNECT treatment, go to COMPLETE */
- s->tunnel_state = TUNNEL_COMPLETE;
- }
- }
- else {
- /* without content-length or chunked encoding, we
- can't keep the connection alive since the close is
- the end signal so we bail out at once instead */
- s->keepon = KEEPON_DONE;
- }
- }
- else
- s->keepon = KEEPON_DONE;
-
- if(s->keepon == KEEPON_DONE && !s->cl)
- /* we did the full CONNECT treatment, go to COMPLETE */
- s->tunnel_state = TUNNEL_COMPLETE;
-
- DEBUGASSERT(s->keepon == KEEPON_IGNORE || s->keepon == KEEPON_DONE);
- continue;
- }
-
- if((checkprefix("WWW-Authenticate:", linep) &&
- (401 == k->httpcode)) ||
- (checkprefix("Proxy-authenticate:", linep) &&
- (407 == k->httpcode))) {
-
- bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
- char *auth = Curl_copy_header_value(linep);
- if(!auth)
- return CURLE_OUT_OF_MEMORY;
-
- result = Curl_http_input_auth(data, proxy, auth);
-
- free(auth);
-
- if(result)
- return result;
- }
- else if(checkprefix("Content-Length:", linep)) {
- if(k->httpcode/100 == 2) {
- /* A client MUST ignore any Content-Length or Transfer-Encoding
- header fields received in a successful response to CONNECT.
- "Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */
- infof(data, "Ignoring Content-Length in CONNECT %03d response",
- k->httpcode);
- }
- else {
- (void)curlx_strtoofft(linep +
- strlen("Content-Length:"), NULL, 10, &s->cl);
- }
- }
- else if(Curl_compareheader(linep,
- STRCONST("Connection:"), STRCONST("close")))
- s->close_connection = TRUE;
- else if(checkprefix("Transfer-Encoding:", linep)) {
- if(k->httpcode/100 == 2) {
- /* A client MUST ignore any Content-Length or Transfer-Encoding
- header fields received in a successful response to CONNECT.
- "Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */
- infof(data, "Ignoring Transfer-Encoding in "
- "CONNECT %03d response", k->httpcode);
- }
- else if(Curl_compareheader(linep,
- STRCONST("Transfer-Encoding:"),
- STRCONST("chunked"))) {
- infof(data, "CONNECT responded chunked");
- s->chunked_encoding = TRUE;
- /* init our chunky engine */
- Curl_httpchunk_init(data);
- }
- }
- else if(Curl_compareheader(linep,
- STRCONST("Proxy-Connection:"),
- STRCONST("close")))
- s->close_connection = TRUE;
- else if(2 == sscanf(linep, "HTTP/1.%d %d",
- &subversion,
- &k->httpcode)) {
- /* store the HTTP code from the proxy */
- data->info.httpproxycode = k->httpcode;
- }
-
- Curl_dyn_reset(&s->rcvbuf);
- } /* while there's buffer left and loop is requested */
-
- if(Curl_pgrsUpdate(data))
- return CURLE_ABORTED_BY_CALLBACK;
-
- if(error)
- return CURLE_RECV_ERROR;
-
- if(data->info.httpproxycode/100 != 2) {
- /* Deal with the possibly already received authenticate
- headers. 'newurl' is set to a new URL if we must loop. */
- result = Curl_http_auth_act(data);
- if(result)
- return result;
-
- if(conn->bits.close)
- /* the connection has been marked for closure, most likely in the
- Curl_http_auth_act() function and thus we can kill it at once
- below */
- s->close_connection = TRUE;
- }
-
- if(s->close_connection && data->req.newurl) {
- /* Connection closed by server. Don't use it anymore */
- Curl_closesocket(data, conn, conn->sock[sockindex]);
- conn->sock[sockindex] = CURL_SOCKET_BAD;
- break;
- }
- } /* END READING RESPONSE PHASE */
-
- /* If we are supposed to continue and request a new URL, which basically
- * means the HTTP authentication is still going on so if the tunnel
- * is complete we start over in INIT state */
- if(data->req.newurl && (TUNNEL_COMPLETE == s->tunnel_state)) {
- connect_init(data, TRUE); /* reinit */
- }
-
- } while(data->req.newurl);
-
- if(data->info.httpproxycode/100 != 2) {
- if(s->close_connection && data->req.newurl) {
- conn->bits.proxy_connect_closed = TRUE;
- infof(data, "Connect me again please");
- Curl_connect_done(data);
- }
- else {
- free(data->req.newurl);
- data->req.newurl = NULL;
- /* failure, close this connection to avoid re-use */
- streamclose(conn, "proxy CONNECT failure");
- }
-
- /* to back to init state */
- s->tunnel_state = TUNNEL_INIT;
-
- if(conn->bits.proxy_connect_closed)
- /* this is not an error, just part of the connection negotiation */
- return CURLE_OK;
- Curl_dyn_free(&s->rcvbuf);
- failf(data, "Received HTTP code %d from proxy after CONNECT",
- data->req.httpcode);
- return CURLE_RECV_ERROR;
+ /* subchain connected and we had already installed the protocol filter.
+ * This means the protocol tunnel is established, we are done.
+ */
+ DEBUGASSERT(ctx->cf_protocol);
+ result = CURLE_OK;
}
- s->tunnel_state = TUNNEL_COMPLETE;
-
- /* If a proxy-authorization header was used for the proxy, then we should
- make sure that it isn't accidentally used for the document request
- after we've connected. So let's free and clear it here. */
- Curl_safefree(data->state.aptr.proxyuserpwd);
- data->state.aptr.proxyuserpwd = NULL;
-
- data->state.authproxy.done = TRUE;
- data->state.authproxy.multipass = FALSE;
-
- infof(data, "Proxy replied %d to CONNECT request",
- data->info.httpproxycode);
- data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
- conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the
- document request */
- Curl_dyn_free(&s->rcvbuf);
- return CURLE_OK;
-}
-#else
-/* The Hyper version of CONNECT */
-static CURLcode CONNECT(struct Curl_easy *data,
- int sockindex,
- const char *hostname,
- int remote_port)
-{
- struct connectdata *conn = data->conn;
- struct hyptransfer *h = &data->hyp;
- curl_socket_t tunnelsocket = conn->sock[sockindex];
- struct http_connect_state *s = conn->connect_state;
- CURLcode result = CURLE_OUT_OF_MEMORY;
- hyper_io *io = NULL;
- hyper_request *req = NULL;
- hyper_headers *headers = NULL;
- hyper_clientconn_options *options = NULL;
- hyper_task *handshake = NULL;
- hyper_task *task = NULL; /* for the handshake */
- hyper_task *sendtask = NULL; /* for the send */
- hyper_clientconn *client = NULL;
- hyper_error *hypererr = NULL;
- char *hostheader = NULL; /* for CONNECT */
- char *host = NULL; /* Host: */
-
- if(Curl_connect_complete(conn))
- return CURLE_OK; /* CONNECT is already completed */
-
- conn->bits.proxy_connect_closed = FALSE;
-
- do {
- switch(s->tunnel_state) {
- case TUNNEL_INIT:
- /* BEGIN CONNECT PHASE */
- io = hyper_io_new();
- if(!io) {
- failf(data, "Couldn't create hyper IO");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- /* tell Hyper how to read/write network data */
- hyper_io_set_userdata(io, data);
- hyper_io_set_read(io, Curl_hyper_recv);
- hyper_io_set_write(io, Curl_hyper_send);
- conn->sockfd = tunnelsocket;
-
- data->state.hconnect = TRUE;
-
- /* create an executor to poll futures */
- if(!h->exec) {
- h->exec = hyper_executor_new();
- if(!h->exec) {
- failf(data, "Couldn't create hyper executor");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- }
-
- options = hyper_clientconn_options_new();
- hyper_clientconn_options_set_preserve_header_case(options, 1);
- hyper_clientconn_options_set_preserve_header_order(options, 1);
-
- if(!options) {
- failf(data, "Couldn't create hyper client options");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
-
- hyper_clientconn_options_exec(options, h->exec);
-
- /* "Both the `io` and the `options` are consumed in this function
- call" */
- handshake = hyper_clientconn_handshake(io, options);
- if(!handshake) {
- failf(data, "Couldn't create hyper client handshake");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- io = NULL;
- options = NULL;
-
- if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
- failf(data, "Couldn't hyper_executor_push the handshake");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- handshake = NULL; /* ownership passed on */
-
- task = hyper_executor_poll(h->exec);
- if(!task) {
- failf(data, "Couldn't hyper_executor_poll the handshake");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
-
- client = hyper_task_value(task);
- hyper_task_free(task);
- req = hyper_request_new();
- if(!req) {
- failf(data, "Couldn't hyper_request_new");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- if(hyper_request_set_method(req, (uint8_t *)"CONNECT",
- strlen("CONNECT"))) {
- failf(data, "error setting method");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
-
- infof(data, "Establish HTTP proxy tunnel to %s:%d",
- hostname, remote_port);
-
- /* This only happens if we've looped here due to authentication
- reasons, and we don't really use the newly cloned URL here
- then. Just free() it. */
- Curl_safefree(data->req.newurl);
-
- result = CONNECT_host(data, conn, hostname, remote_port,
- &hostheader, &host);
- if(result)
- goto error;
-
- if(hyper_request_set_uri(req, (uint8_t *)hostheader,
- strlen(hostheader))) {
- failf(data, "error setting path");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- if(data->set.verbose) {
- char *se = aprintf("CONNECT %s HTTP/1.1\r\n", hostheader);
- if(!se) {
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- Curl_debug(data, CURLINFO_HEADER_OUT, se, strlen(se));
- free(se);
- }
- /* Setup the proxy-authorization header, if any */
- result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
- hostheader, TRUE);
- if(result)
- goto error;
- Curl_safefree(hostheader);
-
- /* default is 1.1 */
- if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) &&
- (HYPERE_OK != hyper_request_set_version(req,
- HYPER_HTTP_VERSION_1_0))) {
- failf(data, "error setting HTTP version");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
-
- headers = hyper_request_headers(req);
- if(!headers) {
- failf(data, "hyper_request_headers");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- if(host) {
- result = Curl_hyper_header(data, headers, host);
- if(result)
- goto error;
- Curl_safefree(host);
- }
-
- if(data->state.aptr.proxyuserpwd) {
- result = Curl_hyper_header(data, headers,
- data->state.aptr.proxyuserpwd);
- if(result)
- goto error;
- }
-
- if(!Curl_checkProxyheaders(data, conn, STRCONST("User-Agent")) &&
- data->set.str[STRING_USERAGENT]) {
- struct dynbuf ua;
- Curl_dyn_init(&ua, DYN_HTTP_REQUEST);
- result = Curl_dyn_addf(&ua, "User-Agent: %s\r\n",
- data->set.str[STRING_USERAGENT]);
- if(result)
- goto error;
- result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&ua));
- if(result)
- goto error;
- Curl_dyn_free(&ua);
- }
-
- if(!Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection"))) {
- result = Curl_hyper_header(data, headers,
- "Proxy-Connection: Keep-Alive");
- if(result)
- goto error;
- }
-
- result = Curl_add_custom_headers(data, TRUE, headers);
- if(result)
- goto error;
-
- sendtask = hyper_clientconn_send(client, req);
- if(!sendtask) {
- failf(data, "hyper_clientconn_send");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
-
- if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
- failf(data, "Couldn't hyper_executor_push the send");
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
-
- hyper_clientconn_free(client);
-
- do {
- task = hyper_executor_poll(h->exec);
- if(task) {
- bool error = hyper_task_type(task) == HYPER_TASK_ERROR;
- if(error)
- hypererr = hyper_task_value(task);
- hyper_task_free(task);
- if(error) {
- /* this could probably use a better error code? */
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- }
- } while(task);
- s->tunnel_state = TUNNEL_CONNECT;
- /* FALLTHROUGH */
- case TUNNEL_CONNECT: {
- int didwhat;
- bool done = FALSE;
- result = Curl_hyper_stream(data, conn, &didwhat, &done,
- CURL_CSELECT_IN | CURL_CSELECT_OUT);
- if(result)
- goto error;
- if(!done)
- break;
- s->tunnel_state = TUNNEL_COMPLETE;
- if(h->exec) {
- hyper_executor_free(h->exec);
- h->exec = NULL;
- }
- if(h->read_waker) {
- hyper_waker_free(h->read_waker);
- h->read_waker = NULL;
- }
- if(h->write_waker) {
- hyper_waker_free(h->write_waker);
- h->write_waker = NULL;
- }
- }
- break;
-
- default:
- break;
- }
-
- if(conn->bits.close && data->req.newurl) {
- /* Connection closed by server. Don't use it anymore */
- Curl_closesocket(data, conn, conn->sock[sockindex]);
- conn->sock[sockindex] = CURL_SOCKET_BAD;
- break;
- }
-
- /* If we are supposed to continue and request a new URL, which basically
- * means the HTTP authentication is still going on so if the tunnel
- * is complete we start over in INIT state */
- if(data->req.newurl && (TUNNEL_COMPLETE == s->tunnel_state)) {
- infof(data, "CONNECT request done, loop to make another");
- connect_init(data, TRUE); /* reinit */
- }
- } while(data->req.newurl);
-
- result = CURLE_OK;
- if(s->tunnel_state == TUNNEL_COMPLETE) {
- if(data->info.httpproxycode/100 != 2) {
- if(conn->bits.close && data->req.newurl) {
- conn->bits.proxy_connect_closed = TRUE;
- infof(data, "Connect me again please");
- Curl_connect_done(data);
- }
- else {
- free(data->req.newurl);
- data->req.newurl = NULL;
- /* failure, close this connection to avoid re-use */
- streamclose(conn, "proxy CONNECT failure");
- Curl_closesocket(data, conn, conn->sock[sockindex]);
- conn->sock[sockindex] = CURL_SOCKET_BAD;
- }
-
- /* to back to init state */
- s->tunnel_state = TUNNEL_INIT;
-
- if(!conn->bits.proxy_connect_closed) {
- failf(data, "Received HTTP code %d from proxy after CONNECT",
- data->req.httpcode);
- result = CURLE_RECV_ERROR;
- }
- }
- }
- error:
- free(host);
- free(hostheader);
- if(io)
- hyper_io_free(io);
-
- if(options)
- hyper_clientconn_options_free(options);
-
- if(handshake)
- hyper_task_free(handshake);
-
- if(hypererr) {
- uint8_t errbuf[256];
- size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
- failf(data, "Hyper: %.*s", (int)errlen, errbuf);
- hyper_error_free(hypererr);
+out:
+ if(!result) {
+ cf->connected = TRUE;
+ *done = TRUE;
}
return result;
}
-#endif
-void Curl_connect_free(struct Curl_easy *data)
-{
- struct connectdata *conn = data->conn;
- struct http_connect_state *s = conn->connect_state;
- if(s) {
- free(s);
- conn->connect_state = NULL;
- }
-}
-
-/*
- * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
- * function will issue the necessary commands to get a seamless tunnel through
- * this proxy. After that, the socket can be used just as a normal socket.
- */
-
-CURLcode Curl_proxyCONNECT(struct Curl_easy *data,
- int sockindex,
- const char *hostname,
- int remote_port)
-{
- CURLcode result;
- struct connectdata *conn = data->conn;
- if(!conn->connect_state) {
- result = connect_init(data, FALSE);
- if(result)
- return result;
- }
- result = CONNECT(data, sockindex, hostname, remote_port);
-
- if(result || Curl_connect_complete(conn))
- Curl_connect_done(data);
-
- return result;
-}
-
-#else
-void Curl_connect_free(struct Curl_easy *data)
+void Curl_cf_http_proxy_get_host(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char **phost,
+ const char **pdisplay_host,
+ int *pport)
{
(void)data;
+ if(!cf->connected) {
+ *phost = cf->conn->http_proxy.host.name;
+ *pdisplay_host = cf->conn->http_proxy.host.dispname;
+ *pport = (int)cf->conn->http_proxy.port;
+ }
+ else {
+ cf->next->cft->get_host(cf->next, data, phost, pdisplay_host, pport);
+ }
}
-#endif /* CURL_DISABLE_PROXY */
+static void http_proxy_cf_destroy(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_proxy_ctx *ctx = cf->ctx;
+
+ (void)data;
+ DEBUGF(LOG_CF(data, cf, "destroy"));
+ free(ctx);
+}
+
+static void http_proxy_cf_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_proxy_ctx *ctx = cf->ctx;
+
+ DEBUGF(LOG_CF(data, cf, "close"));
+ cf->connected = FALSE;
+ if(ctx->cf_protocol) {
+ struct Curl_cfilter *f;
+ /* if someone already removed it, we assume he also
+ * took care of destroying it. */
+ for(f = cf->next; f; f = f->next) {
+ if(f == ctx->cf_protocol) {
+ /* still in our sub-chain */
+ Curl_conn_cf_discard_sub(cf, ctx->cf_protocol, data, FALSE);
+ break;
+ }
+ }
+ ctx->cf_protocol = NULL;
+ }
+ if(cf->next)
+ cf->next->cft->do_close(cf->next, data);
+}
+
+
+struct Curl_cftype Curl_cft_http_proxy = {
+ "HTTP-PROXY",
+ CF_TYPE_IP_CONNECT,
+ 0,
+ http_proxy_cf_destroy,
+ http_proxy_cf_connect,
+ http_proxy_cf_close,
+ Curl_cf_http_proxy_get_host,
+ Curl_cf_def_get_select_socks,
+ Curl_cf_def_data_pending,
+ Curl_cf_def_send,
+ Curl_cf_def_recv,
+ Curl_cf_def_cntrl,
+ Curl_cf_def_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ Curl_cf_def_query,
+};
+
+CURLcode Curl_cf_http_proxy_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf;
+ struct cf_proxy_ctx *ctx = NULL;
+ CURLcode result;
+
+ (void)data;
+ ctx = calloc(1, sizeof(*ctx));
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ result = Curl_cf_create(&cf, &Curl_cft_http_proxy, ctx);
+ if(result)
+ goto out;
+ ctx = NULL;
+ Curl_conn_cf_insert_after(cf_at, cf);
+
+out:
+ free(ctx);
+ return result;
+}
+
+#endif /* ! CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */
diff --git a/lib/http_proxy.h b/lib/http_proxy.h
index 1e650ee..a1a0372 100644
--- a/lib/http_proxy.h
+++ b/lib/http_proxy.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,57 +25,28 @@
***************************************************************************/
#include "curl_setup.h"
-#include "urldata.h"
#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
-/* ftp can use this as well */
-CURLcode Curl_proxyCONNECT(struct Curl_easy *data,
- int tunnelsocket,
- const char *hostname, int remote_port);
+
+#include "urldata.h"
/* Default proxy timeout in milliseconds */
#define PROXY_TIMEOUT (3600*1000)
-CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex);
+void Curl_cf_http_proxy_get_host(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char **phost,
+ const char **pdisplay_host,
+ int *pport);
-bool Curl_connect_complete(struct connectdata *conn);
-bool Curl_connect_ongoing(struct connectdata *conn);
-int Curl_connect_getsock(struct connectdata *conn);
-void Curl_connect_done(struct Curl_easy *data);
+CURLcode Curl_cf_http_proxy_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data);
-#else
-#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN
-#define Curl_proxy_connect(x,y) CURLE_OK
-#define Curl_connect_complete(x) CURLE_OK
-#define Curl_connect_ongoing(x) FALSE
-#define Curl_connect_getsock(x) 0
-#define Curl_connect_done(x)
-#endif
+extern struct Curl_cftype Curl_cft_http_proxy;
-void Curl_connect_free(struct Curl_easy *data);
+#endif /* !CURL_DISABLE_PROXY && !CURL_DISABLE_HTTP */
-/* struct for HTTP CONNECT state data */
-struct http_connect_state {
- struct HTTP http_proxy;
- struct HTTP *prot_save;
- struct dynbuf rcvbuf;
- struct dynbuf req;
- size_t nsend;
- size_t headerlines;
- enum keeponval {
- KEEPON_DONE,
- KEEPON_CONNECT,
- KEEPON_IGNORE
- } keepon;
- curl_off_t cl; /* size of content to read and ignore */
- enum {
- TUNNEL_INIT, /* init/default/no tunnel state */
- TUNNEL_CONNECT, /* CONNECT has been sent off */
- TUNNEL_COMPLETE, /* CONNECT response received completely */
- TUNNEL_EXIT
- } tunnel_state;
- BIT(chunked_encoding);
- BIT(close_connection);
-};
+#define IS_HTTPS_PROXY(t) (((t) == CURLPROXY_HTTPS) || \
+ ((t) == CURLPROXY_HTTPS2))
#endif /* HEADER_CURL_HTTP_PROXY_H */
diff --git a/lib/idn.c b/lib/idn.c
new file mode 100644
index 0000000..5f4b07e
--- /dev/null
+++ b/lib/idn.c
@@ -0,0 +1,202 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+ /*
+ * IDN conversions
+ */
+
+#include "curl_setup.h"
+#include "urldata.h"
+#include "idn.h"
+#include "sendf.h"
+#include "curl_multibyte.h"
+#include "warnless.h"
+
+#ifdef USE_LIBIDN2
+#include <idn2.h>
+
+#if defined(WIN32) && defined(UNICODE)
+#define IDN2_LOOKUP(name, host, flags) \
+ idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags)
+#else
+#define IDN2_LOOKUP(name, host, flags) \
+ idn2_lookup_ul((const char *)name, (char **)host, flags)
+#endif
+#endif /* USE_LIBIDN2 */
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifdef USE_WIN32_IDN
+/* using Windows kernel32 and normaliz libraries. */
+
+#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x600
+WINBASEAPI int WINAPI IdnToAscii(DWORD dwFlags,
+ const WCHAR *lpUnicodeCharStr,
+ int cchUnicodeChar,
+ WCHAR *lpASCIICharStr,
+ int cchASCIIChar);
+WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags,
+ const WCHAR *lpASCIICharStr,
+ int cchASCIIChar,
+ WCHAR *lpUnicodeCharStr,
+ int cchUnicodeChar);
+#endif
+
+#define IDN_MAX_LENGTH 255
+
+bool Curl_win32_idn_to_ascii(const char *in, char **out)
+{
+ bool success = FALSE;
+
+ wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
+ if(in_w) {
+ wchar_t punycode[IDN_MAX_LENGTH];
+ int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH);
+ curlx_unicodefree(in_w);
+ if(chars) {
+ char *mstr = curlx_convert_wchar_to_UTF8(punycode);
+ if(mstr) {
+ *out = strdup(mstr);
+ curlx_unicodefree(mstr);
+ if(*out)
+ success = TRUE;
+ }
+ }
+ }
+
+ return success;
+}
+
+#endif /* USE_WIN32_IDN */
+
+/*
+ * Helpers for IDNA conversions.
+ */
+bool Curl_is_ASCII_name(const char *hostname)
+{
+ /* get an UNSIGNED local version of the pointer */
+ const unsigned char *ch = (const unsigned char *)hostname;
+
+ if(!hostname) /* bad input, consider it ASCII! */
+ return TRUE;
+
+ while(*ch) {
+ if(*ch++ & 0x80)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#ifdef USE_IDN
+/*
+ * Curl_idn_decode() returns an allocated IDN decoded string if it was
+ * possible. NULL on error.
+ */
+static char *idn_decode(const char *input)
+{
+ char *decoded = NULL;
+#ifdef USE_LIBIDN2
+ if(idn2_check_version(IDN2_VERSION)) {
+ int flags = IDN2_NFC_INPUT
+#if IDN2_VERSION_NUMBER >= 0x00140000
+ /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
+ IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
+ processing. */
+ | IDN2_NONTRANSITIONAL
+#endif
+ ;
+ int rc = IDN2_LOOKUP(input, &decoded, flags);
+ if(rc != IDN2_OK)
+ /* fallback to TR46 Transitional mode for better IDNA2003
+ compatibility */
+ rc = IDN2_LOOKUP(input, &decoded, IDN2_TRANSITIONAL);
+ if(rc != IDN2_OK)
+ decoded = NULL;
+ }
+#elif defined(USE_WIN32_IDN)
+ if(!Curl_win32_idn_to_ascii(input, &decoded))
+ decoded = NULL;
+#endif
+ return decoded;
+}
+
+char *Curl_idn_decode(const char *input)
+{
+ char *d = idn_decode(input);
+#ifdef USE_LIBIDN2
+ if(d) {
+ char *c = strdup(d);
+ idn2_free(d);
+ d = c;
+ }
+#endif
+ return d;
+}
+
+/*
+ * Frees data allocated by idnconvert_hostname()
+ */
+void Curl_free_idnconverted_hostname(struct hostname *host)
+{
+ if(host->encalloc) {
+ /* must be freed with idn2_free() if allocated by libidn */
+ Curl_idn_free(host->encalloc);
+ host->encalloc = NULL;
+ }
+}
+
+#endif /* USE_IDN */
+
+/*
+ * Perform any necessary IDN conversion of hostname
+ */
+CURLcode Curl_idnconvert_hostname(struct hostname *host)
+{
+ /* set the name we use to display the host name */
+ host->dispname = host->name;
+
+#ifdef USE_IDN
+ /* Check name for non-ASCII and convert hostname if we can */
+ if(!Curl_is_ASCII_name(host->name)) {
+ char *decoded = idn_decode(host->name);
+ if(decoded) {
+ if(!*decoded) {
+ /* zero length is a bad host name */
+ Curl_idn_free(decoded);
+ return CURLE_URL_MALFORMAT;
+ }
+ /* successful */
+ host->encalloc = decoded;
+ /* change the name pointer to point to the encoded hostname */
+ host->name = host->encalloc;
+ }
+ else
+ return CURLE_URL_MALFORMAT;
+ }
+#endif
+ return CURLE_OK;
+}
diff --git a/lib/idn.h b/lib/idn.h
new file mode 100644
index 0000000..6c0bbb7
--- /dev/null
+++ b/lib/idn.h
@@ -0,0 +1,46 @@
+#ifndef HEADER_CURL_IDN_H
+#define HEADER_CURL_IDN_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#ifdef USE_WIN32_IDN
+bool Curl_win32_idn_to_ascii(const char *in, char **out);
+#endif /* USE_WIN32_IDN */
+bool Curl_is_ASCII_name(const char *hostname);
+CURLcode Curl_idnconvert_hostname(struct hostname *host);
+#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
+#define USE_IDN
+void Curl_free_idnconverted_hostname(struct hostname *host);
+char *Curl_idn_decode(const char *input);
+#ifdef USE_LIBIDN2
+#define Curl_idn_free(x) idn2_free(x)
+#else
+#define Curl_idn_free(x) free(x)
+#endif
+
+#else
+#define Curl_free_idnconverted_hostname(x)
+#define Curl_idn_decode(x) NULL
+#endif
+#endif /* HEADER_CURL_IDN_H */
diff --git a/lib/idn_win32.c b/lib/idn_win32.c
deleted file mode 100644
index dacba01..0000000
--- a/lib/idn_win32.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
- /*
- * IDN conversions using Windows kernel32 and normaliz libraries.
- */
-
-#include "curl_setup.h"
-
-#ifdef USE_WIN32_IDN
-
-#include "curl_multibyte.h"
-#include "curl_memory.h"
-#include "warnless.h"
-
- /* The last #include file should be: */
-#include "memdebug.h"
-
-#ifdef WANT_IDN_PROTOTYPES
-# if defined(_SAL_VERSION)
-WINNORMALIZEAPI int WINAPI
-IdnToAscii(_In_ DWORD dwFlags,
- _In_reads_(cchUnicodeChar) LPCWSTR lpUnicodeCharStr,
- _In_ int cchUnicodeChar,
- _Out_writes_opt_(cchASCIIChar) LPWSTR lpASCIICharStr,
- _In_ int cchASCIIChar);
-WINNORMALIZEAPI int WINAPI
-IdnToUnicode(_In_ DWORD dwFlags,
- _In_reads_(cchASCIIChar) LPCWSTR lpASCIICharStr,
- _In_ int cchASCIIChar,
- _Out_writes_opt_(cchUnicodeChar) LPWSTR lpUnicodeCharStr,
- _In_ int cchUnicodeChar);
-# else
-WINBASEAPI int WINAPI IdnToAscii(DWORD dwFlags,
- const WCHAR *lpUnicodeCharStr,
- int cchUnicodeChar,
- WCHAR *lpASCIICharStr,
- int cchASCIIChar);
-WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags,
- const WCHAR *lpASCIICharStr,
- int cchASCIIChar,
- WCHAR *lpUnicodeCharStr,
- int cchUnicodeChar);
-# endif
-#endif
-
-#define IDN_MAX_LENGTH 255
-
-bool curl_win32_idn_to_ascii(const char *in, char **out);
-bool curl_win32_ascii_to_idn(const char *in, char **out);
-
-bool curl_win32_idn_to_ascii(const char *in, char **out)
-{
- bool success = FALSE;
-
- wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
- if(in_w) {
- wchar_t punycode[IDN_MAX_LENGTH];
- int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH);
- curlx_unicodefree(in_w);
- if(chars) {
- char *mstr = curlx_convert_wchar_to_UTF8(punycode);
- if(mstr) {
- *out = strdup(mstr);
- curlx_unicodefree(mstr);
- if(*out)
- success = TRUE;
- }
- }
- }
-
- return success;
-}
-
-bool curl_win32_ascii_to_idn(const char *in, char **out)
-{
- bool success = FALSE;
-
- wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
- if(in_w) {
- size_t in_len = wcslen(in_w) + 1;
- wchar_t unicode[IDN_MAX_LENGTH];
- int chars = IdnToUnicode(0, in_w, curlx_uztosi(in_len),
- unicode, IDN_MAX_LENGTH);
- curlx_unicodefree(in_w);
- if(chars) {
- char *mstr = curlx_convert_wchar_to_UTF8(unicode);
- if(mstr) {
- *out = strdup(mstr);
- curlx_unicodefree(mstr);
- if(*out)
- success = TRUE;
- }
- }
- }
-
- return success;
-}
-
-#endif /* USE_WIN32_IDN */
diff --git a/lib/if2ip.c b/lib/if2ip.c
index c291948..6bf0ce1 100644
--- a/lib/if2ip.c
+++ b/lib/if2ip.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/if2ip.h b/lib/if2ip.h
index 5d15459..1f97350 100644
--- a/lib/if2ip.h
+++ b/lib/if2ip.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/imap.c b/lib/imap.c
index 4b46ef1..045fe24 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -56,11 +56,6 @@
#include <inet.h>
#endif
-#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
-#undef in_addr_t
-#define in_addr_t unsigned long
-#endif
-
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
@@ -75,14 +70,15 @@
#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
+#include "cfilters.h"
#include "connect.h"
#include "select.h"
#include "multiif.h"
#include "url.h"
-#include "strcase.h"
#include "bufref.h"
#include "curl_sasl.h"
#include "warnless.h"
+#include "curl_ctype.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -389,11 +385,11 @@
/***********************************************************************
*
- * state()
+ * imap_state()
*
* This is the ONLY way to change IMAP state!
*/
-static void state(struct Curl_easy *data, imapstate newstate)
+static void imap_state(struct Curl_easy *data, imapstate newstate)
{
struct imap_conn *imapc = &data->conn->proto.imapc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -445,7 +441,7 @@
result = imap_sendf(data, "CAPABILITY");
if(!result)
- state(data, IMAP_CAPABILITY);
+ imap_state(data, IMAP_CAPABILITY);
return result;
}
@@ -462,7 +458,7 @@
CURLcode result = imap_sendf(data, "STARTTLS");
if(!result)
- state(data, IMAP_STARTTLS);
+ imap_state(data, IMAP_STARTTLS);
return result;
}
@@ -478,19 +474,27 @@
{
/* Start the SSL connection */
struct imap_conn *imapc = &conn->proto.imapc;
- CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
- FIRSTSOCKET, &imapc->ssldone);
+ CURLcode result;
+ bool ssldone = FALSE;
+ if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
+ result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
+ if(result)
+ goto out;
+ }
+
+ result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
if(!result) {
+ imapc->ssldone = ssldone;
if(imapc->state != IMAP_UPGRADETLS)
- state(data, IMAP_UPGRADETLS);
+ imap_state(data, IMAP_UPGRADETLS);
if(imapc->ssldone) {
imap_to_imaps(conn);
result = imap_perform_capability(data, conn);
}
}
-
+out:
return result;
}
@@ -510,7 +514,7 @@
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!data->state.aptr.user) {
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -527,7 +531,7 @@
free(passwd);
if(!result)
- state(data, IMAP_LOGIN);
+ imap_state(data, IMAP_LOGIN);
return result;
}
@@ -611,7 +615,7 @@
with and end the connect phase if we don't */
if(imapc->preauth ||
!Curl_sasl_can_authenticate(&imapc->sasl, data)) {
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -620,7 +624,7 @@
if(!result) {
if(progress == SASL_INPROGRESS)
- state(data, IMAP_AUTHENTICATE);
+ imap_state(data, IMAP_AUTHENTICATE);
else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
/* Perform clear text authentication */
result = imap_perform_login(data, conn);
@@ -663,7 +667,7 @@
}
if(!result)
- state(data, IMAP_LIST);
+ imap_state(data, IMAP_LIST);
return result;
}
@@ -703,7 +707,7 @@
free(mailbox);
if(!result)
- state(data, IMAP_SELECT);
+ imap_state(data, IMAP_SELECT);
return result;
}
@@ -745,7 +749,7 @@
return CURLE_URL_MALFORMAT;
}
if(!result)
- state(data, IMAP_FETCH);
+ imap_state(data, IMAP_FETCH);
return result;
}
@@ -775,7 +779,7 @@
/* Add external headers and mime version. */
curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
- result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
+ result = Curl_mime_prepare_headers(data, &data->set.mimepost, NULL,
NULL, MIMESTRATEGY_MAIL);
if(!result)
@@ -816,7 +820,7 @@
free(mailbox);
if(!result)
- state(data, IMAP_APPEND);
+ imap_state(data, IMAP_APPEND);
return result;
}
@@ -842,7 +846,7 @@
result = imap_sendf(data, "SEARCH %s", imap->query);
if(!result)
- state(data, IMAP_SEARCH);
+ imap_state(data, IMAP_SEARCH);
return result;
}
@@ -859,7 +863,7 @@
CURLcode result = imap_sendf(data, "LOGOUT");
if(!result)
- state(data, IMAP_LOGOUT);
+ imap_state(data, IMAP_LOGOUT);
return result;
}
@@ -950,7 +954,7 @@
line += wordlen;
}
}
- else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ else if(data->set.use_ssl && !Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
/* PREAUTH is not compatible with STARTTLS. */
if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) {
/* Switch to TLS connection now */
@@ -1013,7 +1017,7 @@
if(!result)
switch(progress) {
case SASL_DONE:
- state(data, IMAP_STOP); /* Authenticated */
+ imap_state(data, IMAP_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
if((!imapc->login_disabled) && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
@@ -1045,7 +1049,7 @@
}
else
/* End of connect phase */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -1071,7 +1075,7 @@
result = CURLE_QUOTE_ERROR;
else
/* End of DO phase */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -1139,7 +1143,7 @@
if(imapcode != '*') {
Curl_pgrsSetDownloadSize(data, -1);
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return CURLE_REMOTE_FILE_NOT_FOUND;
}
@@ -1174,7 +1178,7 @@
if(!chunk) {
/* no size, we're done with the data */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return CURLE_OK;
}
result = Curl_client_write(data, CLIENTWRITE_BODY, pp->cache, chunk);
@@ -1220,7 +1224,7 @@
}
/* End of DO phase */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -1238,7 +1242,7 @@
result = CURLE_WEIRD_SERVER_REPLY;
else
/* End of DONE phase */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -1261,7 +1265,7 @@
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
/* End of DO phase */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
}
return result;
@@ -1280,7 +1284,7 @@
result = CURLE_UPLOAD_FAILED;
else
/* End of DONE phase */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -1368,7 +1372,7 @@
/* fallthrough, just stop! */
default:
/* internal error */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
break;
}
} while(!result && imapc->state != IMAP_STOP && Curl_pp_moredata(pp));
@@ -1384,9 +1388,10 @@
struct imap_conn *imapc = &conn->proto.imapc;
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
- result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
- FIRSTSOCKET, &imapc->ssldone);
- if(result || !imapc->ssldone)
+ bool ssldone = FALSE;
+ result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
+ imapc->ssldone = ssldone;
+ if(result || !ssldone)
return result;
}
@@ -1470,7 +1475,7 @@
return result;
/* Start off waiting for the server greeting response */
- state(data, IMAP_SERVERGREET);
+ imap_state(data, IMAP_SERVERGREET);
/* Start off with an response id of '*' */
strcpy(imapc->resptag, "*");
@@ -1506,17 +1511,17 @@
result = status; /* use the already set error code */
}
else if(!data->set.connect_only && !imap->custom &&
- (imap->uid || imap->mindex || data->set.upload ||
+ (imap->uid || imap->mindex || data->state.upload ||
data->set.mimepost.kind != MIMEKIND_NONE)) {
/* Handle responses after FETCH or APPEND transfer has finished */
- if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE)
- state(data, IMAP_FETCH_FINAL);
+ if(!data->state.upload && data->set.mimepost.kind == MIMEKIND_NONE)
+ imap_state(data, IMAP_FETCH_FINAL);
else {
/* End the APPEND command first by sending an empty line */
result = Curl_pp_sendf(data, &conn->proto.imapc.pp, "%s", "");
if(!result)
- state(data, IMAP_APPEND_FINAL);
+ imap_state(data, IMAP_APPEND_FINAL);
}
/* Run the state-machine */
@@ -1560,7 +1565,7 @@
DEBUGF(infof(data, "DO phase starts"));
- if(data->set.opt_no_body) {
+ if(data->req.no_body) {
/* Requested no body means no transfer */
imap->transfer = PPTRANSFER_INFO;
}
@@ -1576,7 +1581,7 @@
selected = TRUE;
/* Start the first command in the DO phase */
- if(data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE)
+ if(data->state.upload || data->set.mimepost.kind != MIMEKIND_NONE)
/* APPEND can be executed directly */
result = imap_perform_append(data);
else if(imap->custom && (selected || !imap->mailbox))
@@ -1602,7 +1607,7 @@
/* Run the state-machine */
result = imap_multi_statemach(data, dophase_done);
- *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+ *connected = Curl_conn_is_connected(conn, FIRSTSOCKET);
if(*dophase_done)
DEBUGF(infof(data, "DO phase is complete"));
@@ -1772,8 +1777,8 @@
/* Calculate the tag based on the connection ID and command ID */
msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
- 'A' + curlx_sltosi(data->conn->connection_id % 26),
- (++imapc->cmdid)%1000);
+ 'A' + curlx_sltosi((long)(data->conn->connection_id % 26)),
+ ++imapc->cmdid);
/* start with a blank buffer */
Curl_dyn_reset(&imapc->dyn);
@@ -1885,22 +1890,17 @@
*/
static bool imap_is_bchar(char ch)
{
+ /* Performing the alnum check with this macro is faster because of ASCII
+ arithmetic */
+ if(ISALNUM(ch))
+ return true;
+
switch(ch) {
/* bchar */
case ':': case '@': case '/':
/* bchar -> achar */
case '&': case '=':
- /* bchar -> achar -> uchar -> unreserved */
- case '0': case '1': case '2': case '3': case '4': case '5': case '6':
- case '7': case '8': case '9':
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
- case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
- case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
- case 'V': case 'W': case 'X': case 'Y': case 'Z':
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
- case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
- case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
- case 'v': case 'w': case 'x': case 'y': case 'z':
+ /* bchar -> achar -> uchar -> unreserved (without alphanumeric) */
case '-': case '.': case '_': case '~':
/* bchar -> achar -> uchar -> sub-delims-sh */
case '!': case '$': case '\'': case '(': case ')': case '*':
@@ -1925,39 +1925,53 @@
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
const char *ptr = conn->options;
+ bool prefer_login = false;
while(!result && ptr && *ptr) {
const char *key = ptr;
const char *value;
while(*ptr && *ptr != '=')
- ptr++;
+ ptr++;
value = ptr + 1;
while(*ptr && *ptr != ';')
ptr++;
- if(strncasecompare(key, "AUTH=", 5))
+ if(strncasecompare(key, "AUTH=+LOGIN", 11)) {
+ /* User prefers plaintext LOGIN over any SASL, including SASL LOGIN */
+ prefer_login = true;
+ imapc->sasl.prefmech = SASL_AUTH_NONE;
+ }
+ else if(strncasecompare(key, "AUTH=", 5)) {
+ prefer_login = false;
result = Curl_sasl_parse_url_auth_option(&imapc->sasl,
value, ptr - value);
- else
+ }
+ else {
+ prefer_login = false;
result = CURLE_URL_MALFORMAT;
+ }
if(*ptr == ';')
ptr++;
}
- switch(imapc->sasl.prefmech) {
- case SASL_AUTH_NONE:
- imapc->preftype = IMAP_TYPE_NONE;
- break;
- case SASL_AUTH_DEFAULT:
- imapc->preftype = IMAP_TYPE_ANY;
- break;
- default:
- imapc->preftype = IMAP_TYPE_SASL;
- break;
+ if(prefer_login)
+ imapc->preftype = IMAP_TYPE_CLEARTEXT;
+ else {
+ switch(imapc->sasl.prefmech) {
+ case SASL_AUTH_NONE:
+ imapc->preftype = IMAP_TYPE_NONE;
+ break;
+ case SASL_AUTH_DEFAULT:
+ imapc->preftype = IMAP_TYPE_ANY;
+ break;
+ default:
+ imapc->preftype = IMAP_TYPE_SASL;
+ break;
+ }
}
return result;
diff --git a/lib/imap.h b/lib/imap.h
index 43cc1e9..784ee97 100644
--- a/lib/imap.h
+++ b/lib/imap.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -72,19 +72,19 @@
struct */
struct imap_conn {
struct pingpong pp;
- imapstate state; /* Always use imap.c:state() to change state! */
- bool ssldone; /* Is connect() over SSL done? */
- bool preauth; /* Is this connection PREAUTH? */
struct SASL sasl; /* SASL-related parameters */
- unsigned int preftype; /* Preferred authentication type */
- unsigned int cmdid; /* Last used command ID */
- char resptag[5]; /* Response tag to wait for */
- bool tls_supported; /* StartTLS capability supported by server */
- bool login_disabled; /* LOGIN command disabled by server */
- bool ir_supported; /* Initial response supported by server */
+ struct dynbuf dyn; /* for the IMAP commands */
char *mailbox; /* The last selected mailbox */
char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */
- struct dynbuf dyn; /* for the IMAP commands */
+ imapstate state; /* Always use imap.c:state() to change state! */
+ char resptag[5]; /* Response tag to wait for */
+ unsigned char preftype; /* Preferred authentication type */
+ unsigned char cmdid; /* Last used command ID */
+ BIT(ssldone); /* Is connect() over SSL done? */
+ BIT(preauth); /* Is this connection PREAUTH? */
+ BIT(tls_supported); /* StartTLS capability supported by server */
+ BIT(login_disabled); /* LOGIN command disabled by server */
+ BIT(ir_supported); /* Initial response supported by server */
};
extern const struct Curl_handler Curl_handler_imap;
@@ -96,6 +96,6 @@
/* Authentication type values */
#define IMAP_TYPE_NONE 0
-#define IMAP_TYPE_ANY ~0U
+#define IMAP_TYPE_ANY (IMAP_TYPE_CLEARTEXT|IMAP_TYPE_SASL)
#endif /* HEADER_CURL_IMAP_H */
diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c
index 024f8da..fa90773 100644
--- a/lib/inet_ntop.c
+++ b/lib/inet_ntop.c
@@ -42,6 +42,15 @@
#define INT16SZ 2
/*
+ * If ENABLE_IPV6 is disabled, we still want to parse IPv6 addresses, so make
+ * sure we have _some_ value for AF_INET6 without polluting our fake value
+ * everywhere.
+ */
+#if !defined(ENABLE_IPV6) && !defined(AF_INET6)
+#define AF_INET6 (AF_INET + 1)
+#endif
+
+/*
* Format an IPv4 address, more or less like inet_ntop().
*
* Returns `dst' (as a const)
@@ -72,7 +81,6 @@
return dst;
}
-#ifdef ENABLE_IPV6
/*
* Convert IPv6 binary address into presentation (printable) format.
*/
@@ -156,7 +164,7 @@
/* Was it a trailing run of 0x00's?
*/
if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
- *tp++ = ':';
+ *tp++ = ':';
*tp++ = '\0';
/* Check for overflow, copy, and we're done.
@@ -168,7 +176,6 @@
strcpy(dst, tmp);
return dst;
}
-#endif /* ENABLE_IPV6 */
/*
* Convert a network format address to presentation format.
@@ -187,10 +194,8 @@
switch(af) {
case AF_INET:
return inet_ntop4((const unsigned char *)src, buf, size);
-#ifdef ENABLE_IPV6
case AF_INET6:
return inet_ntop6((const unsigned char *)src, buf, size);
-#endif
default:
errno = EAFNOSUPPORT;
return NULL;
diff --git a/lib/inet_ntop.h b/lib/inet_ntop.h
index 18fbd8b..7c3ead4 100644
--- a/lib/inet_ntop.h
+++ b/lib/inet_ntop.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/inet_pton.c b/lib/inet_pton.c
index 47fb778..7d3c698 100644
--- a/lib/inet_pton.c
+++ b/lib/inet_pton.c
@@ -1,6 +1,6 @@
/* This is from the BIND 4.9.4 release, modified to compile by itself */
-/* Copyright (c) 2003 - 2022 by Internet Software Consortium.
+/* Copyright (c) Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -39,14 +39,21 @@
#define INT16SZ 2
/*
+ * If ENABLE_IPV6 is disabled, we still want to parse IPv6 addresses, so make
+ * sure we have _some_ value for AF_INET6 without polluting our fake value
+ * everywhere.
+ */
+#if !defined(ENABLE_IPV6) && !defined(AF_INET6)
+#define AF_INET6 (AF_INET + 1)
+#endif
+
+/*
* WARNING: Don't even consider trying to compile this on a system where
* 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);
-#ifdef ENABLE_IPV6
static int inet_pton6(const char *src, unsigned char *dst);
-#endif
/* int
* inet_pton(af, src, dst)
@@ -70,10 +77,8 @@
switch(af) {
case AF_INET:
return (inet_pton4(src, (unsigned char *)dst));
-#ifdef ENABLE_IPV6
case AF_INET6:
return (inet_pton6(src, (unsigned char *)dst));
-#endif
default:
errno = EAFNOSUPPORT;
return (-1);
@@ -135,7 +140,6 @@
return (1);
}
-#ifdef ENABLE_IPV6
/* int
* inet_pton6(src, dst)
* convert presentation level address to network order binary form.
@@ -234,6 +238,5 @@
memcpy(dst, tmp, IN6ADDRSZ);
return (1);
}
-#endif /* ENABLE_IPV6 */
#endif /* HAVE_INET_PTON */
diff --git a/lib/inet_pton.h b/lib/inet_pton.h
index 92ae93e..82fde7e 100644
--- a/lib/inet_pton.h
+++ b/lib/inet_pton.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/krb5.c b/lib/krb5.c
index 517491c..80e4015 100644
--- a/lib/krb5.c
+++ b/lib/krb5.c
@@ -2,7 +2,7 @@
*
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
- * Copyright (c) 2004 - 2022 Daniel Stenberg
+ * Copyright (C) Daniel Stenberg
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -41,8 +41,13 @@
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
#include "urldata.h"
+#include "cfilters.h"
+#include "cf-socket.h"
#include "curl_base64.h"
#include "ftp.h"
#include "curl_gssapi.h"
@@ -204,8 +209,8 @@
gss_ctx_id_t *context = app_data;
struct gss_channel_bindings_struct chan;
size_t base64_sz = 0;
- struct sockaddr_in **remote_addr =
- (struct sockaddr_in **)&conn->ip_addr->ai_addr;
+ struct sockaddr_in *remote_addr =
+ (struct sockaddr_in *)(void *)&conn->remote_addr->sa_addr;
char *stringp;
if(getsockname(conn->sock[FIRSTSOCKET],
@@ -217,7 +222,7 @@
chan.initiator_address.value = &conn->local_addr.sin_addr.s_addr;
chan.acceptor_addrtype = GSS_C_AF_INET;
chan.acceptor_address.length = l - 4;
- chan.acceptor_address.value = &(*remote_addr)->sin_addr.s_addr;
+ chan.acceptor_address.value = &remote_addr->sin_addr.s_addr;
chan.application_data.length = 0;
chan.application_data.value = NULL;
@@ -256,7 +261,7 @@
}
/* We pass NULL as |output_name_type| to avoid a leak. */
gss_display_name(&min, gssname, &output_buffer, NULL);
- infof(data, "Trying against %s", output_buffer.value);
+ infof(data, "Trying against %s", (char *)output_buffer.value);
gssresp = GSS_C_NO_BUFFER;
*context = GSS_C_NO_CONTEXT;
@@ -451,15 +456,15 @@
/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode
saying whether an error occurred or CURLE_OK if |len| was read. */
static CURLcode
-socket_read(curl_socket_t fd, void *to, size_t len)
+socket_read(struct Curl_easy *data, int sockindex, void *to, size_t len)
{
char *to_p = to;
CURLcode result;
ssize_t nread = 0;
while(len > 0) {
- result = Curl_read_plain(fd, to_p, len, &nread);
- if(!result) {
+ nread = Curl_conn_recv(data, sockindex, to_p, len, &result);
+ if(nread > 0) {
len -= nread;
to_p += nread;
}
@@ -477,7 +482,7 @@
CURLcode saying whether an error occurred or CURLE_OK if |len| was
written. */
static CURLcode
-socket_write(struct Curl_easy *data, curl_socket_t fd, const void *to,
+socket_write(struct Curl_easy *data, int sockindex, const void *to,
size_t len)
{
const char *to_p = to;
@@ -485,8 +490,8 @@
ssize_t written;
while(len > 0) {
- result = Curl_write_plain(data, fd, to_p, len, &written);
- if(!result) {
+ written = Curl_conn_send(data, sockindex, to_p, len, &result);
+ if(written > 0) {
len -= written;
to_p += written;
}
@@ -499,15 +504,15 @@
return CURLE_OK;
}
-static CURLcode read_data(struct connectdata *conn,
- curl_socket_t fd,
+static CURLcode read_data(struct Curl_easy *data, int sockindex,
struct krb5buffer *buf)
{
+ struct connectdata *conn = data->conn;
int len;
CURLcode result;
int nread;
- result = socket_read(fd, &len, sizeof(len));
+ result = socket_read(data, sockindex, &len, sizeof(len));
if(result)
return result;
@@ -522,7 +527,7 @@
if(!len || !buf->data)
return CURLE_OUT_OF_MEMORY;
- result = socket_read(fd, buf->data, len);
+ result = socket_read(data, sockindex, buf->data, len);
if(result)
return result;
nread = conn->mech->decode(conn->app_data, buf->data, len,
@@ -551,13 +556,12 @@
size_t bytes_read;
size_t total_read = 0;
struct connectdata *conn = data->conn;
- curl_socket_t fd = conn->sock[sockindex];
*err = CURLE_OK;
/* Handle clear text response. */
if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR)
- return sread(fd, buffer, len);
+ return Curl_conn_recv(data, sockindex, buffer, len, err);
if(conn->in_buffer.eof_flag) {
conn->in_buffer.eof_flag = 0;
@@ -570,7 +574,7 @@
buffer += bytes_read;
while(len > 0) {
- if(read_data(conn, fd, &conn->in_buffer))
+ if(read_data(data, sockindex, &conn->in_buffer))
return -1;
if(conn->in_buffer.size == 0) {
if(bytes_read > 0)
@@ -717,8 +721,7 @@
return 0;
if(buf[3] != '-')
- /* safe to ignore return code */
- (void)sscanf(buf, "%d", &ret_code);
+ ret_code = atoi(buf);
if(buf[decoded_len - 1] == '\n')
buf[decoded_len - 1] = '\0';
@@ -761,8 +764,9 @@
pbsz = strstr(data->state.buffer, "PBSZ=");
if(pbsz) {
- /* ignore return code, use default value if it fails */
- (void)sscanf(pbsz, "PBSZ=%u", &buffer_size);
+ /* stick to default value if the check fails */
+ if(!strncmp(pbsz, "PBSZ=", 5) && ISDIGIT(pbsz[5]))
+ buffer_size = atoi(&pbsz[5]);
if(buffer_size < conn->buffer_size)
conn->buffer_size = buffer_size;
}
diff --git a/lib/ldap.c b/lib/ldap.c
index 51a32dc..6b30ffb 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,7 +37,27 @@
* OpenLDAP library versions, USE_OPENLDAP shall not be defined.
*/
+/* Wincrypt must be included before anything that could include OpenSSL. */
+#if defined(USE_WIN32_CRYPTO)
+#include <wincrypt.h>
+/* Undefine wincrypt conflicting symbols for BoringSSL. */
+#undef X509_NAME
+#undef X509_EXTENSIONS
+#undef PKCS7_ISSUER_AND_SERIAL
+#undef PKCS7_SIGNER_INFO
+#undef OCSP_REQUEST
+#undef OCSP_RESPONSE
+#endif
+
#ifdef USE_WIN32_LDAP /* Use Windows LDAP implementation. */
+# ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4201)
+# endif
+# include <subauth.h> /* for [P]UNICODE_STRING */
+# ifdef _MSC_VER
+# pragma warning(pop)
+# endif
# include <winldap.h>
# ifndef LDAP_VENDOR_NAME
# error Your Platform SDK is NOT sufficient for LDAP support! \
@@ -128,6 +148,14 @@
#define ldap_err2string ldap_err2stringA
#endif
+#if defined(USE_WIN32_LDAP) && defined(_MSC_VER) && (_MSC_VER <= 1600)
+/* Workaround for warning:
+ 'type cast' : conversion from 'int' to 'void *' of greater size */
+#undef LDAP_OPT_ON
+#undef LDAP_OPT_OFF
+#define LDAP_OPT_ON ((void *)(size_t)1)
+#define LDAP_OPT_OFF ((void *)(size_t)0)
+#endif
static CURLcode ldap_do(struct Curl_easy *data, bool *done);
@@ -344,7 +372,7 @@
#ifdef HAVE_LDAP_SSL
#ifdef USE_WIN32_LDAP
/* Win32 LDAP SDK doesn't support insecure mode without CA! */
- server = ldap_sslinit(host, (int)conn->port, 1);
+ server = ldap_sslinit(host, conn->port, 1);
ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
#else
int ldap_option;
@@ -390,9 +418,9 @@
result = CURLE_SSL_CERTPROBLEM;
goto quit;
}
- server = ldapssl_init(host, (int)conn->port, 1);
+ server = ldapssl_init(host, conn->port, 1);
if(!server) {
- failf(data, "LDAP local: Cannot connect to %s:%ld",
+ failf(data, "LDAP local: Cannot connect to %s:%u",
conn->host.dispname, conn->port);
result = CURLE_COULDNT_CONNECT;
goto quit;
@@ -431,9 +459,9 @@
result = CURLE_SSL_CERTPROBLEM;
goto quit;
}
- server = ldap_init(host, (int)conn->port);
+ server = ldap_init(host, conn->port);
if(!server) {
- failf(data, "LDAP local: Cannot connect to %s:%ld",
+ failf(data, "LDAP local: Cannot connect to %s:%u",
conn->host.dispname, conn->port);
result = CURLE_COULDNT_CONNECT;
goto quit;
@@ -472,9 +500,9 @@
goto quit;
}
else {
- server = ldap_init(host, (int)conn->port);
+ server = ldap_init(host, conn->port);
if(!server) {
- failf(data, "LDAP local: Cannot connect to %s:%ld",
+ failf(data, "LDAP local: Cannot connect to %s:%u",
conn->host.dispname, conn->port);
result = CURLE_COULDNT_CONNECT;
goto quit;
@@ -553,8 +581,7 @@
goto quit;
}
- result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) name,
- name_len);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, name, name_len);
if(result) {
FREE_ON_WINLDAP(name);
ldap_memfree(dn);
@@ -610,8 +637,7 @@
goto quit;
}
- result = Curl_client_write(data, CLIENTWRITE_BODY,
- (char *) attr, attr_len);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, attr, attr_len);
if(result) {
ldap_value_free_len(vals);
FREE_ON_WINLDAP(attr);
@@ -636,7 +662,7 @@
dlsize += attr_len + 3;
if((attr_len > 7) &&
- (strcmp(";binary", (char *) attr + (attr_len - 7)) == 0)) {
+ (strcmp(";binary", attr + (attr_len - 7)) == 0)) {
/* Binary attribute, encode to base64. */
result = Curl_base64_encode(vals[i]->bv_val, vals[i]->bv_len,
&val_b64, &val_b64_sz);
@@ -713,7 +739,7 @@
}
if(ber)
- ber_free(ber, 0);
+ ber_free(ber, 0);
}
quit:
@@ -1051,7 +1077,7 @@
*ludpp = NULL;
if(!ludp)
- return LDAP_NO_MEMORY;
+ return LDAP_NO_MEMORY;
rc = _ldap_url_parse2(data, conn, ludp);
if(rc != LDAP_SUCCESS) {
diff --git a/lib/libcurl.rc b/lib/libcurl.rc
index 23134a7..daa2d62 100644
--- a/lib/libcurl.rc
+++ b/lib/libcurl.rc
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/llist.c b/lib/llist.c
index fa2d366..5b6b033 100644
--- a/lib/llist.c
+++ b/lib/llist.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/llist.h b/lib/llist.h
index 2fcb91c..320580e 100644
--- a/lib/llist.h
+++ b/lib/llist.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/macos.c b/lib/macos.c
new file mode 100644
index 0000000..5fe4e0b
--- /dev/null
+++ b/lib/macos.c
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(__APPLE__)
+
+#if !defined(TARGET_OS_OSX) || TARGET_OS_OSX
+
+#include <curl/curl.h>
+
+#include "macos.h"
+
+#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
+#include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
+#endif
+
+CURLcode Curl_macos_init(void)
+{
+#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
+ {
+ /*
+ * The automagic conversion from IPv4 literals to IPv6 literals only
+ * works if the SCDynamicStoreCopyProxies system function gets called
+ * first. As Curl currently doesn't support system-wide HTTP proxies, we
+ * therefore don't use any value this function might return.
+ *
+ * This function is only available on a macOS and is not needed for
+ * IPv4-only builds, hence the conditions above.
+ */
+ CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);
+ if(dict)
+ CFRelease(dict);
+ }
+#endif
+ return CURLE_OK;
+}
+
+#endif /* TARGET_OS_OSX */
+
+#endif /* __APPLE__ */
diff --git a/lib/vquic/msh3.h b/lib/macos.h
similarity index 76%
rename from lib/vquic/msh3.h
rename to lib/macos.h
index ce884d9..3388acd 100644
--- a/lib/vquic/msh3.h
+++ b/lib/macos.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_VQUIC_MSH3_H
-#define HEADER_CURL_VQUIC_MSH3_H
+#ifndef HEADER_CURL_MACOS_H
+#define HEADER_CURL_MACOS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,18 +23,16 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-
#include "curl_setup.h"
-#ifdef USE_MSH3
+#if defined(__APPLE__) && (!defined(TARGET_OS_OSX) || TARGET_OS_OSX)
-#include <msh3.h>
+CURLcode Curl_macos_init(void);
-struct quicsocket {
- MSH3_API* api;
- MSH3_CONNECTION* conn;
-};
+#else
-#endif /* USE_MSQUIC */
+#define Curl_macos_init() CURLE_OK
-#endif /* HEADER_CURL_VQUIC_MSH3_H */
+#endif
+
+#endif /* HEADER_CURL_MACOS_H */
diff --git a/lib/makefile.dj b/lib/makefile.dj
deleted file mode 100644
index bb95f2b..0000000
--- a/lib/makefile.dj
+++ /dev/null
@@ -1,73 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 2003 - 2022, Gisle Vanem <gvanem@yahoo.no>.
-# Copyright (C) 2003 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-#***************************************************************************
-
-#
-# Adapted for djgpp2 / Watt-32 / DOS
-#
-
-DEPEND_PREREQ = curl_config.h
-VPATH = vtls vauth vquic vssh
-TOPDIR = ..
-
-include ../packages/DOS/common.dj
-include Makefile.inc
-
-CFLAGS += -DBUILDING_LIBCURL
-
-SOURCES = $(sort $(CSOURCES))
-OBJECTS = $(addprefix $(OBJ_DIR)/, $(notdir $(SOURCES:.c=.o)))
-
-CURL_LIB = libcurl.a
-
-all: $(OBJ_DIR) curl_config.h $(CURL_LIB)
-
-$(CURL_LIB): $(OBJECTS)
- ar rs $@ $?
-
-curl_config.h: config-dos.h
- $(COPY) $^ $@
-
-# clean generated files
-#
-genclean:
- - $(DELETE) curl_config.h
-
-# clean object files and subdir
-#
-objclean: genclean
- - $(DELETE) $(OBJ_DIR)$(DS)*.o
- - $(RMDIR) $(OBJ_DIR)
-
-# clean without removing built library
-#
-clean: objclean
- - $(DELETE) depend.dj
-
-# clean everything
-#
-realclean vclean: clean
- - $(DELETE) $(CURL_LIB)
-
--include depend.dj
diff --git a/lib/md4.c b/lib/md4.c
index 63bade0..9ff093b 100644
--- a/lib/md4.c
+++ b/lib/md4.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,15 +24,17 @@
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+#if defined(USE_CURL_NTLM_CORE)
+
+#include <string.h>
#include "curl_md4.h"
#include "warnless.h"
-
#ifdef USE_OPENSSL
#include <openssl/opensslconf.h>
-#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \
+ !defined(USE_AMISSL)
/* OpenSSL 3.0.0 marks the MD4 functions as deprecated */
#define OPENSSL_NO_MD4
#endif
@@ -52,21 +54,42 @@
#else
#include <mbedtls/config.h>
#endif
-
#if(MBEDTLS_VERSION_NUMBER >= 0x02070000)
#define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
#endif
#endif /* USE_MBEDTLS */
#if defined(USE_GNUTLS)
-
#include <nettle/md4.h>
+/* When OpenSSL or wolfSSL is available, we use their MD4 functions. */
+#elif defined(USE_WOLFSSL) && !defined(WOLFSSL_NO_MD4)
+#include <wolfssl/openssl/md4.h>
+#elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
+#include <openssl/md4.h>
+#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
+ (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
+ defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
+ (__MAC_OS_X_VERSION_MIN_REQUIRED < 101500)) || \
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
+ (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000) && \
+ defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && \
+ (__IPHONE_OS_VERSION_MIN_REQUIRED < 130000))
+#define AN_APPLE_OS
+#include <CommonCrypto/CommonDigest.h>
+#elif defined(USE_WIN32_CRYPTO)
+#include <wincrypt.h>
+#elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C))
+#include <mbedtls/md4.h>
+#endif
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
#include "curl_memory.h"
-
-/* The last #include file should be: */
#include "memdebug.h"
+
+#if defined(USE_GNUTLS)
+
typedef struct md4_ctx MD4_CTX;
static void MD4_Init(MD4_CTX *ctx)
@@ -84,27 +107,11 @@
md4_digest(ctx, MD4_DIGEST_SIZE, result);
}
-/* When OpenSSL or wolfSSL is available, we use their MD4 functions. */
#elif defined(USE_WOLFSSL) && !defined(WOLFSSL_NO_MD4)
-#include <wolfssl/openssl/md4.h>
#elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
-#include <openssl/md4.h>
-#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
- (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
- defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \
- (__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \
- (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
- (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
-
-#include <CommonCrypto/CommonDigest.h>
-
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
+#elif defined(AN_APPLE_OS)
typedef CC_MD4_CTX MD4_CTX;
static void MD4_Init(MD4_CTX *ctx)
@@ -124,13 +131,6 @@
#elif defined(USE_WIN32_CRYPTO)
-#include <wincrypt.h>
-
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
struct md4_ctx {
HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
@@ -170,13 +170,6 @@
#elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C))
-#include <mbedtls/md4.h>
-
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
struct md4_ctx {
void *data;
unsigned long size;
@@ -254,9 +247,6 @@
* compile-time configuration.
*/
-
-#include <string.h>
-
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD4_u32plus;
@@ -516,4 +506,4 @@
MD4_Final(output, &ctx);
}
-#endif /* CURL_DISABLE_CRYPTO_AUTH */
+#endif /* USE_CURL_NTLM_CORE */
diff --git a/lib/md5.c b/lib/md5.c
index 2164e15..0a02cc0 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,6 +26,7 @@
#ifndef CURL_DISABLE_CRYPTO_AUTH
+#include <string.h>
#include <curl/curl.h>
#include "curl_md5.h"
@@ -41,7 +42,7 @@
#endif
#endif /* USE_MBEDTLS */
-#if defined(USE_OPENSSL) && !defined(USE_AMISSL)
+#ifdef USE_OPENSSL
#include <openssl/opensslconf.h>
#if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_DEPRECATED_3_0)
#define USE_OPENSSL_MD5
@@ -56,12 +57,34 @@
#endif
#if defined(USE_GNUTLS)
-
#include <nettle/md5.h>
+#elif defined(USE_OPENSSL_MD5)
+#include <openssl/md5.h>
+#elif defined(USE_WOLFSSL_MD5)
+#include <wolfssl/openssl/md5.h>
+#elif defined(USE_MBEDTLS)
+#include <mbedtls/md5.h>
+#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
+ (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
+ defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
+ (__MAC_OS_X_VERSION_MIN_REQUIRED < 101500)) || \
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
+ (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000) && \
+ defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && \
+ (__IPHONE_OS_VERSION_MIN_REQUIRED < 130000))
+#define AN_APPLE_OS
+#include <CommonCrypto/CommonDigest.h>
+#elif defined(USE_WIN32_CRYPTO)
+#include <wincrypt.h>
+#endif
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
#include "curl_memory.h"
-/* The last #include file should be: */
#include "memdebug.h"
+#if defined(USE_GNUTLS)
+
typedef struct md5_ctx my_md5_ctx;
static CURLcode my_md5_init(my_md5_ctx *ctx)
@@ -84,17 +107,6 @@
#elif defined(USE_OPENSSL_MD5) || defined(USE_WOLFSSL_MD5)
-/* When OpenSSL or wolfSSL is available, we use their MD5 functions. */
-#if defined(USE_OPENSSL_MD5)
-#include <openssl/md5.h>
-#elif defined(USE_WOLFSSL_MD5)
-#include <wolfssl/openssl/md5.h>
-#endif
-
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
-
typedef MD5_CTX my_md5_ctx;
static CURLcode my_md5_init(my_md5_ctx *ctx)
@@ -119,13 +131,6 @@
#elif defined(USE_MBEDTLS)
-#include <mbedtls/md5.h>
-
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
typedef mbedtls_md5_context my_md5_ctx;
static CURLcode my_md5_init(my_md5_ctx *ctx)
@@ -162,12 +167,7 @@
#endif
}
-#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
- (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
- defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \
- (__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \
- (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
- (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
+#elif defined(AN_APPLE_OS)
/* For Apple operating systems: CommonCrypto has the functions we need.
These functions are available on Tiger and later, as well as iOS 2.0
@@ -175,11 +175,7 @@
Declaring the functions as static like this seems to be a bit more
reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */
-# include <CommonCrypto/CommonDigest.h>
# define my_md5_ctx CC_MD5_CTX
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
static CURLcode my_md5_init(my_md5_ctx *ctx)
{
@@ -203,11 +199,6 @@
#elif defined(USE_WIN32_CRYPTO)
-#include <wincrypt.h>
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
-
struct md5_ctx {
HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
@@ -288,12 +279,6 @@
* compile-time configuration.
*/
-#include <string.h>
-
-/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
-
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD5_u32plus;
diff --git a/lib/memdebug.c b/lib/memdebug.c
index f35a55f..d6952a0 100644
--- a/lib/memdebug.c
+++ b/lib/memdebug.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -129,7 +129,8 @@
return FALSE; /* allow this */
}
-void *curl_dbg_malloc(size_t wantedsize, int line, const char *source)
+ALLOC_FUNC void *curl_dbg_malloc(size_t wantedsize,
+ int line, const char *source)
{
struct memdebug *mem;
size_t size;
@@ -155,8 +156,8 @@
return (mem ? mem->mem : NULL);
}
-void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size,
- int line, const char *source)
+ALLOC_FUNC void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size,
+ int line, const char *source)
{
struct memdebug *mem;
size_t size, user_size;
@@ -183,7 +184,8 @@
return (mem ? mem->mem : NULL);
}
-char *curl_dbg_strdup(const char *str, int line, const char *source)
+ALLOC_FUNC char *curl_dbg_strdup(const char *str,
+ int line, const char *source)
{
char *mem;
size_t len;
@@ -207,7 +209,8 @@
}
#if defined(WIN32) && defined(UNICODE)
-wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source)
+ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
+ int line, const char *source)
{
wchar_t *mem;
size_t wsiz, bsiz;
@@ -410,8 +413,8 @@
return res;
}
-FILE *curl_dbg_fopen(const char *file, const char *mode,
- int line, const char *source)
+ALLOC_FUNC FILE *curl_dbg_fopen(const char *file, const char *mode,
+ int line, const char *source)
{
FILE *res = fopen(file, mode);
@@ -422,8 +425,8 @@
return res;
}
-FILE *curl_dbg_fdopen(int filedes, const char *mode,
- int line, const char *source)
+ALLOC_FUNC FILE *curl_dbg_fdopen(int filedes, const char *mode,
+ int line, const char *source)
{
FILE *res = fdopen(filedes, mode);
if(source)
diff --git a/lib/memdebug.h b/lib/memdebug.h
index 3e41571..c9eb5dc 100644
--- a/lib/memdebug.h
+++ b/lib/memdebug.h
@@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,21 +30,44 @@
* as well as the library. Do not mix with library internals!
*/
+#include <curl/curl.h>
+#include "functypes.h"
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+# define ALLOC_FUNC __attribute__((malloc))
+# define ALLOC_SIZE(s) __attribute__((alloc_size(s)))
+# define ALLOC_SIZE2(n, s) __attribute__((alloc_size(n, s)))
+#elif defined(_MSC_VER)
+# define ALLOC_FUNC __declspec(restrict)
+# define ALLOC_SIZE(s)
+# define ALLOC_SIZE2(n, s)
+#else
+# define ALLOC_FUNC
+# define ALLOC_SIZE(s)
+# define ALLOC_SIZE2(n, s)
+#endif
+
#define CURL_MT_LOGFNAME_BUFSIZE 512
extern FILE *curl_dbg_logfile;
/* memory functions */
-CURL_EXTERN void *curl_dbg_malloc(size_t size, int line, const char *source);
-CURL_EXTERN void *curl_dbg_calloc(size_t elements, size_t size, int line,
- const char *source);
-CURL_EXTERN void *curl_dbg_realloc(void *ptr, size_t size, int line,
- const char *source);
+CURL_EXTERN ALLOC_FUNC ALLOC_SIZE(1) void *curl_dbg_malloc(size_t size,
+ int line,
+ const char *source);
+CURL_EXTERN ALLOC_FUNC ALLOC_SIZE2(1, 2) void *curl_dbg_calloc(size_t elements,
+ size_t size, int line, const char *source);
+CURL_EXTERN ALLOC_SIZE(2) void *curl_dbg_realloc(void *ptr,
+ size_t size,
+ int line,
+ const char *source);
CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source);
-CURL_EXTERN char *curl_dbg_strdup(const char *str, int line, const char *src);
+CURL_EXTERN ALLOC_FUNC char *curl_dbg_strdup(const char *str, int line,
+ const char *src);
#if defined(WIN32) && defined(UNICODE)
-CURL_EXTERN wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line,
- const char *source);
+CURL_EXTERN ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
+ int line,
+ const char *source);
#endif
CURL_EXTERN void curl_dbg_memdebug(const char *logname);
@@ -79,10 +102,10 @@
const char *source);
/* FILE functions */
-CURL_EXTERN FILE *curl_dbg_fopen(const char *file, const char *mode, int line,
- const char *source);
-CURL_EXTERN FILE *curl_dbg_fdopen(int filedes, const char *mode,
+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);
CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source);
diff --git a/lib/mime.c b/lib/mime.c
index 11e614d..0a57e1e 100644
--- a/lib/mime.c
+++ b/lib/mime.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,8 +31,9 @@
#include "urldata.h"
#include "sendf.h"
-#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
- !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
+#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
+ !defined(CURL_DISABLE_SMTP) || \
+ !defined(CURL_DISABLE_IMAP))
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
#include <libgen.h>
@@ -83,7 +84,7 @@
};
/* Base64 encoding table */
-static const char base64[] =
+static const char base64enc[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* Quoted-printable character class table.
@@ -468,10 +469,10 @@
i = st->buf[st->bufbeg++] & 0xFF;
i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
- *ptr++ = base64[(i >> 18) & 0x3F];
- *ptr++ = base64[(i >> 12) & 0x3F];
- *ptr++ = base64[(i >> 6) & 0x3F];
- *ptr++ = base64[i & 0x3F];
+ *ptr++ = base64enc[(i >> 18) & 0x3F];
+ *ptr++ = base64enc[(i >> 12) & 0x3F];
+ *ptr++ = base64enc[(i >> 6) & 0x3F];
+ *ptr++ = base64enc[i & 0x3F];
cursize += 4;
st->pos += 4;
size -= 4;
@@ -495,10 +496,10 @@
i = (st->buf[st->bufbeg + 1] & 0xFF) << 8;
i |= (st->buf[st->bufbeg] & 0xFF) << 16;
- ptr[0] = base64[(i >> 18) & 0x3F];
- ptr[1] = base64[(i >> 12) & 0x3F];
+ ptr[0] = base64enc[(i >> 18) & 0x3F];
+ ptr[1] = base64enc[(i >> 12) & 0x3F];
if(++st->bufbeg != st->bufend) {
- ptr[2] = base64[(i >> 6) & 0x3F];
+ ptr[2] = base64enc[(i >> 6) & 0x3F];
st->bufbeg++;
}
cursize += 4;
@@ -749,7 +750,6 @@
part->fp = NULL;
}
Curl_safefree(part->data);
- part->data = NULL;
}
@@ -1107,7 +1107,7 @@
return CURL_SEEKFUNC_CANTSEEK; /* Only support full rewind. */
if(mime->state.state == MIMESTATE_BEGIN)
- return CURL_SEEKFUNC_OK; /* Already rewound. */
+ return CURL_SEEKFUNC_OK; /* Already rewound. */
for(part = mime->firstpart; part; part = part->nextpart) {
int res = mime_part_rewind(part);
@@ -1174,7 +1174,7 @@
Curl_safefree(part->mimetype);
Curl_safefree(part->name);
Curl_safefree(part->filename);
- Curl_mime_initpart(part, part->easy);
+ Curl_mime_initpart(part);
}
/* Recursively delete a mime handle and its parts. */
@@ -1194,7 +1194,8 @@
}
}
-CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
+CURLcode Curl_mime_duppart(struct Curl_easy *data,
+ curl_mimepart *dst, const curl_mimepart *src)
{
curl_mime *mime;
curl_mimepart *d;
@@ -1223,13 +1224,13 @@
case MIMEKIND_MULTIPART:
/* No one knows about the cloned subparts, thus always attach ownership
to the part. */
- mime = curl_mime_init(dst->easy);
+ mime = curl_mime_init(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) {
d = curl_mime_addpart(mime);
- res = d? Curl_mime_duppart(d, s): CURLE_OUT_OF_MEMORY;
+ res = d? Curl_mime_duppart(data, d, s): CURLE_OUT_OF_MEMORY;
}
break;
default: /* Invalid kind: should not occur. */
@@ -1281,7 +1282,6 @@
mime = (curl_mime *) malloc(sizeof(*mime));
if(mime) {
- mime->easy = easy;
mime->parent = NULL;
mime->firstpart = NULL;
mime->lastpart = NULL;
@@ -1301,10 +1301,9 @@
}
/* Initialize a mime part. */
-void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
+void Curl_mime_initpart(curl_mimepart *part)
{
memset((char *) part, 0, sizeof(*part));
- part->easy = easy;
part->lastreadstatus = 1; /* Successful read status. */
mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
}
@@ -1320,7 +1319,7 @@
part = (curl_mimepart *) malloc(sizeof(*part));
if(part) {
- Curl_mime_initpart(part, mime->easy);
+ Curl_mime_initpart(part);
part->parent = mime;
if(mime->lastpart)
@@ -1341,7 +1340,6 @@
return CURLE_BAD_FUNCTION_ARGUMENT;
Curl_safefree(part->name);
- part->name = NULL;
if(name) {
part->name = strdup(name);
@@ -1359,7 +1357,6 @@
return CURLE_BAD_FUNCTION_ARGUMENT;
Curl_safefree(part->filename);
- part->filename = NULL;
if(filename) {
part->filename = strdup(filename);
@@ -1459,7 +1456,6 @@
return CURLE_BAD_FUNCTION_ARGUMENT;
Curl_safefree(part->mimetype);
- part->mimetype = NULL;
if(mimetype) {
part->mimetype = strdup(mimetype);
@@ -1550,10 +1546,6 @@
cleanup_part_content(part);
if(subparts) {
- /* Must belong to the same data handle. */
- if(part->easy && subparts->easy && part->easy != subparts->easy)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
/* Should not have been attached already. */
if(subparts->parent)
return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -1564,8 +1556,7 @@
while(root->parent && root->parent->parent)
root = root->parent->parent;
if(subparts == root) {
- if(part->easy)
- failf(part->easy, "Can't add itself as a subpart");
+ /* Can't add as a subpart of itself. */
return CURLE_BAD_FUNCTION_ARGUMENT;
}
}
@@ -1635,7 +1626,7 @@
static curl_off_t multipart_size(curl_mime *mime)
{
curl_off_t size;
- size_t boundarysize;
+ curl_off_t boundarysize;
curl_mimepart *part;
if(!mime)
@@ -1743,7 +1734,7 @@
size_t len2 = strlen(ctts[i].extension);
if(len1 >= len2 && strcasecompare(nameend - len2, ctts[i].extension))
- return ctts[i].type;
+ return ctts[i].type;
}
}
return NULL;
@@ -1765,7 +1756,8 @@
return FALSE;
}
-CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
+CURLcode Curl_mime_prepare_headers(struct Curl_easy *data,
+ curl_mimepart *part,
const char *contenttype,
const char *disposition,
enum mimestrategy strategy)
@@ -1834,12 +1826,12 @@
char *filename = NULL;
if(part->name) {
- name = escape_string(part->easy, part->name, strategy);
+ name = escape_string(data, part->name, strategy);
if(!name)
ret = CURLE_OUT_OF_MEMORY;
}
if(!ret && part->filename) {
- filename = escape_string(part->easy, part->filename, strategy);
+ filename = escape_string(data, part->filename, strategy);
if(!filename)
ret = CURLE_OUT_OF_MEMORY;
}
@@ -1896,7 +1888,8 @@
if(content_type_match(contenttype, STRCONST("multipart/form-data")))
disposition = "form-data";
for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) {
- ret = Curl_mime_prepare_headers(subpart, NULL, disposition, strategy);
+ ret = Curl_mime_prepare_headers(data, subpart, NULL,
+ disposition, strategy);
if(ret)
return ret;
}
@@ -1924,8 +1917,8 @@
}
-#else /* !CURL_DISABLE_HTTP && !CURL_DISABLE_MIME ||
- !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
+#else /* !CURL_DISABLE_MIME && (!CURL_DISABLE_HTTP ||
+ !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP) */
/* Mime not compiled in: define stubs for externally-referenced functions. */
curl_mime *curl_mime_init(CURL *easy)
diff --git a/lib/mime.h b/lib/mime.h
index fe1a61c..04adf2d 100644
--- a/lib/mime.h
+++ b/lib/mime.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -99,7 +99,6 @@
/* A mime multipart. */
struct curl_mime {
- struct Curl_easy *easy; /* The associated easy handle. */
curl_mimepart *parent; /* Parent part. */
curl_mimepart *firstpart; /* First part. */
curl_mimepart *lastpart; /* Last part. */
@@ -109,7 +108,6 @@
/* A mime part. */
struct curl_mimepart {
- struct Curl_easy *easy; /* The associated easy handle. */
curl_mime *parent; /* Parent mime structure. */
curl_mimepart *nextpart; /* Forward linked list. */
enum mimekind kind; /* The part kind. */
@@ -134,18 +132,21 @@
CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
-#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
- !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
+#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
+ !defined(CURL_DISABLE_SMTP) || \
+ !defined(CURL_DISABLE_IMAP))
/* Prototypes. */
-void Curl_mime_initpart(struct curl_mimepart *part, struct Curl_easy *easy);
+void Curl_mime_initpart(struct curl_mimepart *part);
void Curl_mime_cleanpart(struct curl_mimepart *part);
-CURLcode Curl_mime_duppart(struct curl_mimepart *dst,
+CURLcode Curl_mime_duppart(struct Curl_easy *data,
+ struct curl_mimepart *dst,
const curl_mimepart *src);
CURLcode Curl_mime_set_subparts(struct curl_mimepart *part,
struct curl_mime *subparts,
int take_ownership);
-CURLcode Curl_mime_prepare_headers(struct curl_mimepart *part,
+CURLcode Curl_mime_prepare_headers(struct Curl_easy *data,
+ struct curl_mimepart *part,
const char *contenttype,
const char *disposition,
enum mimestrategy strategy);
@@ -158,11 +159,11 @@
#else
/* if disabled */
-#define Curl_mime_initpart(x,y)
+#define Curl_mime_initpart(x)
#define Curl_mime_cleanpart(x)
-#define Curl_mime_duppart(x,y) CURLE_OK /* Nothing to duplicate. Succeed */
+#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) CURLE_NOT_BUILT_IN
+#define Curl_mime_prepare_headers(a,b,c,d,e) CURLE_NOT_BUILT_IN
#define Curl_mime_size(x) (curl_off_t) -1
#define Curl_mime_read NULL
#define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN)
diff --git a/lib/mprintf.c b/lib/mprintf.c
index f0401a8..af5d753 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1999 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -318,6 +318,11 @@
flags |= FLAGS_PREC;
precision = strtol(fmt, &fmt, 10);
}
+ if((flags & (FLAGS_PREC | FLAGS_PRECPARAM)) ==
+ (FLAGS_PREC | FLAGS_PRECPARAM))
+ /* it is not permitted to use both kinds of precision for the same
+ argument */
+ return 1;
break;
case 'h':
flags |= FLAGS_SHORT;
@@ -395,7 +400,7 @@
/* out of allowed range */
return 1;
- switch (*fmt) {
+ switch(*fmt) {
case 'S':
flags |= FLAGS_ALT;
/* FALLTHROUGH */
@@ -594,7 +599,7 @@
/* Do the actual %-code parsing */
if(dprintf_Pass1(format, vto, endpos, ap_save))
- return -1;
+ return 0;
end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
created for us */
@@ -738,11 +743,11 @@
goto number;
- unsigned_number:
+unsigned_number:
/* Unsigned number of base BASE. */
is_neg = 0;
- number:
+number:
/* Number of base BASE. */
/* Supply a default precision if none was given. */
@@ -956,7 +961,7 @@
else
*fptr++ = 'f';
- *fptr = 0; /* and a final zero termination */
+ *fptr = 0; /* and a final null-termination */
#ifdef __clang__
#pragma clang diagnostic push
@@ -964,7 +969,11 @@
#endif
/* NOTE NOTE NOTE!! Not all sprintf implementations return number of
output characters */
+#ifdef HAVE_SNPRINTF
+ (snprintf)(work, sizeof(work), formatbuf, p->data.dnum);
+#else
(sprintf)(work, formatbuf, p->data.dnum);
+#endif
#ifdef __clang__
#pragma clang diagnostic pop
#endif
@@ -1025,11 +1034,12 @@
info.max = maxlength;
retcode = dprintf_formatf(&info, addbyter, format, ap_save);
- if((retcode != -1) && info.max) {
+ if(info.max) {
/* we terminate this with a zero byte */
if(info.max == info.length) {
/* we're at maximum, scrap the last letter */
info.buffer[-1] = 0;
+ DEBUGASSERT(retcode);
retcode--; /* don't count the nul byte */
}
else
@@ -1067,13 +1077,12 @@
/* appends the formatted string, returns 0 on success, 1 on error */
int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
{
- int retcode;
struct asprintf info;
info.b = dyn;
info.fail = 0;
- retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
- if((-1 == retcode) || info.fail) {
+ (void)dprintf_formatf(&info, alloc_addbyter, format, ap_save);
+ if(info.fail) {
Curl_dyn_free(info.b);
return 1;
}
@@ -1082,15 +1091,14 @@
char *curl_mvaprintf(const char *format, va_list ap_save)
{
- int retcode;
struct asprintf info;
struct dynbuf dyn;
info.b = &dyn;
Curl_dyn_init(info.b, DYN_APRINTF);
info.fail = 0;
- retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
- if((-1 == retcode) || info.fail) {
+ (void)dprintf_formatf(&info, alloc_addbyter, format, ap_save);
+ if(info.fail) {
Curl_dyn_free(info.b);
return NULL;
}
diff --git a/lib/mqtt.c b/lib/mqtt.c
index 7320747..799a21a 100644
--- a/lib/mqtt.c
+++ b/lib/mqtt.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2019, Björn Stenberg, <bjorn@haxx.se>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Björn Stenberg, <bjorn@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -122,8 +122,9 @@
struct MQTT *mq = data->req.p.mqtt;
ssize_t n;
result = Curl_write(data, sockfd, buf, len, &n);
- if(!result)
- Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
+ if(result)
+ return result;
+ Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
if(len != (size_t)n) {
size_t nsend = len - n;
char *sendleftovers = Curl_memdup(&buf[n], nsend);
@@ -186,7 +187,7 @@
return 0;
}
-/* add user to the CONN packet */
+/* add user to the CONNECT packet */
static int add_user(const char *username, const size_t ulen,
unsigned char *pkt, const size_t start, int remain_pos)
{
@@ -204,7 +205,7 @@
return 0;
}
-/* add client ID to the CONN packet */
+/* add client ID to the CONNECT packet */
static int add_client_id(const char *client_id, const size_t client_id_len,
char *pkt, const size_t start)
{
@@ -216,7 +217,7 @@
return 0;
}
-/* Set initial values of CONN packet */
+/* Set initial values of CONNECT packet */
static int init_connpack(char *packet, char *remain, int remain_pos)
{
/* Fixed header starts */
@@ -242,7 +243,7 @@
/* keep-alive 0 = disabled */
packet[remain_pos + 9] = 0x00;
packet[remain_pos + 10] = 0x3c;
- /*end of variable header*/
+ /* end of variable header */
return remain_pos + 10;
}
@@ -251,7 +252,7 @@
CURLcode result = CURLE_OK;
int pos = 0;
int rc = 0;
- /*remain length*/
+ /* remain length */
int remain_pos = 0;
char remain[4] = {0};
size_t packetlen = 0;
@@ -293,7 +294,7 @@
return CURLE_OUT_OF_MEMORY;
memset(packet, 0, packetlen);
- /* set initial values for CONN pack */
+ /* set initial values for the CONNECT packet */
pos = init_connpack(packet, remain, remain_pos);
result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
@@ -389,10 +390,18 @@
char **topic, size_t *topiclen)
{
char *path = data->state.up.path;
- if(strlen(path) > 1)
- return Curl_urldecode(path + 1, 0, topic, topiclen, REJECT_NADA);
- failf(data, "No MQTT topic found. Forgot to URL encode it?");
- return CURLE_URL_MALFORMAT;
+ CURLcode result = CURLE_URL_MALFORMAT;
+ if(strlen(path) > 1) {
+ result = Curl_urldecode(path + 1, 0, topic, topiclen, REJECT_NADA);
+ if(!result && (*topiclen > 0xffff)) {
+ failf(data, "Too long MQTT topic");
+ result = CURLE_URL_MALFORMAT;
+ }
+ }
+ else
+ failf(data, "No MQTT topic found. Forgot to URL encode it?");
+
+ return result;
}
static CURLcode mqtt_subscribe(struct Curl_easy *data)
@@ -596,7 +605,7 @@
unsigned char packet;
switch(mqtt->state) {
- MQTT_SUBACK_COMING:
+MQTT_SUBACK_COMING:
case MQTT_SUBACK_COMING:
result = mqtt_verify_suback(data);
if(result)
@@ -627,7 +636,7 @@
/* -- switched state -- */
remlen = mq->remaining_length;
- infof(data, "Remaining length: %zd bytes", remlen);
+ infof(data, "Remaining length: %zu bytes", remlen);
if(data->set.max_filesize &&
(curl_off_t)remlen > data->set.max_filesize) {
failf(data, "Maximum file size exceeded");
@@ -679,7 +688,7 @@
result = CURLE_WEIRD_SERVER_REPLY;
goto end;
}
- end:
+end:
return result;
}
@@ -690,7 +699,7 @@
result = mqtt_connect(data);
if(result) {
- failf(data, "Error %d sending MQTT CONN request", result);
+ failf(data, "Error %d sending MQTT CONNECT request", result);
return result;
}
mqstate(data, MQTT_FIRST, MQTT_CONNACK);
diff --git a/lib/mqtt.h b/lib/mqtt.h
index c400d9b..6396136 100644
--- a/lib/mqtt.h
+++ b/lib/mqtt.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Björn Stenberg, <bjorn@haxx.se>
+ * Copyright (C) Björn Stenberg, <bjorn@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/multi.c b/lib/multi.c
index e028044..50bf15a 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,6 +29,7 @@
#include "urldata.h"
#include "transfer.h"
#include "url.h"
+#include "cfilters.h"
#include "connect.h"
#include "progress.h"
#include "easyif.h"
@@ -45,7 +46,6 @@
#include "multihandle.h"
#include "sigpipe.h"
#include "vtls/vtls.h"
-#include "connect.h"
#include "http_proxy.h"
#include "http2.h"
#include "socketpair.h"
@@ -55,6 +55,22 @@
#include "curl_memory.h"
#include "memdebug.h"
+#ifdef __APPLE__
+
+#define wakeup_write write
+#define wakeup_read read
+#define wakeup_close close
+#define wakeup_create pipe
+
+#else /* __APPLE__ */
+
+#define wakeup_write swrite
+#define wakeup_read sread
+#define wakeup_close sclose
+#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p)
+
+#endif /* __APPLE__ */
+
/*
CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
@@ -68,10 +84,23 @@
#define CURL_CONNECTION_HASH_SIZE 97
#endif
+#ifndef CURL_DNS_HASH_SIZE
+#define CURL_DNS_HASH_SIZE 71
+#endif
+
#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
+ * us early warning on things only discovered by valgrind otherwise. */
+#define GOOD_MULTI_HANDLE(x) \
+ (((x) && (x)->magic == CURL_MULTI_HANDLE)? TRUE: \
+ (DEBUGASSERT(!(x)), FALSE))
+#else
#define GOOD_MULTI_HANDLE(x) \
((x) && (x)->magic == CURL_MULTI_HANDLE)
+#endif
static CURLMcode singlesocket(struct Curl_multi *multi,
struct Curl_easy *data);
@@ -83,7 +112,7 @@
static void process_pending_handles(struct Curl_multi *multi);
#ifdef DEBUGBUILD
-static const char * const statename[]={
+static const char * const multi_statename[]={
"INIT",
"PENDING",
"CONNECT",
@@ -141,7 +170,7 @@
NULL, /* TUNNELING */
NULL, /* PROTOCONNECT */
NULL, /* PROTOCONNECTING */
- Curl_connect_free, /* DO */
+ NULL, /* DO */
NULL, /* DOING */
NULL, /* DOING_MORE */
before_perform, /* DID */
@@ -165,15 +194,10 @@
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
if(data->mstate >= MSTATE_PENDING &&
data->mstate < MSTATE_COMPLETED) {
- long connection_id = -5000;
-
- if(data->conn)
- connection_id = data->conn->connection_id;
-
infof(data,
- "STATE: %s => %s handle %p; line %d (connection #%ld)",
- statename[oldstate], statename[data->mstate],
- (void *)data, lineno, connection_id);
+ "STATE: %s => %s handle %p; line %d",
+ multi_statename[oldstate], multi_statename[data->mstate],
+ (void *)data, lineno);
}
#endif
@@ -363,16 +387,15 @@
* Called when a transfer is completed. Adds the given msg pointer to
* the list kept in the multi handle.
*/
-static CURLMcode multi_addmsg(struct Curl_multi *multi,
- struct Curl_message *msg)
+static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg)
{
Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg,
&msg->list);
- return CURLM_OK;
}
struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
- int chashsize) /* connection hash */
+ int chashsize, /* connection hash */
+ int dnssize) /* dns hash */
{
struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
@@ -381,7 +404,7 @@
multi->magic = CURL_MULTI_HANDLE;
- Curl_init_dnscache(&multi->hostcache);
+ Curl_init_dnscache(&multi->hostcache, dnssize);
sh_init(&multi->sockhash, hashsize);
@@ -390,13 +413,13 @@
Curl_llist_init(&multi->msglist, NULL);
Curl_llist_init(&multi->pending, NULL);
+ Curl_llist_init(&multi->msgsent, NULL);
multi->multiplexing = TRUE;
/* -1 means it not set by user, use the default value */
multi->maxconnects = -1;
multi->max_concurrent_streams = 100;
- multi->ipv6_works = Curl_ipv6works(NULL);
#ifdef USE_WINSOCK
multi->wsa_event = WSACreateEvent();
@@ -404,14 +427,14 @@
goto error;
#else
#ifdef ENABLE_WAKEUP
- if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) {
+ if(wakeup_create(multi->wakeup_pair) < 0) {
multi->wakeup_pair[0] = CURL_SOCKET_BAD;
multi->wakeup_pair[1] = CURL_SOCKET_BAD;
}
else if(curlx_nonblock(multi->wakeup_pair[0], TRUE) < 0 ||
curlx_nonblock(multi->wakeup_pair[1], TRUE) < 0) {
- sclose(multi->wakeup_pair[0]);
- sclose(multi->wakeup_pair[1]);
+ wakeup_close(multi->wakeup_pair[0]);
+ wakeup_close(multi->wakeup_pair[1]);
multi->wakeup_pair[0] = CURL_SOCKET_BAD;
multi->wakeup_pair[1] = CURL_SOCKET_BAD;
}
@@ -420,14 +443,11 @@
return multi;
- error:
+error:
sockhash_destroy(&multi->sockhash);
Curl_hash_destroy(&multi->hostcache);
Curl_conncache_destroy(&multi->conn_cache);
- Curl_llist_destroy(&multi->msglist, NULL);
- Curl_llist_destroy(&multi->pending, NULL);
-
free(multi);
return NULL;
}
@@ -435,9 +455,70 @@
struct Curl_multi *curl_multi_init(void)
{
return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
- CURL_CONNECTION_HASH_SIZE);
+ CURL_CONNECTION_HASH_SIZE,
+ CURL_DNS_HASH_SIZE);
}
+#ifdef DEBUGBUILD
+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.");
+ multi->warned = true;
+ }
+}
+#else
+#define multi_warn_debug(x,y) Curl_nop_stmt
+#endif
+
+/* returns TRUE if the easy handle is supposed to be present in the main link
+ list */
+static bool in_main_list(struct Curl_easy *data)
+{
+ return ((data->mstate != MSTATE_PENDING) &&
+ (data->mstate != MSTATE_MSGSENT));
+}
+
+static void link_easy(struct Curl_multi *multi,
+ struct Curl_easy *data)
+{
+ /* We add the new easy entry last in the list. */
+ data->next = NULL; /* end of the line */
+ if(multi->easyp) {
+ struct Curl_easy *last = multi->easylp;
+ last->next = data;
+ data->prev = last;
+ multi->easylp = data; /* the new last node */
+ }
+ else {
+ /* first node, make prev NULL! */
+ data->prev = NULL;
+ multi->easylp = multi->easyp = data; /* both first and last */
+ }
+}
+
+/* unlink the given easy handle from the linked list of easy handles */
+static void unlink_easy(struct Curl_multi *multi,
+ struct Curl_easy *data)
+{
+ /* make the previous node point to our next */
+ if(data->prev)
+ data->prev->next = data->next;
+ else
+ multi->easyp = data->next; /* point to first node */
+
+ /* make our next point to our previous node */
+ if(data->next)
+ data->next->prev = data->prev;
+ else
+ multi->easylp = data->prev; /* point to last node */
+
+ data->prev = data->next = NULL;
+}
+
+
CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
struct Curl_easy *data)
{
@@ -533,19 +614,7 @@
data->psl = &multi->psl;
#endif
- /* We add the new entry last in the list. */
- data->next = NULL; /* end of the line */
- if(multi->easyp) {
- struct Curl_easy *last = multi->easylp;
- last->next = data;
- data->prev = last;
- multi->easylp = data; /* the new last node */
- }
- else {
- /* first node, make prev NULL! */
- data->prev = NULL;
- multi->easylp = multi->easyp = data; /* both first and last */
- }
+ link_easy(multi, data);
/* increase the node-counter */
multi->num_easy++;
@@ -563,8 +632,14 @@
data->set.server_response_timeout;
data->state.conn_cache->closure_handle->set.no_signal =
data->set.no_signal;
+ data->id = data->state.conn_cache->next_easy_id++;
+ if(data->state.conn_cache->next_easy_id <= 0)
+ data->state.conn_cache->next_easy_id = 0;
CONNCACHE_UNLOCK(data);
+ multi_warn_debug(multi, data);
+ infof(data, "processing: %s", data->state.url);
+
return CURLM_OK;
}
@@ -629,13 +704,25 @@
if(CURLE_ABORTED_BY_CALLBACK != result) {
/* avoid this if we already aborted by callback to avoid this calling
another callback */
- CURLcode rc = Curl_pgrsDone(data);
+ int rc = Curl_pgrsDone(data);
if(!result && rc)
result = CURLE_ABORTED_BY_CALLBACK;
}
+ /* Inform connection filters that this transfer is done */
+ Curl_conn_ev_data_done(data, premature);
+
process_pending_handles(data->multi); /* connection / multiplex */
+ Curl_safefree(data->state.ulbuf);
+
+ /* if the transfer was completed in a paused state there can be buffered
+ data left to free */
+ for(i = 0; i < data->state.tempcount; i++) {
+ Curl_dyn_free(&data->state.tempwrite[i].b);
+ }
+ data->state.tempcount = 0;
+
CONNCACHE_LOCK(data);
Curl_detach_connection(data);
if(CONN_INUSE(conn)) {
@@ -654,14 +741,6 @@
conn->dns_entry = NULL;
}
Curl_hostcache_prune(data);
- Curl_safefree(data->state.ulbuf);
-
- /* if the transfer was completed in a paused state there can be buffered
- data left to free */
- for(i = 0; i < data->state.tempcount; i++) {
- Curl_dyn_free(&data->state.tempwrite[i].b);
- }
- data->state.tempcount = 0;
/* 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
@@ -678,6 +757,7 @@
but currently we have no such detail knowledge.
*/
+ data->state.recent_conn_id = conn->connection_id;
if((data->set.reuse_forbid
#if defined(USE_NTLM)
&& !(conn->http_ntlm_state == NTLMSTATE_TYPE2 ||
@@ -688,7 +768,13 @@
conn->proxy_negotiate_state == GSS_AUTHRECV)
#endif
) || conn->bits.close
- || (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
+ || (premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) {
+ DEBUGF(infof(data, "multi_done, not re-using connection=%"
+ CURL_FORMAT_CURL_OFF_T ", forbid=%d"
+ ", close=%d, premature=%d, conn_multiplex=%d",
+ conn->connection_id,
+ data->set.reuse_forbid, conn->bits.close, premature,
+ Curl_conn_is_multiplex(conn, FIRSTSOCKET)));
connclose(conn, "disconnecting");
Curl_conncache_remove_conn(data, conn, FALSE);
CONNCACHE_UNLOCK(data);
@@ -705,15 +791,16 @@
conn->bits.conn_to_host ? conn->conn_to_host.dispname :
conn->host.dispname;
/* create string before returning the connection */
- long connection_id = conn->connection_id;
+ curl_off_t connection_id = conn->connection_id;
msnprintf(buffer, sizeof(buffer),
- "Connection #%ld to host %s left intact",
+ "Connection #%" CURL_FORMAT_CURL_OFF_T " to host %s left intact",
connection_id, host);
/* the connection is no longer in use by this transfer */
CONNCACHE_UNLOCK(data);
if(Curl_conncache_return_conn(data, conn)) {
/* remember the most recently used connection */
data->state.lastconnect_id = connection_id;
+ data->state.recent_conn_id = connection_id;
infof(data, "%s", buffer);
}
else
@@ -731,7 +818,7 @@
if(data->state.lastconnect_id != conn->connection_id)
return 0;
- if(!conn->bits.connect_only)
+ if(!conn->connect_only)
return 1;
connclose(conn, "Removing connect-only easy handle");
@@ -798,10 +885,16 @@
called. Do it after multi_done() in case that sets another time! */
Curl_expire_clear(data);
- if(data->connect_queue.ptr)
- /* the handle was in the pending list waiting for an available connection,
- so go ahead and remove it */
- Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
+ if(data->connect_queue.ptr) {
+ /* the handle is in the pending or msgsent lists, so go ahead and remove
+ it */
+ if(data->mstate == MSTATE_PENDING)
+ Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
+ else
+ Curl_llist_remove(&multi->msgsent, &data->connect_queue, NULL);
+ }
+ if(in_main_list(data))
+ unlink_easy(multi, data);
if(data->dns.hostcachetype == HCACHE_MULTI) {
/* stop using the multi handle's DNS cache, *after* the possible
@@ -812,10 +905,6 @@
Curl_wildcard_dtor(&data->wildcard);
- /* destroy the timeout list that is held in the easy handle, do this *after*
- multi_done() as that may actually call Curl_expire that uses this */
- Curl_llist_destroy(&data->state.timeoutlist, NULL);
-
/* change state without using multistate(), only to make singlesocket() do
what we want */
data->mstate = MSTATE_COMPLETED;
@@ -828,6 +917,24 @@
/* Remove the association between the connection and the handle */
Curl_detach_connection(data);
+ if(data->set.connect_only && !data->multi_easy) {
+ /* This removes a handle that was part the multi interface that used
+ CONNECT_ONLY, that connection is now left alive but since this handle
+ has bits.close set nothing can use that transfer anymore and it is
+ forbidden from reuse. And this easy handle cannot find the connection
+ anymore once removed from the multi handle
+
+ Better close the connection here, at once.
+ */
+ struct connectdata *c;
+ curl_socket_t s;
+ s = Curl_getconnectinfo(data, &c);
+ if((s != CURL_SOCKET_BAD) && c) {
+ Curl_conncache_remove_conn(data, c, TRUE);
+ Curl_disconnect(data, c, TRUE);
+ }
+ }
+
if(data->state.lastconnect_id != -1) {
/* Mark any connect-only connection for closure */
Curl_conncache_foreach(data, data->state.conn_cache,
@@ -848,7 +955,6 @@
/* make sure there's no pending message in the queue sent from this easy
handle */
-
for(e = multi->msglist.head; e; e = e->next) {
struct Curl_message *msg = e->ptr;
@@ -859,29 +965,6 @@
}
}
- /* Remove from the pending list if it is there. Otherwise this will
- remain on the pending list forever due to the state change. */
- for(e = multi->pending.head; e; e = e->next) {
- struct Curl_easy *curr_data = e->ptr;
-
- if(curr_data == data) {
- Curl_llist_remove(&multi->pending, e, NULL);
- break;
- }
- }
-
- /* make the previous node point to our next */
- if(data->prev)
- data->prev->next = data->next;
- else
- multi->easyp = data->next; /* point to first node */
-
- /* make our next point to our previous node */
- if(data->next)
- data->next->prev = data->prev;
- else
- multi->easylp = data->prev; /* point to last node */
-
/* NOTE NOTE NOTE
We do not touch the easy handle here! */
multi->num_easy--; /* one less to care about now */
@@ -910,9 +993,8 @@
{
struct connectdata *conn = data->conn;
if(conn) {
- Curl_connect_done(data); /* if mid-CONNECT, shut it down */
+ Curl_conn_ev_data_detach(conn, data);
Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
- Curl_ssl_detach_conn(data, conn);
}
data->conn = NULL;
}
@@ -930,53 +1012,9 @@
data->conn = conn;
Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data,
&data->conn_queue);
- if(conn->handler->attach)
+ if(conn->handler && conn->handler->attach)
conn->handler->attach(data, conn);
- Curl_ssl_associate_conn(data, conn);
-}
-
-static int waitconnect_getsock(struct connectdata *conn,
- curl_socket_t *sock)
-{
- int i;
- int s = 0;
- int rc = 0;
-
-#ifdef USE_SSL
-#ifndef CURL_DISABLE_PROXY
- if(CONNECT_FIRSTSOCKET_PROXY_SSL())
- return Curl_ssl->getsock(conn, sock);
-#endif
-#endif
-
- if(SOCKS_STATE(conn->cnnct.state))
- return Curl_SOCKS_getsock(conn, sock, FIRSTSOCKET);
-
- for(i = 0; i<2; i++) {
- if(conn->tempsock[i] != CURL_SOCKET_BAD) {
- sock[s] = conn->tempsock[i];
- rc |= GETSOCK_WRITESOCK(s);
-#ifdef ENABLE_QUIC
- if(conn->transport == TRNSPRT_QUIC)
- /* when connecting QUIC, we want to read the socket too */
- rc |= GETSOCK_READSOCK(s);
-#endif
- s++;
- }
- }
-
- return rc;
-}
-
-static int waitproxyconnect_getsock(struct connectdata *conn,
- curl_socket_t *sock)
-{
- sock[0] = conn->sock[FIRSTSOCKET];
-
- if(conn->connect_state)
- return Curl_connect_getsock(conn);
-
- return GETSOCK_WRITESOCK(0);
+ Curl_conn_ev_data_attach(conn, data);
}
static int domore_getsock(struct Curl_easy *data,
@@ -1003,11 +1041,7 @@
{
if(conn->handler->proto_getsock)
return conn->handler->proto_getsock(data, conn, socks);
- /* Backup getsock logic. Since there is a live socket in use, we must wait
- for it or it will be removed from watching when the multi_socket API is
- used. */
- socks[0] = conn->sock[FIRSTSOCKET];
- return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
+ return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks);
}
/* returns bitmapped flags for this handle and its sockets. The 'socks[]'
@@ -1038,10 +1072,8 @@
return doing_getsock(data, conn, socks);
case MSTATE_TUNNELING:
- return waitproxyconnect_getsock(conn, socks);
-
case MSTATE_CONNECTING:
- return waitconnect_getsock(conn, socks);
+ return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks);
case MSTATE_DOING_MORE:
return domore_getsock(data, conn, socks);
@@ -1114,6 +1146,22 @@
return CURLM_OK;
}
+#ifdef USE_WINSOCK
+/* Reset FD_WRITE for TCP sockets. Nothing is actually sent. UDP sockets can't
+ * be reset this way because an empty datagram would be sent. #9203
+ *
+ * "On Windows the internal state of FD_WRITE as returned from
+ * WSAEnumNetworkEvents is only reset after successful send()."
+ */
+static void reset_socket_fdwrite(curl_socket_t s)
+{
+ int t;
+ int l = (int)sizeof(t);
+ if(!getsockopt(s, SOL_SOCKET, SO_TYPE, (char *)&t, &l) && t == SOCK_STREAM)
+ send(s, NULL, 0, 0);
+}
+#endif
+
#define NUM_POLLS_ON_STACK 10
static CURLMcode multi_wait(struct Curl_multi *multi,
@@ -1235,7 +1283,7 @@
s = sockbunch[i];
#ifdef USE_WINSOCK
mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
- send(s, NULL, 0, 0); /* reset FD_WRITE */
+ reset_socket_fdwrite(s);
#endif
ufds[nfds].fd = s;
ufds[nfds].events = POLLOUT;
@@ -1269,7 +1317,7 @@
mask |= FD_OOB;
if(extra_fds[i].events & CURL_WAIT_POLLOUT) {
mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
- send(extra_fds[i].fd, NULL, 0, 0); /* reset FD_WRITE */
+ reset_socket_fdwrite(extra_fds[i].fd);
}
if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) {
if(ufds_malloc)
@@ -1309,8 +1357,6 @@
pollrc = Curl_poll(ufds, nfds, 0); /* just pre-check with WinSock */
else
pollrc = 0;
- if(pollrc <= 0) /* now wait... if not ready during the pre-check above */
- WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
#else
pollrc = Curl_poll(ufds, nfds, timeout_ms); /* wait... */
#endif
@@ -1321,6 +1367,9 @@
retcode = pollrc;
#ifdef USE_WINSOCK
}
+ else { /* now wait... if not ready during the pre-check (pollrc == 0) */
+ WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
+ }
/* With WinSock, we have to run the following section unconditionally
to call WSAEventSelect(fd, event, 0) on all the sockets */
{
@@ -1332,20 +1381,23 @@
unsigned r = ufds[curlfds + i].revents;
unsigned short mask = 0;
#ifdef USE_WINSOCK
+ curl_socket_t s = extra_fds[i].fd;
wsa_events.lNetworkEvents = 0;
- if(WSAEnumNetworkEvents(extra_fds[i].fd, NULL, &wsa_events) == 0) {
+ if(WSAEnumNetworkEvents(s, NULL, &wsa_events) == 0) {
if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))
mask |= CURL_WAIT_POLLIN;
if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE))
mask |= CURL_WAIT_POLLOUT;
if(wsa_events.lNetworkEvents & FD_OOB)
mask |= CURL_WAIT_POLLPRI;
- if(ret && pollrc <= 0 && wsa_events.lNetworkEvents)
+ if(ret && !pollrc && wsa_events.lNetworkEvents)
retcode++;
}
- WSAEventSelect(extra_fds[i].fd, multi->wsa_event, 0);
- if(pollrc <= 0)
+ WSAEventSelect(s, multi->wsa_event, 0);
+ if(!pollrc) {
+ extra_fds[i].revents = mask;
continue;
+ }
#endif
if(r & POLLIN)
mask |= CURL_WAIT_POLLIN;
@@ -1368,7 +1420,7 @@
if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
wsa_events.lNetworkEvents = 0;
if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) {
- if(ret && pollrc <= 0 && wsa_events.lNetworkEvents)
+ if(ret && !pollrc && wsa_events.lNetworkEvents)
retcode++;
}
WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
@@ -1395,7 +1447,7 @@
data from it until it receives an error (except EINTR).
In normal cases it will get EAGAIN or EWOULDBLOCK
when there is no more data, breaking the loop. */
- nread = sread(multi->wakeup_pair[0], buf, sizeof(buf));
+ nread = wakeup_read(multi->wakeup_pair[0], buf, sizeof(buf));
if(nread <= 0) {
if(nread < 0 && EINTR == SOCKERRNO)
continue;
@@ -1488,7 +1540,7 @@
that will call curl_multi_wait(). If swrite() returns that it
would block, it's considered successful because it means that
previous calls to this function will wake up the poll(). */
- if(swrite(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
+ if(wakeup_write(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
int err = SOCKERRNO;
int return_success;
#ifdef USE_WINSOCK
@@ -1695,7 +1747,8 @@
*protocol_done = FALSE;
- if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
+ 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 don't know if the protocol is actually done.
@@ -1709,21 +1762,6 @@
}
if(!conn->bits.protoconnstart) {
-#ifndef CURL_DISABLE_PROXY
- result = Curl_proxy_connect(data, FIRSTSOCKET);
- if(result)
- return result;
-
- if(CONNECT_FIRSTSOCKET_PROXY_SSL())
- /* wait for HTTPS proxy SSL initialization to complete */
- return CURLE_OK;
-
- if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
- Curl_connect_ongoing(conn))
- /* when using an HTTP tunnel proxy, await complete tunnel establishment
- before proceeding further. Return CURLE_OK so we'll be called again */
- return CURLE_OK;
-#endif
if(conn->handler->connect_it) {
/* is there a protocol-specific connect() procedure? */
@@ -1743,6 +1781,90 @@
}
/*
+ * readrewind() rewinds the read stream. This is typically used for HTTP
+ * POST/PUT with multi-pass authentication when a sending was denied and a
+ * resend is necessary.
+ */
+static CURLcode readrewind(struct Curl_easy *data)
+{
+ struct connectdata *conn = data->conn;
+ curl_mimepart *mimepart = &data->set.mimepost;
+ DEBUGASSERT(conn);
+
+ data->state.rewindbeforesend = FALSE; /* we rewind now */
+
+ /* explicitly switch off sending data on this connection now since we are
+ about to restart a new transfer and thus we want to avoid inadvertently
+ sending more data on the existing connection until the next transfer
+ starts */
+ data->req.keepon &= ~KEEP_SEND;
+
+ /* We have sent away data. If not using CURLOPT_POSTFIELDS or
+ CURLOPT_HTTPPOST, call app to rewind
+ */
+ if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
+ struct HTTP *http = data->req.p.http;
+
+ if(http->sendit)
+ mimepart = http->sendit;
+ }
+ if(data->set.postfields ||
+ (data->state.httpreq == HTTPREQ_GET) ||
+ (data->state.httpreq == HTTPREQ_HEAD))
+ ; /* no need to rewind */
+ else if(data->state.httpreq == HTTPREQ_POST_MIME ||
+ data->state.httpreq == HTTPREQ_POST_FORM) {
+ CURLcode result = Curl_mime_rewind(mimepart);
+ if(result) {
+ failf(data, "Cannot rewind mime/post data");
+ return result;
+ }
+ }
+ else {
+ if(data->set.seek_func) {
+ int err;
+
+ Curl_set_in_callback(data, true);
+ err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
+ Curl_set_in_callback(data, false);
+ if(err) {
+ failf(data, "seek callback returned error %d", (int)err);
+ return CURLE_SEND_FAIL_REWIND;
+ }
+ }
+ else if(data->set.ioctl_func) {
+ curlioerr err;
+
+ Curl_set_in_callback(data, true);
+ err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
+ data->set.ioctl_client);
+ Curl_set_in_callback(data, false);
+ infof(data, "the ioctl callback returned %d", (int)err);
+
+ if(err) {
+ failf(data, "ioctl callback returned error %d", (int)err);
+ return CURLE_SEND_FAIL_REWIND;
+ }
+ }
+ else {
+ /* If no CURLOPT_READFUNCTION is used, we know that we operate on a
+ given FILE * stream and we can actually attempt to rewind that
+ ourselves with fseek() */
+ if(data->state.fread_func == (curl_read_callback)fread) {
+ if(-1 != fseek(data->state.in, 0, SEEK_SET))
+ /* successful rewind */
+ return CURLE_OK;
+ }
+
+ /* no callback set or failure above, makes us fail at once */
+ failf(data, "necessary data rewind wasn't possible");
+ return CURLE_SEND_FAIL_REWIND;
+ }
+ }
+ return CURLE_OK;
+}
+
+/*
* Curl_preconnect() is called immediately before a connect starts. When a
* redirect is followed, this is then called multiple times during a single
* transfer.
@@ -1754,6 +1876,7 @@
if(!data->state.buffer)
return CURLE_OUT_OF_MEMORY;
}
+
return CURLE_OK;
}
@@ -1790,6 +1913,8 @@
multistate(data, MSTATE_COMPLETED);
}
+ multi_warn_debug(multi, data);
+
do {
/* A "stream" here is a logical stream if the protocol can handle that
(HTTP/2), or the full connection for older protocols */
@@ -1840,11 +1965,6 @@
}
break;
- case MSTATE_PENDING:
- /* We will stay here until there is a connection available. Then
- we try again in the MSTATE_CONNECT state. */
- break;
-
case MSTATE_CONNECT:
/* Connect. We want to get a connection identifier filled in. */
/* init this transfer. */
@@ -1859,7 +1979,7 @@
if(data->set.connecttimeout)
Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
- result = Curl_connect(data, &async, &protocol_connected);
+ 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. */
@@ -1868,6 +1988,8 @@
/* add this handle to the list of connect-pending handles */
Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
&data->connect_queue);
+ /* unlink from the main list */
+ unlink_easy(multi, data);
result = CURLE_OK;
break;
}
@@ -1887,15 +2009,10 @@
WAITDO or DO! */
rc = CURLM_CALL_MULTI_PERFORM;
- if(protocol_connected)
- multistate(data, MSTATE_DO);
+ if(connected)
+ multistate(data, MSTATE_PROTOCONNECT);
else {
-#ifndef CURL_DISABLE_HTTP
- if(Curl_connect_ongoing(data->conn))
- multistate(data, MSTATE_TUNNELING);
- else
-#endif
- multistate(data, MSTATE_CONNECTING);
+ multistate(data, MSTATE_CONNECTING);
}
}
}
@@ -1915,7 +2032,7 @@
else
#endif
if(conn->bits.conn_to_host)
- hostname = conn->conn_to_host.name;
+ hostname = conn->conn_to_host.name;
else
hostname = conn->host.name;
@@ -1947,7 +2064,7 @@
if(dns) {
/* Perform the next step in the connection phase, and then move on
to the WAITCONNECT state */
- result = Curl_once_resolved(data, &protocol_connected);
+ result = Curl_once_resolved(data, &connected);
if(result)
/* if Curl_once_resolved() returns failure, the connection struct
@@ -1956,15 +2073,10 @@
else {
/* call again please so that we get the next socket setup */
rc = CURLM_CALL_MULTI_PERFORM;
- if(protocol_connected)
- multistate(data, MSTATE_DO);
+ if(connected)
+ multistate(data, MSTATE_PROTOCONNECT);
else {
-#ifndef CURL_DISABLE_HTTP
- if(Curl_connect_ongoing(data->conn))
- multistate(data, MSTATE_TUNNELING);
- else
-#endif
- multistate(data, MSTATE_CONNECTING);
+ multistate(data, MSTATE_CONNECTING);
}
}
}
@@ -1993,16 +2105,9 @@
else
#endif
if(!result) {
- if(
-#ifndef CURL_DISABLE_PROXY
- (data->conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
- data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
-#endif
- Curl_connect_complete(data->conn)) {
- rc = CURLM_CALL_MULTI_PERFORM;
- /* initiate protocol connect phase */
- multistate(data, MSTATE_PROTOCONNECT);
- }
+ rc = CURLM_CALL_MULTI_PERFORM;
+ /* initiate protocol connect phase */
+ multistate(data, MSTATE_PROTOCONNECT);
}
else
stream_error = TRUE;
@@ -2012,27 +2117,10 @@
case MSTATE_CONNECTING:
/* awaiting a completion of an asynch TCP connect */
DEBUGASSERT(data->conn);
- result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected);
+ result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &connected);
if(connected && !result) {
-#ifndef CURL_DISABLE_HTTP
- if(
-#ifndef CURL_DISABLE_PROXY
- (data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
- !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
-#endif
- Curl_connect_ongoing(data->conn)) {
- multistate(data, MSTATE_TUNNELING);
- break;
- }
-#endif
rc = CURLM_CALL_MULTI_PERFORM;
-#ifndef CURL_DISABLE_PROXY
- multistate(data,
- data->conn->bits.tunnel_proxy?
- MSTATE_TUNNELING : MSTATE_PROTOCONNECT);
-#else
multistate(data, MSTATE_PROTOCONNECT);
-#endif
}
else if(result) {
/* failure detected */
@@ -2044,7 +2132,19 @@
break;
case MSTATE_PROTOCONNECT:
- result = protocol_connect(data, &protocol_connected);
+ if(data->state.rewindbeforesend)
+ result = readrewind(data);
+
+ if(!result && data->conn->bits.reuse) {
+ /* ftp seems to hang when protoconnect on reused connection
+ * since we handle PROTOCONNECT in general inside the filers, it
+ * seems wrong to restart this on a reused connection. */
+ multistate(data, MSTATE_DO);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ break;
+ }
+ if(!result)
+ result = protocol_connect(data, &protocol_connected);
if(!result && !protocol_connected)
/* switch to waiting state */
multistate(data, MSTATE_PROTOCONNECTING);
@@ -2100,7 +2200,7 @@
}
}
- if(data->set.connect_only) {
+ if(data->set.connect_only == 1) {
/* keep connection open for application to use the socket */
connkeep(data->conn, "CONNECT_ONLY");
multistate(data, MSTATE_DONE);
@@ -2118,7 +2218,7 @@
#ifndef CURL_DISABLE_FTP
/* some steps needed for wildcard matching */
if(data->state.wildcardmatch) {
- struct WildcardData *wc = &data->wildcard;
+ struct WildcardData *wc = data->wildcard;
if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
/* skip some states if it is important */
multi_done(data, CURLE_OK, FALSE);
@@ -2134,7 +2234,6 @@
/* DO was not completed in one function call, we must continue
DOING... */
multistate(data, MSTATE_DOING);
- rc = CURLM_OK;
}
/* after DO, go DO_DONE... or DO_MORE */
@@ -2142,7 +2241,6 @@
/* we're supposed to do more, but we need to sit down, relax
and wait a little while first */
multistate(data, MSTATE_DOING_MORE);
- rc = CURLM_OK;
}
else {
/* we're done with the DO, now DID */
@@ -2243,9 +2341,8 @@
MSTATE_DID : MSTATE_DOING);
rc = CURLM_CALL_MULTI_PERFORM;
}
- else
- /* stay in DO_MORE */
- rc = CURLM_OK;
+ /* else
+ stay in DO_MORE */
}
else {
/* failure detected */
@@ -2270,7 +2367,7 @@
#ifndef CURL_DISABLE_FTP
if(data->state.wildcardmatch &&
((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
- data->wildcard.state = CURLWC_DONE;
+ data->wildcard->state = CURLWC_DONE;
}
#endif
multistate(data, MSTATE_DONE);
@@ -2474,7 +2571,6 @@
won't get stuck on this transfer at the expense of other concurrent
transfers */
Curl_expire(data, 0, EXPIRE_RUN_NOW);
- rc = CURLM_OK;
}
break;
}
@@ -2500,7 +2596,7 @@
#ifndef CURL_DISABLE_FTP
if(data->state.wildcardmatch) {
- if(data->wildcard.state != CURLWC_DONE) {
+ if(data->wildcard->state != CURLWC_DONE) {
/* if a wildcard is set and we are not ending -> lets start again
with MSTATE_INIT */
multistate(data, MSTATE_INIT);
@@ -2516,9 +2612,11 @@
case MSTATE_COMPLETED:
break;
+ case MSTATE_PENDING:
case MSTATE_MSGSENT:
- data->result = result;
- return CURLM_OK; /* do nothing */
+ /* handles in these states should NOT be in this list */
+ DEBUGASSERT(0);
+ break;
default:
return CURLM_INTERNAL_ERROR;
@@ -2538,7 +2636,7 @@
multi_handle_timeout(data, nowp, &stream_error, &result, TRUE);
}
- statemachine_end:
+statemachine_end:
if(data->mstate < MSTATE_COMPLETED) {
if(result) {
@@ -2606,10 +2704,17 @@
msg->extmsg.easy_handle = data;
msg->extmsg.data.result = result;
- rc = multi_addmsg(multi, msg);
+ multi_addmsg(multi, msg);
DEBUGASSERT(!data->conn);
}
multistate(data, MSTATE_MSGSENT);
+
+ /* add this handle to the list of msgsent handles */
+ Curl_llist_insert_next(&multi->msgsent, multi->msgsent.tail, data,
+ &data->connect_queue);
+ /* unlink from the main list */
+ unlink_easy(multi, data);
+ return CURLM_OK;
}
} while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
@@ -2632,18 +2737,28 @@
return CURLM_RECURSIVE_API_CALL;
data = multi->easyp;
- while(data) {
+ if(data) {
CURLMcode result;
+ bool nosig = data->set.no_signal;
SIGPIPE_VARIABLE(pipe_st);
-
sigpipe_ignore(data, &pipe_st);
- result = multi_runsingle(multi, &now, data);
+ /* Do the loop and only alter the signal ignore state if the next handle
+ has a different NO_SIGNAL state than the previous */
+ do {
+ /* the current node might be unlinked in multi_runsingle(), get the next
+ pointer now */
+ struct Curl_easy *datanext = data->next;
+ if(data->set.no_signal != nosig) {
+ sigpipe_restore(&pipe_st);
+ sigpipe_ignore(data, &pipe_st);
+ nosig = data->set.no_signal;
+ }
+ result = multi_runsingle(multi, &now, data);
+ if(result)
+ returncode = result;
+ data = datanext; /* operate on next handle */
+ } while(data);
sigpipe_restore(&pipe_st);
-
- if(result)
- returncode = result;
-
- data = data->next; /* operate on next handle */
}
/*
@@ -2672,6 +2787,18 @@
return returncode;
}
+/* unlink_all_msgsent_handles() detaches all those easy handles from this
+ multi handle */
+static void unlink_all_msgsent_handles(struct Curl_multi *multi)
+{
+ struct Curl_llist_element *e = multi->msgsent.head;
+ if(e) {
+ struct Curl_easy *data = e->ptr;
+ DEBUGASSERT(data->mstate == MSTATE_MSGSENT);
+ data->multi = NULL;
+ }
+}
+
CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
{
struct Curl_easy *data;
@@ -2683,6 +2810,8 @@
multi->magic = 0; /* not good anymore */
+ unlink_all_msgsent_handles(multi);
+ process_pending_handles(multi);
/* First remove all remaining easy handles */
data = multi->easyp;
while(data) {
@@ -2714,9 +2843,6 @@
sockhash_destroy(&multi->sockhash);
Curl_conncache_destroy(&multi->conn_cache);
- Curl_llist_destroy(&multi->msglist, NULL);
- Curl_llist_destroy(&multi->pending, NULL);
-
Curl_hash_destroy(&multi->hostcache);
Curl_psl_destroy(&multi->psl);
@@ -2724,10 +2850,15 @@
WSACloseEvent(multi->wsa_event);
#else
#ifdef ENABLE_WAKEUP
- sclose(multi->wakeup_pair[0]);
- sclose(multi->wakeup_pair[1]);
+ wakeup_close(multi->wakeup_pair[0]);
+ wakeup_close(multi->wakeup_pair[1]);
#endif
#endif
+
+#ifdef USE_SSL
+ Curl_free_multi_ssl_backend_data(multi->ssl_backend_data);
+#endif
+
free(multi);
return CURLM_OK;
@@ -3060,6 +3191,9 @@
struct Curl_easy *data = NULL;
struct Curl_tree *t;
struct curltime now = Curl_now();
+ bool first = FALSE;
+ bool nosig = FALSE;
+ SIGPIPE_VARIABLE(pipe_st);
if(checkall) {
/* *perform() deals with running_handles on its own */
@@ -3102,7 +3236,7 @@
if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
/* set socket event bitmask if they're not locked */
- data->conn->cselect_bits = ev_bitmask;
+ data->conn->cselect_bits = (unsigned char)ev_bitmask;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
@@ -3134,18 +3268,24 @@
do {
/* the first loop lap 'data' can be NULL */
if(data) {
- SIGPIPE_VARIABLE(pipe_st);
-
- sigpipe_ignore(data, &pipe_st);
+ if(!first) {
+ first = TRUE;
+ nosig = data->set.no_signal; /* initial state */
+ sigpipe_ignore(data, &pipe_st);
+ }
+ else if(data->set.no_signal != nosig) {
+ sigpipe_restore(&pipe_st);
+ sigpipe_ignore(data, &pipe_st);
+ nosig = data->set.no_signal; /* remember new state */
+ }
result = multi_runsingle(multi, &now, data);
- sigpipe_restore(&pipe_st);
if(CURLM_OK >= result) {
/* get the socket(s) and check if the state has been changed since
last */
result = singlesocket(multi, data);
if(result)
- return result;
+ break;
}
}
@@ -3159,6 +3299,8 @@
}
} while(t);
+ if(first)
+ sigpipe_restore(&pipe_st);
*running_handles = multi->num_alive;
return result;
@@ -3193,7 +3335,7 @@
multi->push_userp = va_arg(param, void *);
break;
case CURLMOPT_PIPELINING:
- multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX;
+ multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX ? 1 : 0;
break;
case CURLMOPT_TIMERFUNCTION:
multi->timer_cb = va_arg(param, curl_multi_timer_callback);
@@ -3559,7 +3701,7 @@
}
#ifdef DEBUGBUILD
- infof(data, "Expire cleared (transfer %p)", data);
+ infof(data, "Expire cleared");
#endif
nowp->tv_sec = 0;
nowp->tv_usec = 0;
@@ -3612,6 +3754,8 @@
process_pending_handles(data->multi);
}
+/* process_pending_handles() moves all handles from PENDING
+ back into the main list and change state to CONNECT */
static void process_pending_handles(struct Curl_multi *multi)
{
struct Curl_llist_element *e = multi->pending.head;
@@ -3620,6 +3764,9 @@
DEBUGASSERT(data->mstate == MSTATE_PENDING);
+ /* put it back into the main list */
+ link_easy(multi, data);
+
multistate(data, MSTATE_CONNECT);
/* Remove this node from the list */
@@ -3662,7 +3809,7 @@
/* only display handles that are not completed */
fprintf(stderr, "handle %p, state %s, %d sockets\n",
(void *)data,
- statename[data->mstate], data->numsocks);
+ multi_statename[data->mstate], data->numsocks);
for(i = 0; i < data->numsocks; i++) {
curl_socket_t s = data->sockets[i];
struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
diff --git a/lib/multihandle.h b/lib/multihandle.h
index 76a67a8..5b16bb6 100644
--- a/lib/multihandle.h
+++ b/lib/multihandle.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -79,6 +79,10 @@
/* value for MAXIMUM CONCURRENT STREAMS upper limit */
#define INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)
+/* Curl_multi SSL backend-specific data; declared differently by each SSL
+ backend */
+struct multi_ssl_backend_data;
+
/* This is the struct known as CURLM on the outside */
struct Curl_multi {
/* First a simple identifier to easier detect if a user mix up
@@ -97,6 +101,8 @@
struct Curl_llist pending; /* Curl_easys that are in the
MSTATE_PENDING state */
+ struct Curl_llist msgsent; /* Curl_easys that are in the
+ MSTATE_MSGSENT state */
/* callback function and user data pointer for the *socket() API */
curl_socket_callback socket_cb;
@@ -118,6 +124,10 @@
times of all currently set timers */
struct Curl_tree *timetree;
+#if defined(USE_SSL)
+ struct multi_ssl_backend_data *ssl_backend_data;
+#endif
+
/* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
the pluralis form, there can be more than one easy handle waiting on the
same actual socket) */
@@ -150,16 +160,21 @@
0 is used for read, 1 is used for write */
#endif
#endif
- /* multiplexing wanted */
- bool multiplexing;
- bool recheckstate; /* see Curl_multi_connchanged */
- bool in_callback; /* true while executing a callback */
- bool ipv6_works;
+#define IPV6_UNKNOWN 0
+#define IPV6_DEAD 1
+#define IPV6_WORKS 2
+ unsigned char ipv6_up; /* IPV6_* defined */
+ BIT(multiplexing); /* multiplexing wanted */
+ BIT(recheckstate); /* see Curl_multi_connchanged */
+ BIT(in_callback); /* true while executing a callback */
#ifdef USE_OPENSSL
- bool ssl_seeded;
+ BIT(ssl_seeded);
#endif
- bool dead; /* a callback returned error, everything needs to crash and
+ BIT(dead); /* a callback returned error, everything needs to crash and
burn */
+#ifdef DEBUGBUILD
+ BIT(warned); /* true after user warned of DEBUGBUILD */
+#endif
};
#endif /* HEADER_CURL_MULTIHANDLE_H */
diff --git a/lib/multiif.h b/lib/multiif.h
index e0aa00b..cae02cb 100644
--- a/lib/multiif.h
+++ b/lib/multiif.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,8 +42,9 @@
CURLcode Curl_preconnect(struct Curl_easy *data);
/* Internal version of curl_multi_init() accepts size parameters for the
- socket and connection hashes */
-struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize);
+ socket, connection and dns hashes */
+struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize,
+ int dnssize);
/* the write bits start at bit 16 for the *getsock() bitmap */
#define GETSOCK_WRITEBITSTART 16
diff --git a/lib/netrc.c b/lib/netrc.c
index 83fe6a7..e6a09b1 100644
--- a/lib/netrc.c
+++ b/lib/netrc.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,6 +33,7 @@
#include "netrc.h"
#include "strtok.h"
#include "strcase.h"
+#include "curl_get_line.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -58,8 +59,6 @@
static int parsenetrc(const char *host,
char **loginp,
char **passwordp,
- bool *login_changed,
- bool *password_changed,
char *netrcfile)
{
FILE *file;
@@ -73,8 +72,8 @@
char state_login = 0; /* Found a login keyword */
char state_password = 0; /* Found a password keyword */
- int state_our_login = FALSE; /* With specific_login, found *our* login
- name */
+ int state_our_login = TRUE; /* With specific_login, found *our* login
+ name (or login-less line) */
DEBUGASSERT(netrcfile);
@@ -84,7 +83,7 @@
char netrcbuffer[4096];
int netrcbuffsize = (int)sizeof(netrcbuffer);
- while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
+ while(!done && Curl_get_line(netrcbuffer, netrcbuffsize, file)) {
char *tok;
char *tok_end;
bool quoted;
@@ -96,7 +95,7 @@
}
tok = netrcbuffer;
while(tok) {
- while(ISSPACE(*tok))
+ while(ISBLANK(*tok))
tok++;
/* tok is first non-space letter */
if(!*tok || (*tok == '#'))
@@ -198,9 +197,9 @@
/* we are now parsing sub-keywords concerning "our" host */
if(state_login) {
if(specific_login) {
- state_our_login = strcasecompare(login, tok);
+ state_our_login = !Curl_timestrcmp(login, tok);
}
- else if(!login || strcmp(login, tok)) {
+ else if(!login || Curl_timestrcmp(login, tok)) {
if(login_alloc) {
free(login);
login_alloc = FALSE;
@@ -216,7 +215,7 @@
}
else if(state_password) {
if((state_our_login || !specific_login)
- && (!password || strcmp(password, tok))) {
+ && (!password || Curl_timestrcmp(password, tok))) {
if(password_alloc) {
free(password);
password_alloc = FALSE;
@@ -243,24 +242,20 @@
} /* switch (state) */
tok = ++tok_end;
}
- } /* while fgets() */
+ } /* while Curl_get_line() */
- out:
+out:
if(!retcode) {
/* success */
- *login_changed = FALSE;
- *password_changed = FALSE;
if(login_alloc) {
if(*loginp)
free(*loginp);
*loginp = login;
- *login_changed = TRUE;
}
if(password_alloc) {
if(*passwordp)
free(*passwordp);
*passwordp = password;
- *password_changed = TRUE;
}
}
else {
@@ -281,11 +276,7 @@
* *loginp and *passwordp MUST be allocated if they aren't NULL when passed
* in.
*/
-int Curl_parsenetrc(const char *host,
- char **loginp,
- char **passwordp,
- bool *login_changed,
- bool *password_changed,
+int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
char *netrcfile)
{
int retcode = 1;
@@ -334,8 +325,7 @@
free(homea);
return -1;
}
- retcode = parsenetrc(host, loginp, passwordp, login_changed,
- password_changed, filealloc);
+ retcode = parsenetrc(host, loginp, passwordp, filealloc);
free(filealloc);
#ifdef WIN32
if(retcode == NETRC_FILE_MISSING) {
@@ -345,16 +335,14 @@
free(homea);
return -1;
}
- retcode = parsenetrc(host, loginp, passwordp, login_changed,
- password_changed, filealloc);
+ retcode = parsenetrc(host, loginp, passwordp, filealloc);
free(filealloc);
}
#endif
free(homea);
}
else
- retcode = parsenetrc(host, loginp, passwordp, login_changed,
- password_changed, netrcfile);
+ retcode = parsenetrc(host, loginp, passwordp, netrcfile);
return retcode;
}
diff --git a/lib/netrc.h b/lib/netrc.h
index 53e315b..9f2815f 100644
--- a/lib/netrc.h
+++ b/lib/netrc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,12 +28,8 @@
#ifndef CURL_DISABLE_NETRC
/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
-int Curl_parsenetrc(const char *host,
- char **loginp,
- char **passwordp,
- bool *login_changed,
- bool *password_changed,
- char *filename);
+int Curl_parsenetrc(const char *host, char **loginp,
+ char **passwordp, 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.
diff --git a/lib/nonblock.c b/lib/nonblock.c
index ce73af3..f4eb656 100644
--- a/lib/nonblock.c
+++ b/lib/nonblock.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,9 +31,6 @@
#include <fcntl.h>
#endif
-#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
-#include <sys/filio.h>
-#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
diff --git a/lib/nonblock.h b/lib/nonblock.h
index a42f443..4a1a615 100644
--- a/lib/nonblock.h
+++ b/lib/nonblock.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/noproxy.c b/lib/noproxy.c
new file mode 100644
index 0000000..2b9908d
--- /dev/null
+++ b/lib/noproxy.c
@@ -0,0 +1,266 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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"
+
+#ifndef CURL_DISABLE_PROXY
+
+#include "inet_pton.h"
+#include "strcase.h"
+#include "noproxy.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+/*
+ * Curl_cidr4_match() returns TRUE if the given IPv4 address is within the
+ * specified CIDR address range.
+ */
+UNITTEST bool Curl_cidr4_match(const char *ipv4, /* 1.2.3.4 address */
+ const char *network, /* 1.2.3.4 address */
+ unsigned int bits)
+{
+ unsigned int address = 0;
+ unsigned int check = 0;
+
+ if(bits > 32)
+ /* strange input */
+ return FALSE;
+
+ if(1 != Curl_inet_pton(AF_INET, ipv4, &address))
+ return FALSE;
+ if(1 != Curl_inet_pton(AF_INET, network, &check))
+ return FALSE;
+
+ if(bits && (bits != 32)) {
+ unsigned int mask = 0xffffffff << (32 - bits);
+ unsigned int haddr = htonl(address);
+ unsigned int hcheck = htonl(check);
+#if 0
+ fprintf(stderr, "Host %s (%x) network %s (%x) bits %u mask %x => %x\n",
+ ipv4, haddr, network, hcheck, bits, mask,
+ (haddr ^ hcheck) & mask);
+#endif
+ if((haddr ^ hcheck) & mask)
+ return FALSE;
+ return TRUE;
+ }
+ return (address == check);
+}
+
+UNITTEST bool Curl_cidr6_match(const char *ipv6,
+ const char *network,
+ unsigned int bits)
+{
+#ifdef ENABLE_IPV6
+ int bytes;
+ int rest;
+ unsigned char address[16];
+ unsigned char check[16];
+
+ if(!bits)
+ bits = 128;
+
+ bytes = bits/8;
+ rest = bits & 0x07;
+ if(1 != Curl_inet_pton(AF_INET6, ipv6, address))
+ return FALSE;
+ if(1 != Curl_inet_pton(AF_INET6, network, check))
+ return FALSE;
+ if((bytes > 16) || ((bytes == 16) && rest))
+ return FALSE;
+ if(bytes && memcmp(address, check, bytes))
+ return FALSE;
+ if(rest && !((address[bytes] ^ check[bytes]) & (0xff << (8 - rest))))
+ return FALSE;
+
+ return TRUE;
+#else
+ (void)ipv6;
+ (void)network;
+ (void)bits;
+ return FALSE;
+#endif
+}
+
+enum nametype {
+ TYPE_HOST,
+ TYPE_IPV4,
+ TYPE_IPV6
+};
+
+/****************************************************************
+* 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,
+ bool *spacesep)
+{
+ char hostip[128];
+ *spacesep = FALSE;
+ /*
+ * If we don't have a hostname at all, like for example with a FILE
+ * transfer, we have nothing to interrogate the noproxy list with.
+ */
+ if(!name || name[0] == '\0')
+ return FALSE;
+
+ /* no_proxy=domain1.dom,host.domain2.dom
+ * (a comma-separated list of hosts which should
+ * not be proxied, or an asterisk to override
+ * all proxy variables)
+ */
+ if(no_proxy && no_proxy[0]) {
+ const char *p = no_proxy;
+ size_t namelen;
+ enum nametype type = TYPE_HOST;
+ if(!strcmp("*", no_proxy))
+ return TRUE;
+
+ /* NO_PROXY was specified and it wasn't 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;
+ type = TYPE_IPV6;
+ }
+ else {
+ unsigned int address;
+ namelen = strlen(name);
+ if(1 == Curl_inet_pton(AF_INET, name, &address))
+ type = TYPE_IPV4;
+ else {
+ /* ignore trailing dots in the host name */
+ if(name[namelen - 1] == '.')
+ namelen--;
+ }
+ }
+
+ while(*p) {
+ const char *token;
+ size_t tokenlen = 0;
+ bool match = FALSE;
+
+ /* pass blanks */
+ while(*p && ISBLANK(*p))
+ p++;
+
+ token = p;
+ /* pass over the pattern */
+ while(*p && !ISBLANK(*p) && (*p != ',')) {
+ p++;
+ tokenlen++;
+ }
+
+ 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 = strncasecompare(token, name, namelen);
+ else if(tokenlen < namelen) {
+ /* case B, tailmatch domain */
+ match = (name[namelen - tokenlen - 1] == '.') &&
+ strncasecompare(token, name + (namelen - tokenlen),
+ tokenlen);
+ }
+ /* case C passes through, not a match */
+ break;
+ case TYPE_IPV4:
+ /* FALLTHROUGH */
+ 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;
+
+ slash = strchr(check, '/');
+ /* if the slash is part of this token, use it */
+ if(slash) {
+ bits = 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 */
+ while(ISBLANK(*p))
+ p++;
+ /* if not a comma! */
+ if(*p && (*p != ',')) {
+ *spacesep = TRUE;
+ continue;
+ }
+ /* pass any number of commas */
+ while(*p == ',')
+ p++;
+ } /* while(*p) */
+ } /* NO_PROXY was specified and it wasn't just an asterisk */
+
+ return FALSE;
+}
+
+#endif /* CURL_DISABLE_PROXY */
diff --git a/lib/noproxy.h b/lib/noproxy.h
new file mode 100644
index 0000000..a3a6807
--- /dev/null
+++ b/lib/noproxy.h
@@ -0,0 +1,45 @@
+#ifndef HEADER_CURL_NOPROXY_H
+#define HEADER_CURL_NOPROXY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_PROXY
+
+#ifdef DEBUGBUILD
+
+UNITTEST bool Curl_cidr4_match(const char *ipv4, /* 1.2.3.4 address */
+ const char *network, /* 1.2.3.4 address */
+ unsigned int bits);
+UNITTEST bool Curl_cidr6_match(const char *ipv6,
+ const char *network,
+ unsigned int bits);
+#endif
+
+bool Curl_check_noproxy(const char *name, const char *no_proxy,
+ bool *spacesep);
+
+#endif
+
+#endif /* HEADER_CURL_NOPROXY_H */
diff --git a/lib/openldap.c b/lib/openldap.c
index 19f2ad9..41fecf9 100644
--- a/lib/openldap.c
+++ b/lib/openldap.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2011 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Howard Chu, <hyc@openldap.org>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,6 +47,7 @@
#include "transfer.h"
#include "curl_ldap.h"
#include "curl_base64.h"
+#include "cfilters.h"
#include "connect.h"
#include "curl_sasl.h"
#include "strcase.h"
@@ -294,7 +295,7 @@
const char *value;
while(*ptr && *ptr != '=')
- ptr++;
+ ptr++;
value = ptr + 1;
@@ -500,8 +501,7 @@
struct ldapconninfo *li = conn->proto.ldapc;
bool ssldone = 0;
- result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
- FIRSTSOCKET, &ssldone);
+ result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
if(!result) {
state(data, newstate);
@@ -1068,8 +1068,8 @@
if(!binary) {
/* check for leading or trailing whitespace */
- if(ISSPACE(bvals[i].bv_val[0]) ||
- ISSPACE(bvals[i].bv_val[bvals[i].bv_len - 1]))
+ if(ISBLANK(bvals[i].bv_val[0]) ||
+ ISBLANK(bvals[i].bv_val[bvals[i].bv_len - 1]))
binval = 1;
else {
/* check for unprintable characters */
@@ -1153,7 +1153,7 @@
(void)arg;
if(opt == LBER_SB_OPT_DATA_READY) {
struct Curl_easy *data = sbiod->sbiod_pvt;
- return Curl_ssl_data_pending(data->conn, FIRSTSOCKET);
+ return Curl_conn_data_pending(data, FIRSTSOCKET);
}
return 0;
}
diff --git a/lib/optiontable.pl b/lib/optiontable.pl
old mode 100644
new mode 100755
index 31f8b0e..25d6a66
--- a/lib/optiontable.pl
+++ b/lib/optiontable.pl
@@ -3,12 +3,12 @@
print <<HEAD
/***************************************************************************
* _ _ ____ _
- * Project ___| | | | _ \| |
+ * Project ___| | | | _ \\| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
+ * \\___|\\___/|_| \\_\\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,37 +37,69 @@
my $lastnum=0;
+sub add {
+ my($opt, $type, $num)=@_;
+ my $name;
+ # remove all spaces from the type
+ $type =~ s/ //g;
+ my $ext = $type;
+
+ if($opt =~ /OBSOLETE/) {
+ # skip obsolete options
+ next;
+ }
+
+ if($opt =~ /^CURLOPT_(.*)/) {
+ $name=$1;
+ }
+ $ext =~ s/CURLOPTTYPE_//;
+ $ext =~ s/CBPOINT/CBPTR/;
+ $ext =~ s/POINT\z//;
+ $type = "CURLOT_$ext";
+
+ $opt{$name} = $opt;
+ $type{$name} = $type;
+ push @names, $name;
+ if($num < $lastnum) {
+ print STDERR "ERROR: $opt has bad number: $num < $lastnum\n";
+ exit 2;
+ }
+ else {
+ $lastnum = $num;
+ }
+}
+
+
+my $fl;
while(<STDIN>) {
- if(/^ *CURLOPT\(([^,]*), ([^,]*), (\d+)\)/) {
- my($opt, $type, $num)=($1,$2,$3);
- my $name;
- my $ext = $type;
+ my $l = $_;
+ if($fl) {
+ # continued deprecation
+ if($l =~ /(.*)\),/) {
+ $fl .= $1;
- if($opt =~ /OBSOLETE/) {
- # skip obsolete options
- next;
- }
-
- if($opt =~ /^CURLOPT_(.*)/) {
- $name=$1;
- }
- $ext =~ s/CURLOPTTYPE_//;
- $ext =~ s/CBPOINT/CBPTR/;
- $ext =~ s/POINT\z//;
- $type = "CURLOT_$ext";
-
- $opt{$name} = $opt;
- $type{$name} = $type;
- push @names, $name;
- if($num < $lastnum) {
- print STDERR "ERROR: $opt has bad number\n";
- exit 2;
+ # the end
+ my @p=split(/, */, $fl);
+ add($p[0], $p[1], $p[2]);
+ undef $fl;
}
else {
- $lastnum = $num;
+ # another line to append
+ chomp $l;
+ $fl .= $l;
}
}
+ if(/^ *CURLOPTDEPRECATED\((.*)/) {
+ $fl = $1;
+ chomp $fl;
+ }
+
+ if(/^ *CURLOPT\(([^,]*), ([^,]*), (\d+)\)/) {
+ my($opt, $type, $num)=($1,$2,$3);
+ add($opt, $type, $num);
+ }
+
# alias for an older option
# old = new
if(/^#define (CURLOPT_[^ ]*) *(CURLOPT_\S*)/) {
@@ -103,7 +135,7 @@
}
print <<FOOT
- {NULL, CURLOPT_LASTENTRY, 0, 0} /* end of table */
+ {NULL, CURLOPT_LASTENTRY, CURLOT_LONG, 0} /* end of table */
};
#ifdef DEBUGBUILD
diff --git a/lib/parsedate.c b/lib/parsedate.c
index 5ed8819..1a7195b 100644
--- a/lib/parsedate.c
+++ b/lib/parsedate.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -212,56 +212,55 @@
{
int i;
const char * const *what;
- bool found = FALSE;
if(len > 3)
what = &weekday[0];
- else
+ else if(len == 3)
what = &Curl_wkday[0];
+ else
+ return -1; /* too short */
for(i = 0; i<7; i++) {
- if(strcasecompare(check, what[0])) {
- found = TRUE;
- break;
- }
+ size_t ilen = strlen(what[0]);
+ if((ilen == len) &&
+ strncasecompare(check, what[0], len))
+ return i;
what++;
}
- return found?i:-1;
+ return -1;
}
-static int checkmonth(const char *check)
+static int checkmonth(const char *check, size_t len)
{
int i;
- const char * const *what;
- bool found = FALSE;
+ const char * const *what = &Curl_month[0];
+ if(len != 3)
+ return -1; /* not a month */
- what = &Curl_month[0];
for(i = 0; i<12; i++) {
- if(strcasecompare(check, what[0])) {
- found = TRUE;
- break;
- }
+ if(strncasecompare(check, what[0], 3))
+ return i;
what++;
}
- return found?i:-1; /* return the offset or -1, no real offset is -1 */
+ return -1; /* return the offset or -1, no real offset is -1 */
}
/* return the time zone offset between GMT and the input one, in number
of seconds or -1 if the timezone wasn't found/legal */
-static int checktz(const char *check)
+static int checktz(const char *check, size_t len)
{
unsigned int i;
- const struct tzinfo *what;
- bool found = FALSE;
+ const struct tzinfo *what = tz;
+ if(len > 4) /* longer than any valid timezone */
+ return -1;
- what = tz;
for(i = 0; i< sizeof(tz)/sizeof(tz[0]); i++) {
- if(strcasecompare(check, what->name)) {
- found = TRUE;
- break;
- }
+ size_t ilen = strlen(what->name);
+ if((ilen == len) &&
+ strncasecompare(check, what->name, len))
+ return what->offset*60;
what++;
}
- return found?what->offset*60:-1;
+ return -1;
}
static void skip(const char **date)
@@ -294,6 +293,53 @@
+ hour) * 60 + min) * 60 + sec;
}
+/* Returns the value of a single-digit or two-digit decimal number, return
+ then pointer to after the number. The 'date' pointer is known to point to a
+ digit. */
+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');
+ }
+ *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)
+{
+ const char *p;
+ int hh, mm, ss = 0;
+ hh = oneortwodigit(date, &p);
+ if((hh < 24) && (*p == ':') && ISDIGIT(p[1])) {
+ mm = oneortwodigit(&p[1], &p);
+ if(mm < 60) {
+ if((*p == ':') && ISDIGIT(p[1])) {
+ ss = oneortwodigit(&p[1], &p);
+ if(ss <= 60) {
+ /* valid HH:MM:SS */
+ goto match;
+ }
+ }
+ else {
+ /* valid HH:MM */
+ goto match;
+ }
+ }
+ }
+ return FALSE; /* not a time string */
+match:
+ *h = hh;
+ *m = mm;
+ *s = ss;
+ *endp = (char *)p;
+ return TRUE;
+}
+
/*
* parsedate()
*
@@ -305,6 +351,9 @@
* PARSEDATE_SOONER - time underflow at the low end of time_t
*/
+/* Wednesday is the longest name this parser knows about */
+#define NAME_LEN 12
+
static int parsedate(const char *date, time_t *output)
{
time_t t = 0;
@@ -327,32 +376,32 @@
if(ISALPHA(*date)) {
/* a name coming up */
- char buf[32]="";
- size_t len;
- if(sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz]", buf))
- len = strlen(buf);
- else
- len = 0;
-
- if(wdaynum == -1) {
- wdaynum = checkday(buf, len);
- if(wdaynum != -1)
- found = TRUE;
- }
- if(!found && (monnum == -1)) {
- monnum = checkmonth(buf);
- if(monnum != -1)
- found = TRUE;
+ size_t len = 0;
+ const char *p = date;
+ while(ISALPHA(*p) && (len < NAME_LEN)) {
+ p++;
+ len++;
}
- if(!found && (tzoff == -1)) {
- /* this just must be a time zone string */
- tzoff = checktz(buf);
- if(tzoff != -1)
- found = TRUE;
- }
+ if(len != NAME_LEN) {
+ if(wdaynum == -1) {
+ wdaynum = checkday(date, len);
+ if(wdaynum != -1)
+ found = TRUE;
+ }
+ if(!found && (monnum == -1)) {
+ monnum = checkmonth(date, len);
+ if(monnum != -1)
+ found = TRUE;
+ }
+ if(!found && (tzoff == -1)) {
+ /* this just must be a time zone string */
+ tzoff = checktz(date, len);
+ if(tzoff != -1)
+ found = TRUE;
+ }
+ }
if(!found)
return PARSEDATE_FAIL; /* bad string */
@@ -362,18 +411,10 @@
/* a digit */
int val;
char *end;
- int len = 0;
if((secnum == -1) &&
- (3 == sscanf(date, "%02d:%02d:%02d%n",
- &hournum, &minnum, &secnum, &len))) {
- /* time stamp! */
- date += len;
- }
- else if((secnum == -1) &&
- (2 == sscanf(date, "%02d:%02d%n", &hournum, &minnum, &len))) {
- /* time stamp without seconds */
- date += len;
- secnum = 0;
+ match_time(date, &hournum, &minnum, &secnum, &end)) {
+ /* time stamp */
+ date = end;
}
else {
long lval;
diff --git a/lib/parsedate.h b/lib/parsedate.h
index 4e43477..84c37f1 100644
--- a/lib/parsedate.h
+++ b/lib/parsedate.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/pingpong.c b/lib/pingpong.c
index cd55173..f3f7cb9 100644
--- a/lib/pingpong.c
+++ b/lib/pingpong.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,6 +28,7 @@
#include "curl_setup.h"
#include "urldata.h"
+#include "cfilters.h"
#include "sendf.h"
#include "select.h"
#include "progress.h"
@@ -102,12 +103,12 @@
else
interval_ms = 0; /* immediate */
- if(Curl_ssl_data_pending(conn, FIRSTSOCKET))
+ if(Curl_conn_data_pending(data, FIRSTSOCKET))
rc = 1;
else if(Curl_pp_moredata(pp))
/* We are receiving and there is data in the cache so just read it */
rc = 1;
- else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET))
+ else if(!pp->sendleft && Curl_conn_data_pending(data, FIRSTSOCKET))
/* We are receiving and there is data ready in the SSL library */
rc = 1;
else
@@ -210,7 +211,7 @@
#ifdef HAVE_GSSAPI
data_sec = conn->data_prot;
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
- conn->data_prot = data_sec;
+ conn->data_prot = (unsigned char)data_sec;
#endif
Curl_debug(data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written);
@@ -315,7 +316,7 @@
&gotbytes);
#ifdef HAVE_GSSAPI
DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST);
- conn->data_prot = prot;
+ conn->data_prot = (unsigned char)prot;
#endif
if(result == CURLE_AGAIN)
return CURLE_OK; /* return */
@@ -330,7 +331,7 @@
else if(gotbytes <= 0) {
keepon = FALSE;
result = CURLE_RECV_ERROR;
- failf(data, "response reading failed");
+ failf(data, "response reading failed (errno: %d)", SOCKERRNO);
}
else {
/* we got a whole chunk of data, which can be anything from one
@@ -398,7 +399,8 @@
}
else if(keepon) {
- if((perline == gotbytes) && (gotbytes > data->set.buffer_size/2)) {
+ if((perline == gotbytes) &&
+ (gotbytes > (ssize_t)data->set.buffer_size/2)) {
/* We got an excessive line without newlines and we need to deal
with it. We keep the first bytes of the line then we throw
away the rest. */
diff --git a/lib/pingpong.h b/lib/pingpong.h
index cefae07..80d3f77 100644
--- a/lib/pingpong.h
+++ b/lib/pingpong.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/pop3.c b/lib/pop3.c
index 3151a3f..ddb98bf 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -58,11 +58,6 @@
#include <inet.h>
#endif
-#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
-#undef in_addr_t
-#define in_addr_t unsigned long
-#endif
-
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
@@ -76,6 +71,7 @@
#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
+#include "cfilters.h"
#include "connect.h"
#include "select.h"
#include "multiif.h"
@@ -286,11 +282,11 @@
/***********************************************************************
*
- * state()
+ * pop3_state()
*
* This is the ONLY way to change POP3 state!
*/
-static void state(struct Curl_easy *data, pop3state newstate)
+static void pop3_state(struct Curl_easy *data, pop3state newstate)
{
struct pop3_conn *pop3c = &data->conn->proto.pop3c;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -339,7 +335,7 @@
result = Curl_pp_sendf(data, &pop3c->pp, "%s", "CAPA");
if(!result)
- state(data, POP3_CAPA);
+ pop3_state(data, POP3_CAPA);
return result;
}
@@ -357,7 +353,7 @@
CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "STLS");
if(!result)
- state(data, POP3_STARTTLS);
+ pop3_state(data, POP3_STARTTLS);
return result;
}
@@ -373,20 +369,28 @@
{
/* Start the SSL connection */
struct pop3_conn *pop3c = &conn->proto.pop3c;
- CURLcode result =
- Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET,
- &pop3c->ssldone);
+ CURLcode result;
+ bool ssldone = FALSE;
+
+ if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
+ result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
+ if(result)
+ goto out;
+ }
+
+ result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
if(!result) {
+ pop3c->ssldone = ssldone;
if(pop3c->state != POP3_UPGRADETLS)
- state(data, POP3_UPGRADETLS);
+ pop3_state(data, POP3_UPGRADETLS);
if(pop3c->ssldone) {
pop3_to_pop3s(conn);
result = pop3_perform_capa(data, conn);
}
}
-
+out:
return result;
}
@@ -404,7 +408,7 @@
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!data->state.aptr.user) {
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return result;
}
@@ -413,7 +417,7 @@
result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "USER %s",
conn->user ? conn->user : "");
if(!result)
- state(data, POP3_USER);
+ pop3_state(data, POP3_USER);
return result;
}
@@ -438,7 +442,7 @@
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!data->state.aptr.user) {
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return result;
}
@@ -464,7 +468,7 @@
result = Curl_pp_sendf(data, &pop3c->pp, "APOP %s %s", conn->user, secret);
if(!result)
- state(data, POP3_APOP);
+ pop3_state(data, POP3_APOP);
return result;
}
@@ -548,7 +552,7 @@
/* Check we have enough data to authenticate with and end the
connect phase if we don't */
if(!Curl_sasl_can_authenticate(&pop3c->sasl, data)) {
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return result;
}
@@ -558,7 +562,7 @@
if(!result)
if(progress == SASL_INPROGRESS)
- state(data, POP3_AUTH);
+ pop3_state(data, POP3_AUTH);
}
if(!result && progress == SASL_IDLE) {
@@ -616,7 +620,7 @@
pop3->custom : command));
if(!result)
- state(data, POP3_COMMAND);
+ pop3_state(data, POP3_COMMAND);
return result;
}
@@ -634,7 +638,7 @@
CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "QUIT");
if(!result)
- state(data, POP3_QUIT);
+ pop3_state(data, POP3_QUIT);
return result;
}
@@ -767,7 +771,7 @@
if(pop3code != '+')
pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
- if(!data->set.use_ssl || conn->ssl[FIRSTSOCKET].use)
+ if(!data->set.use_ssl || Curl_conn_is_ssl(conn, FIRSTSOCKET))
result = pop3_perform_authentication(data, conn);
else if(pop3code == '+' && pop3c->tls_supported)
/* Switch to TLS connection now */
@@ -827,7 +831,7 @@
if(!result)
switch(progress) {
case SASL_DONE:
- state(data, POP3_STOP); /* Authenticated */
+ pop3_state(data, POP3_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
#ifndef CURL_DISABLE_CRYPTO_AUTH
@@ -865,7 +869,7 @@
}
else
/* End of connect phase */
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return result;
}
@@ -888,7 +892,7 @@
result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "PASS %s",
conn->passwd ? conn->passwd : "");
if(!result)
- state(data, POP3_PASS);
+ pop3_state(data, POP3_PASS);
return result;
}
@@ -906,7 +910,7 @@
}
else
/* End of connect phase */
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return result;
}
@@ -925,7 +929,7 @@
(void)instate; /* no use for this yet */
if(pop3code != '+') {
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return CURLE_WEIRD_SERVER_REPLY;
}
@@ -948,7 +952,7 @@
content so send it as such. Note that there may even be additional
"headers" after the body */
- if(!data->set.opt_no_body) {
+ if(!data->req.no_body) {
result = Curl_pop3_write(data, pp->cache, pp->cache_size);
if(result)
return result;
@@ -963,7 +967,7 @@
}
/* End of DO phase */
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return result;
}
@@ -1033,12 +1037,12 @@
break;
case POP3_QUIT:
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
break;
default:
/* internal error */
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
break;
}
} while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp));
@@ -1054,8 +1058,9 @@
struct pop3_conn *pop3c = &conn->proto.pop3c;
if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
- result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
- FIRSTSOCKET, &pop3c->ssldone);
+ bool ssldone = FALSE;
+ result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
+ pop3c->ssldone = ssldone;
if(result || !pop3c->ssldone)
return result;
}
@@ -1138,7 +1143,7 @@
return result;
/* Start off waiting for the server greeting response */
- state(data, POP3_SERVERGREET);
+ pop3_state(data, POP3_SERVERGREET);
result = pop3_multi_statemach(data, done);
@@ -1192,12 +1197,11 @@
{
/* This is POP3 and no proxy */
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
struct POP3 *pop3 = data->req.p.pop3;
DEBUGF(infof(data, "DO phase starts"));
- if(data->set.opt_no_body) {
+ if(data->req.no_body) {
/* Requested no body means no transfer */
pop3->transfer = PPTRANSFER_INFO;
}
@@ -1211,7 +1215,7 @@
/* Run the state-machine */
result = pop3_multi_statemach(data, dophase_done);
- *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+ *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
if(*dophase_done)
DEBUGF(infof(data, "DO phase is complete"));
@@ -1372,7 +1376,7 @@
const char *value;
while(*ptr && *ptr != '=')
- ptr++;
+ ptr++;
value = ptr + 1;
diff --git a/lib/pop3.h b/lib/pop3.h
index bb0645f..83f0f83 100644
--- a/lib/pop3.h
+++ b/lib/pop3.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -62,16 +62,16 @@
struct pop3_conn {
struct pingpong pp;
pop3state state; /* Always use pop3.c:state() to change state! */
- bool ssldone; /* Is connect() over SSL done? */
- bool tls_supported; /* StartTLS capability supported by server */
size_t eob; /* Number of bytes of the EOB (End Of Body) that
have been received so far */
size_t strip; /* Number of bytes from the start to ignore as
non-body */
struct SASL sasl; /* SASL-related storage */
- unsigned int authtypes; /* Accepted authentication types */
- unsigned int preftype; /* Preferred authentication type */
char *apoptimestamp; /* APOP timestamp from the server greeting */
+ unsigned char authtypes; /* Accepted authentication types */
+ unsigned char preftype; /* Preferred authentication type */
+ BIT(ssldone); /* Is connect() over SSL done? */
+ BIT(tls_supported); /* StartTLS capability supported by server */
};
extern const struct Curl_handler Curl_handler_pop3;
@@ -84,7 +84,7 @@
/* Authentication type values */
#define POP3_TYPE_NONE 0
-#define POP3_TYPE_ANY ~0U
+#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"
diff --git a/lib/progress.c b/lib/progress.c
index 4a1e1da..6092b78 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -87,8 +87,6 @@
CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE,
(bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) );
-#if (SIZEOF_CURL_OFF_T > 4)
-
else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE)
/* 'XXXXM' is good until we're at 10000MB or above */
msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
@@ -111,15 +109,8 @@
/* up to 10000PB, display without decimal: XXXXP */
msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE);
- /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number
- can hold, but our data type is signed so 8192PB will be the maximum. */
-
-#else
-
- else
- msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
-
-#endif
+ /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number can
+ hold, but our data type is signed so 8192PB will be the maximum. */
return max5;
}
@@ -166,14 +157,11 @@
/*
*
- * Curl_pgrsTime(). Store the current time at the given label. This fetches a
- * fresh "now" and returns it.
- *
- * @unittest: 1399
+ * Curl_pgrsTimeWas(). Store the timestamp time at the given label.
*/
-struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer)
+void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
+ struct curltime timestamp)
{
- struct curltime now = Curl_now();
timediff_t *delta = NULL;
switch(timer) {
@@ -183,15 +171,15 @@
break;
case TIMER_STARTOP:
/* This is set at the start of a transfer */
- data->progress.t_startop = now;
+ data->progress.t_startop = timestamp;
break;
case TIMER_STARTSINGLE:
/* This is set at the start of each single fetch */
- data->progress.t_startsingle = now;
+ data->progress.t_startsingle = timestamp;
data->progress.is_t_startransfer_set = false;
break;
case TIMER_STARTACCEPT:
- data->progress.t_acceptdata = now;
+ data->progress.t_acceptdata = timestamp;
break;
case TIMER_NAMELOOKUP:
delta = &data->progress.t_nslookup;
@@ -214,7 +202,7 @@
* changing the t_starttransfer time.
*/
if(data->progress.is_t_startransfer_set) {
- return now;
+ return;
}
else {
data->progress.is_t_startransfer_set = true;
@@ -224,15 +212,30 @@
/* this is the normal end-of-transfer thing */
break;
case TIMER_REDIRECT:
- data->progress.t_redirect = Curl_timediff_us(now, data->progress.start);
+ data->progress.t_redirect = Curl_timediff_us(timestamp,
+ data->progress.start);
break;
}
if(delta) {
- timediff_t us = Curl_timediff_us(now, data->progress.t_startsingle);
+ timediff_t us = Curl_timediff_us(timestamp, data->progress.t_startsingle);
if(us < 1)
us = 1; /* make sure at least one microsecond passed */
*delta += us;
}
+}
+
+/*
+ *
+ * Curl_pgrsTime(). Store the current time at the given label. This fetches a
+ * fresh "now" and returns it.
+ *
+ * @unittest: 1399
+ */
+struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer)
+{
+ struct curltime now = Curl_now();
+
+ Curl_pgrsTimeWas(data, timer, now);
return now;
}
diff --git a/lib/progress.h b/lib/progress.h
index a129315..0049cd0 100644
--- a/lib/progress.h
+++ b/lib/progress.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -57,6 +57,13 @@
curl_off_t limit,
struct curltime start,
struct curltime now);
+/**
+ * Update progress timer with the elapsed time from its start to `timestamp`.
+ * This allows updating timers later and is used by happy eyeballing, where
+ * we only want to record the winner's times.
+ */
+void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
+ struct curltime timestamp);
#define PGRS_HIDE (1<<4)
#define PGRS_UL_SIZE_KNOWN (1<<5)
diff --git a/lib/psl.c b/lib/psl.c
index 60c98a4..626a203 100644
--- a/lib/psl.c
+++ b/lib/psl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/psl.h b/lib/psl.h
index 34f0a5c..23cfa92 100644
--- a/lib/psl.h
+++ b/lib/psl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/quic.h b/lib/quic.h
deleted file mode 100644
index b357747..0000000
--- a/lib/quic.h
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef HEADER_CURL_QUIC_H
-#define HEADER_CURL_QUIC_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the 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"
-
-#ifdef ENABLE_QUIC
-#ifdef USE_NGTCP2
-#include "vquic/ngtcp2.h"
-#endif
-#ifdef USE_QUICHE
-#include "vquic/quiche.h"
-#endif
-#ifdef USE_MSH3
-#include "vquic/msh3.h"
-#endif
-
-#include "urldata.h"
-
-/* functions provided by the specific backends */
-CURLcode Curl_quic_connect(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t sockfd,
- int sockindex,
- const struct sockaddr *addr,
- socklen_t addrlen);
-CURLcode Curl_quic_is_connected(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
- bool *connected);
-void Curl_quic_ver(char *p, size_t len);
-CURLcode Curl_quic_done_sending(struct Curl_easy *data);
-void Curl_quic_done(struct Curl_easy *data, bool premature);
-bool Curl_quic_data_pending(const struct Curl_easy *data);
-void Curl_quic_disconnect(struct Curl_easy *data,
- struct connectdata *conn, int tempindex);
-CURLcode Curl_quic_idle(struct Curl_easy *data);
-
-#else /* ENABLE_QUIC */
-#define Curl_quic_done_sending(x)
-#define Curl_quic_done(x,y)
-#define Curl_quic_data_pending(x)
-#define Curl_quic_disconnect(x,y,z)
-#endif /* !ENABLE_QUIC */
-
-#endif /* HEADER_CURL_QUIC_H */
diff --git a/lib/rand.c b/lib/rand.c
index dd02f52..7d24765 100644
--- a/lib/rand.c
+++ b/lib/rand.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,10 +27,18 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_ARC4RANDOM
+/* Some platforms might have the prototype missing (ubuntu + libressl) */
+uint32_t arc4random(void);
+#endif
#include <curl/curl.h>
#include "vtls/vtls.h"
#include "sendf.h"
+#include "timeval.h"
#include "rand.h"
/* The last 3 #include files should be in this order */
@@ -38,6 +46,64 @@
#include "curl_memory.h"
#include "memdebug.h"
+#ifdef WIN32
+
+#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+# define HAVE_MINGW_ORIGINAL
+#endif
+
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 && \
+ !defined(HAVE_MINGW_ORIGINAL)
+# define HAVE_WIN_BCRYPTGENRANDOM
+# include <bcrypt.h>
+# ifdef _MSC_VER
+# pragma comment(lib, "bcrypt.lib")
+# endif
+# ifndef BCRYPT_USE_SYSTEM_PREFERRED_RNG
+# define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002
+# endif
+# ifndef STATUS_SUCCESS
+# define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+# endif
+#elif defined(USE_WIN32_CRYPTO)
+# include <wincrypt.h>
+# ifdef _MSC_VER
+# pragma comment(lib, "advapi32.lib")
+# endif
+#endif
+
+CURLcode Curl_win32_random(unsigned char *entropy, size_t length)
+{
+ memset(entropy, 0, length);
+
+#if defined(HAVE_WIN_BCRYPTGENRANDOM)
+ if(BCryptGenRandom(NULL, entropy, (ULONG)length,
+ BCRYPT_USE_SYSTEM_PREFERRED_RNG) != STATUS_SUCCESS)
+ return CURLE_FAILED_INIT;
+
+ return CURLE_OK;
+#elif defined(USE_WIN32_CRYPTO)
+ {
+ HCRYPTPROV hCryptProv = 0;
+
+ if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ return CURLE_FAILED_INIT;
+
+ if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
+ CryptReleaseContext(hCryptProv, 0UL);
+ return CURLE_FAILED_INIT;
+ }
+
+ CryptReleaseContext(hCryptProv, 0UL);
+ }
+ return CURLE_OK;
+#else
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
+#endif
+
static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
{
unsigned int r;
@@ -73,6 +139,19 @@
/* ---- non-cryptographic version following ---- */
+#ifdef WIN32
+ if(!seeded) {
+ result = Curl_win32_random((unsigned char *)rnd, sizeof(*rnd));
+ if(result != CURLE_NOT_BUILT_IN)
+ return result;
+ }
+#endif
+
+#ifdef HAVE_ARC4RANDOM
+ *rnd = (unsigned int)arc4random();
+ return CURLE_OK;
+#endif
+
#if defined(RANDOM_FILE) && !defined(WIN32)
if(!seeded) {
/* if there's a random file to read a seed from, use it */
@@ -104,8 +183,8 @@
}
/*
- * Curl_rand() stores 'num' number of random unsigned integers in the buffer
- * 'rndptr' points to.
+ * Curl_rand() stores 'num' number of random unsigned characters in the buffer
+ * 'rnd' points to.
*
* If libcurl is built without TLS support or with a TLS backend that lacks a
* proper random API (rustls, Gskit or mbedTLS), this function will use "weak"
@@ -146,7 +225,7 @@
/*
* Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
- * hexadecimal digits PLUS a zero terminating byte. It must be an odd number
+ * hexadecimal digits PLUS a null-terminating byte. It must be an odd number
* size.
*/
@@ -169,7 +248,7 @@
/* make sure it fits in the local buffer and that it is an odd number! */
return CURLE_BAD_FUNCTION_ARGUMENT;
- num--; /* save one for zero termination */
+ num--; /* save one for null-termination */
result = Curl_rand(data, buffer, num/2);
if(result)
diff --git a/lib/rand.h b/lib/rand.h
index 2f442f5..cbe0567 100644
--- a/lib/rand.h
+++ b/lib/rand.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,10 +42,16 @@
/*
* Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
- * hexadecimal digits PLUS a zero terminating byte. It must be an odd number
+ * 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);
+#ifdef WIN32
+/* Random generator shared between the Schannel vtls and Curl_rand*()
+ functions */
+CURLcode Curl_win32_random(unsigned char *entropy, size_t length);
+#endif
+
#endif /* HEADER_CURL_RAND_H */
diff --git a/lib/rename.c b/lib/rename.c
index cfb3699..97a66e9 100644
--- a/lib/rename.c
+++ b/lib/rename.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/rename.h b/lib/rename.h
index 9958e2c..0444082 100644
--- a/lib/rename.h
+++ b/lib/rename.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/rtsp.c b/lib/rtsp.c
index 5a6644b..ccd7264 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -38,14 +38,13 @@
#include "strcase.h"
#include "select.h"
#include "connect.h"
+#include "cfilters.h"
#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-#define RTP_PKT_CHANNEL(p) ((int)((unsigned char)((p)[1])))
-
#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \
((int)((unsigned char)((p)[3]))))
@@ -90,6 +89,8 @@
static
CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len);
+static
+CURLcode rtsp_parse_transport(struct Curl_easy *data, char *transport);
/*
@@ -118,6 +119,7 @@
PROTOPT_NONE /* flags */
};
+#define MAX_RTP_BUFFERSIZE 1000000 /* arbitrary */
static CURLcode rtsp_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
@@ -129,41 +131,12 @@
if(!rtsp)
return CURLE_OUT_OF_MEMORY;
+ Curl_dyn_init(&conn->proto.rtspc.buf, MAX_RTP_BUFFERSIZE);
return CURLE_OK;
}
/*
- * The server may send us RTP data at any point, and RTSPREQ_RECEIVE does not
- * want to block the application forever while receiving a stream. Therefore,
- * we cannot assume that an RTSP socket is dead just because it is readable.
- *
- * Instead, if it is readable, run Curl_connalive() to peek at the socket
- * and distinguish between closed and data.
- */
-static bool rtsp_connisdead(struct connectdata *check)
-{
- int sval;
- bool ret_val = TRUE;
-
- sval = SOCKET_READABLE(check->sock[FIRSTSOCKET], 0);
- if(sval == 0) {
- /* timeout */
- ret_val = FALSE;
- }
- else if(sval & CURL_CSELECT_ERR) {
- /* socket is in an error state */
- ret_val = TRUE;
- }
- else if(sval & CURL_CSELECT_IN) {
- /* readable with no error. could still be closed */
- ret_val = !Curl_connalive(check);
- }
-
- return ret_val;
-}
-
-/*
* Function to check on various aspects of a connection.
*/
static unsigned int rtsp_conncheck(struct Curl_easy *data,
@@ -174,7 +147,8 @@
(void)data;
if(checks_to_perform & CONNCHECK_ISDEAD) {
- if(rtsp_connisdead(conn))
+ bool input_pending;
+ if(!Curl_conn_is_alive(data, conn, &input_pending))
ret_val |= CONNRESULT_DEAD;
}
@@ -204,7 +178,7 @@
{
(void) dead;
(void) data;
- Curl_safefree(conn->proto.rtspc.rtp_buf);
+ Curl_dyn_free(&conn->proto.rtspc.buf);
return CURLE_OK;
}
@@ -232,7 +206,7 @@
return CURLE_RTSP_CSEQ_ERROR;
}
if(data->set.rtspreq == RTSPREQ_RECEIVE &&
- (data->conn->proto.rtspc.rtp_channel == -1)) {
+ (data->conn->proto.rtspc.rtp_channel == -1)) {
infof(data, "Got an RTP Receive with a CSeq of %ld", CSeq_recv);
}
}
@@ -267,11 +241,23 @@
rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq;
rtsp->CSeq_recv = 0;
+ /* Setup the first_* fields to allow auth details get sent
+ to this origin */
+
+ if(!data->state.first_host) {
+ data->state.first_host = strdup(conn->host.name);
+ if(!data->state.first_host)
+ return CURLE_OUT_OF_MEMORY;
+
+ data->state.first_remote_port = conn->remote_port;
+ data->state.first_remote_protocol = conn->handler->protocol;
+ }
+
/* Setup the 'p_request' pointer to the proper p_request string
* Since all RTSP requests are included here, there is no need to
* support custom requests like HTTP.
**/
- data->set.opt_no_body = TRUE; /* most requests don't contain a body */
+ data->req.no_body = TRUE; /* most requests don't contain a body */
switch(rtspreq) {
default:
failf(data, "Got invalid RTSP request");
@@ -281,7 +267,7 @@
break;
case RTSPREQ_DESCRIBE:
p_request = "DESCRIBE";
- data->set.opt_no_body = FALSE;
+ data->req.no_body = FALSE;
break;
case RTSPREQ_ANNOUNCE:
p_request = "ANNOUNCE";
@@ -301,7 +287,7 @@
case RTSPREQ_GET_PARAMETER:
/* GET_PARAMETER's no_body status is determined later */
p_request = "GET_PARAMETER";
- data->set.opt_no_body = FALSE;
+ data->req.no_body = FALSE;
break;
case RTSPREQ_SET_PARAMETER:
p_request = "SET_PARAMETER";
@@ -311,8 +297,8 @@
break;
case RTSPREQ_RECEIVE:
p_request = "";
- /* Treat interleaved RTP as body*/
- data->set.opt_no_body = FALSE;
+ /* Treat interleaved RTP as body */
+ data->req.no_body = FALSE;
break;
case RTSPREQ_LAST:
failf(data, "Got invalid RTSP request: RTSPREQ_LAST");
@@ -390,7 +376,6 @@
if(Curl_checkheaders(data, STRCONST("User-Agent")) &&
data->state.aptr.uagent) {
Curl_safefree(data->state.aptr.uagent);
- data->state.aptr.uagent = NULL;
}
else if(!Curl_checkheaders(data, STRCONST("User-Agent")) &&
data->set.str[STRING_USERAGENT]) {
@@ -410,8 +395,6 @@
Curl_safefree(data->state.aptr.ref);
if(data->state.referer && !Curl_checkheaders(data, STRCONST("Referer")))
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
- else
- data->state.aptr.ref = NULL;
p_referrer = data->state.aptr.ref;
@@ -492,7 +475,6 @@
* with basic and digest, it will be freed anyway by the next request
*/
Curl_safefree(data->state.aptr.userpwd);
- data->state.aptr.userpwd = NULL;
if(result)
return result;
@@ -511,7 +493,7 @@
rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
- if(data->set.upload) {
+ if(data->state.upload) {
putsize = data->state.infilesize;
data->state.httpreq = HTTPREQ_PUT;
@@ -530,7 +512,7 @@
result =
Curl_dyn_addf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
- (data->set.upload ? putsize : postsize));
+ (data->state.upload ? putsize : postsize));
if(result)
return result;
}
@@ -561,7 +543,7 @@
else if(rtspreq == RTSPREQ_GET_PARAMETER) {
/* Check for an empty GET_PARAMETER (heartbeat) request */
data->state.httpreq = HTTPREQ_HEAD;
- data->set.opt_no_body = TRUE;
+ data->req.no_body = TRUE;
}
}
@@ -580,7 +562,7 @@
}
/* issue the request */
- result = Curl_buffer_send(&req_buffer, data,
+ result = Curl_buffer_send(&req_buffer, data, data->req.p.http,
&data->info.request_size, 0, FIRSTSOCKET);
if(result) {
failf(data, "Failed sending RTSP request");
@@ -610,26 +592,20 @@
bool *readmore) {
struct SingleRequest *k = &data->req;
struct rtsp_conn *rtspc = &(conn->proto.rtspc);
+ unsigned char *rtp_channel_mask = data->state.rtp_channel_mask;
char *rtp; /* moving pointer to rtp data */
ssize_t rtp_dataleft; /* how much data left to parse in this round */
- char *scratch;
CURLcode result;
+ bool interleaved = false;
+ size_t skip_size = 0;
- if(rtspc->rtp_buf) {
- /* There was some leftover data the last time. Merge buffers */
- char *newptr = Curl_saferealloc(rtspc->rtp_buf,
- rtspc->rtp_bufsize + *nread);
- if(!newptr) {
- rtspc->rtp_buf = NULL;
- rtspc->rtp_bufsize = 0;
+ if(Curl_dyn_len(&rtspc->buf)) {
+ /* There was some leftover data the last time. Append new buffers */
+ if(Curl_dyn_addn(&rtspc->buf, k->str, *nread))
return CURLE_OUT_OF_MEMORY;
- }
- rtspc->rtp_buf = newptr;
- memcpy(rtspc->rtp_buf + rtspc->rtp_bufsize, k->str, *nread);
- rtspc->rtp_bufsize += *nread;
- rtp = rtspc->rtp_buf;
- rtp_dataleft = rtspc->rtp_bufsize;
+ rtp = Curl_dyn_ptr(&rtspc->buf);
+ rtp_dataleft = Curl_dyn_len(&rtspc->buf);
}
else {
/* Just parse the request buffer directly */
@@ -637,71 +613,107 @@
rtp_dataleft = *nread;
}
- while((rtp_dataleft > 0) &&
- (rtp[0] == '$')) {
- if(rtp_dataleft > 4) {
- int rtp_length;
+ while(rtp_dataleft > 0) {
+ if(rtp[0] == '$') {
+ if(rtp_dataleft > 4) {
+ unsigned char rtp_channel;
+ int rtp_length;
+ int idx;
+ int off;
- /* Parse the header */
- /* The channel identifier immediately follows and is 1 byte */
- rtspc->rtp_channel = RTP_PKT_CHANNEL(rtp);
+ /* Parse the header */
+ /* The channel identifier immediately follows and is 1 byte */
+ rtp_channel = (unsigned char)rtp[1];
+ idx = rtp_channel / 8;
+ off = rtp_channel % 8;
+ if(!(rtp_channel_mask[idx] & (1 << off))) {
+ /* invalid channel number, maybe not an RTP packet */
+ rtp++;
+ rtp_dataleft--;
+ skip_size++;
+ continue;
+ }
+ if(skip_size > 0) {
+ DEBUGF(infof(data, "Skip the malformed interleaved data %lu "
+ "bytes", skip_size));
+ }
+ skip_size = 0;
+ rtspc->rtp_channel = rtp_channel;
- /* The length is two bytes */
- rtp_length = RTP_PKT_LENGTH(rtp);
+ /* The length is two bytes */
+ rtp_length = RTP_PKT_LENGTH(rtp);
- if(rtp_dataleft < rtp_length + 4) {
- /* Need more - incomplete payload*/
+ if(rtp_dataleft < rtp_length + 4) {
+ /* Need more - incomplete payload */
+ *readmore = TRUE;
+ break;
+ }
+ interleaved = true;
+ /* We have the full RTP interleaved packet
+ * Write out the header including the leading '$' */
+ DEBUGF(infof(data, "RTP write channel %d rtp_length %d",
+ rtspc->rtp_channel, rtp_length));
+ result = rtp_client_write(data, &rtp[0], rtp_length + 4);
+ if(result) {
+ *readmore = FALSE;
+ return result;
+ }
+
+ /* Move forward in the buffer */
+ rtp_dataleft -= rtp_length + 4;
+ rtp += rtp_length + 4;
+
+ if(data->set.rtspreq == RTSPREQ_RECEIVE) {
+ /* If we are in a passive receive, give control back
+ * to the app as often as we can.
+ */
+ k->keepon &= ~KEEP_RECV;
+ }
+ }
+ else {
+ /* Need more - incomplete header */
*readmore = TRUE;
break;
}
- /* We have the full RTP interleaved packet
- * Write out the header including the leading '$' */
- DEBUGF(infof(data, "RTP write channel %d rtp_length %d",
- rtspc->rtp_channel, rtp_length));
- result = rtp_client_write(data, &rtp[0], rtp_length + 4);
- if(result) {
- failf(data, "Got an error writing an RTP packet");
- *readmore = FALSE;
- Curl_safefree(rtspc->rtp_buf);
- rtspc->rtp_buf = NULL;
- rtspc->rtp_bufsize = 0;
- return result;
- }
-
- /* Move forward in the buffer */
- rtp_dataleft -= rtp_length + 4;
- rtp += rtp_length + 4;
-
- if(data->set.rtspreq == RTSPREQ_RECEIVE) {
- /* If we are in a passive receive, give control back
- * to the app as often as we can.
- */
- k->keepon &= ~KEEP_RECV;
- }
}
else {
- /* Need more - incomplete header */
- *readmore = TRUE;
- break;
+ /* If the following data begins with 'RTSP/', which might be an RTSP
+ message, we should stop skipping the data. */
+ /* If `k-> headerline> 0 && !interleaved` is true, we are maybe in the
+ middle of an RTSP message. It is difficult to determine this, so we
+ stop skipping. */
+ size_t prefix_len = (rtp_dataleft < 5) ? rtp_dataleft : 5;
+ if((k->headerline > 0 && !interleaved) ||
+ strncmp(rtp, "RTSP/", prefix_len) == 0) {
+ if(skip_size > 0) {
+ DEBUGF(infof(data, "Skip the malformed interleaved data %lu "
+ "bytes", skip_size));
+ }
+ break; /* maybe is an RTSP message */
+ }
+ /* Skip incorrect data util the next RTP packet or RTSP message */
+ do {
+ rtp++;
+ rtp_dataleft--;
+ skip_size++;
+ } while(rtp_dataleft > 0 && rtp[0] != '$' && rtp[0] != 'R');
}
}
if(rtp_dataleft && rtp[0] == '$') {
DEBUGF(infof(data, "RTP Rewinding %zd %s", rtp_dataleft,
- *readmore ? "(READMORE)" : ""));
+ *readmore ? "(READMORE)" : ""));
/* Store the incomplete RTP packet for a "rewind" */
- scratch = malloc(rtp_dataleft);
- if(!scratch) {
- Curl_safefree(rtspc->rtp_buf);
- rtspc->rtp_buf = NULL;
- rtspc->rtp_bufsize = 0;
- return CURLE_OUT_OF_MEMORY;
+ if(!Curl_dyn_len(&rtspc->buf)) {
+ /* nothing was stored, add this data */
+ if(Curl_dyn_addn(&rtspc->buf, rtp, rtp_dataleft))
+ return CURLE_OUT_OF_MEMORY;
}
- memcpy(scratch, rtp, rtp_dataleft);
- Curl_safefree(rtspc->rtp_buf);
- rtspc->rtp_buf = scratch;
- rtspc->rtp_bufsize = rtp_dataleft;
+ else {
+ /* keep the remainder */
+ Curl_dyn_tail(&rtspc->buf, rtp_dataleft);
+ }
/* As far as the transfer is concerned, this data is consumed */
*nread = 0;
@@ -710,20 +722,10 @@
/* Fix up k->str to point just after the last RTP packet */
k->str += *nread - rtp_dataleft;
- /* either all of the data has been read or...
- * rtp now points at the next byte to parse
- */
- if(rtp_dataleft > 0)
- DEBUGASSERT(k->str[0] == rtp[0]);
-
- DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */
-
*nread = rtp_dataleft;
/* If we get here, we have finished with the leftover/merge buffer */
- Curl_safefree(rtspc->rtp_buf);
- rtspc->rtp_buf = NULL;
- rtspc->rtp_bufsize = 0;
+ Curl_dyn_free(&rtspc->buf);
return CURLE_OK;
}
@@ -772,12 +774,14 @@
CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
{
- long CSeq = 0;
-
if(checkprefix("CSeq:", header)) {
- /* Store the received CSeq. Match is verified in rtsp_done */
- int nc = sscanf(&header[4], ": %ld", &CSeq);
- if(nc == 1) {
+ long CSeq = 0;
+ char *endp;
+ char *p = &header[5];
+ while(ISBLANK(*p))
+ p++;
+ CSeq = strtol(p, &endp, 10);
+ if(p != endp) {
struct RTSP *rtsp = data->req.p.rtsp;
rtsp->CSeq_recv = CSeq; /* mark the request */
data->state.rtsp_CSeq_recv = CSeq; /* update the handle */
@@ -794,7 +798,7 @@
/* Find the first non-space letter */
start = header + 8;
- while(*start && ISSPACE(*start))
+ while(*start && ISBLANK(*start))
start++;
if(!*start) {
@@ -836,7 +840,63 @@
(data->set.str[STRING_RTSP_SESSION_ID])[idlen] = '\0';
}
}
+ else if(checkprefix("Transport:", header)) {
+ CURLcode result;
+ result = rtsp_parse_transport(data, header + 10);
+ if(result)
+ return result;
+ }
return CURLE_OK;
}
+static
+CURLcode rtsp_parse_transport(struct Curl_easy *data, char *transport)
+{
+ /* If we receive multiple Transport response-headers, the linterleaved
+ channels of each response header is recorded and used together for
+ subsequent data validity checks.*/
+ /* e.g.: ' RTP/AVP/TCP;unicast;interleaved=5-6' */
+ char *start;
+ char *end;
+ start = transport;
+ while(start && *start) {
+ while(*start && ISBLANK(*start) )
+ start++;
+ end = strchr(start, ';');
+ if(checkprefix("interleaved=", start)) {
+ long chan1, chan2, chan;
+ char *endp;
+ char *p = start + 12;
+ chan1 = strtol(p, &endp, 10);
+ if(p != endp && chan1 >= 0 && chan1 <= 255) {
+ unsigned char *rtp_channel_mask = data->state.rtp_channel_mask;
+ chan2 = chan1;
+ if(*endp == '-') {
+ p = endp + 1;
+ chan2 = strtol(p, &endp, 10);
+ if(p == endp || chan2 < 0 || chan2 > 255) {
+ infof(data, "Unable to read the interleaved parameter from "
+ "Transport header: [%s]", transport);
+ chan2 = chan1;
+ }
+ }
+ for(chan = chan1; chan <= chan2; chan++) {
+ long idx = chan / 8;
+ long off = chan % 8;
+ rtp_channel_mask[idx] |= (unsigned char)(1 << off);
+ }
+ }
+ else {
+ infof(data, "Unable to read the interleaved parameter from "
+ "Transport header: [%s]", transport);
+ }
+ break;
+ }
+ /* skip to next parameter */
+ start = (!end) ? end : (end + 1);
+ }
+ return CURLE_OK;
+}
+
+
#endif /* CURL_DISABLE_RTSP or using Hyper */
diff --git a/lib/rtsp.h b/lib/rtsp.h
index 377c828..111bac2 100644
--- a/lib/rtsp.h
+++ b/lib/rtsp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -45,8 +45,7 @@
* Currently, only used for tracking incomplete RTP data reads
*/
struct rtsp_conn {
- char *rtp_buf;
- ssize_t rtp_bufsize;
+ struct dynbuf buf;
int rtp_channel;
};
@@ -62,7 +61,7 @@
* HTTP functions can safely treat this as an HTTP struct, but RTSP aware
* functions can also index into the later elements.
*/
- struct HTTP http_wrapper; /*wrap HTTP to do the heavy lifting */
+ struct HTTP http_wrapper; /* wrap HTTP to do the heavy lifting */
long CSeq_sent; /* CSeq of this request */
long CSeq_recv; /* CSeq received */
diff --git a/lib/select.c b/lib/select.c
index c16358d..cae9beb 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -61,8 +61,8 @@
* for the intended use of this function in the library.
*
* Return values:
- * -1 = system call error, invalid timeout value, or interrupted
- * 0 = specified timeout has elapsed
+ * -1 = system call error, or invalid timeout value
+ * 0 = specified timeout has elapsed, or interrupted
*/
int Curl_wait_ms(timediff_t timeout_ms)
{
@@ -99,8 +99,13 @@
}
#endif /* HAVE_POLL_FINE */
#endif /* USE_WINSOCK */
- if(r)
- r = -1;
+ if(r) {
+ if((r == -1) && (SOCKERRNO == EINTR))
+ /* make EINTR from select or poll not a "lethal" error */
+ r = 0;
+ else
+ r = -1;
+ }
return r;
}
@@ -230,14 +235,14 @@
if(readfd0 != CURL_SOCKET_BAD) {
if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
r |= CURL_CSELECT_IN;
- if(pfd[num].revents & (POLLRDBAND|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))
r |= CURL_CSELECT_IN2;
- if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
+ if(pfd[num].revents & (POLLPRI|POLLNVAL))
r |= CURL_CSELECT_ERR;
num++;
}
@@ -310,8 +315,12 @@
else
pending_ms = 0;
r = poll(ufds, nfds, pending_ms);
- if(r <= 0)
+ if(r <= 0) {
+ if((r == -1) && (SOCKERRNO == EINTR))
+ /* make EINTR from select or poll not a "lethal" error */
+ r = 0;
return r;
+ }
for(i = 0; i < nfds; i++) {
if(ufds[i].fd == CURL_SOCKET_BAD)
diff --git a/lib/select.h b/lib/select.h
index eaff7d9..5b1ca23 100644
--- a/lib/select.h
+++ b/lib/select.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,8 +36,7 @@
* Definition of pollfd struct and constants for platforms lacking them.
*/
-#if !defined(HAVE_STRUCT_POLLFD) && \
- !defined(HAVE_SYS_POLL_H) && \
+#if !defined(HAVE_SYS_POLL_H) && \
!defined(HAVE_POLL_H) && \
!defined(POLLIN)
diff --git a/lib/sendf.c b/lib/sendf.c
index a210284..437fa74 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -38,6 +38,7 @@
#include "urldata.h"
#include "sendf.h"
+#include "cfilters.h"
#include "connect.h"
#include "vtls/vtls.h"
#include "vssh/ssh.h"
@@ -48,6 +49,7 @@
#include "strdup.h"
#include "http2.h"
#include "headers.h"
+#include "ws.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -136,151 +138,6 @@
}
#endif /* CURL_DO_LINEEND_CONV && !CURL_DISABLE_FTP */
-#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
-bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
-{
- struct postponed_data * const psnd = &(conn->postponed[sockindex]);
- return psnd->buffer && psnd->allocated_size &&
- psnd->recv_size > psnd->recv_processed;
-}
-
-static CURLcode pre_receive_plain(struct Curl_easy *data,
- struct connectdata *conn, int num)
-{
- const curl_socket_t sockfd = conn->sock[num];
- struct postponed_data * const psnd = &(conn->postponed[num]);
- size_t bytestorecv = psnd->allocated_size - psnd->recv_size;
- /* WinSock will destroy unread received data if send() is
- failed.
- To avoid lossage of received data, recv() must be
- performed before every send() if any incoming data is
- available. However, skip this, if buffer is already full. */
- if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 &&
- conn->recv[num] == Curl_recv_plain &&
- (!psnd->buffer || bytestorecv)) {
- const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD,
- CURL_SOCKET_BAD, 0);
- if(readymask != -1 && (readymask & CURL_CSELECT_IN) != 0) {
- /* Have some incoming data */
- if(!psnd->buffer) {
- /* Use buffer double default size for intermediate buffer */
- psnd->allocated_size = 2 * data->set.buffer_size;
- psnd->buffer = malloc(psnd->allocated_size);
- if(!psnd->buffer)
- return CURLE_OUT_OF_MEMORY;
- psnd->recv_size = 0;
- psnd->recv_processed = 0;
-#ifdef DEBUGBUILD
- psnd->bindsock = sockfd; /* Used only for DEBUGASSERT */
-#endif /* DEBUGBUILD */
- bytestorecv = psnd->allocated_size;
- }
- if(psnd->buffer) {
- ssize_t recvedbytes;
- DEBUGASSERT(psnd->bindsock == sockfd);
- recvedbytes = sread(sockfd, psnd->buffer + psnd->recv_size,
- bytestorecv);
- if(recvedbytes > 0)
- psnd->recv_size += recvedbytes;
- }
- else
- psnd->allocated_size = 0;
- }
- }
- return CURLE_OK;
-}
-
-static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf,
- size_t len)
-{
- struct postponed_data * const psnd = &(conn->postponed[num]);
- size_t copysize;
- if(!psnd->buffer)
- return 0;
-
- DEBUGASSERT(psnd->allocated_size > 0);
- DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
- DEBUGASSERT(psnd->recv_processed <= psnd->recv_size);
- /* Check and process data that already received and storied in internal
- intermediate buffer */
- if(psnd->recv_size > psnd->recv_processed) {
- DEBUGASSERT(psnd->bindsock == conn->sock[num]);
- copysize = CURLMIN(len, psnd->recv_size - psnd->recv_processed);
- memcpy(buf, psnd->buffer + psnd->recv_processed, copysize);
- psnd->recv_processed += copysize;
- }
- else
- copysize = 0; /* buffer was allocated, but nothing was received */
-
- /* Free intermediate buffer if it has no unprocessed data */
- if(psnd->recv_processed == psnd->recv_size) {
- free(psnd->buffer);
- psnd->buffer = NULL;
- psnd->allocated_size = 0;
- psnd->recv_size = 0;
- psnd->recv_processed = 0;
-#ifdef DEBUGBUILD
- psnd->bindsock = CURL_SOCKET_BAD;
-#endif /* DEBUGBUILD */
- }
- return (ssize_t)copysize;
-}
-#else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
-/* Use "do-nothing" macros instead of functions when workaround not used */
-bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
-{
- (void)conn;
- (void)sockindex;
- return false;
-}
-#define pre_receive_plain(d,c,n) CURLE_OK
-#define get_pre_recved(c,n,b,l) 0
-#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
-
-/* Curl_infof() is for info message along the way */
-#define MAXINFO 2048
-
-void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
-{
- DEBUGASSERT(!strchr(fmt, '\n'));
- if(data && data->set.verbose) {
- va_list ap;
- size_t len;
- char buffer[MAXINFO + 2];
- va_start(ap, fmt);
- len = mvsnprintf(buffer, MAXINFO, fmt, ap);
- va_end(ap);
- buffer[len++] = '\n';
- buffer[len] = '\0';
- Curl_debug(data, CURLINFO_TEXT, buffer, len);
- }
-}
-
-/* Curl_failf() is for messages stating why we failed.
- * The message SHALL NOT include any LF or CR.
- */
-
-void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
-{
- DEBUGASSERT(!strchr(fmt, '\n'));
- if(data->set.verbose || data->set.errorbuffer) {
- va_list ap;
- size_t len;
- char error[CURL_ERROR_SIZE + 2];
- va_start(ap, fmt);
- len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
-
- if(data->set.errorbuffer && !data->state.errorbuf) {
- strcpy(data->set.errorbuffer, error);
- data->state.errorbuf = TRUE; /* wrote error string */
- }
- error[len++] = '\n';
- error[len] = '\0';
- Curl_debug(data, CURLINFO_TEXT, error, len);
- va_end(ap);
- }
-}
-
/*
* Curl_write() is an internal write function that sends data to the
* server. Works with plain sockets, SCP, SSL or kerberos.
@@ -301,7 +158,7 @@
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
conn = data->conn;
- num = (sockfd == conn->sock[SECONDARYSOCKET]);
+ num = (sockfd != CURL_SOCKET_BAD && sockfd == conn->sock[SECONDARYSOCKET]);
#ifdef CURLDEBUG
{
@@ -338,139 +195,6 @@
}
}
-ssize_t Curl_send_plain(struct Curl_easy *data, int num,
- const void *mem, size_t len, CURLcode *code)
-{
- struct connectdata *conn;
- curl_socket_t sockfd;
- ssize_t bytes_written;
-
- DEBUGASSERT(data);
- DEBUGASSERT(data->conn);
- conn = data->conn;
- sockfd = conn->sock[num];
- /* WinSock will destroy unread received data if send() is
- failed.
- To avoid lossage of received data, recv() must be
- performed before every send() if any incoming data is
- available. */
- if(pre_receive_plain(data, conn, num)) {
- *code = CURLE_OUT_OF_MEMORY;
- return -1;
- }
-
-#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
- if(conn->bits.tcp_fastopen) {
- bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN,
- conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen);
- conn->bits.tcp_fastopen = FALSE;
- }
- else
-#endif
- bytes_written = swrite(sockfd, mem, len);
-
- *code = CURLE_OK;
- if(-1 == bytes_written) {
- int err = SOCKERRNO;
-
- if(
-#ifdef WSAEWOULDBLOCK
- /* This is how Windows does it */
- (WSAEWOULDBLOCK == err)
-#else
- /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
- due to its inability to send off data without blocking. We therefore
- treat both error codes the same here */
- (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) ||
- (EINPROGRESS == err)
-#endif
- ) {
- /* this is just a case of EWOULDBLOCK */
- bytes_written = 0;
- *code = CURLE_AGAIN;
- }
- else {
- char buffer[STRERROR_LEN];
- failf(data, "Send failure: %s",
- Curl_strerror(err, buffer, sizeof(buffer)));
- data->state.os_errno = err;
- *code = CURLE_SEND_ERROR;
- }
- }
- return bytes_written;
-}
-
-/*
- * Curl_write_plain() is an internal write function that sends data to the
- * server using plain sockets only. Otherwise meant to have the exact same
- * proto as Curl_write()
- */
-CURLcode Curl_write_plain(struct Curl_easy *data,
- curl_socket_t sockfd,
- const void *mem,
- size_t len,
- ssize_t *written)
-{
- CURLcode result;
- struct connectdata *conn = data->conn;
- int num;
- DEBUGASSERT(conn);
- num = (sockfd == conn->sock[SECONDARYSOCKET]);
-
- *written = Curl_send_plain(data, num, mem, len, &result);
-
- return result;
-}
-
-ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
- size_t len, CURLcode *code)
-{
- struct connectdata *conn;
- curl_socket_t sockfd;
- ssize_t nread;
- DEBUGASSERT(data);
- DEBUGASSERT(data->conn);
- conn = data->conn;
- sockfd = conn->sock[num];
- /* Check and return data that already received and storied in internal
- intermediate buffer */
- nread = get_pre_recved(conn, num, buf, len);
- if(nread > 0) {
- *code = CURLE_OK;
- return nread;
- }
-
- nread = sread(sockfd, buf, len);
-
- *code = CURLE_OK;
- if(-1 == nread) {
- int err = SOCKERRNO;
-
- if(
-#ifdef WSAEWOULDBLOCK
- /* This is how Windows does it */
- (WSAEWOULDBLOCK == err)
-#else
- /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
- due to its inability to send off data without blocking. We therefore
- treat both error codes the same here */
- (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
-#endif
- ) {
- /* this is just a case of EWOULDBLOCK */
- *code = CURLE_AGAIN;
- }
- else {
- char buffer[STRERROR_LEN];
- failf(data, "Recv failure: %s",
- Curl_strerror(err, buffer, sizeof(buffer)));
- data->state.os_errno = err;
- *code = CURLE_RECV_ERROR;
- }
- }
- return nread;
-}
-
static CURLcode pausewrite(struct Curl_easy *data,
int type, /* what type of data */
const char *ptr,
@@ -484,8 +208,7 @@
unsigned int i;
bool newtype = TRUE;
- /* If this transfers over HTTP/2, pause the stream! */
- Curl_http2_stream_pause(data, TRUE);
+ Curl_conn_ev_data_pause(data, TRUE);
if(s->tempcount) {
for(i = 0; i< s->tempcount; i++) {
@@ -496,6 +219,9 @@
}
}
DEBUGASSERT(i < 3);
+ if(i >= 3)
+ /* There are more types to store than what fits: very bad */
+ return CURLE_OUT_OF_MEMORY;
}
else
i = 0;
@@ -531,6 +257,7 @@
curl_write_callback writebody = NULL;
char *ptr = optr;
size_t len = olen;
+ void *writebody_ptr = data->set.out;
if(!len)
return CURLE_OK;
@@ -541,8 +268,16 @@
return pausewrite(data, type, ptr, len);
/* Determine the callback(s) to use. */
- if(type & CLIENTWRITE_BODY)
+ if(type & CLIENTWRITE_BODY) {
+#ifdef USE_WEBSOCKETS
+ if(conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) {
+ writebody = Curl_ws_writecb;
+ writebody_ptr = data;
+ }
+ else
+#endif
writebody = data->set.fwrite_func;
+ }
if((type & CLIENTWRITE_HEADER) &&
(data->set.fwrite_header || data->set.writeheader)) {
/*
@@ -560,7 +295,7 @@
if(writebody) {
size_t wrote;
Curl_set_in_callback(data, true);
- wrote = writebody(ptr, 1, chunklen, data->set.out);
+ wrote = writebody(ptr, 1, chunklen, writebody_ptr);
Curl_set_in_callback(data, false);
if(CURL_WRITEFUNC_PAUSE == wrote) {
@@ -583,18 +318,20 @@
len -= chunklen;
}
+#ifndef CURL_DISABLE_HTTP
/* HTTP header, but not status-line */
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
(type & CLIENTWRITE_HEADER) && !(type & CLIENTWRITE_STATUS) ) {
- CURLcode result =
- Curl_headers_push(data, optr,
- type & CLIENTWRITE_CONNECT ? CURLH_CONNECT :
- (type & CLIENTWRITE_1XX ? CURLH_1XX :
- (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER :
- CURLH_HEADER)));
+ unsigned char htype = (unsigned char)
+ (type & CLIENTWRITE_CONNECT ? CURLH_CONNECT :
+ (type & CLIENTWRITE_1XX ? CURLH_1XX :
+ (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER :
+ CURLH_HEADER)));
+ CURLcode result = Curl_headers_push(data, optr, htype);
if(result)
return result;
}
+#endif
if(writeheader) {
size_t wrote;
@@ -607,8 +344,10 @@
/* here we pass in the HEADER bit only since if this was body as well
then it was passed already and clearly that didn't trigger the
pause, so this is saved for later with the HEADER bit only */
- return pausewrite(data, CLIENTWRITE_HEADER, optr, olen);
-
+ return pausewrite(data, CLIENTWRITE_HEADER |
+ (type & (CLIENTWRITE_STATUS|CLIENTWRITE_CONNECT|
+ CLIENTWRITE_1XX|CLIENTWRITE_TRAILER)),
+ optr, olen);
if(wrote != olen) {
failf(data, "Failed writing header");
return CURLE_WRITE_ERROR;
@@ -645,32 +384,6 @@
return chop_write(data, type, ptr, len);
}
-CURLcode Curl_read_plain(curl_socket_t sockfd,
- char *buf,
- size_t bytesfromsocket,
- ssize_t *n)
-{
- ssize_t nread = sread(sockfd, buf, bytesfromsocket);
-
- if(-1 == nread) {
- const int err = SOCKERRNO;
- const bool return_error =
-#ifdef USE_WINSOCK
- WSAEWOULDBLOCK == err
-#else
- EWOULDBLOCK == err || EAGAIN == err || EINTR == err
-#endif
- ;
- *n = 0; /* no data returned */
- if(return_error)
- return CURLE_AGAIN;
- return CURLE_RECV_ERROR;
- }
-
- *n = nread;
- return CURLE_OK;
-}
-
/*
* Internal read-from-socket function. This is meant to deal with plain
* sockets, SSL sockets and kerberos sockets.
@@ -701,38 +414,11 @@
nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result);
if(nread < 0)
- return result;
+ goto out;
*n += nread;
-
- return CURLE_OK;
+ result = CURLE_OK;
+out:
+ return result;
}
-/* return 0 on success */
-int Curl_debug(struct Curl_easy *data, curl_infotype type,
- char *ptr, size_t size)
-{
- int rc = 0;
- if(data->set.verbose) {
- static const char s_infotype[CURLINFO_END][3] = {
- "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
- if(data->set.fdebug) {
- Curl_set_in_callback(data, true);
- rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
- Curl_set_in_callback(data, false);
- }
- else {
- switch(type) {
- case CURLINFO_TEXT:
- case CURLINFO_HEADER_OUT:
- case CURLINFO_HEADER_IN:
- fwrite(s_infotype[type], 2, 1, data->set.err);
- fwrite(ptr, size, 1, data->set.err);
- break;
- default: /* nada */
- break;
- }
- }
- }
- return rc;
-}
diff --git a/lib/sendf.h b/lib/sendf.h
index 075d70e..d0c9275 100644
--- a/lib/sendf.h
+++ b/lib/sendf.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,26 +26,8 @@
#include "curl_setup.h"
-void Curl_infof(struct Curl_easy *, const char *fmt, ...);
-void Curl_failf(struct Curl_easy *, const char *fmt, ...);
+#include "curl_log.h"
-#if defined(CURL_DISABLE_VERBOSE_STRINGS)
-
-#if defined(HAVE_VARIADIC_MACROS_C99)
-#define infof(...) Curl_nop_stmt
-#elif defined(HAVE_VARIADIC_MACROS_GCC)
-#define infof(x...) Curl_nop_stmt
-#else
-#error "missing VARIADIC macro define, fix and rebuild!"
-#endif
-
-#else /* CURL_DISABLE_VERBOSE_STRINGS */
-
-#define infof Curl_infof
-
-#endif /* CURL_DISABLE_VERBOSE_STRINGS */
-
-#define failf Curl_failf
#define CLIENTWRITE_BODY (1<<0)
#define CLIENTWRITE_HEADER (1<<1)
@@ -58,19 +40,6 @@
CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr,
size_t len) WARN_UNUSED_RESULT;
-bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex);
-
-/* internal read-function, does plain socket only */
-CURLcode Curl_read_plain(curl_socket_t sockfd,
- char *buf,
- size_t bytesfromsocket,
- ssize_t *n);
-
-ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
- size_t len, CURLcode *code);
-ssize_t Curl_send_plain(struct Curl_easy *data, int num,
- const void *mem, size_t len, CURLcode *code);
-
/* internal read-function, does plain socket, SSL and krb4 */
CURLcode Curl_read(struct Curl_easy *data, curl_socket_t sockfd,
char *buf, size_t buffersize,
@@ -82,15 +51,4 @@
const void *mem, size_t len,
ssize_t *written);
-/* internal write-function, does plain sockets ONLY */
-CURLcode Curl_write_plain(struct Curl_easy *data,
- curl_socket_t sockfd,
- const void *mem, size_t len,
- ssize_t *written);
-
-/* the function used to output verbose information */
-int Curl_debug(struct Curl_easy *data, curl_infotype type,
- char *ptr, size_t size);
-
-
#endif /* HEADER_CURL_SENDF_H */
diff --git a/lib/setopt.c b/lib/setopt.c
index 6b16e1c..b05162a 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -115,7 +115,11 @@
/* Parse the login details if specified. It not then we treat NULL as a hint
to clear the existing data */
if(option) {
- result = Curl_parse_login_details(option, strlen(option),
+ size_t len = strlen(option);
+ if(len > CURL_MAX_INPUT_LENGTH)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ result = Curl_parse_login_details(option, len,
(userp ? &user : NULL),
(passwdp ? &passwd : NULL),
NULL);
@@ -148,6 +152,40 @@
#define C_SSLVERSION_VALUE(x) (x & 0xffff)
#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000)
+static CURLcode protocol2num(const char *str, curl_prot_t *val)
+{
+ if(!str)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(curl_strequal(str, "all")) {
+ *val = ~(curl_prot_t) 0;
+ return CURLE_OK;
+ }
+
+ *val = 0;
+
+ do {
+ const char *token = str;
+ size_t tlen;
+
+ str = strchr(str, ',');
+ tlen = str? (size_t) (str - token): strlen(token);
+ if(tlen) {
+ const struct Curl_handler *h = Curl_builtin_scheme(token, tlen);
+
+ if(!h)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+
+ *val |= h->protocol;
+ }
+ } while(str && str++);
+
+ if(!*val)
+ /* no protocol listed */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ return CURLE_OK;
+}
+
/*
* Do not make Curl_vsetopt() static: it is called from
* packages/OS400/ccsidcurl.c.
@@ -157,9 +195,7 @@
char *argptr;
CURLcode result = CURLE_OK;
long arg;
-#ifdef ENABLE_IPV6
unsigned long uarg;
-#endif
curl_off_t bigsize;
switch(option) {
@@ -167,7 +203,19 @@
arg = va_arg(param, long);
if(arg < -1)
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.dns_cache_timeout = arg;
+ else if(arg > INT_MAX)
+ arg = INT_MAX;
+
+ data->set.dns_cache_timeout = (int)arg;
+ break;
+ case CURLOPT_CA_CACHE_TIMEOUT:
+ arg = va_arg(param, long);
+ if(arg < -1)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ else if(arg > INT_MAX)
+ arg = INT_MAX;
+
+ data->set.general_ssl.ca_cache_timeout = (int)arg;
break;
case CURLOPT_DNS_USE_GLOBAL_CACHE:
/* deprecated */
@@ -185,7 +233,7 @@
break;
#endif
case CURLOPT_TLS13_CIPHERS:
- if(Curl_ssl_tls13_ciphersuites()) {
+ if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) {
/* set preferred list of TLS 1.3 cipher suites */
result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST],
va_arg(param, char *));
@@ -195,7 +243,7 @@
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_TLS13_CIPHERS:
- if(Curl_ssl_tls13_ciphersuites()) {
+ if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) {
/* set preferred list of TLS 1.3 cipher suites for proxy */
result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY],
va_arg(param, char *));
@@ -285,8 +333,8 @@
* We want to sent data to the remote host. If this is HTTP, that equals
* using the PUT request.
*/
- data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE;
- if(data->set.upload) {
+ arg = va_arg(param, long);
+ if(arg) {
/* If this is HTTP, PUT is what's needed to "upload" */
data->set.method = HTTPREQ_PUT;
data->set.opt_no_body = FALSE; /* this is implied */
@@ -314,7 +362,7 @@
*/
arg = va_arg(param, long);
if((arg >= 0) && (arg <= (INT_MAX/1000)))
- data->set.server_response_timeout = arg * 1000;
+ data->set.server_response_timeout = (unsigned int)arg * 1000;
else
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
@@ -344,7 +392,7 @@
arg = va_arg(param, long);
if((arg < CURL_NETRC_IGNORED) || (arg >= CURL_NETRC_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.use_netrc = (enum CURL_NETRC_OPTION)arg;
+ data->set.use_netrc = (unsigned char)arg;
break;
case CURLOPT_NETRC_FILE:
/*
@@ -371,7 +419,7 @@
arg = va_arg(param, long);
if((arg < CURL_TIMECOND_NONE) || (arg >= CURL_TIMECOND_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.timecondition = (curl_TimeCond)arg;
+ data->set.timecondition = (unsigned char)(curl_TimeCond)arg;
break;
case CURLOPT_TIMEVALUE:
/*
@@ -419,8 +467,8 @@
version_max >= CURL_SSLVERSION_MAX_LAST)
return CURLE_BAD_FUNCTION_ARGUMENT;
- primary->version = version;
- primary->version_max = version_max;
+ primary->version = (unsigned char)version;
+ primary->version_max = (unsigned int)version_max;
}
#else
result = CURLE_NOT_BUILT_IN;
@@ -563,7 +611,7 @@
case CURLOPT_FOLLOWLOCATION:
/*
- * Follow Location: header hints on a HTTP-server.
+ * Follow Location: header hints on an HTTP-server.
*/
data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
@@ -618,6 +666,7 @@
data->set.method = HTTPREQ_GET;
break;
+#ifndef CURL_DISABLE_MIME
case CURLOPT_HTTPPOST:
/*
* Set to make us do HTTP POST
@@ -626,6 +675,7 @@
data->set.method = HTTPREQ_POST_FORM;
data->set.opt_no_body = FALSE; /* this is implied */
break;
+#endif
case CURLOPT_AWS_SIGV4:
/*
@@ -641,18 +691,6 @@
data->set.httpauth = CURLAUTH_AWS_SIGV4;
break;
- case CURLOPT_MIMEPOST:
- /*
- * Set to make us do MIME/form POST
- */
- result = Curl_mime_set_subparts(&data->set.mimepost,
- va_arg(param, curl_mime *), FALSE);
- if(!result) {
- data->set.method = HTTPREQ_POST_MIME;
- data->set.opt_no_body = FALSE; /* this is implied */
- }
- break;
-
case CURLOPT_REFERER:
/*
* String to set in the HTTP Referer: field.
@@ -674,13 +712,6 @@
va_arg(param, char *));
break;
- case CURLOPT_HTTPHEADER:
- /*
- * Set a list with HTTP headers to use (or replace internals with)
- */
- data->set.headers = va_arg(param, struct curl_slist *);
- break;
-
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXYHEADER:
/*
@@ -704,13 +735,6 @@
data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE);
break;
- case CURLOPT_HTTP200ALIASES:
- /*
- * Set a list of aliases for HTTP 200 in response header
- */
- data->set.http200aliases = va_arg(param, struct curl_slist *);
- break;
-
#if !defined(CURL_DISABLE_COOKIES)
case CURLOPT_COOKIE:
/*
@@ -732,18 +756,18 @@
return CURLE_BAD_FUNCTION_ARGUMENT;
/* append the cookie file name to the list of file names, and deal with
them later */
- cl = curl_slist_append(data->state.cookielist, argptr);
+ cl = curl_slist_append(data->set.cookielist, argptr);
if(!cl) {
- curl_slist_free_all(data->state.cookielist);
- data->state.cookielist = NULL;
+ curl_slist_free_all(data->set.cookielist);
+ data->set.cookielist = NULL;
return CURLE_OUT_OF_MEMORY;
}
- data->state.cookielist = cl; /* store the list for later use */
+ data->set.cookielist = cl; /* store the list for later use */
}
else {
/* clear the list of cookie files */
- curl_slist_free_all(data->state.cookielist);
- data->state.cookielist = NULL;
+ curl_slist_free_all(data->set.cookielist);
+ data->set.cookielist = NULL;
if(!data->share || !data->share->cookies) {
/* throw away all existing cookies if this isn't a shared cookie
@@ -863,7 +887,6 @@
*/
if(va_arg(param, long)) {
data->set.method = HTTPREQ_GET;
- data->set.upload = FALSE; /* switch off upload */
data->set.opt_no_body = FALSE; /* this is implied */
}
break;
@@ -874,28 +897,44 @@
* the listed enums in curl/curl.h.
*/
arg = va_arg(param, long);
- if(arg < CURL_HTTP_VERSION_NONE)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-#ifdef ENABLE_QUIC
- if(arg == CURL_HTTP_VERSION_3)
- ;
- else
-#endif
-#ifndef USE_HTTP2
- if(arg >= CURL_HTTP_VERSION_2)
- return CURLE_UNSUPPORTED_PROTOCOL;
-#else
- if(arg >= CURL_HTTP_VERSION_LAST)
- return CURLE_UNSUPPORTED_PROTOCOL;
- if(arg == CURL_HTTP_VERSION_NONE)
+ switch(arg) {
+ case CURL_HTTP_VERSION_NONE:
+#ifdef USE_HTTP2
+ /* TODO: this seems an undesirable quirk to force a behaviour on
+ * lower implementations that they should recognize independently? */
arg = CURL_HTTP_VERSION_2TLS;
#endif
+ /* accepted */
+ break;
+ case CURL_HTTP_VERSION_1_0:
+ case CURL_HTTP_VERSION_1_1:
+ /* accepted */
+ break;
+#ifdef USE_HTTP2
+ case CURL_HTTP_VERSION_2_0:
+ case CURL_HTTP_VERSION_2TLS:
+ case CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE:
+ /* accepted */
+ break;
+#endif
+#ifdef ENABLE_QUIC
+ case CURL_HTTP_VERSION_3:
+ case CURL_HTTP_VERSION_3ONLY:
+ /* accepted */
+ break;
+#endif
+ default:
+ /* not accepted */
+ if(arg < CURL_HTTP_VERSION_NONE)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
data->set.httpwant = (unsigned char)arg;
break;
case CURLOPT_EXPECT_100_TIMEOUT_MS:
/*
- * Time to wait for a response to a HTTP request containing an
+ * Time to wait for a response to an HTTP request containing an
* Expect: 100-continue header before sending the data anyway.
*/
arg = va_arg(param, long);
@@ -916,8 +955,45 @@
data->set.http09_allowed = arg ? TRUE : FALSE;
#endif
break;
+
+ case CURLOPT_HTTP200ALIASES:
+ /*
+ * Set a list of aliases for HTTP 200 in response header
+ */
+ data->set.http200aliases = va_arg(param, struct curl_slist *);
+ break;
#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_MIME)
+ case CURLOPT_HTTPHEADER:
+ /*
+ * Set a list with HTTP headers to use (or replace internals with)
+ */
+ data->set.headers = va_arg(param, struct curl_slist *);
+ break;
+# endif
+
+# ifndef CURL_DISABLE_MIME
+ case CURLOPT_MIMEPOST:
+ /*
+ * Set to make us do MIME POST
+ */
+ result = Curl_mime_set_subparts(&data->set.mimepost,
+ va_arg(param, curl_mime *), FALSE);
+ if(!result) {
+ data->set.method = HTTPREQ_POST_MIME;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ break;
+
+ case CURLOPT_MIME_OPTIONS:
+ data->set.mime_options = (unsigned int)va_arg(param, long);
+ break;
+# endif
+#endif
+
case CURLOPT_HTTPAUTH:
/*
* Set HTTP Authentication type BITMASK.
@@ -999,7 +1075,7 @@
arg = va_arg(param, long);
if((arg < 0) || (arg > 65535))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.proxyport = arg;
+ data->set.proxyport = (unsigned short)arg;
break;
case CURLOPT_PROXYAUTH:
@@ -1081,12 +1157,12 @@
case CURLOPT_PROXYTYPE:
/*
- * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
+ * Set proxy type.
*/
arg = va_arg(param, long);
if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.proxytype = (curl_proxytype)arg;
+ data->set.proxytype = (unsigned char)(curl_proxytype)arg;
break;
case CURLOPT_PROXY_TRANSFER_MODE:
@@ -1108,7 +1184,7 @@
break;
case CURLOPT_SOCKS5_AUTH:
- data->set.socks5auth = va_arg(param, unsigned long);
+ data->set.socks5auth = (unsigned char)va_arg(param, unsigned long);
if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
result = CURLE_NOT_BUILT_IN;
break;
@@ -1185,7 +1261,7 @@
arg = va_arg(param, long);
if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ftp_filemethod = (curl_ftpfile)arg;
+ data->set.ftp_filemethod = (unsigned char)(curl_ftpfile)arg;
break;
case CURLOPT_FTPPORT:
/*
@@ -1212,7 +1288,7 @@
arg = va_arg(param, long);
if((arg < CURLFTPSSL_CCC_NONE) || (arg >= CURLFTPSSL_CCC_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ftp_ccc = (curl_ftpccc)arg;
+ data->set.ftp_ccc = (unsigned char)(curl_ftpccc)arg;
break;
case CURLOPT_FTP_SKIP_PASV_IP:
@@ -1240,7 +1316,7 @@
arg = va_arg(param, long);
if((arg < CURLFTPAUTH_DEFAULT) || (arg >= CURLFTPAUTH_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ftpsslauth = (curl_ftpauth)arg;
+ data->set.ftpsslauth = (unsigned char)(curl_ftpauth)arg;
break;
case CURLOPT_KRBLEVEL:
/*
@@ -1251,6 +1327,7 @@
data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
break;
#endif
+#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
case CURLOPT_FTP_CREATE_MISSING_DIRS:
/*
* An FTP/SFTP option that modifies an upload to create missing
@@ -1262,8 +1339,28 @@
(arg > CURLFTP_CREATE_DIR_RETRY))
result = CURLE_BAD_FUNCTION_ARGUMENT;
else
- data->set.ftp_create_missing_dirs = (int)arg;
+ data->set.ftp_create_missing_dirs = (unsigned char)arg;
break;
+
+ case CURLOPT_POSTQUOTE:
+ /*
+ * List of RAW FTP commands to use after a transfer
+ */
+ data->set.postquote = va_arg(param, struct curl_slist *);
+ break;
+ case CURLOPT_PREQUOTE:
+ /*
+ * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
+ */
+ data->set.prequote = va_arg(param, struct curl_slist *);
+ break;
+ case CURLOPT_QUOTE:
+ /*
+ * List of RAW FTP commands to use before a transfer
+ */
+ data->set.quote = va_arg(param, struct curl_slist *);
+ break;
+#endif
case CURLOPT_READDATA:
/*
* FILE pointer to read the file to be uploaded from. Or possibly
@@ -1352,12 +1449,12 @@
break;
case CURLOPT_PORT:
/*
- * The port number to use when getting the URL
+ * The port number to use when getting the URL. 0 disables it.
*/
arg = va_arg(param, long);
if((arg < 0) || (arg > 65535))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.use_port = arg;
+ data->set.use_port = (unsigned short)arg;
break;
case CURLOPT_TIMEOUT:
/*
@@ -1366,16 +1463,16 @@
*/
arg = va_arg(param, long);
if((arg >= 0) && (arg <= (INT_MAX/1000)))
- data->set.timeout = arg * 1000;
+ data->set.timeout = (unsigned int)arg * 1000;
else
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
case CURLOPT_TIMEOUT_MS:
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.timeout = arg;
+ uarg = va_arg(param, unsigned long);
+ if(uarg > UINT_MAX)
+ uarg = UINT_MAX;
+ data->set.timeout = (unsigned int)uarg;
break;
case CURLOPT_CONNECTTIMEOUT:
@@ -1384,16 +1481,16 @@
*/
arg = va_arg(param, long);
if((arg >= 0) && (arg <= (INT_MAX/1000)))
- data->set.connecttimeout = arg * 1000;
+ data->set.connecttimeout = (unsigned int)arg * 1000;
else
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
case CURLOPT_CONNECTTIMEOUT_MS:
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.connecttimeout = arg;
+ uarg = va_arg(param, unsigned long);
+ if(uarg > UINT_MAX)
+ uarg = UINT_MAX;
+ data->set.connecttimeout = (unsigned int)uarg;
break;
#ifndef CURL_DISABLE_FTP
@@ -1401,10 +1498,10 @@
/*
* The maximum time for curl to wait for FTP server connect
*/
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.accepttimeout = arg;
+ uarg = va_arg(param, unsigned long);
+ if(uarg > UINT_MAX)
+ uarg = UINT_MAX;
+ data->set.accepttimeout = (unsigned int)uarg;
break;
#endif
@@ -1448,24 +1545,6 @@
va_arg(param, char *));
break;
- case CURLOPT_POSTQUOTE:
- /*
- * List of RAW FTP commands to use after a transfer
- */
- data->set.postquote = va_arg(param, struct curl_slist *);
- break;
- case CURLOPT_PREQUOTE:
- /*
- * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
- */
- data->set.prequote = va_arg(param, struct curl_slist *);
- break;
- case CURLOPT_QUOTE:
- /*
- * List of RAW FTP commands to use before a transfer
- */
- data->set.quote = va_arg(param, struct curl_slist *);
- break;
case CURLOPT_RESOLVE:
/*
* List of HOST:PORT:[addresses] strings to populate the DNS cache with
@@ -1788,6 +1867,15 @@
*/
data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
+ case CURLOPT_HAPROXY_CLIENT_IP:
+ /*
+ * Set the client IP to send through HAProxy PROXY protocol
+ */
+ result = Curl_setstropt(&data->set.str[STRING_HAPROXY_CLIENT_IP],
+ va_arg(param, char *));
+ /* We enable implicitly the HAProxy protocol if we use this flag. */
+ data->set.haproxyprotocol = TRUE;
+ break;
#endif
case CURLOPT_INTERFACE:
/*
@@ -1813,16 +1901,15 @@
arg = va_arg(param, long);
if((arg < 0) || (arg > 65535))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.localportrange = curlx_sltosi(arg);
+ data->set.localportrange = curlx_sltous(arg);
break;
case CURLOPT_GSSAPI_DELEGATION:
/*
* GSS-API credential delegation bitmask
*/
- arg = va_arg(param, long);
- if(arg < CURLGSSAPI_DELEGATION_NONE)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.gssapi_delegation = arg;
+ uarg = va_arg(param, unsigned long);
+ data->set.gssapi_delegation = (unsigned char)uarg&
+ (CURLGSSAPI_DELEGATION_POLICY_FLAG|CURLGSSAPI_DELEGATION_FLAG);
break;
case CURLOPT_SSL_VERIFYPEER:
/*
@@ -1943,7 +2030,7 @@
* Set a SSL_CTX callback
*/
#ifdef USE_SSL
- if(Curl_ssl->supports & SSLSUPP_SSL_CTX)
+ if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX))
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
else
#endif
@@ -1954,7 +2041,7 @@
* Set a SSL_CTX callback parameter pointer
*/
#ifdef USE_SSL
- if(Curl_ssl->supports & SSLSUPP_SSL_CTX)
+ if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX))
data->set.ssl.fsslctxp = va_arg(param, void *);
else
#endif
@@ -1964,7 +2051,7 @@
/*
* Enable TLS false start.
*/
- if(!Curl_ssl_false_start()) {
+ if(!Curl_ssl_false_start(data)) {
result = CURLE_NOT_BUILT_IN;
break;
}
@@ -1973,7 +2060,7 @@
break;
case CURLOPT_CERTINFO:
#ifdef USE_SSL
- if(Curl_ssl->supports & SSLSUPP_CERTINFO)
+ if(Curl_ssl_supports(data, SSLSUPP_CERTINFO))
data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
else
#endif
@@ -1985,7 +2072,7 @@
* Specify file name of the public key in DER format.
*/
#ifdef USE_SSL
- if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
+ if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
va_arg(param, char *));
else
@@ -1999,7 +2086,7 @@
* Specify file name of the public key in DER format.
*/
#ifdef USE_SSL
- if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
+ if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
va_arg(param, char *));
else
@@ -2020,7 +2107,7 @@
* Specify entire PEM of the CA certificate
*/
#ifdef USE_SSL
- if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB)
+ if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO],
va_arg(param, struct curl_blob *));
else
@@ -2043,7 +2130,7 @@
* Specify entire PEM of the CA certificate
*/
#ifdef USE_SSL
- if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB)
+ if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY],
va_arg(param, struct curl_blob *));
else
@@ -2057,7 +2144,7 @@
* certificates which have been prepared using openssl c_rehash utility.
*/
#ifdef USE_SSL
- if(Curl_ssl->supports & SSLSUPP_CA_PATH)
+ if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
/* This does not work on windows. */
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH],
va_arg(param, char *));
@@ -2072,7 +2159,7 @@
* CA certificates which have been prepared using openssl c_rehash utility.
*/
#ifdef USE_SSL
- if(Curl_ssl->supports & SSLSUPP_CA_PATH)
+ if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
/* This does not work on windows. */
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
va_arg(param, char *));
@@ -2156,7 +2243,7 @@
else if(arg < READBUFFER_MIN)
arg = READBUFFER_MIN;
- data->set.buffer_size = arg;
+ data->set.buffer_size = (unsigned int)arg;
break;
case CURLOPT_UPLOAD_BUFFERSIZE:
@@ -2202,9 +2289,14 @@
data->cookies = NULL;
#endif
+#ifndef CURL_DISABLE_HSTS
+ if(data->share->hsts == data->hsts)
+ data->hsts = NULL;
+#endif
+#ifdef USE_SSL
if(data->share->sslsession == data->state.session)
data->state.session = NULL;
-
+#endif
#ifdef USE_LIBPSL
if(data->psl == &data->share->psl)
data->psl = data->multi? &data->multi->psl: NULL;
@@ -2238,10 +2330,19 @@
data->cookies = data->share->cookies;
}
#endif /* CURL_DISABLE_HTTP */
+#ifndef CURL_DISABLE_HSTS
+ if(data->share->hsts) {
+ /* first free the private one if any */
+ Curl_hsts_cleanup(&data->hsts);
+ data->hsts = data->share->hsts;
+ }
+#endif /* CURL_DISABLE_HTTP */
+#ifdef USE_SSL
if(data->share->sslsession) {
data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
data->state.session = data->share->sslsession;
}
+#endif
#ifdef USE_LIBPSL
if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL))
data->psl = &data->share->psl;
@@ -2279,7 +2380,7 @@
arg = va_arg(param, long);
if((arg < CURLUSESSL_NONE) || (arg >= CURLUSESSL_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.use_ssl = (curl_usessl)arg;
+ data->set.use_ssl = (unsigned char)arg;
break;
case CURLOPT_SSL_OPTIONS:
@@ -2350,9 +2451,14 @@
case CURLOPT_CONNECT_ONLY:
/*
- * No data transfer, set up connection and let application use the socket
+ * No data transfer.
+ * (1) - only do connection
+ * (2) - do first get request but get no content
*/
- data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ arg = va_arg(param, long);
+ if(arg > 2)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.connect_only = (unsigned char)arg;
break;
case CURLOPT_SOCKOPTFUNCTION:
@@ -2452,6 +2558,14 @@
va_arg(param, char *));
break;
+ case CURLOPT_SSH_KNOWNHOSTS:
+ /*
+ * Store the file name to read known hosts from.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
+ va_arg(param, char *));
+ break;
+#ifdef USE_LIBSSH2
case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256:
/*
* Option to allow for the SHA256 of the host public key to be checked
@@ -2461,14 +2575,6 @@
va_arg(param, char *));
break;
- case CURLOPT_SSH_KNOWNHOSTS:
- /*
- * Store the file name to read known hosts from.
- */
- result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
- va_arg(param, char *));
- break;
-#ifdef USE_LIBSSH2
case CURLOPT_SSH_HOSTKEYFUNCTION:
/* the callback to check the hostkey without the knownhost file */
data->set.ssh_hostkeyfunc = va_arg(param, curl_sshhostkeycallback);
@@ -2481,6 +2587,7 @@
data->set.ssh_hostkeyfunc_userp = va_arg(param, void *);
break;
#endif
+
case CURLOPT_SSH_KEYFUNCTION:
/* setting to NULL is fine since the ssh.c functions themselves will
then revert to use the internal default */
@@ -2527,7 +2634,8 @@
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.new_file_perms = (unsigned int)arg;
break;
-
+#endif
+#ifdef USE_SSH
case CURLOPT_NEW_DIRECTORY_PERMS:
/*
* Uses these permissions instead of 0755
@@ -2560,16 +2668,36 @@
transfer, which thus helps the app which takes URLs from users or other
external inputs and want to restrict what protocol(s) to deal
with. Defaults to CURLPROTO_ALL. */
- data->set.allowed_protocols = (unsigned int)va_arg(param, long);
+ data->set.allowed_protocols = (curl_prot_t)va_arg(param, long);
break;
case CURLOPT_REDIR_PROTOCOLS:
/* set the bitmask for the protocols that libcurl is allowed to follow to,
as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
to be set in both bitmasks to be allowed to get redirected to. */
- data->set.redir_protocols = (unsigned int)va_arg(param, long);
+ data->set.redir_protocols = (curl_prot_t)va_arg(param, long);
break;
+ case CURLOPT_PROTOCOLS_STR: {
+ curl_prot_t prot;
+ argptr = va_arg(param, char *);
+ result = protocol2num(argptr, &prot);
+ if(result)
+ return result;
+ data->set.allowed_protocols = prot;
+ break;
+ }
+
+ case CURLOPT_REDIR_PROTOCOLS_STR: {
+ curl_prot_t prot;
+ argptr = va_arg(param, char *);
+ result = protocol2num(argptr, &prot);
+ if(result)
+ return result;
+ data->set.redir_protocols = prot;
+ break;
+ }
+
case CURLOPT_DEFAULT_PROTOCOL:
/* Set the protocol to use when the URL doesn't include any protocol */
result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
@@ -2592,19 +2720,12 @@
/* Set the list of mail recipients */
data->set.mail_rcpt = va_arg(param, struct curl_slist *);
break;
- case CURLOPT_MAIL_RCPT_ALLLOWFAILS:
+ case CURLOPT_MAIL_RCPT_ALLOWFAILS:
/* allow RCPT TO command to fail for some recipients */
data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
#endif
-#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
- !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
- case CURLOPT_MIME_OPTIONS:
- data->set.mime_options = (unsigned int)va_arg(param, long);
- break;
-#endif
-
case CURLOPT_SASL_AUTHZID:
/* Authorization identity (identity to act as) */
result = Curl_setstropt(&data->set.str[STRING_SASL_AUTHZID],
@@ -2739,7 +2860,7 @@
data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
break;
case CURLOPT_CHUNK_DATA:
- data->wildcard.customptr = va_arg(param, void *);
+ data->set.wildcardptr = va_arg(param, void *);
break;
case CURLOPT_FNMATCH_DATA:
data->set.fnmatch_data = va_arg(param, void *);
@@ -2749,52 +2870,33 @@
case CURLOPT_TLSAUTH_USERNAME:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME] &&
- !data->set.ssl.primary.authtype)
- data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_TLSAUTH_USERNAME:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
- !data->set.proxy_ssl.primary.authtype)
- data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default to
- SRP */
break;
#endif
case CURLOPT_TLSAUTH_PASSWORD:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME] &&
- !data->set.ssl.primary.authtype)
- data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default */
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_TLSAUTH_PASSWORD:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
- !data->set.proxy_ssl.primary.authtype)
- data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default */
break;
#endif
case CURLOPT_TLSAUTH_TYPE:
argptr = va_arg(param, char *);
- if(!argptr ||
- strncasecompare(argptr, "SRP", strlen("SRP")))
- data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP;
- else
- data->set.ssl.primary.authtype = CURL_TLSAUTH_NONE;
+ if(argptr && !strncasecompare(argptr, "SRP", strlen("SRP")))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_TLSAUTH_TYPE:
argptr = va_arg(param, char *);
- if(!argptr ||
- strncasecompare(argptr, "SRP", strlen("SRP")))
- data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP;
- else
- data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_NONE;
+ if(argptr || !strncasecompare(argptr, "SRP", strlen("SRP")))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
break;
#endif
#endif
@@ -2856,7 +2958,6 @@
#endif
break;
case CURLOPT_SSL_ENABLE_NPN:
- data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
case CURLOPT_SSL_ENABLE_ALPN:
data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
@@ -2881,29 +2982,23 @@
data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
case CURLOPT_STREAM_WEIGHT:
-#ifndef USE_NGHTTP2
- return CURLE_NOT_BUILT_IN;
-#else
+#if defined(USE_HTTP2) || defined(USE_HTTP3)
arg = va_arg(param, long);
if((arg >= 1) && (arg <= 256))
- data->set.stream_weight = (int)arg;
+ data->set.priority.weight = (int)arg;
break;
+#else
+ return CURLE_NOT_BUILT_IN;
#endif
case CURLOPT_STREAM_DEPENDS:
case CURLOPT_STREAM_DEPENDS_E:
{
-#ifndef USE_NGHTTP2
- return CURLE_NOT_BUILT_IN;
-#else
struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
if(!dep || GOOD_EASY_HANDLE(dep)) {
- if(data->set.stream_depends_on) {
- Curl_http2_remove_child(data->set.stream_depends_on, data);
- }
- Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
+ return Curl_data_priority_add_child(dep, data,
+ option == CURLOPT_STREAM_DEPENDS_E);
}
break;
-#endif
}
case CURLOPT_CONNECT_TO:
data->set.connect_to = va_arg(param, struct curl_slist *);
@@ -2912,10 +3007,10 @@
data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS:
- arg = va_arg(param, long);
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.happy_eyeballs_timeout = arg;
+ uarg = va_arg(param, unsigned long);
+ if(uarg > UINT_MAX)
+ uarg = UINT_MAX;
+ data->set.happy_eyeballs_timeout = (unsigned int)uarg;
break;
#ifndef CURL_DISABLE_SHUFFLE_DNS
case CURLOPT_DNS_SHUFFLE_ADDRESSES:
@@ -2974,19 +3069,39 @@
case CURLOPT_HSTSWRITEDATA:
data->set.hsts_write_userp = va_arg(param, void *);
break;
- case CURLOPT_HSTS:
+ case CURLOPT_HSTS: {
+ struct curl_slist *h;
if(!data->hsts) {
data->hsts = Curl_hsts_init();
if(!data->hsts)
return CURLE_OUT_OF_MEMORY;
}
argptr = va_arg(param, char *);
- result = Curl_setstropt(&data->set.str[STRING_HSTS], argptr);
- if(result)
- return result;
- if(argptr)
- (void)Curl_hsts_loadfile(data, data->hsts, argptr);
+ if(argptr) {
+ result = Curl_setstropt(&data->set.str[STRING_HSTS], argptr);
+ if(result)
+ return result;
+ /* this needs to build a list of file names to read from, so that it can
+ read them later, as we might get a shared HSTS handle to load them
+ into */
+ h = curl_slist_append(data->set.hstslist, argptr);
+ if(!h) {
+ curl_slist_free_all(data->set.hstslist);
+ data->set.hstslist = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ data->set.hstslist = h; /* store the list for later use */
+ }
+ else {
+ /* clear the list of HSTS files */
+ curl_slist_free_all(data->set.hstslist);
+ data->set.hstslist = NULL;
+ if(!data->share || !data->share->hsts)
+ /* throw away the HSTS cache unless shared */
+ Curl_hsts_cleanup(&data->hsts);
+ }
break;
+ }
case CURLOPT_HSTS_CTRL:
arg = va_arg(param, long);
if(arg & CURLHSTS_ENABLE) {
@@ -3032,6 +3147,18 @@
case CURLOPT_PREREQDATA:
data->set.prereq_userp = va_arg(param, void *);
break;
+#ifdef USE_WEBSOCKETS
+ case CURLOPT_WS_OPTIONS: {
+ bool raw;
+ arg = va_arg(param, long);
+ raw = (arg & CURLWS_RAW_MODE);
+ data->set.ws_raw_mode = raw;
+ break;
+ }
+#endif
+ case CURLOPT_QUICK_EXIT:
+ data->set.quick_exit = (0 != va_arg(param, long)) ? 1L:0L;
+ break;
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_UNKNOWN_OPTION;
diff --git a/lib/setopt.h b/lib/setopt.h
index ffc77a7..3c14a05 100644
--- a/lib/setopt.h
+++ b/lib/setopt.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/setup-os400.h b/lib/setup-os400.h
index 6023ca2..7595834 100644
--- a/lib/setup-os400.h
+++ b/lib/setup-os400.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -49,11 +49,11 @@
struct addrinfo **res);
#define getaddrinfo Curl_getaddrinfo_a
-
+/* Note socklen_t must be used as this is declared before curl_socklen_t */
extern int Curl_getnameinfo_a(const struct sockaddr *sa,
- curl_socklen_t salen,
- char *nodename, curl_socklen_t nodenamelen,
- char *servname, curl_socklen_t servnamelen,
+ socklen_t salen,
+ char *nodename, socklen_t nodenamelen,
+ char *servname, socklen_t servnamelen,
int flags);
#define getnameinfo Curl_getnameinfo_a
@@ -205,7 +205,7 @@
extern int Curl_os400_connect(int sd, struct sockaddr *destaddr, int addrlen);
extern int Curl_os400_bind(int sd, struct sockaddr *localaddr, int addrlen);
extern int Curl_os400_sendto(int sd, char *buffer, int buflen, int flags,
- struct sockaddr *dstaddr, int addrlen);
+ const struct sockaddr *dstaddr, int addrlen);
extern int Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags,
struct sockaddr *fromaddr, int *addrlen);
extern int Curl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen);
diff --git a/lib/setup-vms.h b/lib/setup-vms.h
index b570683..46657b2 100644
--- a/lib/setup-vms.h
+++ b/lib/setup-vms.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/setup-win32.h b/lib/setup-win32.h
index c16928d..1394838 100644
--- a/lib/setup-win32.h
+++ b/lib/setup-win32.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,10 +37,21 @@
#ifdef HAVE_WINDOWS_H
# if defined(UNICODE) && !defined(_UNICODE)
-# define _UNICODE
+# error "UNICODE is defined but _UNICODE is not defined"
# endif
# if defined(_UNICODE) && !defined(UNICODE)
-# define UNICODE
+# error "_UNICODE is defined but UNICODE is not defined"
+# endif
+/*
+ * Don't include unneeded stuff in Windows headers to avoid compiler
+ * warnings and macro clashes.
+ * Make sure to define this macro before including any Windows headers.
+ */
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# ifndef NOGDI
+# define NOGDI
# endif
# include <winerror.h>
# include <windows.h>
diff --git a/lib/sha256.c b/lib/sha256.c
index 60720f5..767d879 100644
--- a/lib/sha256.c
+++ b/lib/sha256.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017, Florin Petriuc, <petriuc.florin@gmail.com>
- * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Florin Petriuc, <petriuc.florin@gmail.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -57,6 +57,34 @@
#endif
#endif /* USE_MBEDTLS */
+#if defined(USE_OPENSSL_SHA256)
+
+/* When OpenSSL or wolfSSL is available we use their SHA256-functions. */
+#if defined(USE_OPENSSL)
+#include <openssl/evp.h>
+#elif defined(USE_WOLFSSL)
+#include <wolfssl/openssl/evp.h>
+#endif
+
+#elif defined(USE_GNUTLS)
+#include <nettle/sha.h>
+#elif defined(USE_MBEDTLS)
+#include <mbedtls/sha256.h>
+#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
+ (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
+ (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
+#include <CommonCrypto/CommonDigest.h>
+#define AN_APPLE_OS
+#elif defined(USE_WIN32_CRYPTO)
+#include <wincrypt.h>
+#endif
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
/* Please keep the SSL backend-specific #if branches in this order:
*
* 1. USE_OPENSSL
@@ -71,20 +99,6 @@
#if defined(USE_OPENSSL_SHA256)
-/* When OpenSSL or wolfSSL is available is available we use their
- * SHA256-functions.
- */
-#if defined(USE_OPENSSL)
-#include <openssl/evp.h>
-#elif defined(USE_WOLFSSL)
-#include <wolfssl/openssl/evp.h>
-#endif
-
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
struct sha256_ctx {
EVP_MD_CTX *openssl_ctx;
};
@@ -115,13 +129,6 @@
#elif defined(USE_GNUTLS)
-#include <nettle/sha.h>
-
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
typedef struct sha256_ctx my_sha256_ctx;
static CURLcode my_sha256_init(my_sha256_ctx *ctx)
@@ -144,13 +151,6 @@
#elif defined(USE_MBEDTLS)
-#include <mbedtls/sha256.h>
-
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
typedef mbedtls_sha256_context my_sha256_ctx;
static CURLcode my_sha256_init(my_sha256_ctx *ctx)
@@ -183,18 +183,7 @@
#endif
}
-#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
- (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
- (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
- (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
-
-#include <CommonCrypto/CommonDigest.h>
-
-#include "curl_memory.h"
-
-/* The last #include file should be: */
-#include "memdebug.h"
-
+#elif defined(AN_APPLE_OS)
typedef CC_SHA256_CTX my_sha256_ctx;
static CURLcode my_sha256_init(my_sha256_ctx *ctx)
@@ -217,8 +206,6 @@
#elif defined(USE_WIN32_CRYPTO)
-#include <wincrypt.h>
-
struct sha256_ctx {
HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
diff --git a/lib/share.c b/lib/share.c
index 8b18360..c0a8d80 100644
--- a/lib/share.c
+++ b/lib/share.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,9 +29,11 @@
#include "share.h"
#include "psl.h"
#include "vtls/vtls.h"
-#include "curl_memory.h"
+#include "hsts.h"
-/* The last #include file should be: */
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
#include "memdebug.h"
struct Curl_share *
@@ -41,7 +43,7 @@
if(share) {
share->magic = CURL_GOOD_SHARE;
share->specifier |= (1<<CURL_LOCK_DATA_SHARE);
- Curl_init_dnscache(&share->hostcache);
+ Curl_init_dnscache(&share->hostcache, 23);
}
return share;
@@ -89,6 +91,18 @@
#endif
break;
+ case CURL_LOCK_DATA_HSTS:
+#ifndef CURL_DISABLE_HSTS
+ if(!share->hsts) {
+ share->hsts = Curl_hsts_init();
+ if(!share->hsts)
+ res = CURLSHE_NOMEM;
+ }
+#else /* CURL_DISABLE_HSTS */
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
case CURL_LOCK_DATA_SSL_SESSION:
#ifdef USE_SSL
if(!share->sslsession) {
@@ -141,6 +155,16 @@
#endif
break;
+ case CURL_LOCK_DATA_HSTS:
+#ifndef CURL_DISABLE_HSTS
+ if(share->hsts) {
+ Curl_hsts_cleanup(&share->hsts);
+ }
+#else /* CURL_DISABLE_HSTS */
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
case CURL_LOCK_DATA_SSL_SESSION:
#ifdef USE_SSL
Curl_safefree(share->sslsession);
@@ -207,6 +231,10 @@
Curl_cookie_cleanup(share->cookies);
#endif
+#ifndef CURL_DISABLE_HSTS
+ Curl_hsts_cleanup(&share->hsts);
+#endif
+
#ifdef USE_SSL
if(share->sslsession) {
size_t i;
diff --git a/lib/share.h b/lib/share.h
index 32be416..7f55aac 100644
--- a/lib/share.h
+++ b/lib/share.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -59,10 +59,14 @@
#ifdef USE_LIBPSL
struct PslCache psl;
#endif
-
+#ifndef CURL_DISABLE_HSTS
+ struct hsts *hsts;
+#endif
+#ifdef USE_SSL
struct Curl_ssl_session *sslsession;
size_t max_ssl_sessions;
long sessionage;
+#endif
};
CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data,
diff --git a/lib/sigpipe.h b/lib/sigpipe.h
index d12b317..48761ad 100644
--- a/lib/sigpipe.h
+++ b/lib/sigpipe.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -50,7 +50,6 @@
if(!data->set.no_signal) {
struct sigaction action;
/* first, extract the existing situation */
- memset(&ig->old_pipe_act, 0, sizeof(struct sigaction));
sigaction(SIGPIPE, NULL, &ig->old_pipe_act);
action = ig->old_pipe_act;
/* ignore this signal */
diff --git a/lib/slist.c b/lib/slist.c
index 6c80722..366b247 100644
--- a/lib/slist.c
+++ b/lib/slist.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/slist.h b/lib/slist.h
index 4e5834c..9561fd0 100644
--- a/lib/slist.h
+++ b/lib/slist.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/smb.c b/lib/smb.c
index 039d680..bc4e883 100644
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2016 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,24 +25,17 @@
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
- (SIZEOF_CURL_OFF_T > 4)
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE)
-#define BUILDING_CURL_SMB_C
-
-#ifdef HAVE_PROCESS_H
-#include <process.h>
-#ifdef CURL_WINDOWS_APP
+#ifdef WIN32
#define getpid GetCurrentProcessId
-#elif !defined(MSDOS)
-#define getpid _getpid
-#endif
#endif
#include "smb.h"
#include "urldata.h"
#include "sendf.h"
#include "multiif.h"
+#include "cfilters.h"
#include "connect.h"
#include "progress.h"
#include "transfer.h"
@@ -55,6 +48,199 @@
#include "curl_memory.h"
#include "memdebug.h"
+/*
+ * Definitions for SMB protocol data structures
+ */
+#if defined(_MSC_VER) || defined(__ILEC400__)
+# define PACK
+# pragma pack(push)
+# pragma pack(1)
+#elif defined(__GNUC__)
+# define PACK __attribute__((packed))
+#else
+# define PACK
+#endif
+
+#define SMB_COM_CLOSE 0x04
+#define SMB_COM_READ_ANDX 0x2e
+#define SMB_COM_WRITE_ANDX 0x2f
+#define SMB_COM_TREE_DISCONNECT 0x71
+#define SMB_COM_NEGOTIATE 0x72
+#define SMB_COM_SETUP_ANDX 0x73
+#define SMB_COM_TREE_CONNECT_ANDX 0x75
+#define SMB_COM_NT_CREATE_ANDX 0xa2
+#define SMB_COM_NO_ANDX_COMMAND 0xff
+
+#define SMB_WC_CLOSE 0x03
+#define SMB_WC_READ_ANDX 0x0c
+#define SMB_WC_WRITE_ANDX 0x0e
+#define SMB_WC_SETUP_ANDX 0x0d
+#define SMB_WC_TREE_CONNECT_ANDX 0x04
+#define SMB_WC_NT_CREATE_ANDX 0x18
+
+#define SMB_FLAGS_CANONICAL_PATHNAMES 0x10
+#define SMB_FLAGS_CASELESS_PATHNAMES 0x08
+#define SMB_FLAGS2_UNICODE_STRINGS 0x8000
+#define SMB_FLAGS2_IS_LONG_NAME 0x0040
+#define SMB_FLAGS2_KNOWS_LONG_NAME 0x0001
+
+#define SMB_CAP_LARGE_FILES 0x08
+#define SMB_GENERIC_WRITE 0x40000000
+#define SMB_GENERIC_READ 0x80000000
+#define SMB_FILE_SHARE_ALL 0x07
+#define SMB_FILE_OPEN 0x01
+#define SMB_FILE_OVERWRITE_IF 0x05
+
+#define SMB_ERR_NOACCESS 0x00050001
+
+struct smb_header {
+ unsigned char nbt_type;
+ unsigned char nbt_flags;
+ unsigned short nbt_length;
+ unsigned char magic[4];
+ unsigned char command;
+ unsigned int status;
+ unsigned char flags;
+ unsigned short flags2;
+ unsigned short pid_high;
+ unsigned char signature[8];
+ unsigned short pad;
+ unsigned short tid;
+ unsigned short pid;
+ unsigned short uid;
+ unsigned short mid;
+} PACK;
+
+struct smb_negotiate_response {
+ struct smb_header h;
+ unsigned char word_count;
+ unsigned short dialect_index;
+ unsigned char security_mode;
+ unsigned short max_mpx_count;
+ unsigned short max_number_vcs;
+ unsigned int max_buffer_size;
+ unsigned int max_raw_size;
+ unsigned int session_key;
+ unsigned int capabilities;
+ unsigned int system_time_low;
+ unsigned int system_time_high;
+ unsigned short server_time_zone;
+ unsigned char encryption_key_length;
+ unsigned short byte_count;
+ char bytes[1];
+} PACK;
+
+struct andx {
+ unsigned char command;
+ unsigned char pad;
+ unsigned short offset;
+} PACK;
+
+struct smb_setup {
+ unsigned char word_count;
+ struct andx andx;
+ unsigned short max_buffer_size;
+ unsigned short max_mpx_count;
+ unsigned short vc_number;
+ unsigned int session_key;
+ unsigned short lengths[2];
+ unsigned int pad;
+ unsigned int capabilities;
+ unsigned short byte_count;
+ char bytes[1024];
+} PACK;
+
+struct smb_tree_connect {
+ unsigned char word_count;
+ struct andx andx;
+ unsigned short flags;
+ unsigned short pw_len;
+ unsigned short byte_count;
+ char bytes[1024];
+} PACK;
+
+struct smb_nt_create {
+ unsigned char word_count;
+ struct andx andx;
+ unsigned char pad;
+ unsigned short name_length;
+ unsigned int flags;
+ unsigned int root_fid;
+ unsigned int access;
+ curl_off_t allocation_size;
+ unsigned int ext_file_attributes;
+ unsigned int share_access;
+ unsigned int create_disposition;
+ unsigned int create_options;
+ unsigned int impersonation_level;
+ unsigned char security_flags;
+ unsigned short byte_count;
+ char bytes[1024];
+} PACK;
+
+struct smb_nt_create_response {
+ struct smb_header h;
+ unsigned char word_count;
+ struct andx andx;
+ unsigned char op_lock_level;
+ unsigned short fid;
+ unsigned int create_disposition;
+
+ curl_off_t create_time;
+ curl_off_t last_access_time;
+ curl_off_t last_write_time;
+ curl_off_t last_change_time;
+ unsigned int ext_file_attributes;
+ curl_off_t allocation_size;
+ curl_off_t end_of_file;
+} PACK;
+
+struct smb_read {
+ unsigned char word_count;
+ struct andx andx;
+ unsigned short fid;
+ unsigned int offset;
+ unsigned short max_bytes;
+ unsigned short min_bytes;
+ unsigned int timeout;
+ unsigned short remaining;
+ unsigned int offset_high;
+ unsigned short byte_count;
+} PACK;
+
+struct smb_write {
+ struct smb_header h;
+ unsigned char word_count;
+ struct andx andx;
+ unsigned short fid;
+ unsigned int offset;
+ unsigned int timeout;
+ unsigned short write_mode;
+ unsigned short remaining;
+ unsigned short pad;
+ unsigned short data_length;
+ unsigned short data_offset;
+ unsigned int offset_high;
+ unsigned short byte_count;
+ unsigned char pad2;
+} PACK;
+
+struct smb_close {
+ unsigned char word_count;
+ unsigned short fid;
+ unsigned int last_mtime;
+ unsigned short byte_count;
+} PACK;
+
+struct smb_tree_disconnect {
+ unsigned char word_count;
+ unsigned short byte_count;
+} PACK;
+
+#if defined(_MSC_VER) || defined(__ILEC400__)
+# pragma pack(pop)
+#endif
+
/* Local API functions */
static CURLcode smb_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
@@ -62,8 +248,6 @@
static CURLcode smb_connection_state(struct Curl_easy *data, bool *done);
static CURLcode smb_do(struct Curl_easy *data, bool *done);
static CURLcode smb_request_state(struct Curl_easy *data, bool *done);
-static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
- bool premature);
static CURLcode smb_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead);
static int smb_getsock(struct Curl_easy *data, struct connectdata *conn,
@@ -78,7 +262,7 @@
"SMB", /* scheme */
smb_setup_connection, /* setup_connection */
smb_do, /* do_it */
- smb_done, /* done */
+ ZERO_NULL, /* done */
ZERO_NULL, /* do_more */
smb_connect, /* connect_it */
smb_connection_state, /* connecting */
@@ -105,7 +289,7 @@
"SMBS", /* scheme */
smb_setup_connection, /* setup_connection */
smb_do, /* do_it */
- smb_done, /* done */
+ ZERO_NULL, /* done */
ZERO_NULL, /* do_more */
smb_connect, /* connect_it */
smb_connection_state, /* connecting */
@@ -537,7 +721,7 @@
byte_count = strlen(req->path);
msg.name_length = smb_swap16((unsigned short)byte_count);
msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL);
- if(data->set.upload) {
+ if(data->state.upload) {
msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE);
msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF);
}
@@ -671,8 +855,7 @@
#ifdef USE_SSL
if((conn->handler->flags & PROTOPT_SSL)) {
bool ssl_done = FALSE;
- result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
- FIRSTSOCKET, &ssl_done);
+ result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssl_done);
if(result && result != CURLE_AGAIN)
return result;
if(!ssl_done)
@@ -770,6 +953,11 @@
void *msg = NULL;
const struct smb_nt_create_response *smb_m;
+ if(data->state.upload && (data->state.infilesize < 0)) {
+ failf(data, "SMB upload needs to know the size up front");
+ return CURLE_SEND_ERROR;
+ }
+
/* Start the request */
if(req->state == SMB_REQUESTING) {
result = smb_send_tree_connect(data);
@@ -816,13 +1004,12 @@
smb_m = (const struct smb_nt_create_response*) msg;
req->fid = smb_swap16(smb_m->fid);
data->req.offset = 0;
- if(data->set.upload) {
+ if(data->state.upload) {
data->req.size = data->state.infilesize;
Curl_pgrsSetUploadSize(data, data->req.size);
next_state = SMB_UPLOAD;
}
else {
- smb_m = (const struct smb_nt_create_response*) msg;
data->req.size = smb_swap64(smb_m->end_of_file);
if(data->req.size < 0) {
req->result = CURLE_WEIRD_SERVER_REPLY;
@@ -941,14 +1128,6 @@
return CURLE_OK;
}
-static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
- bool premature)
-{
- (void) premature;
- Curl_safefree(data->req.p.smb);
- return status;
-}
-
static CURLcode smb_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead)
{
@@ -1008,6 +1187,7 @@
/* The share must be present */
if(!slash) {
Curl_safefree(smbc->share);
+ failf(data, "missing share in URL path for SMB");
return CURLE_URL_MALFORMAT;
}
diff --git a/lib/smb.h b/lib/smb.h
index 919f3ac..437f4a5 100644
--- a/lib/smb.h
+++ b/lib/smb.h
@@ -7,8 +7,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
- * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,203 +48,6 @@
size_t got;
};
-/*
- * Definitions for SMB protocol data structures
- */
-#ifdef BUILDING_CURL_SMB_C
-
-#if defined(_MSC_VER) || defined(__ILEC400__)
-# define PACK
-# pragma pack(push)
-# pragma pack(1)
-#elif defined(__GNUC__)
-# define PACK __attribute__((packed))
-#else
-# define PACK
-#endif
-
-#define SMB_COM_CLOSE 0x04
-#define SMB_COM_READ_ANDX 0x2e
-#define SMB_COM_WRITE_ANDX 0x2f
-#define SMB_COM_TREE_DISCONNECT 0x71
-#define SMB_COM_NEGOTIATE 0x72
-#define SMB_COM_SETUP_ANDX 0x73
-#define SMB_COM_TREE_CONNECT_ANDX 0x75
-#define SMB_COM_NT_CREATE_ANDX 0xa2
-#define SMB_COM_NO_ANDX_COMMAND 0xff
-
-#define SMB_WC_CLOSE 0x03
-#define SMB_WC_READ_ANDX 0x0c
-#define SMB_WC_WRITE_ANDX 0x0e
-#define SMB_WC_SETUP_ANDX 0x0d
-#define SMB_WC_TREE_CONNECT_ANDX 0x04
-#define SMB_WC_NT_CREATE_ANDX 0x18
-
-#define SMB_FLAGS_CANONICAL_PATHNAMES 0x10
-#define SMB_FLAGS_CASELESS_PATHNAMES 0x08
-#define SMB_FLAGS2_UNICODE_STRINGS 0x8000
-#define SMB_FLAGS2_IS_LONG_NAME 0x0040
-#define SMB_FLAGS2_KNOWS_LONG_NAME 0x0001
-
-#define SMB_CAP_LARGE_FILES 0x08
-#define SMB_GENERIC_WRITE 0x40000000
-#define SMB_GENERIC_READ 0x80000000
-#define SMB_FILE_SHARE_ALL 0x07
-#define SMB_FILE_OPEN 0x01
-#define SMB_FILE_OVERWRITE_IF 0x05
-
-#define SMB_ERR_NOACCESS 0x00050001
-
-struct smb_header {
- unsigned char nbt_type;
- unsigned char nbt_flags;
- unsigned short nbt_length;
- unsigned char magic[4];
- unsigned char command;
- unsigned int status;
- unsigned char flags;
- unsigned short flags2;
- unsigned short pid_high;
- unsigned char signature[8];
- unsigned short pad;
- unsigned short tid;
- unsigned short pid;
- unsigned short uid;
- unsigned short mid;
-} PACK;
-
-struct smb_negotiate_response {
- struct smb_header h;
- unsigned char word_count;
- unsigned short dialect_index;
- unsigned char security_mode;
- unsigned short max_mpx_count;
- unsigned short max_number_vcs;
- unsigned int max_buffer_size;
- unsigned int max_raw_size;
- unsigned int session_key;
- unsigned int capabilities;
- unsigned int system_time_low;
- unsigned int system_time_high;
- unsigned short server_time_zone;
- unsigned char encryption_key_length;
- unsigned short byte_count;
- char bytes[1];
-} PACK;
-
-struct andx {
- unsigned char command;
- unsigned char pad;
- unsigned short offset;
-} PACK;
-
-struct smb_setup {
- unsigned char word_count;
- struct andx andx;
- unsigned short max_buffer_size;
- unsigned short max_mpx_count;
- unsigned short vc_number;
- unsigned int session_key;
- unsigned short lengths[2];
- unsigned int pad;
- unsigned int capabilities;
- unsigned short byte_count;
- char bytes[1024];
-} PACK;
-
-struct smb_tree_connect {
- unsigned char word_count;
- struct andx andx;
- unsigned short flags;
- unsigned short pw_len;
- unsigned short byte_count;
- char bytes[1024];
-} PACK;
-
-struct smb_nt_create {
- unsigned char word_count;
- struct andx andx;
- unsigned char pad;
- unsigned short name_length;
- unsigned int flags;
- unsigned int root_fid;
- unsigned int access;
- curl_off_t allocation_size;
- unsigned int ext_file_attributes;
- unsigned int share_access;
- unsigned int create_disposition;
- unsigned int create_options;
- unsigned int impersonation_level;
- unsigned char security_flags;
- unsigned short byte_count;
- char bytes[1024];
-} PACK;
-
-struct smb_nt_create_response {
- struct smb_header h;
- unsigned char word_count;
- struct andx andx;
- unsigned char op_lock_level;
- unsigned short fid;
- unsigned int create_disposition;
-
- curl_off_t create_time;
- curl_off_t last_access_time;
- curl_off_t last_write_time;
- curl_off_t last_change_time;
- unsigned int ext_file_attributes;
- curl_off_t allocation_size;
- curl_off_t end_of_file;
-} PACK;
-
-struct smb_read {
- unsigned char word_count;
- struct andx andx;
- unsigned short fid;
- unsigned int offset;
- unsigned short max_bytes;
- unsigned short min_bytes;
- unsigned int timeout;
- unsigned short remaining;
- unsigned int offset_high;
- unsigned short byte_count;
-} PACK;
-
-struct smb_write {
- struct smb_header h;
- unsigned char word_count;
- struct andx andx;
- unsigned short fid;
- unsigned int offset;
- unsigned int timeout;
- unsigned short write_mode;
- unsigned short remaining;
- unsigned short pad;
- unsigned short data_length;
- unsigned short data_offset;
- unsigned int offset_high;
- unsigned short byte_count;
- unsigned char pad2;
-} PACK;
-
-struct smb_close {
- unsigned char word_count;
- unsigned short fid;
- unsigned int last_mtime;
- unsigned short byte_count;
-} PACK;
-
-struct smb_tree_disconnect {
- unsigned char word_count;
- unsigned short byte_count;
-} PACK;
-
-#if defined(_MSC_VER) || defined(__ILEC400__)
-# pragma pack(pop)
-#endif
-
-#endif /* BUILDING_CURL_SMB_C */
-
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
(SIZEOF_CURL_OFF_T > 4)
diff --git a/lib/smtp.c b/lib/smtp.c
index 6ebb41a..afcdd10 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -60,11 +60,6 @@
#include <inet.h>
#endif
-#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
-#undef in_addr_t
-#define in_addr_t unsigned long
-#endif
-
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
@@ -79,6 +74,7 @@
#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
+#include "cfilters.h"
#include "connect.h"
#include "select.h"
#include "multiif.h"
@@ -87,6 +83,7 @@
#include "bufref.h"
#include "curl_sasl.h"
#include "warnless.h"
+#include "idn.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -109,7 +106,7 @@
static CURLcode smtp_parse_url_options(struct connectdata *conn);
static CURLcode smtp_parse_url_path(struct Curl_easy *data);
static CURLcode smtp_parse_custom_request(struct Curl_easy *data);
-static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
+static CURLcode smtp_parse_address(const char *fqma,
char **address, struct hostname *host);
static CURLcode smtp_perform_auth(struct Curl_easy *data, const char *mech,
const struct bufref *initresp);
@@ -284,11 +281,11 @@
/***********************************************************************
*
- * state()
+ * smtp_state()
*
* This is the ONLY way to change SMTP state!
*/
-static void state(struct Curl_easy *data, smtpstate newstate)
+static void smtp_state(struct Curl_easy *data, smtpstate newstate)
{
struct smtp_conn *smtpc = &data->conn->proto.smtpc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -341,7 +338,7 @@
result = Curl_pp_sendf(data, &smtpc->pp, "EHLO %s", smtpc->domain);
if(!result)
- state(data, SMTP_EHLO);
+ smtp_state(data, SMTP_EHLO);
return result;
}
@@ -365,7 +362,7 @@
result = Curl_pp_sendf(data, &smtpc->pp, "HELO %s", smtpc->domain);
if(!result)
- state(data, SMTP_HELO);
+ smtp_state(data, SMTP_HELO);
return result;
}
@@ -384,7 +381,7 @@
"%s", "STARTTLS");
if(!result)
- state(data, SMTP_STARTTLS);
+ smtp_state(data, SMTP_STARTTLS);
return result;
}
@@ -400,20 +397,27 @@
/* Start the SSL connection */
struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
- CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
- FIRSTSOCKET,
- &smtpc->ssldone);
+ CURLcode result;
+ bool ssldone = FALSE;
+ if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
+ result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
+ if(result)
+ goto out;
+ }
+
+ result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
if(!result) {
+ smtpc->ssldone = ssldone;
if(smtpc->state != SMTP_UPGRADETLS)
- state(data, SMTP_UPGRADETLS);
+ smtp_state(data, SMTP_UPGRADETLS);
if(smtpc->ssldone) {
smtp_to_smtps(conn);
result = smtp_perform_ehlo(data);
}
}
-
+out:
return result;
}
@@ -495,7 +499,7 @@
server supports authentication, and end the connect phase if not */
if(!smtpc->auth_supported ||
!Curl_sasl_can_authenticate(&smtpc->sasl, data)) {
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
return result;
}
@@ -504,7 +508,7 @@
if(!result) {
if(progress == SASL_INPROGRESS)
- state(data, SMTP_AUTH);
+ smtp_state(data, SMTP_AUTH);
else {
/* Other mechanisms not supported */
infof(data, "No known authentication mechanisms supported");
@@ -540,7 +544,7 @@
/* Parse the mailbox to verify into the local address and host name
parts, converting the host name to an IDN A-label if necessary */
- result = smtp_parse_address(data, smtp->rcpt->data,
+ result = smtp_parse_address(smtp->rcpt->data,
&address, &host);
if(result)
return result;
@@ -582,7 +586,7 @@
smtp->custom : "HELP");
if(!result)
- state(data, SMTP_COMMAND);
+ smtp_state(data, SMTP_COMMAND);
return result;
}
@@ -614,7 +618,7 @@
/* Parse the FROM mailbox into the local address and host name parts,
converting the host name to an IDN A-label if necessary */
- result = smtp_parse_address(data, data->set.str[STRING_MAIL_FROM],
+ result = smtp_parse_address(data->set.str[STRING_MAIL_FROM],
&address, &host);
if(result)
return result;
@@ -652,7 +656,7 @@
/* Parse the AUTH mailbox into the local address and host name parts,
converting the host name to an IDN A-label if necessary */
- result = smtp_parse_address(data, data->set.str[STRING_MAIL_AUTH],
+ result = smtp_parse_address(data->set.str[STRING_MAIL_AUTH],
&address, &host);
if(result) {
free(from);
@@ -696,7 +700,7 @@
/* Add external headers and mime version. */
curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
- result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
+ result = Curl_mime_prepare_headers(data, &data->set.mimepost, NULL,
NULL, MIMESTRATEGY_MAIL);
if(!result)
@@ -767,7 +771,7 @@
free(size);
if(!result)
- state(data, SMTP_MAIL);
+ smtp_state(data, SMTP_MAIL);
return result;
}
@@ -789,7 +793,7 @@
/* Parse the recipient mailbox into the local address and host name parts,
converting the host name to an IDN A-label if necessary */
- result = smtp_parse_address(data, smtp->rcpt->data,
+ result = smtp_parse_address(smtp->rcpt->data,
&address, &host);
if(result)
return result;
@@ -808,7 +812,7 @@
free(address);
if(!result)
- state(data, SMTP_RCPT);
+ smtp_state(data, SMTP_RCPT);
return result;
}
@@ -826,7 +830,7 @@
CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "QUIT");
if(!result)
- state(data, SMTP_QUIT);
+ smtp_state(data, SMTP_QUIT);
return result;
}
@@ -888,7 +892,8 @@
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2 && smtpcode != 1) {
- if(data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use)
+ if(data->set.use_ssl <= CURLUSESSL_TRY
+ || Curl_conn_is_ssl(conn, FIRSTSOCKET))
result = smtp_perform_helo(data, conn);
else {
failf(data, "Remote access denied: %d", smtpcode);
@@ -953,7 +958,7 @@
}
if(smtpcode != 1) {
- if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ if(data->set.use_ssl && !Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
/* We don't have a SSL/TLS connection yet, but SSL is requested */
if(smtpc->tls_supported)
/* Switch to TLS connection now */
@@ -991,7 +996,7 @@
}
else
/* End of connect phase */
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
return result;
}
@@ -1012,7 +1017,7 @@
if(!result)
switch(progress) {
case SASL_DONE:
- state(data, SMTP_STOP); /* Authenticated */
+ smtp_state(data, SMTP_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
failf(data, "Authentication cancelled");
@@ -1043,7 +1048,7 @@
}
else {
/* Temporarily add the LF character back and send as body to the client */
- if(!data->set.opt_no_body) {
+ if(!data->req.no_body) {
line[len] = '\n';
result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1);
line[len] = '\0';
@@ -1059,11 +1064,11 @@
}
else
/* End of DO phase */
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
}
else
/* End of DO phase */
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
}
}
@@ -1140,7 +1145,7 @@
result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "DATA");
if(!result)
- state(data, SMTP_DATA);
+ smtp_state(data, SMTP_DATA);
}
}
}
@@ -1167,7 +1172,7 @@
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
/* End of DO phase */
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
}
return result;
@@ -1187,7 +1192,7 @@
result = CURLE_WEIRD_SERVER_REPLY;
/* End of DONE phase */
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
return result;
}
@@ -1269,7 +1274,7 @@
/* fallthrough, just stop! */
default:
/* internal error */
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
break;
}
} while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp));
@@ -1285,8 +1290,9 @@
struct smtp_conn *smtpc = &conn->proto.smtpc;
if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
- result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
- FIRSTSOCKET, &smtpc->ssldone);
+ bool ssldone = FALSE;
+ result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
+ smtpc->ssldone = ssldone;
if(result || !smtpc->ssldone)
return result;
}
@@ -1373,7 +1379,7 @@
return result;
/* Start off waiting for the server greeting response */
- state(data, SMTP_SERVERGREET);
+ smtp_state(data, SMTP_SERVERGREET);
result = smtp_multi_statemach(data, done);
@@ -1413,7 +1419,7 @@
result = status; /* use the already set error code */
}
else if(!data->set.connect_only && data->set.mail_rcpt &&
- (data->set.upload || data->set.mimepost.kind)) {
+ (data->state.upload || data->set.mimepost.kind)) {
/* Calculate the EOB taking into account any terminating CRLF from the
previous line of the email or the CRLF of the DATA command when there
is "no mail data". RFC-5321, sect. 4.1.1.4.
@@ -1455,7 +1461,7 @@
free(eob);
}
- state(data, SMTP_POSTDATA);
+ smtp_state(data, SMTP_POSTDATA);
/* Run the state-machine */
result = smtp_block_statemach(data, conn, FALSE);
@@ -1479,12 +1485,11 @@
{
/* This is SMTP and no proxy */
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
struct SMTP *smtp = data->req.p.smtp;
DEBUGF(infof(data, "DO phase starts"));
- if(data->set.opt_no_body) {
+ if(data->req.no_body) {
/* Requested no body means no transfer */
smtp->transfer = PPTRANSFER_INFO;
}
@@ -1506,7 +1511,7 @@
smtp->eob = 2;
/* Start the first command in the DO phase */
- if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
+ if((data->state.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
/* MAIL transfer */
result = smtp_perform_mail(data);
else
@@ -1519,7 +1524,7 @@
/* Run the state-machine */
result = smtp_multi_statemach(data, dophase_done);
- *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+ *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
if(*dophase_done)
DEBUGF(infof(data, "DO phase is complete"));
@@ -1782,8 +1787,8 @@
* calling function deems it to be) then the input will simply be returned in
* the address part with the host name being NULL.
*/
-static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
- char **address, struct hostname *host)
+static CURLcode smtp_parse_address(const char *fqma, char **address,
+ struct hostname *host)
{
CURLcode result = CURLE_OK;
size_t length;
@@ -1807,7 +1812,7 @@
host->name = host->name + 1;
/* Attempt to convert the host name to IDN ACE */
- (void) Curl_idnconvert_hostname(data, host);
+ (void) Curl_idnconvert_hostname(host);
/* If Curl_idnconvert_hostname() fails then we shall attempt to continue
and send the host name using UTF-8 rather than as 7-bit ACE (which is
diff --git a/lib/smtp.h b/lib/smtp.h
index 24c5589..7a04c21 100644
--- a/lib/smtp.h
+++ b/lib/smtp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -57,28 +57,28 @@
curl_pp_transfer transfer;
char *custom; /* Custom Request */
struct curl_slist *rcpt; /* Recipient list */
- bool rcpt_had_ok; /* Whether any of RCPT TO commands (depends on
- total number of recipients) succeeded so far */
- bool trailing_crlf; /* Specifies if the trailing CRLF is present */
int rcpt_last_error; /* The last error received for RCPT TO command */
size_t eob; /* Number of bytes of the EOB (End Of Body) that
have been received so far */
+ BIT(rcpt_had_ok); /* Whether any of RCPT TO commands (depends on
+ total number of recipients) succeeded so far */
+ BIT(trailing_crlf); /* Specifies if the trailing CRLF is present */
};
/* smtp_conn is used for struct connection-oriented data in the connectdata
struct */
struct smtp_conn {
struct pingpong pp;
- smtpstate state; /* Always use smtp.c:state() to change state! */
- bool ssldone; /* Is connect() over SSL done? */
- char *domain; /* Client address/name to send in the EHLO */
struct SASL sasl; /* SASL-related storage */
- bool tls_supported; /* StartTLS capability supported by server */
- bool size_supported; /* If server supports SIZE extension according to
+ smtpstate state; /* Always use smtp.c:state() to change state! */
+ char *domain; /* Client address/name to send in the EHLO */
+ BIT(ssldone); /* Is connect() over SSL done? */
+ BIT(tls_supported); /* StartTLS capability supported by server */
+ BIT(size_supported); /* If server supports SIZE extension according to
RFC 1870 */
- bool utf8_supported; /* If server supports SMTPUTF8 extension according
+ BIT(utf8_supported); /* If server supports SMTPUTF8 extension according
to RFC 6531 */
- bool auth_supported; /* AUTH capability supported by server */
+ BIT(auth_supported); /* AUTH capability supported by server */
};
extern const struct Curl_handler Curl_handler_smtp;
diff --git a/lib/sockaddr.h b/lib/sockaddr.h
index 77ec833..5a6bb20 100644
--- a/lib/sockaddr.h
+++ b/lib/sockaddr.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/socketpair.c b/lib/socketpair.c
index 0f8798f..963e140 100644
--- a/lib/socketpair.c
+++ b/lib/socketpair.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,6 +24,8 @@
#include "curl_setup.h"
#include "socketpair.h"
+#include "urldata.h"
+#include "rand.h"
#if !defined(HAVE_SOCKETPAIR) && !defined(CURL_DISABLE_SOCKETPAIR)
#ifdef WIN32
@@ -65,7 +67,7 @@
union {
struct sockaddr_in inaddr;
struct sockaddr addr;
- } a, a2;
+ } a;
curl_socket_t listener;
curl_socklen_t addrlen = sizeof(a.inaddr);
int reuse = 1;
@@ -85,9 +87,22 @@
socks[0] = socks[1] = CURL_SOCKET_BAD;
+#if defined(WIN32) || defined(__CYGWIN__)
+ /* don't set SO_REUSEADDR on Windows */
+ (void)reuse;
+#ifdef SO_EXCLUSIVEADDRUSE
+ {
+ int exclusive = 1;
+ if(setsockopt(listener, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
+ (char *)&exclusive, (curl_socklen_t)sizeof(exclusive)) == -1)
+ goto error;
+ }
+#endif
+#else
if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR,
(char *)&reuse, (curl_socklen_t)sizeof(reuse)) == -1)
goto error;
+#endif
if(bind(listener, &a.addr, sizeof(a.inaddr)) == -1)
goto error;
if(getsockname(listener, &a.addr, &addrlen) == -1 ||
@@ -107,29 +122,68 @@
pfd[0].fd = listener;
pfd[0].events = POLLIN;
pfd[0].revents = 0;
- (void)Curl_poll(pfd, 1, 10*1000); /* 10 seconds */
+ (void)Curl_poll(pfd, 1, 1000); /* one second */
socks[1] = accept(listener, NULL, NULL);
if(socks[1] == CURL_SOCKET_BAD)
goto error;
+ else {
+ struct curltime start = Curl_now();
+ char rnd[9];
+ char check[sizeof(rnd)];
+ char *p = &check[0];
+ size_t s = sizeof(check);
- /* verify that nothing else connected */
- addrlen = sizeof(a.inaddr);
- if(getsockname(socks[0], &a.addr, &addrlen) == -1 ||
- addrlen < (int)sizeof(a.inaddr))
- goto error;
- addrlen = sizeof(a2.inaddr);
- if(getpeername(socks[1], &a2.addr, &addrlen) == -1 ||
- addrlen < (int)sizeof(a2.inaddr))
- goto error;
- if(a.inaddr.sin_family != a2.inaddr.sin_family ||
- a.inaddr.sin_addr.s_addr != a2.inaddr.sin_addr.s_addr ||
- a.inaddr.sin_port != a2.inaddr.sin_port)
- goto error;
+ if(Curl_rand(NULL, (unsigned char *)rnd, sizeof(rnd)))
+ goto error;
+
+ /* write data to the socket */
+ swrite(socks[0], rnd, sizeof(rnd));
+ /* verify that we read the correct data */
+ do {
+ ssize_t nread;
+
+ pfd[0].fd = socks[1];
+ pfd[0].events = POLLIN;
+ pfd[0].revents = 0;
+ (void)Curl_poll(pfd, 1, 1000); /* one second */
+
+ nread = sread(socks[1], p, s);
+ if(nread == -1) {
+ int sockerr = SOCKERRNO;
+ /* Don't block forever */
+ if(Curl_timediff(Curl_now(), start) > (60 * 1000))
+ goto error;
+ if(
+#ifdef WSAEWOULDBLOCK
+ /* This is how Windows does it */
+ (WSAEWOULDBLOCK == sockerr)
+#else
+ /* errno may be EWOULDBLOCK or on some systems EAGAIN when it
+ returned due to its inability to send off data without
+ blocking. We therefore treat both error codes the same here */
+ (EWOULDBLOCK == sockerr) || (EAGAIN == sockerr) ||
+ (EINTR == sockerr) || (EINPROGRESS == sockerr)
+#endif
+ ) {
+ continue;
+ }
+ goto error;
+ }
+ s -= nread;
+ if(s) {
+ p += nread;
+ continue;
+ }
+ if(memcmp(rnd, check, sizeof(check)))
+ goto error;
+ break;
+ } while(1);
+ }
sclose(listener);
return 0;
- error:
+error:
sclose(listener);
sclose(socks[0]);
sclose(socks[1]);
diff --git a/lib/socketpair.h b/lib/socketpair.h
index f91a3c6..306ab5d 100644
--- a/lib/socketpair.h
+++ b/lib/socketpair.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,6 +26,8 @@
#include "curl_setup.h"
#ifndef HAVE_SOCKETPAIR
+#include <curl/curl.h>
+
int Curl_socketpair(int domain, int type, int protocol,
curl_socket_t socks[2]);
#else
diff --git a/lib/socks.c b/lib/socks.c
index 52c2988..c492d66 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,17 +36,52 @@
#include "urldata.h"
#include "sendf.h"
#include "select.h"
+#include "cfilters.h"
#include "connect.h"
#include "timeval.h"
#include "socks.h"
#include "multiif.h" /* for getsock macros */
#include "inet_pton.h"
+#include "url.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
+/* for the (SOCKS) connect state machine */
+enum connect_t {
+ CONNECT_INIT,
+ CONNECT_SOCKS_INIT, /* 1 */
+ CONNECT_SOCKS_SEND, /* 2 waiting to send more first data */
+ CONNECT_SOCKS_READ_INIT, /* 3 set up read */
+ CONNECT_SOCKS_READ, /* 4 read server response */
+ CONNECT_GSSAPI_INIT, /* 5 */
+ CONNECT_AUTH_INIT, /* 6 setup outgoing auth buffer */
+ CONNECT_AUTH_SEND, /* 7 send auth */
+ CONNECT_AUTH_READ, /* 8 read auth response */
+ CONNECT_REQ_INIT, /* 9 init SOCKS "request" */
+ CONNECT_RESOLVING, /* 10 */
+ CONNECT_RESOLVED, /* 11 */
+ CONNECT_RESOLVE_REMOTE, /* 12 */
+ CONNECT_REQ_SEND, /* 13 */
+ CONNECT_REQ_SENDING, /* 14 */
+ CONNECT_REQ_READ, /* 15 */
+ CONNECT_REQ_READ_MORE, /* 16 */
+ CONNECT_DONE /* 17 connected fine to the remote or the SOCKS proxy */
+};
+
+struct socks_state {
+ enum connect_t state;
+ ssize_t outstanding; /* send this many bytes more */
+ unsigned char *outp; /* send from this pointer */
+
+ const char *hostname;
+ int remote_port;
+ const char *proxy_user;
+ const char *proxy_password;
+};
+
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
/*
* Helper read-from-socket functions. Does the same as Curl_read() but it
@@ -54,8 +89,8 @@
*
* This is STUPID BLOCKING behavior. Only used by the SOCKS GSSAPI functions.
*/
-int Curl_blockread_all(struct Curl_easy *data, /* transfer */
- curl_socket_t sockfd, /* read from this socket */
+int Curl_blockread_all(struct Curl_cfilter *cf,
+ struct Curl_easy *data, /* transfer */
char *buf, /* store read data here */
ssize_t buffersize, /* max amount to read */
ssize_t *n) /* amount bytes read */
@@ -63,6 +98,8 @@
ssize_t nread = 0;
ssize_t allread = 0;
int result;
+ CURLcode err = CURLE_OK;
+
*n = 0;
for(;;) {
timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
@@ -73,15 +110,19 @@
}
if(!timeout_ms)
timeout_ms = TIMEDIFF_T_MAX;
- if(SOCKET_READABLE(sockfd, timeout_ms) <= 0) {
+ if(SOCKET_READABLE(cf->conn->sock[cf->sockindex], timeout_ms) <= 0) {
result = ~CURLE_OK;
break;
}
- result = Curl_read_plain(sockfd, buf, buffersize, &nread);
- if(CURLE_AGAIN == result)
- continue;
- if(result)
- break;
+ nread = Curl_conn_cf_recv(cf->next, data, buf, buffersize, &err);
+ if(nread <= 0) {
+ result = err;
+ if(CURLE_AGAIN == err)
+ continue;
+ if(err) {
+ break;
+ }
+ }
if(buffersize == nread) {
allread += nread;
@@ -104,24 +145,23 @@
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
#define DEBUG_AND_VERBOSE
-#define sxstate(x,y) socksstate(x,y, __LINE__)
+#define sxstate(x,d,y) socksstate(x,d,y, __LINE__)
#else
-#define sxstate(x,y) socksstate(x,y)
+#define sxstate(x,d,y) socksstate(x,d,y)
#endif
/* always use this function to change state, to make debugging easier */
-static void socksstate(struct Curl_easy *data,
+static void socksstate(struct socks_state *sx, struct Curl_easy *data,
enum connect_t state
#ifdef DEBUG_AND_VERBOSE
, int lineno
#endif
)
{
- struct connectdata *conn = data->conn;
- enum connect_t oldstate = conn->cnnct.state;
+ enum connect_t oldstate = sx->state;
#ifdef DEBUG_AND_VERBOSE
/* synced with the state list in urldata.h */
- static const char * const statename[] = {
+ static const char * const socks_statename[] = {
"INIT",
"SOCKS_INIT",
"SOCKS_SEND",
@@ -143,38 +183,81 @@
};
#endif
+ (void)data;
if(oldstate == state)
/* don't bother when the new state is the same as the old state */
return;
- conn->cnnct.state = state;
+ sx->state = state;
#ifdef DEBUG_AND_VERBOSE
infof(data,
- "SXSTATE: %s => %s conn %p; line %d",
- statename[oldstate], statename[conn->cnnct.state], conn,
+ "SXSTATE: %s => %s; line %d",
+ socks_statename[oldstate], socks_statename[sx->state],
lineno);
#endif
}
-int Curl_SOCKS_getsock(struct connectdata *conn, curl_socket_t *sock,
- int sockindex)
+static CURLproxycode socks_state_send(struct Curl_cfilter *cf,
+ struct socks_state *sx,
+ struct Curl_easy *data,
+ CURLproxycode failcode,
+ const char *description)
{
- int rc = 0;
- sock[0] = conn->sock[sockindex];
- switch(conn->cnnct.state) {
- case CONNECT_RESOLVING:
- case CONNECT_SOCKS_READ:
- case CONNECT_AUTH_READ:
- case CONNECT_REQ_READ:
- case CONNECT_REQ_READ_MORE:
- rc = GETSOCK_READSOCK(0);
- break;
- default:
- rc = GETSOCK_WRITESOCK(0);
- break;
+ ssize_t nwritten;
+ CURLcode result;
+
+ nwritten = Curl_conn_cf_send(cf->next, data, (char *)sx->outp,
+ sx->outstanding, &result);
+ if(nwritten <= 0) {
+ if(CURLE_AGAIN == result) {
+ return CURLPX_OK;
+ }
+ else if(CURLE_OK == result) {
+ /* connection closed */
+ failf(data, "connection to proxy closed");
+ return CURLPX_CLOSED;
+ }
+ failf(data, "Failed to send %s: %s", description,
+ curl_easy_strerror(result));
+ return failcode;
}
- return rc;
+ DEBUGASSERT(sx->outstanding >= nwritten);
+ /* not done, remain in state */
+ sx->outstanding -= nwritten;
+ sx->outp += nwritten;
+ return CURLPX_OK;
+}
+
+static CURLproxycode socks_state_recv(struct Curl_cfilter *cf,
+ struct socks_state *sx,
+ struct Curl_easy *data,
+ CURLproxycode failcode,
+ const char *description)
+{
+ ssize_t nread;
+ CURLcode result;
+
+ nread = Curl_conn_cf_recv(cf->next, data, (char *)sx->outp,
+ sx->outstanding, &result);
+ if(nread <= 0) {
+ if(CURLE_AGAIN == result) {
+ return CURLPX_OK;
+ }
+ else if(CURLE_OK == result) {
+ /* connection closed */
+ failf(data, "connection to proxy closed");
+ return CURLPX_CLOSED;
+ }
+ failf(data, "SOCKS4: Failed receiving %s: %s", description,
+ curl_easy_strerror(result));
+ return failcode;
+ }
+ /* remain in reading state */
+ DEBUGASSERT(sx->outstanding >= nread);
+ sx->outstanding -= nread;
+ sx->outp += nread;
+ return CURLPX_OK;
}
/*
@@ -188,39 +271,31 @@
* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
* Nonsupport "Identification Protocol (RFC1413)"
*/
-CURLproxycode Curl_SOCKS4(const char *proxy_user,
- const char *hostname,
- int remote_port,
- int sockindex,
- struct Curl_easy *data,
- bool *done)
+static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
+ struct socks_state *sx,
+ struct Curl_easy *data)
{
- struct connectdata *conn = data->conn;
+ struct connectdata *conn = cf->conn;
const bool protocol4a =
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
unsigned char *socksreq = (unsigned char *)data->state.buffer;
CURLcode result;
- curl_socket_t sockfd = conn->sock[sockindex];
- struct connstate *sx = &conn->cnnct;
+ CURLproxycode presult;
struct Curl_dns_entry *dns = NULL;
- ssize_t actualread;
- ssize_t written;
/* make sure that the buffer is at least 600 bytes */
DEBUGASSERT(READBUFFER_MIN >= 600);
- if(!SOCKS_STATE(sx->state) && !*done)
- sxstate(data, CONNECT_SOCKS_INIT);
-
switch(sx->state) {
case CONNECT_SOCKS_INIT:
/* SOCKS4 can only do IPv4, insist! */
conn->ip_version = CURL_IPRESOLVE_V4;
if(conn->bits.httpproxy)
infof(data, "SOCKS4%s: connecting to HTTP proxy %s port %d",
- protocol4a ? "a" : "", hostname, remote_port);
+ protocol4a ? "a" : "", sx->hostname, sx->remote_port);
- infof(data, "SOCKS4 communication to %s:%d", hostname, remote_port);
+ infof(data, "SOCKS4 communication to %s:%d",
+ sx->hostname, sx->remote_port);
/*
* Compose socks4 request
@@ -235,40 +310,40 @@
socksreq[0] = 4; /* version (SOCKS4) */
socksreq[1] = 1; /* connect */
- socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */
- socksreq[3] = (unsigned char)(remote_port & 0xff); /* PORT LSB */
+ socksreq[2] = (unsigned char)((sx->remote_port >> 8) & 0xff); /* MSB */
+ socksreq[3] = (unsigned char)(sx->remote_port & 0xff); /* LSB */
/* DNS resolve only for SOCKS4, not SOCKS4a */
if(!protocol4a) {
enum resolve_t rc =
- Curl_resolv(data, hostname, remote_port, FALSE, &dns);
+ Curl_resolv(data, sx->hostname, sx->remote_port, TRUE, &dns);
if(rc == CURLRESOLV_ERROR)
return CURLPX_RESOLVE_HOST;
else if(rc == CURLRESOLV_PENDING) {
- sxstate(data, CONNECT_RESOLVING);
- infof(data, "SOCKS4 non-blocking resolve of %s", hostname);
+ sxstate(sx, data, CONNECT_RESOLVING);
+ infof(data, "SOCKS4 non-blocking resolve of %s", sx->hostname);
return CURLPX_OK;
}
- sxstate(data, CONNECT_RESOLVED);
+ sxstate(sx, data, CONNECT_RESOLVED);
goto CONNECT_RESOLVED;
}
/* socks4a doesn't resolve anything locally */
- sxstate(data, CONNECT_REQ_INIT);
+ sxstate(sx, data, CONNECT_REQ_INIT);
goto CONNECT_REQ_INIT;
case CONNECT_RESOLVING:
/* check if we have the name resolved by now */
- dns = Curl_fetch_addr(data, hostname, (int)conn->port);
+ dns = Curl_fetch_addr(data, sx->hostname, (int)conn->port);
if(dns) {
#ifdef CURLRES_ASYNCH
data->state.async.dns = dns;
data->state.async.done = TRUE;
#endif
- infof(data, "Hostname '%s' was found", hostname);
- sxstate(data, CONNECT_RESOLVED);
+ infof(data, "Hostname '%s' was found", sx->hostname);
+ sxstate(sx, data, CONNECT_RESOLVED);
}
else {
result = Curl_resolv_check(data, &dns);
@@ -279,7 +354,7 @@
}
}
/* FALLTHROUGH */
- CONNECT_RESOLVED:
+CONNECT_RESOLVED:
case CONNECT_RESOLVED: {
struct Curl_addrinfo *hp = NULL;
/*
@@ -309,30 +384,30 @@
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
}
else
- failf(data, "SOCKS4 connection to %s not supported", hostname);
+ failf(data, "SOCKS4 connection to %s not supported", sx->hostname);
}
else
failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
- hostname);
+ sx->hostname);
if(!hp)
return CURLPX_RESOLVE_HOST;
}
/* FALLTHROUGH */
- CONNECT_REQ_INIT:
+CONNECT_REQ_INIT:
case CONNECT_REQ_INIT:
/*
* This is currently not supporting "Identification Protocol (RFC1413)".
*/
socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
- if(proxy_user) {
- size_t plen = strlen(proxy_user);
+ if(sx->proxy_user) {
+ size_t plen = strlen(sx->proxy_user);
if(plen >= (size_t)data->set.buffer_size - 8) {
failf(data, "Too long SOCKS proxy user name, can't use");
return CURLPX_LONG_USER;
}
/* copy the proxy name WITH trailing zero */
- memcpy(socksreq + 8, proxy_user, plen + 1);
+ memcpy(socksreq + 8, sx->proxy_user, plen + 1);
}
/*
@@ -350,9 +425,9 @@
socksreq[6] = 0;
socksreq[7] = 1;
/* append hostname */
- hostnamelen = strlen(hostname) + 1; /* length including NUL */
+ hostnamelen = strlen(sx->hostname) + 1; /* length including NUL */
if(hostnamelen <= 255)
- strcpy((char *)socksreq + packetsize, hostname);
+ strcpy((char *)socksreq + packetsize, sx->hostname);
else {
failf(data, "SOCKS4: too long host name");
return CURLPX_LONG_HOSTNAME;
@@ -361,51 +436,36 @@
}
sx->outp = socksreq;
sx->outstanding = packetsize;
- sxstate(data, CONNECT_REQ_SENDING);
+ sxstate(sx, data, CONNECT_REQ_SENDING);
}
/* FALLTHROUGH */
case CONNECT_REQ_SENDING:
/* Send request */
- result = Curl_write_plain(data, sockfd, (char *)sx->outp,
- sx->outstanding, &written);
- if(result && (CURLE_AGAIN != result)) {
- failf(data, "Failed to send SOCKS4 connect request.");
- return CURLPX_SEND_CONNECT;
- }
- if(written != sx->outstanding) {
- /* not done, remain in state */
- sx->outstanding -= written;
- sx->outp += written;
+ presult = socks_state_send(cf, sx, data, CURLPX_SEND_CONNECT,
+ "SOCKS4 connect request");
+ if(CURLPX_OK != presult)
+ return presult;
+ else if(sx->outstanding) {
+ /* remain in sending state */
return CURLPX_OK;
}
-
/* done sending! */
sx->outstanding = 8; /* receive data size */
sx->outp = socksreq;
- sxstate(data, CONNECT_SOCKS_READ);
+ sxstate(sx, data, CONNECT_SOCKS_READ);
/* FALLTHROUGH */
case CONNECT_SOCKS_READ:
/* Receive response */
- result = Curl_read_plain(sockfd, (char *)sx->outp,
- sx->outstanding, &actualread);
- if(result && (CURLE_AGAIN != result)) {
- failf(data, "SOCKS4: Failed receiving connect request ack: %s",
- curl_easy_strerror(result));
- return CURLPX_RECV_CONNECT;
- }
- else if(!result && !actualread) {
- /* connection closed */
- failf(data, "connection to proxy closed");
- return CURLPX_CLOSED;
- }
- else if(actualread != sx->outstanding) {
+ presult = socks_state_recv(cf, sx, data, CURLPX_RECV_CONNECT,
+ "connect request ack");
+ if(CURLPX_OK != presult)
+ return presult;
+ else if(sx->outstanding) {
/* remain in reading state */
- sx->outstanding -= actualread;
- sx->outp += actualread;
return CURLPX_OK;
}
- sxstate(data, CONNECT_DONE);
+ sxstate(sx, data, CONNECT_DONE);
break;
default: /* lots of unused states in SOCKS4 */
break;
@@ -478,7 +538,6 @@
return CURLPX_UNKNOWN_FAIL;
}
- *done = TRUE;
return CURLPX_OK; /* Proxy was successful! */
}
@@ -486,13 +545,9 @@
* This function logs in to a SOCKS5 proxy and sends the specifics to the final
* destination server.
*/
-CURLproxycode Curl_SOCKS5(const char *proxy_user,
- const char *proxy_password,
- const char *hostname,
- int remote_port,
- int sockindex,
- struct Curl_easy *data,
- bool *done)
+static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
+ struct socks_state *sx,
+ struct Curl_easy *data)
{
/*
According to the RFC1928, section "6. Replies". This is what a SOCK5
@@ -510,31 +565,25 @@
o REP Reply field:
o X'00' succeeded
*/
- struct connectdata *conn = data->conn;
+ struct connectdata *conn = cf->conn;
unsigned char *socksreq = (unsigned char *)data->state.buffer;
- char dest[256] = "unknown"; /* printable hostname:port */
int idx;
- ssize_t actualread;
- ssize_t written;
CURLcode result;
- curl_socket_t sockfd = conn->sock[sockindex];
+ CURLproxycode presult;
bool socks5_resolve_local =
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
- const size_t hostname_len = strlen(hostname);
+ const size_t hostname_len = strlen(sx->hostname);
ssize_t len = 0;
- const unsigned long auth = data->set.socks5auth;
+ const unsigned char auth = data->set.socks5auth;
bool allow_gssapi = FALSE;
- struct connstate *sx = &conn->cnnct;
struct Curl_dns_entry *dns = NULL;
- if(!SOCKS_STATE(sx->state) && !*done)
- sxstate(data, CONNECT_SOCKS_INIT);
-
+ DEBUGASSERT(auth & (CURLAUTH_BASIC | CURLAUTH_GSSAPI));
switch(sx->state) {
case CONNECT_SOCKS_INIT:
if(conn->bits.httpproxy)
infof(data, "SOCKS5: connecting to HTTP proxy %s port %d",
- hostname, remote_port);
+ sx->hostname, sx->remote_port);
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
if(!socks5_resolve_local && hostname_len > 255) {
@@ -545,11 +594,11 @@
if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
infof(data,
- "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu",
+ "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %u",
auth);
if(!(auth & CURLAUTH_BASIC))
/* disable username/password auth */
- proxy_user = NULL;
+ sx->proxy_user = NULL;
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
if(auth & CURLAUTH_GSSAPI)
allow_gssapi = TRUE;
@@ -561,59 +610,45 @@
socksreq[idx++] = 0; /* no authentication */
if(allow_gssapi)
socksreq[idx++] = 1; /* GSS-API */
- if(proxy_user)
+ if(sx->proxy_user)
socksreq[idx++] = 2; /* username/password */
/* write the number of authentication methods */
socksreq[1] = (unsigned char) (idx - 2);
- result = Curl_write_plain(data, sockfd, (char *)socksreq, idx, &written);
- if(result && (CURLE_AGAIN != result)) {
- failf(data, "Unable to send initial SOCKS5 request.");
- return CURLPX_SEND_CONNECT;
- }
- if(written != idx) {
- sxstate(data, CONNECT_SOCKS_SEND);
- sx->outstanding = idx - written;
- sx->outp = &socksreq[written];
+ sx->outp = socksreq;
+ sx->outstanding = idx;
+ presult = socks_state_send(cf, sx, data, CURLPX_SEND_CONNECT,
+ "initial SOCKS5 request");
+ if(CURLPX_OK != presult)
+ return presult;
+ else if(sx->outstanding) {
+ /* remain in sending state */
return CURLPX_OK;
}
- sxstate(data, CONNECT_SOCKS_READ);
+ sxstate(sx, data, CONNECT_SOCKS_READ);
goto CONNECT_SOCKS_READ_INIT;
case CONNECT_SOCKS_SEND:
- result = Curl_write_plain(data, sockfd, (char *)sx->outp,
- sx->outstanding, &written);
- if(result && (CURLE_AGAIN != result)) {
- failf(data, "Unable to send initial SOCKS5 request.");
- return CURLPX_SEND_CONNECT;
- }
- if(written != sx->outstanding) {
- /* not done, remain in state */
- sx->outstanding -= written;
- sx->outp += written;
+ presult = socks_state_send(cf, sx, data, CURLPX_SEND_CONNECT,
+ "initial SOCKS5 request");
+ if(CURLPX_OK != presult)
+ return presult;
+ else if(sx->outstanding) {
+ /* remain in sending state */
return CURLPX_OK;
}
/* FALLTHROUGH */
- CONNECT_SOCKS_READ_INIT:
+CONNECT_SOCKS_READ_INIT:
case CONNECT_SOCKS_READ_INIT:
sx->outstanding = 2; /* expect two bytes */
sx->outp = socksreq; /* store it here */
/* FALLTHROUGH */
case CONNECT_SOCKS_READ:
- result = Curl_read_plain(sockfd, (char *)sx->outp,
- sx->outstanding, &actualread);
- if(result && (CURLE_AGAIN != result)) {
- failf(data, "Unable to receive initial SOCKS5 response.");
- return CURLPX_RECV_CONNECT;
- }
- else if(!result && !actualread) {
- /* connection closed */
- failf(data, "Connection to proxy closed");
- return CURLPX_CLOSED;
- }
- else if(actualread != sx->outstanding) {
+ presult = socks_state_recv(cf, sx, data, CURLPX_RECV_CONNECT,
+ "initial SOCKS5 response");
+ if(CURLPX_OK != presult)
+ return presult;
+ else if(sx->outstanding) {
/* remain in reading state */
- sx->outstanding -= actualread;
- sx->outp += actualread;
return CURLPX_OK;
}
else if(socksreq[0] != 5) {
@@ -622,18 +657,18 @@
}
else if(socksreq[1] == 0) {
/* DONE! No authentication needed. Send request. */
- sxstate(data, CONNECT_REQ_INIT);
+ sxstate(sx, data, CONNECT_REQ_INIT);
goto CONNECT_REQ_INIT;
}
else if(socksreq[1] == 2) {
/* regular name + password authentication */
- sxstate(data, CONNECT_AUTH_INIT);
+ sxstate(sx, data, CONNECT_AUTH_INIT);
goto CONNECT_AUTH_INIT;
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
else if(allow_gssapi && (socksreq[1] == 1)) {
- sxstate(data, CONNECT_GSSAPI_INIT);
- result = Curl_SOCKS5_gssapi_negotiate(sockindex, data);
+ sxstate(sx, data, CONNECT_GSSAPI_INIT);
+ result = Curl_SOCKS5_gssapi_negotiate(cf, data);
if(result) {
failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
return CURLPX_GSSAPI;
@@ -664,13 +699,13 @@
default: /* do nothing! */
break;
- CONNECT_AUTH_INIT:
+CONNECT_AUTH_INIT:
case CONNECT_AUTH_INIT: {
/* Needs user name and password */
size_t proxy_user_len, proxy_password_len;
- if(proxy_user && proxy_password) {
- proxy_user_len = strlen(proxy_user);
- proxy_password_len = strlen(proxy_password);
+ if(sx->proxy_user && sx->proxy_password) {
+ proxy_user_len = strlen(sx->proxy_user);
+ proxy_password_len = strlen(sx->proxy_password);
}
else {
proxy_user_len = 0;
@@ -687,63 +722,50 @@
len = 0;
socksreq[len++] = 1; /* username/pw subnegotiation version */
socksreq[len++] = (unsigned char) proxy_user_len;
- if(proxy_user && proxy_user_len) {
+ if(sx->proxy_user && proxy_user_len) {
/* the length must fit in a single byte */
- if(proxy_user_len >= 255) {
+ if(proxy_user_len > 255) {
failf(data, "Excessive user name length for proxy auth");
return CURLPX_LONG_USER;
}
- memcpy(socksreq + len, proxy_user, proxy_user_len);
+ memcpy(socksreq + len, sx->proxy_user, proxy_user_len);
}
len += proxy_user_len;
socksreq[len++] = (unsigned char) proxy_password_len;
- if(proxy_password && proxy_password_len) {
+ if(sx->proxy_password && proxy_password_len) {
/* the length must fit in a single byte */
if(proxy_password_len > 255) {
failf(data, "Excessive password length for proxy auth");
return CURLPX_LONG_PASSWD;
}
- memcpy(socksreq + len, proxy_password, proxy_password_len);
+ memcpy(socksreq + len, sx->proxy_password, proxy_password_len);
}
len += proxy_password_len;
- sxstate(data, CONNECT_AUTH_SEND);
+ sxstate(sx, data, CONNECT_AUTH_SEND);
sx->outstanding = len;
sx->outp = socksreq;
}
/* FALLTHROUGH */
case CONNECT_AUTH_SEND:
- result = Curl_write_plain(data, sockfd, (char *)sx->outp,
- sx->outstanding, &written);
- if(result && (CURLE_AGAIN != result)) {
- failf(data, "Failed to send SOCKS5 sub-negotiation request.");
- return CURLPX_SEND_AUTH;
- }
- if(sx->outstanding != written) {
- /* remain in state */
- sx->outstanding -= written;
- sx->outp += written;
+ presult = socks_state_send(cf, sx, data, CURLPX_SEND_AUTH,
+ "SOCKS5 sub-negotiation request");
+ if(CURLPX_OK != presult)
+ return presult;
+ else if(sx->outstanding) {
+ /* remain in sending state */
return CURLPX_OK;
}
sx->outp = socksreq;
sx->outstanding = 2;
- sxstate(data, CONNECT_AUTH_READ);
+ sxstate(sx, data, CONNECT_AUTH_READ);
/* FALLTHROUGH */
case CONNECT_AUTH_READ:
- result = Curl_read_plain(sockfd, (char *)sx->outp,
- sx->outstanding, &actualread);
- if(result && (CURLE_AGAIN != result)) {
- failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
- return CURLPX_RECV_AUTH;
- }
- else if(!result && !actualread) {
- /* connection closed */
- failf(data, "connection to proxy closed");
- return CURLPX_CLOSED;
- }
- else if(actualread != sx->outstanding) {
- /* remain in state */
- sx->outstanding -= actualread;
- sx->outp += actualread;
+ presult = socks_state_recv(cf, sx, data, CURLPX_RECV_AUTH,
+ "SOCKS5 sub-negotiation response");
+ if(CURLPX_OK != presult)
+ return presult;
+ else if(sx->outstanding) {
+ /* remain in reading state */
return CURLPX_OK;
}
/* ignore the first (VER) byte */
@@ -754,36 +776,36 @@
}
/* Everything is good so far, user was authenticated! */
- sxstate(data, CONNECT_REQ_INIT);
+ sxstate(sx, data, CONNECT_REQ_INIT);
/* FALLTHROUGH */
- CONNECT_REQ_INIT:
+CONNECT_REQ_INIT:
case CONNECT_REQ_INIT:
if(socks5_resolve_local) {
- enum resolve_t rc = Curl_resolv(data, hostname, remote_port,
- FALSE, &dns);
+ enum resolve_t rc = Curl_resolv(data, sx->hostname, sx->remote_port,
+ TRUE, &dns);
if(rc == CURLRESOLV_ERROR)
return CURLPX_RESOLVE_HOST;
if(rc == CURLRESOLV_PENDING) {
- sxstate(data, CONNECT_RESOLVING);
+ sxstate(sx, data, CONNECT_RESOLVING);
return CURLPX_OK;
}
- sxstate(data, CONNECT_RESOLVED);
+ sxstate(sx, data, CONNECT_RESOLVED);
goto CONNECT_RESOLVED;
}
goto CONNECT_RESOLVE_REMOTE;
case CONNECT_RESOLVING:
/* check if we have the name resolved by now */
- dns = Curl_fetch_addr(data, hostname, remote_port);
+ dns = Curl_fetch_addr(data, sx->hostname, sx->remote_port);
if(dns) {
#ifdef CURLRES_ASYNCH
data->state.async.dns = dns;
data->state.async.done = TRUE;
#endif
- infof(data, "SOCKS5: hostname '%s' found", hostname);
+ infof(data, "SOCKS5: hostname '%s' found", sx->hostname);
}
if(!dns) {
@@ -795,21 +817,19 @@
}
}
/* FALLTHROUGH */
- CONNECT_RESOLVED:
+CONNECT_RESOLVED:
case CONNECT_RESOLVED: {
+ char dest[MAX_IPADR_LEN] = "unknown"; /* printable address */
struct Curl_addrinfo *hp = NULL;
- size_t destlen;
if(dns)
hp = dns->addr;
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
- hostname);
+ sx->hostname);
return CURLPX_RESOLVE_HOST;
}
Curl_printable_address(hp, dest, sizeof(dest));
- destlen = strlen(dest);
- msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", remote_port);
len = 0;
socksreq[len++] = 5; /* version (SOCKS5) */
@@ -825,7 +845,8 @@
socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i];
}
- infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)", dest);
+ infof(data, "SOCKS5 connect to %s:%d (locally resolved)", dest,
+ sx->remote_port);
}
#ifdef ENABLE_IPV6
else if(hp->ai_family == AF_INET6) {
@@ -839,7 +860,8 @@
((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i];
}
- infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)", dest);
+ infof(data, "SOCKS5 connect to [%s]:%d (locally resolved)", dest,
+ sx->remote_port);
}
#endif
else {
@@ -850,7 +872,7 @@
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
goto CONNECT_REQ_SEND;
}
- CONNECT_RESOLVE_REMOTE:
+CONNECT_RESOLVE_REMOTE:
case CONNECT_RESOLVE_REMOTE:
/* Authentication is complete, now specify destination to the proxy */
len = 0;
@@ -866,7 +888,7 @@
#ifdef ENABLE_IPV6
if(conn->bits.ipv6_ip) {
char ip6[16];
- if(1 != Curl_inet_pton(AF_INET6, hostname, ip6))
+ if(1 != Curl_inet_pton(AF_INET6, sx->hostname, ip6))
return CURLPX_BAD_ADDRESS_TYPE;
socksreq[len++] = 4;
memcpy(&socksreq[len], ip6, sizeof(ip6));
@@ -874,7 +896,7 @@
}
else
#endif
- if(1 == Curl_inet_pton(AF_INET, hostname, ip4)) {
+ if(1 == Curl_inet_pton(AF_INET, sx->hostname, ip4)) {
socksreq[len++] = 1;
memcpy(&socksreq[len], ip4, sizeof(ip4));
len += sizeof(ip4);
@@ -882,20 +904,20 @@
else {
socksreq[len++] = 3;
socksreq[len++] = (char) hostname_len; /* one byte address length */
- memcpy(&socksreq[len], hostname, hostname_len); /* address w/o NULL */
+ memcpy(&socksreq[len], sx->hostname, hostname_len); /* w/o NULL */
len += hostname_len;
}
infof(data, "SOCKS5 connect to %s:%d (remotely resolved)",
- hostname, remote_port);
+ sx->hostname, sx->remote_port);
}
/* FALLTHROUGH */
- CONNECT_REQ_SEND:
+CONNECT_REQ_SEND:
case CONNECT_REQ_SEND:
/* PORT MSB */
- socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff);
+ socksreq[len++] = (unsigned char)((sx->remote_port >> 8) & 0xff);
/* PORT LSB */
- socksreq[len++] = (unsigned char)(remote_port & 0xff);
+ socksreq[len++] = (unsigned char)(sx->remote_port & 0xff);
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
if(conn->socks5_gssapi_enctype) {
@@ -905,19 +927,15 @@
#endif
sx->outp = socksreq;
sx->outstanding = len;
- sxstate(data, CONNECT_REQ_SENDING);
+ sxstate(sx, data, CONNECT_REQ_SENDING);
/* FALLTHROUGH */
case CONNECT_REQ_SENDING:
- result = Curl_write_plain(data, sockfd, (char *)sx->outp,
- sx->outstanding, &written);
- if(result && (CURLE_AGAIN != result)) {
- failf(data, "Failed to send SOCKS5 connect request.");
- return CURLPX_SEND_REQUEST;
- }
- if(sx->outstanding != written) {
- /* remain in state */
- sx->outstanding -= written;
- sx->outp += written;
+ presult = socks_state_send(cf, sx, data, CURLPX_SEND_REQUEST,
+ "SOCKS5 connect request");
+ if(CURLPX_OK != presult)
+ return presult;
+ else if(sx->outstanding) {
+ /* remain in send state */
return CURLPX_OK;
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
@@ -928,28 +946,18 @@
#endif
sx->outstanding = 10; /* minimum packet size is 10 */
sx->outp = socksreq;
- sxstate(data, CONNECT_REQ_READ);
+ sxstate(sx, data, CONNECT_REQ_READ);
/* FALLTHROUGH */
case CONNECT_REQ_READ:
- result = Curl_read_plain(sockfd, (char *)sx->outp,
- sx->outstanding, &actualread);
- if(result && (CURLE_AGAIN != result)) {
- failf(data, "Failed to receive SOCKS5 connect request ack.");
- return CURLPX_RECV_REQACK;
- }
- else if(!result && !actualread) {
- /* connection closed */
- failf(data, "connection to proxy closed");
- return CURLPX_CLOSED;
- }
- else if(actualread != sx->outstanding) {
- /* remain in state */
- sx->outstanding -= actualread;
- sx->outp += actualread;
+ presult = socks_state_recv(cf, sx, data, CURLPX_RECV_REQACK,
+ "SOCKS5 connect request ack");
+ if(CURLPX_OK != presult)
+ return presult;
+ else if(sx->outstanding) {
+ /* remain in reading state */
return CURLPX_OK;
}
-
- if(socksreq[0] != 5) { /* version */
+ else if(socksreq[0] != 5) { /* version */
failf(data,
"SOCKS5 reply has wrong version, version should be 5.");
return CURLPX_BAD_VERSION;
@@ -958,7 +966,7 @@
CURLproxycode rc = CURLPX_REPLY_UNASSIGNED;
int code = socksreq[1];
failf(data, "Can't complete SOCKS5 connection to %s. (%d)",
- hostname, (unsigned char)socksreq[1]);
+ sx->hostname, (unsigned char)socksreq[1]);
if(code < 9) {
/* RFC 1928 section 6 lists: */
static const CURLproxycode lookup[] = {
@@ -1019,10 +1027,10 @@
if(len > 10) {
sx->outstanding = len - 10; /* get the rest */
sx->outp = &socksreq[10];
- sxstate(data, CONNECT_REQ_READ_MORE);
+ sxstate(sx, data, CONNECT_REQ_READ_MORE);
}
else {
- sxstate(data, CONNECT_DONE);
+ sxstate(sx, data, CONNECT_DONE);
break;
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
@@ -1030,29 +1038,216 @@
#endif
/* FALLTHROUGH */
case CONNECT_REQ_READ_MORE:
- result = Curl_read_plain(sockfd, (char *)sx->outp,
- sx->outstanding, &actualread);
- if(result && (CURLE_AGAIN != result)) {
- failf(data, "Failed to receive SOCKS5 connect request ack.");
- return CURLPX_RECV_ADDRESS;
- }
- else if(!result && !actualread) {
- /* connection closed */
- failf(data, "connection to proxy closed");
- return CURLPX_CLOSED;
- }
- else if(actualread != sx->outstanding) {
- /* remain in state */
- sx->outstanding -= actualread;
- sx->outp += actualread;
+ presult = socks_state_recv(cf, sx, data, CURLPX_RECV_ADDRESS,
+ "SOCKS5 connect request address");
+ if(CURLPX_OK != presult)
+ return presult;
+ else if(sx->outstanding) {
+ /* remain in reading state */
return CURLPX_OK;
}
- sxstate(data, CONNECT_DONE);
+ sxstate(sx, data, CONNECT_DONE);
}
infof(data, "SOCKS5 request granted.");
- *done = TRUE;
return CURLPX_OK; /* Proxy was successful! */
}
+static CURLcode connect_SOCKS(struct Curl_cfilter *cf,
+ struct socks_state *sxstate,
+ struct Curl_easy *data)
+{
+ CURLcode result = CURLE_OK;
+ CURLproxycode pxresult = CURLPX_OK;
+ struct connectdata *conn = cf->conn;
+
+ switch(conn->socks_proxy.proxytype) {
+ case CURLPROXY_SOCKS5:
+ case CURLPROXY_SOCKS5_HOSTNAME:
+ pxresult = do_SOCKS5(cf, sxstate, data);
+ break;
+
+ case CURLPROXY_SOCKS4:
+ case CURLPROXY_SOCKS4A:
+ pxresult = do_SOCKS4(cf, sxstate, data);
+ break;
+
+ default:
+ failf(data, "unknown proxytype option given");
+ result = CURLE_COULDNT_CONNECT;
+ } /* switch proxytype */
+ if(pxresult) {
+ result = CURLE_PROXY;
+ data->info.pxcode = pxresult;
+ }
+
+ return result;
+}
+
+static void socks_proxy_cf_free(struct Curl_cfilter *cf)
+{
+ struct socks_state *sxstate = cf->ctx;
+ if(sxstate) {
+ free(sxstate);
+ cf->ctx = NULL;
+ }
+}
+
+/* After a TCP connection to the proxy has been verified, this function does
+ the next magic steps. If 'done' isn't set TRUE, it is not done yet and
+ must be called again.
+
+ Note: this function's sub-functions call failf()
+
+*/
+static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ CURLcode result;
+ struct connectdata *conn = cf->conn;
+ int sockindex = cf->sockindex;
+ struct socks_state *sx = cf->ctx;
+
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ result = cf->next->cft->do_connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ return result;
+
+ if(!sx) {
+ sx = calloc(sizeof(*sx), 1);
+ if(!sx)
+ return CURLE_OUT_OF_MEMORY;
+ cf->ctx = sx;
+ }
+
+ if(sx->state == CONNECT_INIT) {
+ /* for the secondary socket (FTP), use the "connect to host"
+ * but ignore the "connect to port" (use the secondary port)
+ */
+ sxstate(sx, data, CONNECT_SOCKS_INIT);
+ sx->hostname =
+ conn->bits.httpproxy ?
+ conn->http_proxy.host.name :
+ conn->bits.conn_to_host ?
+ conn->conn_to_host.name :
+ sockindex == SECONDARYSOCKET ?
+ conn->secondaryhostname : conn->host.name;
+ sx->remote_port =
+ conn->bits.httpproxy ? (int)conn->http_proxy.port :
+ sockindex == SECONDARYSOCKET ? conn->secondary_port :
+ conn->bits.conn_to_port ? conn->conn_to_port :
+ conn->remote_port;
+ sx->proxy_user = conn->socks_proxy.user;
+ sx->proxy_password = conn->socks_proxy.passwd;
+ }
+
+ result = connect_SOCKS(cf, sx, data);
+ if(!result && sx->state == CONNECT_DONE) {
+ cf->connected = TRUE;
+ Curl_verboseconnect(data, conn);
+ socks_proxy_cf_free(cf);
+ }
+
+ *done = cf->connected;
+ return result;
+}
+
+static int socks_cf_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ struct socks_state *sx = cf->ctx;
+ int fds;
+
+ fds = cf->next->cft->get_select_socks(cf->next, data, socks);
+ if(!fds && cf->next->connected && !cf->connected && sx) {
+ /* If we are not connected, the filter below is and has nothing
+ * to wait on, we determine what to wait for. */
+ socks[0] = Curl_conn_cf_get_socket(cf, data);
+ switch(sx->state) {
+ case CONNECT_RESOLVING:
+ case CONNECT_SOCKS_READ:
+ case CONNECT_AUTH_READ:
+ case CONNECT_REQ_READ:
+ case CONNECT_REQ_READ_MORE:
+ fds = GETSOCK_READSOCK(0);
+ break;
+ default:
+ fds = GETSOCK_WRITESOCK(0);
+ break;
+ }
+ }
+ return fds;
+}
+
+static void socks_proxy_cf_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+
+ DEBUGASSERT(cf->next);
+ cf->connected = FALSE;
+ socks_proxy_cf_free(cf);
+ cf->next->cft->do_close(cf->next, data);
+}
+
+static void socks_proxy_cf_destroy(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ (void)data;
+ socks_proxy_cf_free(cf);
+}
+
+static void socks_cf_get_host(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char **phost,
+ const char **pdisplay_host,
+ int *pport)
+{
+ (void)data;
+ if(!cf->connected) {
+ *phost = cf->conn->socks_proxy.host.name;
+ *pdisplay_host = cf->conn->http_proxy.host.dispname;
+ *pport = (int)cf->conn->socks_proxy.port;
+ }
+ else {
+ cf->next->cft->get_host(cf->next, data, phost, pdisplay_host, pport);
+ }
+}
+
+struct Curl_cftype Curl_cft_socks_proxy = {
+ "SOCKS-PROXYY",
+ CF_TYPE_IP_CONNECT,
+ 0,
+ socks_proxy_cf_destroy,
+ socks_proxy_cf_connect,
+ socks_proxy_cf_close,
+ socks_cf_get_host,
+ socks_cf_get_select_socks,
+ Curl_cf_def_data_pending,
+ Curl_cf_def_send,
+ Curl_cf_def_recv,
+ Curl_cf_def_cntrl,
+ Curl_cf_def_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ Curl_cf_def_query,
+};
+
+CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result;
+
+ (void)data;
+ result = Curl_cf_create(&cf, &Curl_cft_socks_proxy, NULL);
+ if(!result)
+ Curl_conn_cf_insert_after(cf_at, cf);
+ return result;
+}
+
#endif /* CURL_DISABLE_PROXY */
diff --git a/lib/socks.h b/lib/socks.h
index ff83aa5..a3adcc6 100644
--- a/lib/socks.h
+++ b/lib/socks.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,46 +37,25 @@
*
* This is STUPID BLOCKING behavior
*/
-int Curl_blockread_all(struct Curl_easy *data,
- curl_socket_t sockfd,
+int Curl_blockread_all(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
char *buf,
ssize_t buffersize,
ssize_t *n);
-int Curl_SOCKS_getsock(struct connectdata *conn,
- curl_socket_t *sock,
- int sockindex);
-/*
- * This function logs in to a SOCKS4(a) proxy and sends the specifics to the
- * final destination server.
- */
-CURLproxycode Curl_SOCKS4(const char *proxy_name,
- const char *hostname,
- int remote_port,
- int sockindex,
- struct Curl_easy *data,
- bool *done);
-
-/*
- * This function logs in to a SOCKS5 proxy and sends the specifics to the
- * final destination server.
- */
-CURLproxycode Curl_SOCKS5(const char *proxy_name,
- const char *proxy_password,
- const char *hostname,
- int remote_port,
- int sockindex,
- struct Curl_easy *data,
- bool *done);
-
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
/*
* This function handles the SOCKS5 GSS-API negotiation and initialization
*/
-CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
+CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
struct Curl_easy *data);
#endif
+CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data);
+
+extern struct Curl_cftype Curl_cft_socks_proxy;
+
#endif /* CURL_DISABLE_PROXY */
#endif /* HEADER_CURL_SOCKS_H */
diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c
index f14099f..2ede8c7 100644
--- a/lib/socks_gssapi.c
+++ b/lib/socks_gssapi.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2012, Markus Moeller, <markus_moeller@compuserve.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Markus Moeller, <markus_moeller@compuserve.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,6 +30,7 @@
#include "curl_gssapi.h"
#include "urldata.h"
#include "sendf.h"
+#include "cfilters.h"
#include "connect.h"
#include "timeval.h"
#include "socks.h"
@@ -101,14 +102,14 @@
return 0;
}
-CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
+CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
- struct connectdata *conn = data->conn;
- curl_socket_t sock = conn->sock[sockindex];
+ struct connectdata *conn = cf->conn;
+ curl_socket_t sock = conn->sock[cf->sockindex];
CURLcode code;
ssize_t actualread;
- ssize_t written;
+ ssize_t nwritten;
int result;
OM_uint32 gss_major_status, gss_minor_status, gss_status;
OM_uint32 gss_ret_flags;
@@ -203,8 +204,8 @@
us_length = htons((short)gss_send_token.length);
memcpy(socksreq + 2, &us_length, sizeof(short));
- code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
- if(code || (4 != written)) {
+ nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, &code);
+ if(code || (4 != nwritten)) {
failf(data, "Failed to send GSS-API authentication request.");
gss_release_name(&gss_status, &server);
gss_release_buffer(&gss_status, &gss_recv_token);
@@ -213,10 +214,10 @@
return CURLE_COULDNT_CONNECT;
}
- code = Curl_write_plain(data, sock, (char *)gss_send_token.value,
- gss_send_token.length, &written);
-
- if(code || ((ssize_t)gss_send_token.length != written)) {
+ nwritten = Curl_conn_cf_send(cf->next, data,
+ (char *)gss_send_token.value,
+ gss_send_token.length, &code);
+ if(code || ((ssize_t)gss_send_token.length != nwritten)) {
failf(data, "Failed to send GSS-API authentication token.");
gss_release_name(&gss_status, &server);
gss_release_buffer(&gss_status, &gss_recv_token);
@@ -242,7 +243,7 @@
* +----+------+-----+----------------+
*/
- result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(cf, data, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive GSS-API authentication response.");
gss_release_name(&gss_status, &server);
@@ -281,7 +282,7 @@
return CURLE_OUT_OF_MEMORY;
}
- result = Curl_blockread_all(data, sock, (char *)gss_recv_token.value,
+ result = Curl_blockread_all(cf, data, (char *)gss_recv_token.value,
gss_recv_token.length, &actualread);
if(result || (actualread != us_length)) {
@@ -410,8 +411,8 @@
memcpy(socksreq + 2, &us_length, sizeof(short));
}
- code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
- if(code || (4 != written)) {
+ nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, &code);
+ if(code || (4 != nwritten)) {
failf(data, "Failed to send GSS-API encryption request.");
gss_release_buffer(&gss_status, &gss_w_token);
gss_delete_sec_context(&gss_status, &gss_context, NULL);
@@ -420,17 +421,18 @@
if(data->set.socks5_gssapi_nec) {
memcpy(socksreq, &gss_enc, 1);
- code = Curl_write_plain(data, sock, socksreq, 1, &written);
- if(code || ( 1 != written)) {
+ nwritten = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, &code);
+ if(code || ( 1 != nwritten)) {
failf(data, "Failed to send GSS-API encryption type.");
gss_delete_sec_context(&gss_status, &gss_context, NULL);
return CURLE_COULDNT_CONNECT;
}
}
else {
- code = Curl_write_plain(data, sock, (char *)gss_w_token.value,
- gss_w_token.length, &written);
- if(code || ((ssize_t)gss_w_token.length != written)) {
+ nwritten = Curl_conn_cf_send(cf->next, data,
+ (char *)gss_w_token.value,
+ gss_w_token.length, &code);
+ if(code || ((ssize_t)gss_w_token.length != nwritten)) {
failf(data, "Failed to send GSS-API encryption type.");
gss_release_buffer(&gss_status, &gss_w_token);
gss_delete_sec_context(&gss_status, &gss_context, NULL);
@@ -439,7 +441,7 @@
gss_release_buffer(&gss_status, &gss_w_token);
}
- result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(cf, data, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive GSS-API encryption response.");
gss_delete_sec_context(&gss_status, &gss_context, NULL);
@@ -470,7 +472,7 @@
gss_delete_sec_context(&gss_status, &gss_context, NULL);
return CURLE_OUT_OF_MEMORY;
}
- result = Curl_blockread_all(data, sock, (char *)gss_recv_token.value,
+ result = Curl_blockread_all(cf, data, (char *)gss_recv_token.value,
gss_recv_token.length, &actualread);
if(result || (actualread != us_length)) {
diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c
index 210a0df..d1200ea 100644
--- a/lib/socks_sspi.c
+++ b/lib/socks_sspi.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2012, 2011, Markus Moeller, <markus_moeller@compuserve.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Markus Moeller, <markus_moeller@compuserve.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,6 +29,7 @@
#include "urldata.h"
#include "sendf.h"
+#include "cfilters.h"
#include "connect.h"
#include "strerror.h"
#include "timeval.h"
@@ -62,11 +63,11 @@
}
/* This is the SSPI-using version of this function */
-CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
+CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
- struct connectdata *conn = data->conn;
- curl_socket_t sock = conn->sock[sockindex];
+ struct connectdata *conn = cf->conn;
+ curl_socket_t sock = conn->sock[cf->sockindex];
CURLcode code;
ssize_t actualread;
ssize_t written;
@@ -206,7 +207,7 @@
us_length = htons((short)sspi_send_token.cbBuffer);
memcpy(socksreq + 2, &us_length, sizeof(short));
- code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
+ written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, &code);
if(code || (4 != written)) {
failf(data, "Failed to send SSPI authentication request.");
free(service_name);
@@ -219,8 +220,9 @@
return CURLE_COULDNT_CONNECT;
}
- code = Curl_write_plain(data, sock, (char *)sspi_send_token.pvBuffer,
- sspi_send_token.cbBuffer, &written);
+ written = Curl_conn_cf_send(cf->next, data,
+ (char *)sspi_send_token.pvBuffer,
+ sspi_send_token.cbBuffer, &code);
if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
failf(data, "Failed to send SSPI authentication token.");
free(service_name);
@@ -260,7 +262,7 @@
* +----+------+-----+----------------+
*/
- result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(cf, data, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive SSPI authentication response.");
free(service_name);
@@ -300,7 +302,7 @@
s_pSecFn->DeleteSecurityContext(&sspi_context);
return CURLE_OUT_OF_MEMORY;
}
- result = Curl_blockread_all(data, sock, (char *)sspi_recv_token.pvBuffer,
+ result = Curl_blockread_all(cf, data, (char *)sspi_recv_token.pvBuffer,
sspi_recv_token.cbBuffer, &actualread);
if(result || (actualread != us_length)) {
@@ -468,7 +470,7 @@
memcpy(socksreq + 2, &us_length, sizeof(short));
}
- code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
+ written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, &code);
if(code || (4 != written)) {
failf(data, "Failed to send SSPI encryption request.");
if(sspi_send_token.pvBuffer)
@@ -479,7 +481,7 @@
if(data->set.socks5_gssapi_nec) {
memcpy(socksreq, &gss_enc, 1);
- code = Curl_write_plain(data, sock, (char *)socksreq, 1, &written);
+ written = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, &code);
if(code || (1 != written)) {
failf(data, "Failed to send SSPI encryption type.");
s_pSecFn->DeleteSecurityContext(&sspi_context);
@@ -487,8 +489,9 @@
}
}
else {
- code = Curl_write_plain(data, sock, (char *)sspi_send_token.pvBuffer,
- sspi_send_token.cbBuffer, &written);
+ written = Curl_conn_cf_send(cf->next, data,
+ (char *)sspi_send_token.pvBuffer,
+ sspi_send_token.cbBuffer, &code);
if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
failf(data, "Failed to send SSPI encryption type.");
if(sspi_send_token.pvBuffer)
@@ -500,7 +503,7 @@
s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
}
- result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(cf, data, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive SSPI encryption response.");
s_pSecFn->DeleteSecurityContext(&sspi_context);
@@ -532,7 +535,7 @@
return CURLE_OUT_OF_MEMORY;
}
- result = Curl_blockread_all(data, sock, (char *)sspi_w_token[0].pvBuffer,
+ result = Curl_blockread_all(cf, data, (char *)sspi_w_token[0].pvBuffer,
sspi_w_token[0].cbBuffer, &actualread);
if(result || (actualread != us_length)) {
diff --git a/lib/speedcheck.c b/lib/speedcheck.c
index 3ddc43d..580efbd 100644
--- a/lib/speedcheck.c
+++ b/lib/speedcheck.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/speedcheck.h b/lib/speedcheck.h
index cb44eb0..bff2f32 100644
--- a/lib/speedcheck.h
+++ b/lib/speedcheck.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/splay.c b/lib/splay.c
index e7d86f1..48e079b 100644
--- a/lib/splay.c
+++ b/lib/splay.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1997 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -103,7 +103,7 @@
struct Curl_tree *node)
{
static const struct curltime KEY_NOTUSED = {
- (time_t)-1, (unsigned int)-1
+ ~0, -1
}; /* will *NEVER* appear */
if(!node)
@@ -213,7 +213,7 @@
struct Curl_tree **newroot)
{
static const struct curltime KEY_NOTUSED = {
- (time_t)-1, (unsigned int)-1
+ ~0, -1
}; /* will *NEVER* appear */
struct Curl_tree *x;
diff --git a/lib/splay.h b/lib/splay.h
index 015e2ca..dd1d07a 100644
--- a/lib/splay.h
+++ b/lib/splay.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1997 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/strcase.c b/lib/strcase.c
index f932485..7c0b4ef 100644
--- a/lib/strcase.c
+++ b/lib/strcase.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,8 +28,6 @@
#include "strcase.h"
-static char raw_tolower(char in);
-
/* 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,
@@ -79,22 +77,19 @@
/* Portable, consistent tolower. Do not use tolower() because its behavior is
altered by the current locale. */
-static char raw_tolower(char in)
+char Curl_raw_tolower(char in)
{
return tolowermap[(unsigned char) in];
}
/*
- * Curl_strcasecompare() is for doing "raw" case insensitive strings. This is
- * meant to be locale independent and only compare strings we know are safe
- * for this. See
- * https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for some
- * further explanation to why this function is necessary.
- *
- * @unittest: 1301
+ * curl_strequal() is for doing "raw" case insensitive strings. This is meant
+ * to be locale independent and only compare strings we know are safe for
+ * this. See https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
+ * further explanations as to why this function is necessary.
*/
-int Curl_strcasecompare(const char *first, const char *second)
+static int casecompare(const char *first, const char *second)
{
while(*first && *second) {
if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
@@ -110,25 +105,22 @@
return !*first == !*second;
}
-int Curl_safe_strcasecompare(const char *first, const char *second)
+/* --- public function --- */
+int curl_strequal(const char *first, const char *second)
{
if(first && second)
/* both pointers point to something then compare them */
- return Curl_strcasecompare(first, second);
+ return casecompare(first, second);
/* if both pointers are NULL then treat them as equal */
return (NULL == first && NULL == second);
}
-/*
- * @unittest: 1301
- */
-int Curl_strncasecompare(const char *first, const char *second, size_t max)
+static int ncasecompare(const char *first, const char *second, size_t max)
{
while(*first && *second && max) {
- if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
- break;
- }
+ if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
+ return 0;
max--;
first++;
second++;
@@ -139,6 +131,16 @@
return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
}
+/* --- public function --- */
+int curl_strnequal(const char *first, const char *second, size_t max)
+{
+ if(first && second)
+ /* both pointers point to something then compare them */
+ return ncasecompare(first, second, max);
+
+ /* if both pointers are NULL then treat them as equal if max is non-zero */
+ return (NULL == first && NULL == second && max);
+}
/* Copy an upper case version of the string from src to dest. The
* strings may overlap. No more than n characters of the string are copied
* (including any NUL) and the destination string will NOT be
@@ -165,7 +167,7 @@
return;
do {
- *dest++ = raw_tolower(*src);
+ *dest++ = Curl_raw_tolower(*src);
} while(*src++ && --n);
}
@@ -179,13 +181,24 @@
return !a && !b;
}
-/* --- public functions --- */
+/*
+ * Curl_timestrcmp() returns 0 if the two strings are identical. The time this
+ * function spends is a function of the shortest string, not of the contents.
+ */
+int Curl_timestrcmp(const char *a, const char *b)
+{
+ int match = 0;
+ int i = 0;
-int curl_strequal(const char *first, const char *second)
-{
- return Curl_strcasecompare(first, second);
-}
-int curl_strnequal(const char *first, const char *second, size_t max)
-{
- return Curl_strncasecompare(first, second, max);
+ if(a && b) {
+ while(1) {
+ match |= a[i]^b[i];
+ if(!a[i] || !b[i])
+ break;
+ i++;
+ }
+ }
+ else
+ return a || b;
+ return match;
}
diff --git a/lib/strcase.h b/lib/strcase.h
index d245929..8c50bbc 100644
--- a/lib/strcase.h
+++ b/lib/strcase.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,14 +35,11 @@
* Result is 1 if text matches and 0 if not.
*/
-#define strcasecompare(a,b) Curl_strcasecompare(a,b)
-#define strncasecompare(a,b,c) Curl_strncasecompare(a,b,c)
-
-int Curl_strcasecompare(const char *first, const char *second);
-int Curl_safe_strcasecompare(const char *first, const char *second);
-int Curl_strncasecompare(const char *first, const char *second, size_t max);
+#define strcasecompare(a,b) curl_strequal(a,b)
+#define strncasecompare(a,b,c) curl_strnequal(a,b,c)
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 */
@@ -52,5 +49,6 @@
void Curl_strntolower(char *dest, const char *src, size_t n);
bool Curl_safecmp(char *a, char *b);
+int Curl_timestrcmp(const char *first, const char *second);
#endif /* HEADER_CURL_STRCASE_H */
diff --git a/lib/strdup.c b/lib/strdup.c
index ac22b6d..07a6139 100644
--- a/lib/strdup.c
+++ b/lib/strdup.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@
#include "memdebug.h"
#ifndef HAVE_STRDUP
-char *curlx_strdup(const char *str)
+char *Curl_strdup(const char *str)
{
size_t len;
char *newstr;
diff --git a/lib/strdup.h b/lib/strdup.h
index fb46808..c3430b5 100644
--- a/lib/strdup.h
+++ b/lib/strdup.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,7 +26,7 @@
#include "curl_setup.h"
#ifndef HAVE_STRDUP
-extern char *curlx_strdup(const char *str);
+char *Curl_strdup(const char *str);
#endif
#ifdef WIN32
wchar_t* Curl_wcsdup(const wchar_t* src);
diff --git a/lib/strerror.c b/lib/strerror.c
index be43fd6..bd9cc53 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2004 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -181,13 +181,13 @@
case CURLE_INTERFACE_FAILED:
return "Failed binding local connection end";
- case CURLE_TOO_MANY_REDIRECTS :
+ case CURLE_TOO_MANY_REDIRECTS:
return "Number of redirects hit maximum amount";
case CURLE_UNKNOWN_OPTION:
return "An unknown option was passed in to libcurl";
- case CURLE_SETOPT_OPTION_SYNTAX :
+ case CURLE_SETOPT_OPTION_SYNTAX:
return "Malformed option provided in a setopt";
case CURLE_GOT_NOTHING:
@@ -265,9 +265,6 @@
case CURLE_TFTP_NOSUCHUSER:
return "TFTP: No such user";
- case CURLE_CONV_FAILED:
- return "Conversion failed";
-
case CURLE_REMOTE_FILE_NOT_FOUND:
return "Remote file not found";
@@ -334,6 +331,7 @@
case CURLE_OBSOLETE51:
case CURLE_OBSOLETE57:
case CURLE_OBSOLETE62:
+ case CURLE_OBSOLETE75:
case CURLE_OBSOLETE76:
case CURL_LAST:
break;
@@ -478,7 +476,7 @@
return "Port number was not a decimal number between 0 and 65535";
case CURLUE_UNSUPPORTED_SCHEME:
- return "This libcurl build doesn't support the given URL scheme";
+ return "Unsupported URL scheme";
case CURLUE_URLDECODE:
return "URL decode error, most likely because of rubbish in the input";
@@ -532,7 +530,7 @@
return "Bad file:// URL";
case CURLUE_BAD_SLASHES:
- return "Unsupported number of slashes";
+ return "Unsupported number of slashes following scheme";
case CURLUE_BAD_SCHEME:
return "Bad scheme";
@@ -552,6 +550,9 @@
case CURLUE_BAD_USER:
return "Bad user";
+ case CURLUE_LACKS_IDN:
+ return "libcurl lacks IDN support";
+
case CURLUE_LAST:
break;
}
diff --git a/lib/strerror.h b/lib/strerror.h
index 658f16c..399712f 100644
--- a/lib/strerror.h
+++ b/lib/strerror.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/strtok.c b/lib/strtok.c
index 6120bcc..d8e1e81 100644
--- a/lib/strtok.c
+++ b/lib/strtok.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/strtok.h b/lib/strtok.h
index 641a3da..321cba2 100644
--- a/lib/strtok.h
+++ b/lib/strtok.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/strtoofft.c b/lib/strtoofft.c
index 30908fd..077b257 100644
--- a/lib/strtoofft.c
+++ b/lib/strtoofft.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -87,7 +87,7 @@
/* Skip leading whitespace. */
end = (char *)nptr;
- while(ISSPACE(end[0])) {
+ while(ISBLANK(end[0])) {
end++;
}
@@ -221,10 +221,11 @@
curl_off_t number;
errno = 0;
*num = 0; /* clear by default */
+ DEBUGASSERT(base); /* starting now, avoid base zero */
- while(*str && ISSPACE(*str))
+ while(*str && ISBLANK(*str))
str++;
- if('-' == *str) {
+ if(('-' == *str) || (ISSPACE(*str))) {
if(endp)
*endp = (char *)str; /* didn't actually move */
return CURL_OFFT_INVAL; /* nothing parsed */
diff --git a/lib/strtoofft.h b/lib/strtoofft.h
index 311dae4..34d293b 100644
--- a/lib/strtoofft.h
+++ b/lib/strtoofft.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/system_win32.c b/lib/system_win32.c
index bede9c7..0cdaf3b 100644
--- a/lib/system_win32.c
+++ b/lib/system_win32.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2016 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/system_win32.h b/lib/system_win32.h
index 167804e..24899cb 100644
--- a/lib/system_win32.h
+++ b/lib/system_win32.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2016 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/telnet.c b/lib/telnet.c
index 923c7f8..1d7a592 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -571,7 +571,7 @@
sendsuboption(data, option);
}
else if(tn->subnegotiation[option] == CURL_YES) {
- /* send information to achieve this option*/
+ /* send information to achieve this option */
tn->us[option] = CURL_YES;
send_negotiation(data, CURL_WILL, option);
sendsuboption(data, option);
@@ -770,22 +770,39 @@
}
}
+#ifdef _MSC_VER
+#pragma warning(push)
+/* warning C4706: assignment within conditional expression */
+#pragma warning(disable:4706)
+#endif
+static bool str_is_nonascii(const char *str)
+{
+ char c;
+ while((c = *str++))
+ if(c & 0x80)
+ return TRUE;
+
+ return FALSE;
+}
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
static CURLcode check_telnet_options(struct Curl_easy *data)
{
struct curl_slist *head;
struct curl_slist *beg;
- char option_keyword[128] = "";
- char option_arg[256] = "";
struct TELNET *tn = data->req.p.telnet;
- struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
- int binary_option;
/* Add the user name as an environment variable if it
was given on the command line */
if(data->state.aptr.user) {
- msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
- beg = curl_slist_append(tn->telnet_vars, option_arg);
+ char buffer[256];
+ if(str_is_nonascii(data->conn->user))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ msnprintf(buffer, sizeof(buffer), "USER,%s", data->conn->user);
+ beg = curl_slist_append(tn->telnet_vars, buffer);
if(!beg) {
curl_slist_free_all(tn->telnet_vars);
tn->telnet_vars = NULL;
@@ -795,68 +812,100 @@
tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
}
- for(head = data->set.telnet_options; head; head = head->next) {
- if(sscanf(head->data, "%127[^= ]%*[ =]%255s",
- option_keyword, option_arg) == 2) {
-
- /* Terminal type */
- if(strcasecompare(option_keyword, "TTYPE")) {
- strncpy(tn->subopt_ttype, option_arg, 31);
- tn->subopt_ttype[31] = 0; /* String termination */
- tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
+ for(head = data->set.telnet_options; head && !result; head = head->next) {
+ size_t olen;
+ char *option = head->data;
+ char *arg;
+ char *sep = strchr(option, '=');
+ if(sep) {
+ olen = sep - option;
+ arg = ++sep;
+ if(str_is_nonascii(arg))
continue;
- }
-
- /* Display variable */
- if(strcasecompare(option_keyword, "XDISPLOC")) {
- strncpy(tn->subopt_xdisploc, option_arg, 127);
- tn->subopt_xdisploc[127] = 0; /* String termination */
- tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
- continue;
- }
-
- /* Environment variable */
- if(strcasecompare(option_keyword, "NEW_ENV")) {
- beg = curl_slist_append(tn->telnet_vars, option_arg);
- if(!beg) {
- result = CURLE_OUT_OF_MEMORY;
- break;
+ switch(olen) {
+ case 5:
+ /* Terminal type */
+ if(strncasecompare(option, "TTYPE", 5)) {
+ strncpy(tn->subopt_ttype, arg, 31);
+ tn->subopt_ttype[31] = 0; /* String termination */
+ tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
}
- tn->telnet_vars = beg;
- tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
- continue;
- }
+ else
+ result = CURLE_UNKNOWN_OPTION;
+ break;
- /* Window Size */
- if(strcasecompare(option_keyword, "WS")) {
- if(sscanf(option_arg, "%hu%*[xX]%hu",
- &tn->subopt_wsx, &tn->subopt_wsy) == 2)
- tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES;
- else {
- failf(data, "Syntax error in telnet option: %s", head->data);
- result = CURLE_SETOPT_OPTION_SYNTAX;
- break;
+ case 8:
+ /* Display variable */
+ if(strncasecompare(option, "XDISPLOC", 8)) {
+ strncpy(tn->subopt_xdisploc, arg, 127);
+ tn->subopt_xdisploc[127] = 0; /* String termination */
+ tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
}
- continue;
- }
+ else
+ result = CURLE_UNKNOWN_OPTION;
+ break;
- /* To take care or not of the 8th bit in data exchange */
- if(strcasecompare(option_keyword, "BINARY")) {
- binary_option = atoi(option_arg);
- if(binary_option != 1) {
- tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO;
- tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO;
+ case 7:
+ /* Environment variable */
+ if(strncasecompare(option, "NEW_ENV", 7)) {
+ beg = curl_slist_append(tn->telnet_vars, arg);
+ if(!beg) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ tn->telnet_vars = beg;
+ tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
}
- continue;
- }
+ else
+ result = CURLE_UNKNOWN_OPTION;
+ break;
- failf(data, "Unknown telnet option %s", head->data);
- result = CURLE_UNKNOWN_OPTION;
- break;
+ case 2:
+ /* Window Size */
+ if(strncasecompare(option, "WS", 2)) {
+ char *p;
+ unsigned long x = strtoul(arg, &p, 10);
+ unsigned long y = 0;
+ if(x && (x <= 0xffff) && Curl_raw_tolower(*p) == 'x') {
+ p++;
+ y = strtoul(p, NULL, 10);
+ if(y && (y <= 0xffff)) {
+ tn->subopt_wsx = (unsigned short)x;
+ tn->subopt_wsy = (unsigned short)y;
+ tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES;
+ }
+ }
+ if(!y) {
+ failf(data, "Syntax error in telnet option: %s", head->data);
+ result = CURLE_SETOPT_OPTION_SYNTAX;
+ }
+ }
+ else
+ result = CURLE_UNKNOWN_OPTION;
+ break;
+
+ case 6:
+ /* To take care or not of the 8th bit in data exchange */
+ if(strncasecompare(option, "BINARY", 6)) {
+ int binary_option = atoi(arg);
+ if(binary_option != 1) {
+ tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO;
+ tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO;
+ }
+ }
+ else
+ result = CURLE_UNKNOWN_OPTION;
+ break;
+ default:
+ failf(data, "Unknown telnet option %s", head->data);
+ result = CURLE_UNKNOWN_OPTION;
+ break;
+ }
}
- failf(data, "Syntax error in telnet option: %s", head->data);
- result = CURLE_SETOPT_OPTION_SYNTAX;
- break;
+ else {
+ failf(data, "Syntax error in telnet option: %s", head->data);
+ result = CURLE_SETOPT_OPTION_SYNTAX;
+ }
}
if(result) {
@@ -881,8 +930,6 @@
ssize_t bytes_written;
size_t len;
int err;
- char varname[128] = "";
- char varval[128] = "";
struct TELNET *tn = data->req.p.telnet;
struct connectdata *conn = data->conn;
@@ -920,19 +967,18 @@
for(v = tn->telnet_vars; v; v = v->next) {
size_t tmplen = (strlen(v->data) + 1);
- /* Add the variable only if it fits */
+ /* Add the variable if it fits */
if(len + tmplen < (int)sizeof(temp)-6) {
- int rv;
- char sep[2] = "";
- varval[0] = 0;
- rv = sscanf(v->data, "%127[^,]%1[,]%127s", varname, sep, varval);
- if(rv == 1)
+ char *s = strchr(v->data, ',');
+ if(!s)
len += msnprintf((char *)&temp[len], sizeof(temp) - len,
- "%c%s", CURL_NEW_ENV_VAR, varname);
- else if(rv >= 2)
+ "%c%s", CURL_NEW_ENV_VAR, v->data);
+ else {
+ size_t vlen = s - v->data;
len += msnprintf((char *)&temp[len], sizeof(temp) - len,
- "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
- CURL_NEW_ENV_VALUE, varval);
+ "%c%.*s%c%s", CURL_NEW_ENV_VAR,
+ (int)vlen, v->data, CURL_NEW_ENV_VALUE, ++s);
+ }
}
}
msnprintf((char *)&temp[len], sizeof(temp) - len,
@@ -1064,7 +1110,7 @@
break;
case CURL_TS_IAC:
- process_iac:
+process_iac:
DEBUGASSERT(startwrite < 0);
switch(c) {
case CURL_WILL:
@@ -1200,7 +1246,7 @@
j = 0;
for(i = 0; i < nread; i++) {
- outbuf[j++] = buffer[i];
+ outbuf[j++] = (unsigned char)buffer[i];
if((unsigned char)buffer[i] == CURL_IAC)
outbuf[j++] = CURL_IAC;
}
@@ -1248,9 +1294,6 @@
curl_slist_free_all(tn->telnet_vars);
tn->telnet_vars = NULL;
-
- Curl_safefree(data->req.p.telnet);
-
return CURLE_OK;
}
@@ -1491,6 +1534,7 @@
}
while(keepon) {
+ DEBUGF(infof(data, "telnet_do, poll %d fds", poll_cnt));
switch(Curl_poll(pfd, poll_cnt, interval_ms)) {
case -1: /* error, stop reading */
keepon = FALSE;
@@ -1509,6 +1553,13 @@
/* returned not-zero, this an error */
if(result) {
keepon = FALSE;
+ /* TODO: in test 1452, macOS sees a ECONNRESET sometimes?
+ * Is this the telnet test server not shutting down the socket
+ * in a clean way? Seems to be timing related, happens more
+ * on slow debug build */
+ if(data->state.os_errno == ECONNRESET) {
+ DEBUGF(infof(data, "telnet_do, unexpected ECONNRESET on recv"));
+ }
break;
}
/* returned zero but actually received 0 or less here,
diff --git a/lib/telnet.h b/lib/telnet.h
index 6dd99b4..30782d8 100644
--- a/lib/telnet.h
+++ b/lib/telnet.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/tftp.c b/lib/tftp.c
index 9e6d949..8ed1b88 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,6 +48,7 @@
#include "urldata.h"
#include <curl/curl.h>
+#include "cf-socket.h"
#include "transfer.h"
#include "sendf.h"
#include "tftp.h"
@@ -369,7 +370,7 @@
/* tsize should be ignored on upload: Who cares about the size of the
remote file? */
- if(!data->set.upload) {
+ if(!data->state.upload) {
if(!tsize) {
failf(data, "invalid tsize -:%s:- value in OACK packet", value);
return CURLE_TFTP_ILLEGAL;
@@ -450,7 +451,7 @@
return result;
}
- if(data->set.upload) {
+ if(data->state.upload) {
/* If we are uploading, send an WRQ */
setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
state->data->req.upload_fromhere =
@@ -485,7 +486,7 @@
if(!data->set.tftp_no_options) {
char buf[64];
/* add tsize option */
- if(data->set.upload && (data->state.infilesize != -1))
+ if(data->state.upload && (data->state.infilesize != -1))
msnprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
data->state.infilesize);
else
@@ -529,8 +530,8 @@
not have a size_t argument, like older unixes that want an 'int' */
senddata = sendto(state->sockfd, (void *)state->spacket.data,
(SEND_TYPE_ARG3)sbytes, 0,
- data->conn->ip_addr->ai_addr,
- data->conn->ip_addr->ai_addrlen);
+ &data->conn->remote_addr->sa_addr,
+ data->conn->remote_addr->addrlen);
if(senddata != (ssize_t)sbytes) {
char buffer[STRERROR_LEN];
failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
@@ -539,7 +540,7 @@
break;
case TFTP_EVENT_OACK:
- if(data->set.upload) {
+ if(data->state.upload) {
result = tftp_connect_for_tx(state, event);
}
else {
@@ -1014,7 +1015,7 @@
state->requested_blksize = blksize;
((struct sockaddr *)&state->local_addr)->sa_family =
- (CURL_SA_FAMILY_T)(conn->ip_addr->ai_family);
+ (CURL_SA_FAMILY_T)(conn->remote_addr->family);
tftp_set_timeouts(state);
@@ -1033,7 +1034,7 @@
* IPv4 and IPv6...
*/
int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
- conn->ip_addr->ai_addrlen);
+ conn->remote_addr->addrlen);
if(rc) {
char buffer[STRERROR_LEN];
failf(data, "bind() failed; %s",
diff --git a/lib/tftp.h b/lib/tftp.h
index 3f1fda6..5d2d5da 100644
--- a/lib/tftp.h
+++ b/lib/tftp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/timediff.c b/lib/timediff.c
index 27fd911..1b762bb 100644
--- a/lib/timediff.c
+++ b/lib/timediff.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,6 +24,8 @@
#include "timediff.h"
+#include <limits.h>
+
/*
* Converts number of milliseconds into a timeval structure.
*
diff --git a/lib/timediff.h b/lib/timediff.h
index 90e5474..fb318d4 100644
--- a/lib/timediff.h
+++ b/lib/timediff.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/timeval.c b/lib/timeval.c
index 647d7b0..2de79be 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -58,7 +58,8 @@
return now;
}
-#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
+#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) || \
+ defined(HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
struct curltime Curl_now(void)
{
@@ -87,6 +88,19 @@
have_clock_gettime = TRUE;
#endif
+#ifdef HAVE_CLOCK_GETTIME_MONOTONIC_RAW
+ if(
+#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \
+ (HAVE_BUILTIN_AVAILABLE == 1)
+ have_clock_gettime &&
+#endif
+ (0 == clock_gettime(CLOCK_MONOTONIC_RAW, &tsnow))) {
+ cnow.tv_sec = tsnow.tv_sec;
+ cnow.tv_usec = (unsigned int)(tsnow.tv_nsec / 1000);
+ }
+ else
+#endif
+
if(
#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \
(HAVE_BUILTIN_AVAILABLE == 1)
diff --git a/lib/timeval.h b/lib/timeval.h
index 8d4fef4..92e484a 100644
--- a/lib/timeval.h
+++ b/lib/timeval.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/transfer.c b/lib/transfer.c
index 1720b24..b678004 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -64,6 +64,7 @@
#include "content_encoding.h"
#include "hostip.h"
+#include "cfilters.h"
#include "transfer.h"
#include "sendf.h"
#include "speedcheck.h"
@@ -72,6 +73,7 @@
#include "url.h"
#include "getinfo.h"
#include "vtls/vtls.h"
+#include "vquic/vquic.h"
#include "select.h"
#include "multiif.h"
#include "connect.h"
@@ -362,114 +364,17 @@
return CURLE_OK;
}
-
-/*
- * Curl_readrewind() rewinds the read stream. This is typically used for HTTP
- * POST/PUT with multi-pass authentication when a sending was denied and a
- * resend is necessary.
- */
-CURLcode Curl_readrewind(struct Curl_easy *data)
+static int data_pending(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
- curl_mimepart *mimepart = &data->set.mimepost;
-
- conn->bits.rewindaftersend = FALSE; /* we rewind now */
-
- /* explicitly switch off sending data on this connection now since we are
- about to restart a new transfer and thus we want to avoid inadvertently
- sending more data on the existing connection until the next transfer
- starts */
- data->req.keepon &= ~KEEP_SEND;
-
- /* We have sent away data. If not using CURLOPT_POSTFIELDS or
- CURLOPT_HTTPPOST, call app to rewind
- */
- if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
- struct HTTP *http = data->req.p.http;
-
- if(http->sendit)
- mimepart = http->sendit;
- }
- if(data->set.postfields)
- ; /* do nothing */
- else if(data->state.httpreq == HTTPREQ_POST_MIME ||
- data->state.httpreq == HTTPREQ_POST_FORM) {
- CURLcode result = Curl_mime_rewind(mimepart);
- if(result) {
- failf(data, "Cannot rewind mime/post data");
- return result;
- }
- }
- else {
- if(data->set.seek_func) {
- int err;
-
- Curl_set_in_callback(data, true);
- err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
- Curl_set_in_callback(data, false);
- if(err) {
- failf(data, "seek callback returned error %d", (int)err);
- return CURLE_SEND_FAIL_REWIND;
- }
- }
- else if(data->set.ioctl_func) {
- curlioerr err;
-
- Curl_set_in_callback(data, true);
- err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
- data->set.ioctl_client);
- Curl_set_in_callback(data, false);
- infof(data, "the ioctl callback returned %d", (int)err);
-
- if(err) {
- failf(data, "ioctl callback returned error %d", (int)err);
- return CURLE_SEND_FAIL_REWIND;
- }
- }
- else {
- /* If no CURLOPT_READFUNCTION is used, we know that we operate on a
- given FILE * stream and we can actually attempt to rewind that
- ourselves with fseek() */
- if(data->state.fread_func == (curl_read_callback)fread) {
- if(-1 != fseek(data->state.in, 0, SEEK_SET))
- /* successful rewind */
- return CURLE_OK;
- }
-
- /* no callback set or failure above, makes us fail at once */
- failf(data, "necessary data rewind wasn't possible");
- return CURLE_SEND_FAIL_REWIND;
- }
- }
- return CURLE_OK;
-}
-
-static int data_pending(const struct Curl_easy *data)
-{
- struct connectdata *conn = data->conn;
-
-#ifdef ENABLE_QUIC
- if(conn->transport == TRNSPRT_QUIC)
- return Curl_quic_data_pending(data);
-#endif
if(conn->handler->protocol&PROTO_FAMILY_FTP)
- return Curl_ssl_data_pending(conn, SECONDARYSOCKET);
+ 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 conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) ||
-#ifdef USE_NGHTTP2
- /* For HTTP/2, we may read up everything including response body
- with header fields in Curl_http_readwrite_headers. If no
- content-length is provided, curl waits for the connection
- close, which we emulate it using conn->proto.httpc.closed =
- TRUE. The thing is if we read everything, then http2_recv won't
- be called and we cannot signal the HTTP/2 stream has closed. As
- a workaround, we return nonzero here to call http2_recv. */
- ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion >= 20) ||
-#endif
- Curl_ssl_data_pending(conn, FIRSTSOCKET);
+ Curl_conn_data_pending(data, FIRSTSOCKET);
}
/*
@@ -523,6 +428,8 @@
size_t excess = 0; /* excess bytes read */
bool readmore = FALSE; /* used by RTP to signal for more data */
int maxloops = 100;
+ curl_off_t max_recv = data->set.max_recv_speed?
+ data->set.max_recv_speed : CURL_OFF_T_MAX;
char *buf = data->state.buffer;
DEBUGASSERT(buf);
@@ -535,21 +442,16 @@
bool is_empty_data = FALSE;
size_t buffersize = data->set.buffer_size;
size_t bytestoread = buffersize;
-#ifdef USE_NGHTTP2
- bool is_http2 = ((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
- (conn->httpversion == 20));
-#endif
+ /* For HTTP/2 and HTTP/3, read data without caring about the content
+ length. This is safe because body in HTTP/2 is always segmented
+ thanks to its framing layer. Meanwhile, we have to call Curl_read
+ to ensure that http2_handle_stream_close is called when we read all
+ incoming bytes for a particular stream. */
+ bool is_http3 = Curl_conn_is_http3(data, conn, FIRSTSOCKET);
+ bool data_eof_handled = is_http3
+ || Curl_conn_is_http2(data, conn, FIRSTSOCKET);
- if(
-#ifdef USE_NGHTTP2
- /* For HTTP/2, read data without caring about the content length. This
- is safe because body in HTTP/2 is always segmented thanks to its
- framing layer. Meanwhile, we have to call Curl_read to ensure that
- http2_handle_stream_close is called when we read all incoming bytes
- for a particular stream. */
- !is_http2 &&
-#endif
- k->size != -1 && !k->header) {
+ if(!data_eof_handled && k->size != -1 && !k->header) {
/* make sure we don't read too much */
curl_off_t totalleft = k->size - k->bytecount;
if(totalleft < (curl_off_t)bytestoread)
@@ -561,11 +463,13 @@
result = Curl_read(data, conn->sockfd, buf, bytestoread, &nread);
/* read would've blocked */
- if(CURLE_AGAIN == result)
+ if(CURLE_AGAIN == result) {
+ result = CURLE_OK;
break; /* get out of loop */
+ }
if(result>0)
- return result;
+ goto out;
}
else {
/* read nothing but since we wanted nothing we consider this an OK
@@ -589,13 +493,11 @@
buf[nread] = 0;
}
else {
- /* if we receive 0 or less here, either the http2 stream is closed or the
+ /* 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! */
-#ifdef USE_NGHTTP2
- if(is_http2 && !nread)
+ if(data_eof_handled)
DEBUGF(infof(data, "nread == 0, stream closed, bailing"));
else
-#endif
DEBUGF(infof(data, "nread <= 0, server closed connection, bailing"));
k->keepon &= ~KEEP_RECV;
break;
@@ -608,7 +510,7 @@
if(conn->handler->readwrite) {
result = conn->handler->readwrite(data, conn, &nread, &readmore);
if(result)
- return result;
+ goto out;
if(readmore)
break;
}
@@ -621,13 +523,13 @@
bool stop_reading = FALSE;
result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading);
if(result)
- return result;
+ goto out;
if(conn->handler->readwrite &&
(k->maxdownload <= 0 && nread > 0)) {
result = conn->handler->readwrite(data, conn, &nread, &readmore);
if(result)
- return result;
+ goto out;
if(readmore)
break;
}
@@ -654,11 +556,12 @@
is non-headers. */
if(!k->header && (nread > 0 || is_empty_data)) {
- if(data->set.opt_no_body) {
+ if(data->req.no_body) {
/* data arrives although we want none, bail out */
streamclose(conn, "ignoring body");
*done = TRUE;
- return CURLE_WEIRD_SERVER_REPLY;
+ result = CURLE_WEIRD_SERVER_REPLY;
+ goto out;
}
#ifndef CURL_DISABLE_HTTP
@@ -669,7 +572,7 @@
/* HTTP-only checks */
result = Curl_http_firstwrite(data, conn, done);
if(result || *done)
- return result;
+ goto out;
}
} /* this is the first time we write a body part */
#endif /* CURL_DISABLE_HTTP */
@@ -706,10 +609,12 @@
if(CHUNKE_OK < res) {
if(CHUNKE_PASSTHRU_ERROR == res) {
failf(data, "Failed reading the chunked-encoded stream");
- return extra;
+ result = extra;
+ goto out;
}
failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res));
- return CURLE_RECV_ERROR;
+ result = CURLE_RECV_ERROR;
+ goto out;
}
if(CHUNKE_STOP == res) {
/* we're done reading chunks! */
@@ -753,10 +658,17 @@
if(nread < 0) /* this should be unusual */
nread = 0;
- k->keepon &= ~KEEP_RECV; /* we're done reading */
+ /* HTTP/3 over QUIC should keep reading until QUIC connection
+ is closed. In contrast to HTTP/2 which can stop reading
+ from TCP connection, HTTP/3 over QUIC needs ACK from server
+ to ensure stream closure. It should keep reading. */
+ if(!is_http3) {
+ k->keepon &= ~KEEP_RECV; /* we're done reading */
+ }
}
k->bytecount += nread;
+ max_recv -= nread;
Curl_pgrsSetDownloadCounter(data, k->bytecount);
@@ -779,7 +691,7 @@
(size_t)k->maxdownload);
if(result)
- return result;
+ goto out;
}
if(k->badheader < HEADER_ALLBAD) {
/* This switch handles various content encodings. If there's an
@@ -804,7 +716,7 @@
k->badheader = HEADER_NORMAL; /* taken care of now */
if(result)
- return result;
+ goto out;
}
} /* if(!header and data to read) */
@@ -822,7 +734,7 @@
result = conn->handler->readwrite(data, conn, &nread, &readmore);
if(result)
- return result;
+ goto out;
if(readmore)
k->keepon |= KEEP_RECV; /* we're not done reading */
@@ -835,16 +747,16 @@
k->keepon &= ~KEEP_RECV;
}
- if(k->keepon & KEEP_RECV_PAUSE) {
- /* this is a paused transfer */
+ if((k->keepon & KEEP_RECV_PAUSE) || !(k->keepon & KEEP_RECV)) {
+ /* this is a paused or stopped transfer */
break;
}
- } while(data_pending(data) && maxloops--);
+ } while((max_recv > 0) && data_pending(data) && maxloops--);
- if(maxloops <= 0) {
+ if(maxloops <= 0 || max_recv <= 0) {
/* we mark it as read-again-please */
- conn->cselect_bits = CURL_CSELECT_IN;
+ data->state.dselect_bits = CURL_CSELECT_IN;
*comeback = TRUE;
}
@@ -857,24 +769,20 @@
k->keepon &= ~KEEP_SEND; /* no writing anymore either */
}
- return CURLE_OK;
+out:
+ if(result)
+ DEBUGF(infof(data, "readwrite_data() -> %d", result));
+ return result;
}
CURLcode Curl_done_sending(struct Curl_easy *data,
struct SingleRequest *k)
{
- struct connectdata *conn = data->conn;
k->keepon &= ~KEEP_SEND; /* we're done writing */
/* These functions should be moved into the handler struct! */
- Curl_http2_done_sending(data, conn);
- Curl_quic_done_sending(data);
+ Curl_conn_ev_data_done_send(data);
- if(conn->bits.rewindaftersend) {
- CURLcode result = Curl_readrewind(data);
- if(result)
- return result;
- }
return CURLE_OK;
}
@@ -1075,7 +983,15 @@
if(result)
return result;
- win_update_buffer_size(conn->writesockfd);
+#if defined(WIN32) && defined(USE_WINSOCK)
+ {
+ struct curltime n = Curl_now();
+ if(Curl_timediff(n, k->last_sndbuf_update) > 1000) {
+ win_update_buffer_size(conn->writesockfd);
+ k->last_sndbuf_update = n;
+ }
+ }
+#endif
if(k->pendingheader) {
/* parts of what was sent was header */
@@ -1150,73 +1066,73 @@
{
struct SingleRequest *k = &data->req;
CURLcode result;
+ struct curltime now;
int didwhat = 0;
+ int select_bits;
- curl_socket_t fd_read;
- curl_socket_t fd_write;
- int select_res = conn->cselect_bits;
- conn->cselect_bits = 0;
-
- /* only use the proper socket if the *_HOLD bit is not set simultaneously as
- then we are in rate limiting state in that transfer direction */
-
- if((k->keepon & KEEP_RECVBITS) == KEEP_RECV)
- fd_read = conn->sockfd;
- else
- fd_read = CURL_SOCKET_BAD;
-
- if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
- fd_write = conn->writesockfd;
- else
- fd_write = CURL_SOCKET_BAD;
-
-#if defined(USE_HTTP2) || defined(USE_HTTP3)
- if(data->state.drain) {
- select_res |= CURL_CSELECT_IN;
- DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data"));
+ if(data->state.dselect_bits) {
+ select_bits = data->state.dselect_bits;
+ data->state.dselect_bits = 0;
}
-#endif
+ else if(conn->cselect_bits) {
+ select_bits = conn->cselect_bits;
+ conn->cselect_bits = 0;
+ }
+ else {
+ curl_socket_t fd_read;
+ curl_socket_t fd_write;
+ /* only use the proper socket if the *_HOLD bit is not set simultaneously
+ as then we are in rate limiting state in that transfer direction */
+ if((k->keepon & KEEP_RECVBITS) == KEEP_RECV)
+ fd_read = conn->sockfd;
+ else
+ fd_read = CURL_SOCKET_BAD;
- if(!select_res) /* Call for select()/poll() only, if read/write/error
- status is not known. */
- select_res = Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, 0);
+ if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
+ fd_write = conn->writesockfd;
+ else
+ fd_write = CURL_SOCKET_BAD;
- if(select_res == CURL_CSELECT_ERR) {
+ select_bits = Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, 0);
+ }
+
+ if(select_bits == CURL_CSELECT_ERR) {
failf(data, "select/poll returned error");
- return CURLE_SEND_ERROR;
+ result = CURLE_SEND_ERROR;
+ goto out;
}
#ifdef USE_HYPER
if(conn->datastream) {
- result = conn->datastream(data, conn, &didwhat, done, select_res);
+ result = conn->datastream(data, conn, &didwhat, done, select_bits);
if(result || *done)
- return result;
+ goto out;
}
else {
#endif
/* We go ahead and do a read if we have a readable socket or if
the stream was rewound (in which case we have data in a
buffer) */
- if((k->keepon & KEEP_RECV) && (select_res & CURL_CSELECT_IN)) {
+ if((k->keepon & KEEP_RECV) && (select_bits & CURL_CSELECT_IN)) {
result = readwrite_data(data, conn, k, &didwhat, done, comeback);
if(result || *done)
- return result;
+ goto out;
}
/* If we still have writing to do, we check if we have a writable socket. */
- if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) {
+ if((k->keepon & KEEP_SEND) && (select_bits & CURL_CSELECT_OUT)) {
/* write */
result = readwrite_upload(data, conn, &didwhat);
if(result)
- return result;
+ goto out;
}
#ifdef USE_HYPER
}
#endif
- k->now = Curl_now();
+ now = Curl_now();
if(!didwhat) {
/* no read no write, this is a timeout? */
if(k->exp100 == EXP100_AWAITING_CONTINUE) {
@@ -1233,7 +1149,7 @@
*/
- timediff_t ms = Curl_timediff(k->now, k->start100);
+ timediff_t ms = Curl_timediff(now, k->start100);
if(ms >= data->set.expect_100_timeout) {
/* we've waited long enough, continue anyway */
k->exp100 = EXP100_SEND_DATA;
@@ -1243,38 +1159,35 @@
}
}
-#ifdef ENABLE_QUIC
- if(conn->transport == TRNSPRT_QUIC) {
- result = Curl_quic_idle(data);
- if(result)
- return result;
- }
-#endif
+ result = Curl_conn_ev_data_idle(data);
+ if(result)
+ goto out;
}
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(data, k->now);
+ result = Curl_speedcheck(data, now);
if(result)
- return result;
+ goto out;
if(k->keepon) {
- if(0 > Curl_timeleft(data, &k->now, FALSE)) {
+ if(0 > Curl_timeleft(data, &now, FALSE)) {
if(k->size != -1) {
failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
CURL_FORMAT_CURL_OFF_T " bytes received",
- Curl_timediff(k->now, data->progress.t_startsingle),
+ Curl_timediff(now, data->progress.t_startsingle),
k->bytecount, k->size);
}
else {
failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds with %" CURL_FORMAT_CURL_OFF_T " bytes received",
- Curl_timediff(k->now, data->progress.t_startsingle),
+ Curl_timediff(now, data->progress.t_startsingle),
k->bytecount);
}
- return CURLE_OPERATION_TIMEDOUT;
+ result = CURLE_OPERATION_TIMEDOUT;
+ goto out;
}
}
else {
@@ -1283,7 +1196,7 @@
* returning.
*/
- if(!(data->set.opt_no_body) && (k->size != -1) &&
+ if(!(data->req.no_body) && (k->size != -1) &&
(k->bytecount != k->size) &&
#ifdef CURL_DO_LINEEND_CONV
/* Most FTP servers don't adjust their file SIZE response for CRLFs,
@@ -1295,9 +1208,10 @@
!k->newurl) {
failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T
" bytes remaining to read", k->size - k->bytecount);
- return CURLE_PARTIAL_FILE;
+ result = CURLE_PARTIAL_FILE;
+ goto out;
}
- if(!(data->set.opt_no_body) && k->chunk &&
+ if(!(data->req.no_body) && k->chunk &&
(conn->chunk.state != CHUNK_STOP)) {
/*
* In chunked mode, return an error if the connection is closed prior to
@@ -1309,17 +1223,21 @@
*
*/
failf(data, "transfer closed with outstanding read data remaining");
- return CURLE_PARTIAL_FILE;
+ result = CURLE_PARTIAL_FILE;
+ goto out;
}
- if(Curl_pgrsUpdate(data))
- return CURLE_ABORTED_BY_CALLBACK;
+ if(Curl_pgrsUpdate(data)) {
+ result = CURLE_ABORTED_BY_CALLBACK;
+ goto out;
+ }
}
/* Now update the "done" boolean we return */
- *done = (0 == (k->keepon&(KEEP_RECV|KEEP_SEND|
- KEEP_RECV_PAUSE|KEEP_SEND_PAUSE))) ? TRUE : FALSE;
-
- return CURLE_OK;
+ *done = (0 == (k->keepon&(KEEP_RECVBITS|KEEP_SENDBITS))) ? TRUE : FALSE;
+out:
+ if(result)
+ DEBUGF(infof(data, "Curl_readwrite() -> %d", result));
+ return result;
}
/*
@@ -1350,7 +1268,6 @@
/* don't include HOLD and PAUSE connections */
if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) {
-
if((conn->sockfd != conn->writesockfd) ||
bitmap == GETSOCK_BLANK) {
/* only if they are not the same socket and we have a readable
@@ -1375,6 +1292,7 @@
{
data->state.fread_func = data->set.fread_func_set;
data->state.in = data->set.in_set;
+ data->state.upload = (data->state.httpreq == HTTPREQ_PUT);
}
/*
@@ -1410,6 +1328,12 @@
}
}
+ if(data->set.postfields && data->set.set_resume_from) {
+ /* we can't */
+ failf(data, "cannot mix POSTFIELDS with RESUME_FROM");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
data->state.prefer_ascii = data->set.prefer_ascii;
data->state.list_only = data->set.list_only;
data->state.httpreq = data->set.method;
@@ -1422,6 +1346,7 @@
if(result)
return result;
+ data->state.requests = 0;
data->state.followlocation = 0; /* reset the location-follow counter */
data->state.this_is_a_follow = FALSE; /* reset this */
data->state.errorbuf = FALSE; /* no error has occurred */
@@ -1431,6 +1356,7 @@
data->state.authhost.want = data->set.httpauth;
data->state.authproxy.want = data->set.proxyauth;
Curl_safefree(data->info.wouldredirect);
+ Curl_data_priority_clear_state(data);
if(data->state.httpreq == HTTPREQ_PUT)
data->state.infilesize = data->set.filesize;
@@ -1443,15 +1369,16 @@
else
data->state.infilesize = 0;
-#ifndef CURL_DISABLE_COOKIES
/* If there is a list of cookie files to read, do it now! */
- if(data->state.cookielist)
- Curl_cookie_loadfiles(data);
-#endif
+ Curl_cookie_loadfiles(data);
+
/* If there is a list of host pairs to deal with */
if(data->state.resolve)
result = Curl_loadhostpairs(data);
+ /* If there is a list of hsts files to read */
+ Curl_hsts_loadfiles(data);
+
if(!result) {
/* Allow data->set.use_port to set which port to use. This needs to be
* disabled for example when we follow Location: headers to URLs using
@@ -1479,21 +1406,31 @@
#ifndef CURL_DISABLE_FTP
data->state.wildcardmatch = data->set.wildcard_enabled;
if(data->state.wildcardmatch) {
- struct WildcardData *wc = &data->wildcard;
- if(wc->state < CURLWC_INIT) {
+ struct WildcardData *wc;
+ if(!data->wildcard) {
+ data->wildcard = calloc(1, sizeof(struct WildcardData));
+ if(!data->wildcard)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ wc = data->wildcard;
+ if((wc->state < CURLWC_INIT) ||
+ (wc->state >= CURLWC_CLEAN)) {
+ if(wc->ftpwc)
+ 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;
}
}
#endif
- Curl_http2_init_state(&data->state);
result = Curl_hsts_loadcb(data, data->hsts);
}
/*
* Set user-agent. Used for HTTP, but since we can attempt to tunnel
- * basically anything through a http proxy we can't limit this based on
+ * basically anything through an HTTP proxy we can't limit this based on
* protocol.
*/
if(data->set.str[STRING_USERAGENT]) {
@@ -1573,10 +1510,8 @@
to URL */
}
else {
- /* mark the next request as a followed location: */
- data->state.this_is_a_follow = TRUE;
-
- data->state.followlocation++; /* count location-followers */
+ data->state.followlocation++; /* count redirect-followings, including
+ auth reloads */
if(data->set.http_auto_referer) {
CURLU *u;
@@ -1619,10 +1554,11 @@
if((type != FOLLOW_RETRY) &&
(data->req.httpcode != 401) && (data->req.httpcode != 407) &&
- Curl_is_absolute_url(newurl, NULL, 0))
+ Curl_is_absolute_url(newurl, NULL, 0, FALSE)) {
/* If this is not redirect due to a 401 or 407 response and an absolute
URL: don't allow a custom port number */
disallowport = TRUE;
+ }
DEBUGASSERT(data->state.uh);
uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl,
@@ -1631,8 +1567,11 @@
CURLU_ALLOW_SPACE |
(data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
if(uc) {
- if(type != FOLLOW_FAKE)
+ if(type != FOLLOW_FAKE) {
+ failf(data, "The redirect target URL could not be parsed: %s",
+ curl_url_strerror(uc));
return Curl_uc_to_curlcode(uc);
+ }
/* the URL could not be parsed for some reason, but since this is FAKE
mode, just duplicate the field as-is */
@@ -1679,7 +1618,7 @@
return Curl_uc_to_curlcode(uc);
}
- p = Curl_builtin_scheme(scheme);
+ p = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED);
if(p && (p->protocol != data->info.conn_protocol)) {
infof(data, "Clear auth, redirects scheme from %s to %s",
data->info.conn_scheme, scheme);
@@ -1722,7 +1661,7 @@
* differently based on exactly what return code there was.
*
* News from 7.10.6: we can also get here on a 401 or 407, in case we act on
- * a HTTP (proxy-) authentication scheme other than Basic.
+ * an HTTP (proxy-) authentication scheme other than Basic.
*/
switch(data->info.httpcode) {
/* 401 - Act on a WWW-Authenticate, we keep on moving and do the
@@ -1800,9 +1739,8 @@
data->state.httpreq != HTTPREQ_POST_MIME) ||
!(data->set.keep_post & CURL_REDIR_POST_303))) {
data->state.httpreq = HTTPREQ_GET;
- data->set.upload = false;
infof(data, "Switch to %s",
- data->set.opt_no_body?"HEAD":"GET");
+ data->req.no_body?"HEAD":"GET");
}
break;
case 304: /* Not Modified */
@@ -1838,13 +1776,13 @@
/* if we're talking upload, we can't do the checks below, unless the protocol
is HTTP as when uploading over HTTP we will still get a response */
- if(data->set.upload &&
+ if(data->state.upload &&
!(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)))
return CURLE_OK;
if((data->req.bytecount + data->req.headerbytecount == 0) &&
conn->bits.reuse &&
- (!data->set.opt_no_body || (conn->handler->protocol & PROTO_FAMILY_HTTP))
+ (!data->req.no_body || (conn->handler->protocol & PROTO_FAMILY_HTTP))
#ifndef CURL_DISABLE_RTSP
&& (data->set.rtspreq != RTSPREQ_RECEIVE)
#endif
@@ -1890,14 +1828,10 @@
transferred! */
- if(conn->handler->protocol&PROTO_FAMILY_HTTP) {
- if(data->req.writebytecount) {
- CURLcode result = Curl_readrewind(data);
- if(result) {
- Curl_safefree(*url);
- return result;
- }
- }
+ if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
+ data->req.writebytecount) {
+ data->state.rewindbeforesend = TRUE;
+ infof(data, "state.rewindbeforesend = TRUE");
}
}
return CURLE_OK;
@@ -1928,7 +1862,7 @@
httpsending = ((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
(http->sending == HTTPSEND_REQUEST));
- if(conn->bits.multiplex || conn->httpversion == 20 || httpsending) {
+ if(conn->bits.multiplex || conn->httpversion >= 20 || httpsending) {
/* when multiplexing, the read/write sockets need to be the same! */
conn->sockfd = sockindex == -1 ?
((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) :
@@ -1958,7 +1892,7 @@
Curl_pgrsSetDownloadSize(data, size);
}
/* we want header and/or body, if neither then don't do this! */
- if(k->getheader || !data->set.opt_no_body) {
+ if(k->getheader || !data->req.no_body) {
if(sockindex != -1)
k->keepon |= KEEP_RECV;
@@ -1994,6 +1928,6 @@
k->keepon |= KEEP_SEND;
}
} /* if(writesockindex != -1) */
- } /* if(k->getheader || !data->set.opt_no_body) */
+ } /* if(k->getheader || !data->req.no_body) */
}
diff --git a/lib/transfer.h b/lib/transfer.h
index 65fe68e..536ac24 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -50,7 +50,6 @@
bool *comeback);
int Curl_single_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks);
-CURLcode Curl_readrewind(struct Curl_easy *data);
CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
size_t *nreadp);
CURLcode Curl_retry_request(struct Curl_easy *data, char **url);
diff --git a/lib/url.c b/lib/url.c
index 1114c6c..e3e7f45 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -61,25 +61,9 @@
#include <limits.h>
-#ifdef USE_LIBIDN2
-#include <idn2.h>
-
-#if defined(WIN32) && defined(UNICODE)
-#define IDN2_LOOKUP(name, host, flags) \
- idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags)
-#else
-#define IDN2_LOOKUP(name, host, flags) \
- idn2_lookup_ul((const char *)name, (char **)host, flags)
-#endif
-
-#elif defined(USE_WIN32_IDN)
-/* prototype for curl_win32_idn_to_ascii() */
-bool curl_win32_idn_to_ascii(const char *in, char **out);
-#endif /* USE_LIBIDN2 */
-
+#include "doh.h"
#include "urldata.h"
#include "netrc.h"
-
#include "formdata.h"
#include "mime.h"
#include "vtls/vtls.h"
@@ -105,6 +89,9 @@
#include "urlapi-int.h"
#include "system_win32.h"
#include "hsts.h"
+#include "noproxy.h"
+#include "cfilters.h"
+#include "idn.h"
/* And now for the protocols */
#include "ftp.h"
@@ -127,7 +114,6 @@
#include "http_proxy.h"
#include "conncache.h"
#include "multihandle.h"
-#include "dotdot.h"
#include "strdup.h"
#include "setopt.h"
#include "altsvc.h"
@@ -139,7 +125,15 @@
#include "curl_memory.h"
#include "memdebug.h"
-static void conn_free(struct connectdata *conn);
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
+
+#ifdef USE_NGHTTP2
+static void data_priority_cleanup(struct Curl_easy *data);
+#else
+#define data_priority_cleanup(x)
+#endif
/* Some parts of the code (e.g. chunked encoding) assume this buffer has at
* more than just a few bytes to play with. Don't let it become too small or
@@ -153,6 +147,9 @@
#define UNIX_SOCKET_PREFIX "localhost"
#endif
+/* Reject URLs exceeding this length */
+#define MAX_URL_LEN 0xffff
+
/*
* get_protocol_family()
*
@@ -164,7 +161,7 @@
*
* Returns the family as a single bit protocol identifier.
*/
-static unsigned int get_protocol_family(const struct Curl_handler *h)
+static curl_prot_t get_protocol_family(const struct Curl_handler *h)
{
DEBUGASSERT(h);
DEBUGASSERT(h->family);
@@ -188,6 +185,16 @@
&Curl_handler_http,
#endif
+#ifdef USE_WEBSOCKETS
+#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+ &Curl_handler_wss,
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+ &Curl_handler_ws,
+#endif
+#endif
+
#ifndef CURL_DISABLE_FTP
&Curl_handler_ftp,
#endif
@@ -285,33 +292,6 @@
(struct Curl_handler *) NULL
};
-/*
- * Dummy handler for undefined protocol schemes.
- */
-
-static const struct Curl_handler Curl_handler_dummy = {
- "<no protocol>", /* scheme */
- ZERO_NULL, /* setup_connection */
- ZERO_NULL, /* do_it */
- ZERO_NULL, /* done */
- ZERO_NULL, /* do_more */
- ZERO_NULL, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ZERO_NULL, /* proto_getsock */
- ZERO_NULL, /* doing_getsock */
- ZERO_NULL, /* domore_getsock */
- ZERO_NULL, /* perform_getsock */
- ZERO_NULL, /* disconnect */
- ZERO_NULL, /* readwrite */
- ZERO_NULL, /* connection_check */
- ZERO_NULL, /* attach connection */
- 0, /* defport */
- 0, /* protocol */
- 0, /* family */
- PROTOPT_NONE /* flags */
-};
-
void Curl_freeset(struct Curl_easy *data)
{
/* Free all dynamic strings stored in the data->set substructure. */
@@ -338,6 +318,11 @@
data->state.url = NULL;
Curl_mime_cleanpart(&data->set.mimepost);
+
+#ifndef CURL_DISABLE_COOKIES
+ curl_slist_free_all(data->set.cookielist);
+ data->set.cookielist = NULL;
+#endif
}
/* free the URL pieces */
@@ -365,7 +350,6 @@
CURLcode Curl_close(struct Curl_easy **datap)
{
- struct Curl_multi *m;
struct Curl_easy *data;
if(!datap || !*datap)
@@ -379,8 +363,7 @@
/* Detach connection if any is left. This should not be normal, but can be
the case for example with CONNECT_ONLY + recv/send (test 556) */
Curl_detach_connection(data);
- m = data->multi;
- if(m)
+ if(data->multi)
/* This handle is still part of a multi handle, take care of this first
and detach this handle from there. */
curl_multi_remove_handle(data->multi, data);
@@ -392,11 +375,6 @@
data->multi_easy = NULL;
}
- /* Destroy the timeout list that is held in the easy handle. It is
- /normally/ done by curl_multi_remove_handle() but this is "just in
- case" */
- Curl_llist_destroy(&data->state.timeoutlist, NULL);
-
data->magic = 0; /* force a clear AFTER the possibly enforced removal from
the multi handle, since that function uses the magic
field! */
@@ -431,7 +409,11 @@
Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]);
Curl_altsvc_cleanup(&data->asi);
Curl_hsts_save(data, data->hsts, data->set.str[STRING_HSTS]);
- Curl_hsts_cleanup(&data->hsts);
+#ifndef CURL_DISABLE_HSTS
+ if(!data->share || !data->share->hsts)
+ Curl_hsts_cleanup(&data->hsts);
+ curl_slist_free_all(data->set.hstslist); /* clean up list */
+#endif
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
Curl_http_auth_cleanup_digest(data);
#endif
@@ -439,9 +421,10 @@
Curl_safefree(data->info.wouldredirect);
/* this destroys the channel and we cannot use it anymore after this */
+ Curl_resolver_cancel(data);
Curl_resolver_cleanup(data->state.async.resolver);
- Curl_http2_cleanup_dependencies(data);
+ data_priority_cleanup(data);
/* No longer a dirty share, if it exists */
if(data->share) {
@@ -524,12 +507,14 @@
/* Set the default size of the SSL session ID cache */
set->general_ssl.max_ssl_sessions = 5;
+ /* Timeout every 24 hours by default */
+ set->general_ssl.ca_cache_timeout = 24 * 60 * 60;
- set->proxyport = 0;
- set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
set->httpauth = CURLAUTH_BASIC; /* defaults to basic */
#ifndef CURL_DISABLE_PROXY
+ set->proxyport = 0;
+ set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
/* SOCKS5 proxy auth defaults to username/password + GSS-API */
set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI;
@@ -538,7 +523,7 @@
/* make libcurl quiet by default: */
set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
- Curl_mime_initpart(&set->mimepost, data);
+ Curl_mime_initpart(&set->mimepost);
/*
* libcurl 7.10 introduced SSL verification *by default*! This needs to be
@@ -550,11 +535,11 @@
#endif
set->ssl.primary.verifypeer = TRUE;
set->ssl.primary.verifyhost = TRUE;
-#ifdef USE_TLS_SRP
- set->ssl.primary.authtype = CURL_TLSAUTH_NONE;
-#endif
- /* defaults to any auth type */
+#ifdef USE_SSH
+ /* defaults to any auth type */
set->ssh_auth_types = CURLSSH_AUTH_DEFAULT;
+ set->new_directory_perms = 0755; /* Default permissions */
+#endif
set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by
default */
#ifndef CURL_DISABLE_PROXY
@@ -562,12 +547,7 @@
#endif
set->new_file_perms = 0644; /* Default permissions */
- set->new_directory_perms = 0755; /* Default permissions */
-
- /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
- define since we internally only use the lower 16 bits for the passed
- in bitmask to not conflict with the private bits */
- set->allowed_protocols = (unsigned int)CURLPROTO_ALL;
+ set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL;
set->redir_protocols = CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP |
CURLPROTO_FTPS;
@@ -618,7 +598,6 @@
set->tcp_keepidle = 60;
set->tcp_fastopen = FALSE;
set->tcp_nodelay = TRUE;
- set->ssl_enable_npn = TRUE;
set->ssl_enable_alpn = TRUE;
set->expect_100_timeout = 1000L; /* Wait for a second by default. */
set->sep_headers = TRUE; /* separated header lists by default */
@@ -630,14 +609,16 @@
set->maxage_conn = 118;
set->maxlifetime_conn = 0;
set->http09_allowed = FALSE;
- set->httpwant =
#ifdef USE_HTTP2
- CURL_HTTP_VERSION_2TLS
+ set->httpwant = CURL_HTTP_VERSION_2TLS
#else
- CURL_HTTP_VERSION_1_1
+ set->httpwant = CURL_HTTP_VERSION_1_1
#endif
;
- Curl_http2_init_userset(set);
+#if defined(USE_HTTP2) || defined(USE_HTTP3)
+ memset(&set->priority, 0, sizeof(set->priority));
+#endif
+ set->quick_exit = 0L;
return result;
}
@@ -678,6 +659,9 @@
/* most recent connection is not yet defined */
data->state.lastconnect_id = -1;
+ data->state.recent_conn_id = -1;
+ /* and not assigned an id yet */
+ data->id = -1;
data->progress.flags |= PGRS_HIDE;
data->state.current_speed = -1; /* init to negative == impossible */
@@ -696,85 +680,28 @@
return result;
}
-#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
-static void conn_reset_postponed_data(struct connectdata *conn, int num)
+static void conn_shutdown(struct Curl_easy *data)
{
- struct postponed_data * const psnd = &(conn->postponed[num]);
- if(psnd->buffer) {
- DEBUGASSERT(psnd->allocated_size > 0);
- DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
- DEBUGASSERT(psnd->recv_size ?
- (psnd->recv_processed < psnd->recv_size) :
- (psnd->recv_processed == 0));
- DEBUGASSERT(psnd->bindsock != CURL_SOCKET_BAD);
- free(psnd->buffer);
- psnd->buffer = NULL;
- psnd->allocated_size = 0;
- psnd->recv_size = 0;
- psnd->recv_processed = 0;
-#ifdef DEBUGBUILD
- psnd->bindsock = CURL_SOCKET_BAD; /* used only for DEBUGASSERT */
-#endif /* DEBUGBUILD */
- }
- else {
- DEBUGASSERT(psnd->allocated_size == 0);
- DEBUGASSERT(psnd->recv_size == 0);
- DEBUGASSERT(psnd->recv_processed == 0);
- DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
- }
-}
-
-static void conn_reset_all_postponed_data(struct connectdata *conn)
-{
- conn_reset_postponed_data(conn, 0);
- conn_reset_postponed_data(conn, 1);
-}
-#else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
-/* Use "do-nothing" macro instead of function when workaround not used */
-#define conn_reset_all_postponed_data(c) do {} while(0)
-#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
-
-
-static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
-{
- DEBUGASSERT(conn);
DEBUGASSERT(data);
- infof(data, "Closing connection %ld", conn->connection_id);
-
-#ifndef USE_HYPER
- if(conn->connect_state && conn->connect_state->prot_save) {
- /* If this was closed with a CONNECT in progress, cleanup this temporary
- struct arrangement */
- data->req.p.http = NULL;
- Curl_safefree(conn->connect_state->prot_save);
- }
-#endif
+ infof(data, "Closing connection");
/* possible left-overs from the async name resolvers */
Curl_resolver_cancel(data);
- /* close the SSL stuff before we close any sockets since they will/may
- write to the sockets */
- Curl_ssl_close(data, conn, FIRSTSOCKET);
-#ifndef CURL_DISABLE_FTP
- Curl_ssl_close(data, conn, SECONDARYSOCKET);
-#endif
-
- /* close possibly still open sockets */
- if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
- Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
- if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
- Curl_closesocket(data, conn, conn->sock[FIRSTSOCKET]);
- if(CURL_SOCKET_BAD != conn->tempsock[0])
- Curl_closesocket(data, conn, conn->tempsock[0]);
- if(CURL_SOCKET_BAD != conn->tempsock[1])
- Curl_closesocket(data, conn, conn->tempsock[1]);
+ Curl_conn_close(data, SECONDARYSOCKET);
+ Curl_conn_close(data, FIRSTSOCKET);
}
-static void conn_free(struct connectdata *conn)
+static void conn_free(struct Curl_easy *data, struct connectdata *conn)
{
+ size_t i;
+
DEBUGASSERT(conn);
+ for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
+ Curl_conn_cf_discard_all(data, conn, (int)i);
+ }
+
Curl_free_idnconverted_hostname(&conn->host);
Curl_free_idnconverted_hostname(&conn->conn_to_host);
#ifndef CURL_DISABLE_PROXY
@@ -793,15 +720,13 @@
Curl_safefree(conn->sasl_authzid);
Curl_safefree(conn->options);
Curl_safefree(conn->oauth_bearer);
+#ifndef CURL_DISABLE_HTTP
Curl_dyn_free(&conn->trailer);
+#endif
Curl_safefree(conn->host.rawalloc); /* host name buffer */
Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
Curl_safefree(conn->hostname_resolve);
Curl_safefree(conn->secondaryhostname);
- Curl_safefree(conn->connect_state);
-
- conn_reset_all_postponed_data(conn);
- Curl_llist_destroy(&conn->easyq, NULL);
Curl_safefree(conn->localdev);
Curl_free_primary_ssl_config(&conn->ssl_config);
@@ -809,9 +734,6 @@
Curl_safefree(conn->unix_domain_socket);
#endif
-#ifdef USE_SSL
- Curl_safefree(conn->ssl_extra);
-#endif
free(conn); /* free all the connection oriented data */
}
@@ -844,6 +766,9 @@
/* the transfer must be detached from the connection */
DEBUGASSERT(!data->conn);
+ DEBUGF(infof(data, "Curl_disconnect(conn #%"
+ CURL_FORMAT_CURL_OFF_T ", dead=%d)",
+ conn->connection_id, dead_connection));
/*
* If this connection isn't marked to force-close, leave it open if there
* are other users of it
@@ -864,7 +789,7 @@
/* Cleanup NEGOTIATE connection-related data */
Curl_http_auth_cleanup_negotiate(conn);
- if(conn->bits.connect_only)
+ if(conn->connect_only)
/* treat the connection as dead in CONNECT_ONLY situations */
dead_connection = TRUE;
@@ -872,34 +797,16 @@
disconnect and shutdown */
Curl_attach_connection(data, conn);
- if(conn->handler->disconnect)
+ if(conn->handler && conn->handler->disconnect)
/* This is set if protocol-specific cleanups should be made */
conn->handler->disconnect(data, conn, dead_connection);
- conn_shutdown(data, conn);
+ conn_shutdown(data);
/* detach it again */
Curl_detach_connection(data);
- conn_free(conn);
-}
-
-/*
- * This function should return TRUE if the socket is to be assumed to
- * be dead. Most commonly this happens when the server has closed the
- * connection due to inactivity.
- */
-static bool SocketIsDead(curl_socket_t sock)
-{
- int sval;
- bool ret_val = TRUE;
-
- sval = SOCKET_READABLE(sock, 0);
- if(sval == 0)
- /* timeout */
- ret_val = FALSE;
-
- return ret_val;
+ conn_free(data, conn);
}
/*
@@ -913,7 +820,7 @@
{
int avail = 0;
- /* If a HTTP protocol and multiplexing is enabled */
+ /* If an HTTP protocol and multiplexing is enabled */
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
(!conn->bits.protoconnstart || !conn->bits.close)) {
@@ -932,7 +839,7 @@
{
if((data->proxytype == needle->proxytype) &&
(data->port == needle->port) &&
- Curl_safe_strcasecompare(data->host.name, needle->host.name))
+ strcasecompare(data->host.name, needle->host.name))
return TRUE;
return FALSE;
@@ -948,19 +855,11 @@
/* the user information is case-sensitive
or at least it is not defined as case-insensitive
see https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1 */
- if(!data->user != !needle->user)
- return FALSE;
- /* curl_strequal does a case insentive comparison, so do not use it here! */
- if(data->user &&
- needle->user &&
- strcmp(data->user, needle->user) != 0)
- return FALSE;
- if(!data->passwd != !needle->passwd)
- return FALSE;
- /* curl_strequal does a case insentive comparison, so do not use it here! */
- if(data->passwd &&
- needle->passwd &&
- strcmp(data->passwd, needle->passwd) != 0)
+
+ /* curl_strequal does a case insensitive comparison,
+ so do not use it here! */
+ if(Curl_timestrcmp(data->user, needle->user) ||
+ Curl_timestrcmp(data->passwd, needle->passwd))
return FALSE;
return TRUE;
}
@@ -1040,12 +939,27 @@
}
else {
- /* Use the general method for determining the death of a connection */
- dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
+ bool input_pending;
+
+ Curl_attach_connection(data, conn);
+ dead = !Curl_conn_is_alive(data, conn, &input_pending);
+ if(input_pending) {
+ /* For reuse, we want a "clean" connection state. The includes
+ * that we expect - in general - no waiting input data. Input
+ * waiting might be a TLS Notify Close, for example. We reject
+ * that.
+ * For protocols where data from other other end may arrive at
+ * any time (HTTP/2 PING for example), the protocol handler needs
+ * to install its own `connection_check` callback.
+ */
+ dead = TRUE;
+ }
+ Curl_detach_connection(data);
}
if(dead) {
- infof(data, "Connection %ld seems to be dead", conn->connection_id);
+ infof(data, "Connection %" CURL_FORMAT_CURL_OFF_T " seems to be dead",
+ conn->connection_id);
Curl_conncache_remove_conn(data, conn, FALSE);
return TRUE;
}
@@ -1204,13 +1118,13 @@
size_t multiplexed = 0;
/*
- * Note that if we use a HTTP proxy in normal mode (no tunneling), we
+ * Note that if we use an HTTP proxy in normal mode (no tunneling), we
* check connections to that proxy and not to the actual remote server.
*/
check = curr->ptr;
curr = curr->next;
- if(check->bits.connect_only || check->bits.close)
+ if(check->connect_only || check->bits.close)
/* connect-only or to-be-closed connections will not be reused */
continue;
@@ -1240,20 +1154,20 @@
/* primary_ip[0] is NUL only if the resolving of the name hasn't
completed yet and until then we don't re-use this connection */
if(!check->primary_ip[0]) {
- infof(data,
- "Connection #%ld is still name resolving, can't reuse",
+ infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T " is still "
+ "name resolving, can't reuse",
check->connection_id);
continue;
}
}
+ }
- if(check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) {
- foundPendingCandidate = TRUE;
- /* Don't pick a connection that hasn't connected yet */
- infof(data, "Connection #%ld isn't open enough, can't reuse",
- check->connection_id);
- continue;
- }
+ if(!Curl_conn_is_connected(check, FIRSTSOCKET)) {
+ foundPendingCandidate = TRUE;
+ /* Don't pick a connection that hasn't connected yet */
+ infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T
+ "isn't open enough, can't reuse", check->connection_id);
+ continue;
}
#ifdef USE_UNIX_SOCKETS
@@ -1306,21 +1220,19 @@
if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
continue;
- if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
+ if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) {
/* use https proxy */
- if(needle->handler->flags&PROTOPT_SSL) {
+ if(needle->http_proxy.proxytype !=
+ check->http_proxy.proxytype)
+ continue;
+ else if(needle->handler->flags&PROTOPT_SSL) {
/* use double layer ssl */
if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
&check->proxy_ssl_config))
continue;
- if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
- continue;
}
-
- if(!Curl_ssl_config_matches(&needle->ssl_config,
- &check->ssl_config))
- continue;
- if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
+ else if(!Curl_ssl_config_matches(&needle->ssl_config,
+ &check->ssl_config))
continue;
}
}
@@ -1362,35 +1274,55 @@
if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
/* This protocol requires credentials per connection,
so verify that we're using the same name and password as well */
- if(strcmp(needle->user, check->user) ||
- strcmp(needle->passwd, check->passwd) ||
- !Curl_safecmp(needle->sasl_authzid, check->sasl_authzid) ||
- !Curl_safecmp(needle->oauth_bearer, check->oauth_bearer)) {
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd) ||
+ Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) ||
+ Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) {
/* one of them was different */
continue;
}
}
+ /* GSS delegation differences do not actually affect every connection
+ and auth method, but this check takes precaution before efficiency */
+ if(needle->gssapi_delegation != check->gssapi_delegation)
+ continue;
+
/* If multiplexing isn't enabled on the h2 connection and h1 is
explicitly requested, handle it: */
if((needle->handler->protocol & PROTO_FAMILY_HTTP) &&
- (check->httpversion >= 20) &&
- (data->state.httpwant < CURL_HTTP_VERSION_2_0))
+ (((check->httpversion >= 20) &&
+ (data->state.httpwant < CURL_HTTP_VERSION_2_0))
+ || ((check->httpversion >= 30) &&
+ (data->state.httpwant < CURL_HTTP_VERSION_3))))
continue;
-
- if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) {
+#ifdef USE_SSH
+ else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
if(!ssh_config_matches(needle, check))
continue;
}
+#endif
+#ifndef CURL_DISABLE_FTP
+ else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) {
+ /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */
+ if(Curl_timestrcmp(needle->proto.ftpc.account,
+ check->proto.ftpc.account) ||
+ Curl_timestrcmp(needle->proto.ftpc.alternative_to_user,
+ check->proto.ftpc.alternative_to_user) ||
+ (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) ||
+ (needle->proto.ftpc.ccc != check->proto.ftpc.ccc))
+ continue;
+ }
+#endif
if((needle->handler->flags&PROTOPT_SSL)
#ifndef CURL_DISABLE_PROXY
|| !needle->bits.httpproxy || needle->bits.tunnel_proxy
#endif
) {
- /* The requested connection does not use a HTTP proxy or it uses SSL or
- it is a non-SSL protocol tunneled or it is a non-SSL protocol which
- is allowed to be upgraded via TLS */
+ /* The requested connection does not use an HTTP proxy or it uses SSL
+ or it is a non-SSL protocol tunneled or it is a non-SSL protocol
+ which is allowed to be upgraded via TLS */
if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
(get_protocol_family(check->handler) ==
@@ -1410,16 +1342,8 @@
if(!Curl_ssl_config_matches(&needle->ssl_config,
&check->ssl_config)) {
DEBUGF(infof(data,
- "Connection #%ld has different SSL parameters, "
- "can't reuse",
- check->connection_id));
- continue;
- }
- if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
- foundPendingCandidate = TRUE;
- DEBUGF(infof(data,
- "Connection #%ld has not started SSL connect, "
- "can't reuse",
+ "Connection #%" CURL_FORMAT_CURL_OFF_T
+ " has different SSL parameters, can't reuse",
check->connection_id));
continue;
}
@@ -1441,8 +1365,8 @@
possible. (Especially we must not reuse the same connection if
partway through a handshake!) */
if(wantNTLMhttp) {
- if(strcmp(needle->user, check->user) ||
- strcmp(needle->passwd, check->passwd)) {
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd)) {
/* we prefer a credential match, but this is at least a connection
that can be reused and "upgraded" to NTLM */
@@ -1464,8 +1388,10 @@
if(!check->http_proxy.user || !check->http_proxy.passwd)
continue;
- if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
- strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
+ if(Curl_timestrcmp(needle->http_proxy.user,
+ check->http_proxy.user) ||
+ Curl_timestrcmp(needle->http_proxy.passwd,
+ check->http_proxy.passwd))
continue;
}
else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
@@ -1503,9 +1429,8 @@
#ifdef USE_NGHTTP2
/* If multiplexed, make sure we don't go over concurrency limit */
if(check->bits.multiplex) {
- /* Multiplexed connections can only be HTTP/2 for now */
- struct http_conn *httpc = &check->proto.httpc;
- if(multiplexed >= httpc->settings.max_concurrent_streams) {
+ if(multiplexed >= Curl_conn_get_max_concurrent(data, check,
+ FIRSTSOCKET)) {
infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)",
multiplexed);
continue;
@@ -1559,123 +1484,18 @@
struct connectdata *conn)
{
if(data->set.verbose)
- infof(data, "Connected to %s (%s) port %u (#%ld)",
+ infof(data, "Connected to %s (%s) port %u",
#ifndef CURL_DISABLE_PROXY
conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
conn->bits.httpproxy ? conn->http_proxy.host.dispname :
#endif
conn->bits.conn_to_host ? conn->conn_to_host.dispname :
conn->host.dispname,
- conn->primary_ip, conn->port, conn->connection_id);
+ conn->primary_ip, conn->port);
}
#endif
/*
- * Helpers for IDNA conversions.
- */
-bool Curl_is_ASCII_name(const char *hostname)
-{
- /* get an UNSIGNED local version of the pointer */
- const unsigned char *ch = (const unsigned char *)hostname;
-
- if(!hostname) /* bad input, consider it ASCII! */
- return TRUE;
-
- while(*ch) {
- if(*ch++ & 0x80)
- return FALSE;
- }
- return TRUE;
-}
-
-/*
- * Perform any necessary IDN conversion of hostname
- */
-CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
- struct hostname *host)
-{
-#ifndef USE_LIBIDN2
- (void)data;
- (void)data;
-#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
- (void)data;
-#endif
-
- /* set the name we use to display the host name */
- host->dispname = host->name;
-
- /* Check name for non-ASCII and convert hostname to ACE form if we can */
- if(!Curl_is_ASCII_name(host->name)) {
-#ifdef USE_LIBIDN2
- if(idn2_check_version(IDN2_VERSION)) {
- char *ace_hostname = NULL;
-#if IDN2_VERSION_NUMBER >= 0x00140000
- /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
- IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
- processing. */
- int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL;
-#else
- int flags = IDN2_NFC_INPUT;
-#endif
- int rc = IDN2_LOOKUP(host->name, &ace_hostname, flags);
- if(rc != IDN2_OK)
- /* fallback to TR46 Transitional mode for better IDNA2003
- compatibility */
- rc = IDN2_LOOKUP(host->name, &ace_hostname,
- IDN2_TRANSITIONAL);
- if(rc == IDN2_OK) {
- host->encalloc = (char *)ace_hostname;
- /* change the name pointer to point to the encoded hostname */
- host->name = host->encalloc;
- }
- else {
- failf(data, "Failed to convert %s to ACE; %s", host->name,
- idn2_strerror(rc));
- return CURLE_URL_MALFORMAT;
- }
- }
-#elif defined(USE_WIN32_IDN)
- char *ace_hostname = NULL;
-
- if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
- host->encalloc = ace_hostname;
- /* change the name pointer to point to the encoded hostname */
- host->name = host->encalloc;
- }
- else {
- char buffer[STRERROR_LEN];
- failf(data, "Failed to convert %s to ACE; %s", host->name,
- Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
- return CURLE_URL_MALFORMAT;
- }
-#else
- infof(data, "IDN support not present, can't parse Unicode domains");
-#endif
- }
- return CURLE_OK;
-}
-
-/*
- * Frees data allocated by idnconvert_hostname()
- */
-void Curl_free_idnconverted_hostname(struct hostname *host)
-{
-#if defined(USE_LIBIDN2)
- if(host->encalloc) {
- idn2_free(host->encalloc); /* must be freed with idn2_free() since this was
- allocated by libidn */
- host->encalloc = NULL;
- }
-#elif defined(USE_WIN32_IDN)
- free(host->encalloc); /* must be freed with free() since this was
- allocated by curl_win32_idn_to_ascii */
- host->encalloc = NULL;
-#else
- (void)host;
-#endif
-}
-
-/*
* Allocate and initialize a new connectdata object.
*/
static struct connectdata *allocate_conn(struct Curl_easy *data)
@@ -1684,62 +1504,13 @@
if(!conn)
return NULL;
-#ifdef USE_SSL
- /* The SSL backend-specific data (ssl_backend_data) objects are allocated as
- a separate array to ensure suitable alignment.
- Note that these backend pointers can be swapped by vtls (eg ssl backend
- data becomes proxy backend data). */
- {
- size_t onesize = Curl_ssl->sizeof_ssl_backend_data;
- size_t totalsize = onesize;
- char *ssl;
-
-#ifndef CURL_DISABLE_FTP
- totalsize *= 2;
-#endif
-#ifndef CURL_DISABLE_PROXY
- totalsize *= 2;
-#endif
-
- ssl = calloc(1, totalsize);
- if(!ssl) {
- free(conn);
- return NULL;
- }
- conn->ssl_extra = ssl;
- conn->ssl[FIRSTSOCKET].backend = (void *)ssl;
-#ifndef CURL_DISABLE_FTP
- ssl += onesize;
- conn->ssl[SECONDARYSOCKET].backend = (void *)ssl;
-#endif
-#ifndef CURL_DISABLE_PROXY
- ssl += onesize;
- conn->proxy_ssl[FIRSTSOCKET].backend = (void *)ssl;
-#ifndef CURL_DISABLE_FTP
- ssl += onesize;
- conn->proxy_ssl[SECONDARYSOCKET].backend = (void *)ssl;
-#endif
-#endif
- }
-#endif
-
- conn->handler = &Curl_handler_dummy; /* Be sure we have a handler defined
- already from start to avoid NULL
- situations and checks */
-
/* and we setup a few fields in case we end up actually using this struct */
conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
- conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
- conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
conn->connection_id = -1; /* no ID */
conn->port = -1; /* unknown at this point */
conn->remote_port = -1; /* unknown at this point */
-#if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
- conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
- conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
-#endif /* USE_RECV_BEFORE_SEND_WORKAROUND && DEBUGBUILD */
/* Default protocol-independent behavior doesn't support persistent
connections, so we set this to force-close. Protocols that support
@@ -1750,7 +1521,7 @@
conn->created = Curl_now();
/* Store current time to give a baseline to keepalive connection times. */
- conn->keepalive = Curl_now();
+ conn->keepalive = conn->created;
#ifndef CURL_DISABLE_PROXY
conn->http_proxy.proxytype = data->set.proxytype;
@@ -1763,8 +1534,8 @@
conn->bits.httpproxy = (conn->bits.proxy &&
(conn->http_proxy.proxytype == CURLPROXY_HTTP ||
conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
- conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
- TRUE : FALSE;
+ IS_HTTPS_PROXY(conn->http_proxy.proxytype))) ?
+ TRUE : FALSE;
conn->bits.socksproxy = (conn->bits.proxy &&
!conn->bits.httpproxy) ? TRUE : FALSE;
@@ -1794,7 +1565,7 @@
conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options;
#endif
conn->ip_version = data->set.ipver;
- conn->bits.connect_only = data->set.connect_only;
+ conn->connect_only = data->set.connect_only;
conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
@@ -1823,30 +1594,30 @@
it may live on without (this specific) Curl_easy */
conn->fclosesocket = data->set.fclosesocket;
conn->closesocket_client = data->set.closesocket_client;
- conn->lastused = Curl_now(); /* used now */
+ conn->lastused = conn->created;
+ conn->gssapi_delegation = data->set.gssapi_delegation;
return conn;
- error:
+error:
- Curl_llist_destroy(&conn->easyq, NULL);
free(conn->localdev);
-#ifdef USE_SSL
- free(conn->ssl_extra);
-#endif
free(conn);
return NULL;
}
/* returns the handler if the given scheme is built-in */
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme)
+const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
+ size_t schemelen)
{
const struct Curl_handler * const *pp;
const struct Curl_handler *p;
/* Scan protocol handler table and match against 'scheme'. The handler may
be changed later when the protocol specific setup function is called. */
+ if(schemelen == CURL_ZERO_TERMINATED)
+ schemelen = strlen(scheme);
for(pp = protocols; (p = *pp) != NULL; pp++)
- if(strcasecompare(p->scheme, scheme))
- /* Protocol found in table. Check if allowed */
+ if(strncasecompare(p->scheme, scheme, schemelen) && !p->scheme[schemelen])
+ /* Protocol found in table. */
return p;
return NULL; /* not found */
}
@@ -1856,7 +1627,8 @@
struct connectdata *conn,
const char *protostr)
{
- const struct Curl_handler *p = Curl_builtin_scheme(protostr);
+ const struct Curl_handler *p = Curl_builtin_scheme(protostr,
+ CURL_ZERO_TERMINATED);
if(p && /* Protocol found in table. Check if allowed */
(data->set.allowed_protocols & p->protocol)) {
@@ -1980,7 +1752,7 @@
return CURLE_OUT_OF_MEMORY;
if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
- !Curl_is_absolute_url(data->state.url, NULL, 0)) {
+ !Curl_is_absolute_url(data->state.url, NULL, 0, TRUE)) {
char *url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
data->state.url);
if(!url)
@@ -1994,14 +1766,13 @@
if(!use_set_uh) {
char *newurl;
uc = curl_url_set(uh, CURLUPART_URL, data->state.url,
- CURLU_GUESS_SCHEME |
- CURLU_NON_SUPPORT_SCHEME |
- (data->set.disallow_username_in_url ?
- CURLU_DISALLOW_USER : 0) |
- (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
+ CURLU_GUESS_SCHEME |
+ CURLU_NON_SUPPORT_SCHEME |
+ (data->set.disallow_username_in_url ?
+ CURLU_DISALLOW_USER : 0) |
+ (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
if(uc) {
- DEBUGF(infof(data, "curl_url_set rejected %s: %s", data->state.url,
- curl_url_strerror(uc)));
+ failf(data, "URL rejected: %s", curl_url_strerror(uc));
return Curl_uc_to_curlcode(uc);
}
@@ -2024,10 +1795,43 @@
if(!strcasecompare("file", data->state.up.scheme))
return CURLE_OUT_OF_MEMORY;
}
+ else if(strlen(data->state.up.hostname) > MAX_URL_LEN) {
+ failf(data, "Too long host name (maximum is %d)", MAX_URL_LEN);
+ return CURLE_URL_MALFORMAT;
+ }
+ hostname = data->state.up.hostname;
+
+ if(hostname && hostname[0] == '[') {
+ /* This looks like an IPv6 address literal. See if there is an address
+ scope. */
+ size_t hlen;
+ conn->bits.ipv6_ip = TRUE;
+ /* cut off the brackets! */
+ hostname++;
+ hlen = strlen(hostname);
+ hostname[hlen - 1] = 0;
+
+ zonefrom_url(uh, data, conn);
+ }
+
+ /* make sure the connect struct gets its own copy of the host name */
+ conn->host.rawalloc = strdup(hostname ? hostname : "");
+ if(!conn->host.rawalloc)
+ return CURLE_OUT_OF_MEMORY;
+ conn->host.name = conn->host.rawalloc;
+
+ /*************************************************************
+ * IDN-convert the hostnames
+ *************************************************************/
+ result = Curl_idnconvert_hostname(&conn->host);
+ if(result)
+ return result;
#ifndef CURL_DISABLE_HSTS
+ /* HSTS upgrade */
if(data->hsts && strcasecompare("http", data->state.up.scheme)) {
- if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) {
+ /* This MUST use the IDN decoded name */
+ if(Curl_hsts(data->hsts, conn->host.name, TRUE)) {
char *url;
Curl_safefree(data->state.up.scheme);
uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0);
@@ -2060,7 +1864,7 @@
* User name and password set with their own options override the
* credentials possibly set in the URL.
*/
- if(!data->state.aptr.passwd) {
+ if(!data->set.str[STRING_PASSWORD]) {
uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
if(!uc) {
char *decoded;
@@ -2078,7 +1882,7 @@
return Curl_uc_to_curlcode(uc);
}
- if(!data->state.aptr.user) {
+ if(!data->set.str[STRING_USERNAME]) {
/* we don't use the URL API's URL decoder option here since it rejects
control codes and we want to allow them for some schemes in the user
and password fields */
@@ -2128,31 +1932,11 @@
unsigned long port = strtoul(data->state.up.port, NULL, 10);
conn->port = conn->remote_port =
(data->set.use_port && data->state.allow_port) ?
- (int)data->set.use_port : curlx_ultous(port);
+ data->set.use_port : curlx_ultous(port);
}
(void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
- hostname = data->state.up.hostname;
- if(hostname && hostname[0] == '[') {
- /* This looks like an IPv6 address literal. See if there is an address
- scope. */
- size_t hlen;
- conn->bits.ipv6_ip = TRUE;
- /* cut off the brackets! */
- hostname++;
- hlen = strlen(hostname);
- hostname[hlen - 1] = 0;
-
- zonefrom_url(uh, data, conn);
- }
-
- /* make sure the connect struct gets its own copy of the host name */
- conn->host.rawalloc = strdup(hostname ? hostname : "");
- if(!conn->host.rawalloc)
- return CURLE_OUT_OF_MEMORY;
- conn->host.name = conn->host.rawalloc;
-
#ifdef ENABLE_IPV6
if(data->set.scope_id)
/* Override any scope that was set above. */
@@ -2250,83 +2034,6 @@
#ifndef CURL_DISABLE_PROXY
-/****************************************************************
-* Checks if the host is in the noproxy list. returns true if it matches
-* and therefore the proxy should NOT be used.
-****************************************************************/
-static bool check_noproxy(const char *name, const char *no_proxy)
-{
- /* no_proxy=domain1.dom,host.domain2.dom
- * (a comma-separated list of hosts which should
- * not be proxied, or an asterisk to override
- * all proxy variables)
- */
- if(no_proxy && no_proxy[0]) {
- size_t tok_start;
- size_t tok_end;
- const char *separator = ", ";
- size_t no_proxy_len;
- size_t namelen;
- char *endptr;
- if(strcasecompare("*", no_proxy)) {
- return TRUE;
- }
-
- /* NO_PROXY was specified and it wasn't just an asterisk */
-
- no_proxy_len = strlen(no_proxy);
- if(name[0] == '[') {
- /* IPv6 numerical address */
- endptr = strchr(name, ']');
- if(!endptr)
- return FALSE;
- name++;
- namelen = endptr - name;
- }
- else
- namelen = strlen(name);
-
- for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
- while(tok_start < no_proxy_len &&
- strchr(separator, no_proxy[tok_start]) != NULL) {
- /* Look for the beginning of the token. */
- ++tok_start;
- }
-
- if(tok_start == no_proxy_len)
- break; /* It was all trailing separator chars, no more tokens. */
-
- for(tok_end = tok_start; tok_end < no_proxy_len &&
- strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
- /* Look for the end of the token. */
- ;
-
- /* To match previous behavior, where it was necessary to specify
- * ".local.com" to prevent matching "notlocal.com", we will leave
- * the '.' off.
- */
- if(no_proxy[tok_start] == '.')
- ++tok_start;
-
- if((tok_end - tok_start) <= namelen) {
- /* Match the last part of the name to the domain we are checking. */
- const char *checkn = name + namelen - (tok_end - tok_start);
- if(strncasecompare(no_proxy + tok_start, checkn,
- tok_end - tok_start)) {
- if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
- /* We either have an exact match, or the previous character is a .
- * so it is within the same domain, so no proxy for this host.
- */
- return TRUE;
- }
- }
- } /* if((tok_end - tok_start) <= namelen) */
- } /* for(tok_start = 0; tok_start < no_proxy_len;
- tok_start = tok_end + 1) */
- } /* NO_PROXY was specified and it wasn't just an asterisk */
-
- return FALSE;
-}
#ifndef CURL_DISABLE_HTTP
/****************************************************************
@@ -2366,7 +2073,7 @@
/* Now, build <protocol>_proxy and check for such a one to use */
while(*protop)
- *envp++ = (char)tolower((int)*protop++);
+ *envp++ = Curl_raw_tolower(*protop++);
/* append _proxy */
strcpy(envp, "_proxy");
@@ -2454,8 +2161,12 @@
goto error;
}
- if(strcasecompare("https", scheme))
- proxytype = CURLPROXY_HTTPS;
+ if(strcasecompare("https", scheme)) {
+ if(proxytype != CURLPROXY_HTTPS2)
+ proxytype = CURLPROXY_HTTPS;
+ else
+ proxytype = CURLPROXY_HTTPS2;
+ }
else if(strcasecompare("socks5h", scheme))
proxytype = CURLPROXY_SOCKS5_HOSTNAME;
else if(strcasecompare("socks5", scheme))
@@ -2475,17 +2186,18 @@
}
}
else {
- failf(data, "Unsupported proxy syntax in \'%s\'", proxy);
+ failf(data, "Unsupported proxy syntax in \'%s\': %s", proxy,
+ curl_url_strerror(uc));
result = CURLE_COULDNT_RESOLVE_PROXY;
goto error;
}
#ifdef USE_SSL
- if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
+ if(!Curl_ssl_supports(data, SSLSUPP_HTTPS_PROXY))
#endif
- if(proxytype == CURLPROXY_HTTPS) {
+ if(IS_HTTPS_PROXY(proxytype)) {
failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
- "HTTPS-proxy support.", proxy);
+ "HTTPS-proxy support.", proxy);
result = CURLE_NOT_BUILT_IN;
goto error;
}
@@ -2497,7 +2209,7 @@
proxytype == CURLPROXY_SOCKS4;
proxyinfo = sockstype ? &conn->socks_proxy : &conn->http_proxy;
- proxyinfo->proxytype = proxytype;
+ proxyinfo->proxytype = (unsigned char)proxytype;
/* Is there a username and password given in this proxy url? */
uc = curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE);
@@ -2542,7 +2254,7 @@
given */
port = (int)data->set.proxyport;
else {
- if(proxytype == CURLPROXY_HTTPS)
+ if(IS_HTTPS_PROXY(proxytype))
port = CURL_DEFAULT_HTTPS_PROXY_PORT;
else
port = CURL_DEFAULT_PROXY_PORT;
@@ -2567,7 +2279,7 @@
result = CURLE_OUT_OF_MEMORY;
goto error;
}
- /* path will be "/", if no path was was found */
+ /* path will be "/", if no path was found */
if(strcmp("/", path)) {
is_unix_proxy = TRUE;
free(host);
@@ -2600,7 +2312,7 @@
}
#endif
- error:
+error:
free(proxyuser);
free(proxypasswd);
free(host);
@@ -2622,22 +2334,17 @@
data->state.aptr.proxyuser : "";
const char *proxypasswd = data->state.aptr.proxypasswd ?
data->state.aptr.proxypasswd : "";
- CURLcode result = CURLE_OK;
-
- if(proxyuser) {
- result = Curl_urldecode(proxyuser, 0, &conn->http_proxy.user, NULL,
- REJECT_ZERO);
- if(!result)
- result = Curl_setstropt(&data->state.aptr.proxyuser,
- conn->http_proxy.user);
- }
- if(!result && proxypasswd) {
+ CURLcode result = Curl_urldecode(proxyuser, 0, &conn->http_proxy.user, NULL,
+ REJECT_ZERO);
+ if(!result)
+ result = Curl_setstropt(&data->state.aptr.proxyuser,
+ conn->http_proxy.user);
+ if(!result)
result = Curl_urldecode(proxypasswd, 0, &conn->http_proxy.passwd,
NULL, REJECT_ZERO);
- if(!result)
- result = Curl_setstropt(&data->state.aptr.proxypasswd,
- conn->http_proxy.passwd);
- }
+ if(!result)
+ result = Curl_setstropt(&data->state.aptr.proxypasswd,
+ conn->http_proxy.passwd);
return result;
}
@@ -2650,6 +2357,7 @@
char *socksproxy = NULL;
char *no_proxy = NULL;
CURLcode result = CURLE_OK;
+ bool spacesep = FALSE;
/*************************************************************
* Extract the user and password from the authentication string
@@ -2695,8 +2403,9 @@
}
}
- if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
- data->set.str[STRING_NOPROXY] : no_proxy)) {
+ if(Curl_check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
+ data->set.str[STRING_NOPROXY] : no_proxy,
+ &spacesep)) {
Curl_safefree(proxy);
Curl_safefree(socksproxy);
}
@@ -2705,6 +2414,8 @@
/* if the host is not in the noproxy list, detect proxy. */
proxy = detect_proxy(data, conn);
#endif /* CURL_DISABLE_HTTP */
+ if(spacesep)
+ infof(data, "space-separated NOPROXY patterns are deprecated");
Curl_safefree(no_proxy);
@@ -2734,16 +2445,16 @@
* connection that may exist registered to the same proxy host.
***********************************************************************/
if(proxy || socksproxy) {
+ curl_proxytype ptype = (curl_proxytype)conn->http_proxy.proxytype;
if(proxy) {
- result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
+ result = parse_proxy(data, conn, proxy, ptype);
Curl_safefree(proxy); /* parse_proxy copies the proxy string */
if(result)
goto out;
}
if(socksproxy) {
- result = parse_proxy(data, conn, socksproxy,
- conn->socks_proxy.proxytype);
+ result = parse_proxy(data, conn, socksproxy, ptype);
/* parse_proxy copies the socks proxy string */
Curl_safefree(socksproxy);
if(result)
@@ -2752,7 +2463,7 @@
if(conn->http_proxy.host.rawalloc) {
#ifdef CURL_DISABLE_HTTP
- /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
+ /* asking for an HTTP proxy is a bit funny when HTTP is disabled... */
result = CURLE_UNSUPPORTED_PROTOCOL;
goto out;
#else
@@ -2769,7 +2480,7 @@
#endif
}
else {
- conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
+ conn->bits.httpproxy = FALSE; /* not an HTTP proxy */
conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
}
@@ -2858,29 +2569,13 @@
size_t plen;
size_t olen;
- /* the input length check is because this is called directly from setopt
- and isn't going through the regular string length check */
- size_t llen = strlen(login);
- if(llen > CURL_MAX_INPUT_LENGTH)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
/* Attempt to find the password separator */
- if(passwdp) {
- psep = strchr(login, ':');
-
- /* Within the constraint of the login string */
- if(psep >= login + len)
- psep = NULL;
- }
+ if(passwdp)
+ psep = memchr(login, ':', len);
/* Attempt to find the options separator */
- if(optionsp) {
- osep = strchr(login, ';');
-
- /* Within the constraint of the login string */
- if(osep >= login + len)
- osep = NULL;
- }
+ if(optionsp)
+ osep = memchr(login, ';', len);
/* Calculate the portion lengths */
ulen = (psep ?
@@ -2893,15 +2588,15 @@
(psep && psep > osep ? (size_t)(psep - osep) :
(size_t)(login + len - osep)) - 1 : 0);
- /* Allocate the user portion buffer */
- if(userp && ulen) {
+ /* Allocate the user portion buffer, which can be zero length */
+ if(userp) {
ubuf = malloc(ulen + 1);
if(!ubuf)
result = CURLE_OUT_OF_MEMORY;
}
/* Allocate the password portion buffer */
- if(!result && passwdp && plen) {
+ if(!result && passwdp && psep) {
pbuf = malloc(plen + 1);
if(!pbuf) {
free(ubuf);
@@ -2964,7 +2659,7 @@
/* if set, we use this instead of the port possibly given in the URL */
char portbuf[16];
CURLUcode uc;
- conn->remote_port = (unsigned short)data->set.use_port;
+ conn->remote_port = data->set.use_port;
msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port);
uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
if(uc)
@@ -2986,14 +2681,6 @@
char **passwdp = &conn->passwd;
char **optionsp = &conn->options;
-#ifndef CURL_DISABLE_NETRC
- if(data->set.use_netrc == CURL_NETRC_REQUIRED && data->state.aptr.user) {
- Curl_safefree(*userp);
- Curl_safefree(*passwdp);
- Curl_safefree(data->state.aptr.user); /* disable user+password */
- }
-#endif
-
if(data->set.str[STRING_OPTIONS]) {
free(*optionsp);
*optionsp = strdup(data->set.str[STRING_OPTIONS]);
@@ -3002,22 +2689,23 @@
}
#ifndef CURL_DISABLE_NETRC
+ if(data->set.use_netrc == CURL_NETRC_REQUIRED) {
+ Curl_safefree(*userp);
+ Curl_safefree(*passwdp);
+ }
conn->bits.netrc = FALSE;
if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) {
- bool netrc_user_changed = FALSE;
- bool netrc_passwd_changed = FALSE;
int ret;
bool url_provided = FALSE;
- if(data->state.up.user) {
- /* there was a user name in the URL */
- userp = &data->state.up.user;
+ if(data->state.aptr.user) {
+ /* there was a user name in the URL. Use the URL decoded version */
+ userp = &data->state.aptr.user;
url_provided = TRUE;
}
ret = Curl_parsenetrc(conn->host.name,
userp, passwdp,
- &netrc_user_changed, &netrc_passwd_changed,
data->set.str[STRING_NETRC_FILE]);
if(ret > 0) {
infof(data, "Couldn't find host %s in the %s file; using defaults",
@@ -3038,29 +2726,35 @@
conn->user = strdup(*userp);
if(!conn->user)
return CURLE_OUT_OF_MEMORY;
- /* don't update the user name below */
- userp = NULL;
+ }
+ /* no user was set but a password, set a blank user */
+ if(!*userp && *passwdp) {
+ *userp = strdup("");
+ if(!*userp)
+ return CURLE_OUT_OF_MEMORY;
}
}
#endif
/* for updated strings, we update them in the URL */
- if(userp) {
- if(*userp) {
- CURLcode result = Curl_setstropt(&data->state.aptr.user, *userp);
+ if(*userp) {
+ CURLcode result;
+ if(data->state.aptr.user != *userp) {
+ /* nothing to do then */
+ result = Curl_setstropt(&data->state.aptr.user, *userp);
if(result)
return result;
}
- if(data->state.aptr.user) {
- uc = curl_url_set(data->state.uh, CURLUPART_USER, data->state.aptr.user,
- CURLU_URLENCODE);
- if(uc)
- return Curl_uc_to_curlcode(uc);
- if(!*userp) {
- *userp = strdup(data->state.aptr.user);
- if(!*userp)
- return CURLE_OUT_OF_MEMORY;
- }
+ }
+ if(data->state.aptr.user) {
+ uc = curl_url_set(data->state.uh, CURLUPART_USER, data->state.aptr.user,
+ CURLU_URLENCODE);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+ if(!*userp) {
+ *userp = strdup(data->state.aptr.user);
+ if(!*userp)
+ return CURLE_OUT_OF_MEMORY;
}
}
if(*passwdp) {
@@ -3206,17 +2900,16 @@
}
/* now, clone the cleaned host name */
- if(hostptr) {
- *hostname_result = strdup(hostptr);
- if(!*hostname_result) {
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
+ DEBUGASSERT(hostptr);
+ *hostname_result = strdup(hostptr);
+ if(!*hostname_result) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
}
*port_result = port;
- error:
+error:
free(host_dup);
return result;
}
@@ -3413,6 +3106,146 @@
return result;
}
+#ifdef USE_UNIX_SOCKETS
+static CURLcode resolve_unix(struct Curl_easy *data,
+ struct connectdata *conn,
+ char *unix_path)
+{
+ struct Curl_dns_entry *hostaddr = NULL;
+ bool longpath = FALSE;
+
+ DEBUGASSERT(unix_path);
+ DEBUGASSERT(conn->dns_entry == NULL);
+
+ /* 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 filesystem path available. */
+ hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
+ if(!hostaddr)
+ return CURLE_OUT_OF_MEMORY;
+
+ hostaddr->addr = Curl_unix2addr(unix_path, &longpath,
+ conn->bits.abstract_unix_socket);
+ if(!hostaddr->addr) {
+ if(longpath)
+ /* Long paths are not supported for now */
+ failf(data, "Unix socket path too long: '%s'", unix_path);
+ free(hostaddr);
+ return longpath ? CURLE_COULDNT_RESOLVE_HOST : CURLE_OUT_OF_MEMORY;
+ }
+
+ hostaddr->inuse++;
+ conn->dns_entry = hostaddr;
+ return CURLE_OK;
+}
+#endif
+
+#ifndef CURL_DISABLE_PROXY
+static CURLcode resolve_proxy(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool *async)
+{
+ struct Curl_dns_entry *hostaddr = NULL;
+ struct hostname *host;
+ timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ int rc;
+
+ DEBUGASSERT(conn->dns_entry == NULL);
+
+ host = conn->bits.socksproxy ? &conn->socks_proxy.host :
+ &conn->http_proxy.host;
+
+ conn->hostname_resolve = strdup(host->name);
+ if(!conn->hostname_resolve)
+ return CURLE_OUT_OF_MEMORY;
+
+ rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
+ &hostaddr, timeout_ms);
+ conn->dns_entry = hostaddr;
+ if(rc == CURLRESOLV_PENDING)
+ *async = TRUE;
+ else if(rc == CURLRESOLV_TIMEDOUT)
+ return CURLE_OPERATION_TIMEDOUT;
+ else if(!hostaddr) {
+ failf(data, "Couldn't resolve proxy '%s'", host->dispname);
+ return CURLE_COULDNT_RESOLVE_PROXY;
+ }
+
+ return CURLE_OK;
+}
+#endif
+
+static CURLcode resolve_host(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool *async)
+{
+ struct Curl_dns_entry *hostaddr = NULL;
+ struct hostname *connhost;
+ timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ int rc;
+
+ DEBUGASSERT(conn->dns_entry == NULL);
+
+ connhost = conn->bits.conn_to_host ? &conn->conn_to_host : &conn->host;
+
+ /* If not connecting via a proxy, extract the port from the URL, if it is
+ * there, thus overriding any defaults that might have been set above. */
+ conn->port = conn->bits.conn_to_port ? conn->conn_to_port :
+ conn->remote_port;
+
+ /* Resolve target host right on */
+ conn->hostname_resolve = strdup(connhost->name);
+ if(!conn->hostname_resolve)
+ return CURLE_OUT_OF_MEMORY;
+
+ rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
+ &hostaddr, timeout_ms);
+ conn->dns_entry = hostaddr;
+ if(rc == CURLRESOLV_PENDING)
+ *async = TRUE;
+ else if(rc == CURLRESOLV_TIMEDOUT) {
+ failf(data, "Failed to resolve host '%s' with timeout after %ld ms",
+ connhost->dispname,
+ Curl_timediff(Curl_now(), data->progress.t_startsingle));
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ else if(!hostaddr) {
+ failf(data, "Could not resolve host: %s", connhost->dispname);
+ return CURLE_COULDNT_RESOLVE_HOST;
+ }
+
+ return CURLE_OK;
+}
+
+/* Perform a fresh resolve */
+static CURLcode resolve_fresh(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool *async)
+{
+#ifdef USE_UNIX_SOCKETS
+ char *unix_path = conn->unix_domain_socket;
+
+#ifndef CURL_DISABLE_PROXY
+ if(!unix_path && conn->socks_proxy.host.name &&
+ !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
+
+ if(unix_path) {
+ conn->transport = TRNSPRT_UNIX;
+ return resolve_unix(data, conn, unix_path);
+ }
+#endif
+
+#ifndef CURL_DISABLE_PROXY
+ if(CONN_IS_PROXIED(conn))
+ return resolve_proxy(data, conn, async);
+#endif
+
+ return resolve_host(data, conn, async);
+}
+
/*************************************************************
* Resolve the address of the server or proxy
*************************************************************/
@@ -3420,211 +3253,95 @@
struct connectdata *conn,
bool *async)
{
- CURLcode result = CURLE_OK;
- timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
-
DEBUGASSERT(conn);
DEBUGASSERT(data);
- /*************************************************************
- * Resolve the name of the server or proxy
- *************************************************************/
- if(conn->bits.reuse)
+
+ /* Resolve the name of the server or proxy */
+ if(conn->bits.reuse) {
/* We're reusing the connection - no need to resolve anything, and
idnconvert_hostname() was called already in create_conn() for the re-use
case. */
*async = FALSE;
-
- else {
- /* this is a fresh connect */
- int rc;
- struct Curl_dns_entry *hostaddr = NULL;
-
-#ifdef USE_UNIX_SOCKETS
- char *unix_path = NULL;
-
- if(conn->unix_domain_socket)
- unix_path = conn->unix_domain_socket;
-#ifndef CURL_DISABLE_PROXY
- else if(conn->socks_proxy.host.name
- && !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
-
- if(unix_path) {
- /* 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 filesystem path available */
-
- hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
- if(!hostaddr)
- result = CURLE_OUT_OF_MEMORY;
- else {
- bool longpath = FALSE;
- hostaddr->addr = Curl_unix2addr(unix_path, &longpath,
- conn->bits.abstract_unix_socket);
- if(hostaddr->addr)
- hostaddr->inuse++;
- else {
- /* Long paths are not supported for now */
- if(longpath) {
- failf(data, "Unix socket path too long: '%s'", unix_path);
- result = CURLE_COULDNT_RESOLVE_HOST;
- }
- else
- result = CURLE_OUT_OF_MEMORY;
- free(hostaddr);
- hostaddr = NULL;
- }
- }
- }
- else
-#endif
-
- if(!CONN_IS_PROXIED(conn)) {
- struct hostname *connhost;
- if(conn->bits.conn_to_host)
- connhost = &conn->conn_to_host;
- else
- connhost = &conn->host;
-
- /* If not connecting via a proxy, extract the port from the URL, if it is
- * there, thus overriding any defaults that might have been set above. */
- if(conn->bits.conn_to_port)
- conn->port = conn->conn_to_port;
- else
- conn->port = conn->remote_port;
-
- /* Resolve target host right on */
- conn->hostname_resolve = strdup(connhost->name);
- if(!conn->hostname_resolve)
- return CURLE_OUT_OF_MEMORY;
- rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
- &hostaddr, timeout_ms);
- if(rc == CURLRESOLV_PENDING)
- *async = TRUE;
-
- else if(rc == CURLRESOLV_TIMEDOUT) {
- failf(data, "Failed to resolve host '%s' with timeout after %ld ms",
- connhost->dispname,
- Curl_timediff(Curl_now(), data->progress.t_startsingle));
- result = CURLE_OPERATION_TIMEDOUT;
- }
- else if(!hostaddr) {
- failf(data, "Could not resolve host: %s", connhost->dispname);
- result = CURLE_COULDNT_RESOLVE_HOST;
- /* don't return yet, we need to clean up the timeout first */
- }
- }
-#ifndef CURL_DISABLE_PROXY
- else {
- /* This is a proxy that hasn't been resolved yet. */
-
- struct hostname * const host = conn->bits.socksproxy ?
- &conn->socks_proxy.host : &conn->http_proxy.host;
-
- /* resolve proxy */
- conn->hostname_resolve = strdup(host->name);
- if(!conn->hostname_resolve)
- return CURLE_OUT_OF_MEMORY;
- rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
- &hostaddr, timeout_ms);
-
- if(rc == CURLRESOLV_PENDING)
- *async = TRUE;
-
- else if(rc == CURLRESOLV_TIMEDOUT)
- result = CURLE_OPERATION_TIMEDOUT;
-
- else if(!hostaddr) {
- failf(data, "Couldn't resolve proxy '%s'", host->dispname);
- result = CURLE_COULDNT_RESOLVE_PROXY;
- /* don't return yet, we need to clean up the timeout first */
- }
- }
-#endif
- DEBUGASSERT(conn->dns_entry == NULL);
- conn->dns_entry = hostaddr;
+ return CURLE_OK;
}
- return result;
+ return resolve_fresh(data, conn, async);
}
/*
- * Cleanup the connection just allocated before we can move along and use the
- * previously existing one. All relevant data is copied over and old_conn is
- * ready for freeing once this function returns.
+ * Cleanup the connection `temp`, just allocated for `data`, before using the
+ * previously `existing` one for `data`. All relevant info is copied over
+ * and `temp` is freed.
*/
static void reuse_conn(struct Curl_easy *data,
- struct connectdata *old_conn,
- struct connectdata *conn)
+ struct connectdata *temp,
+ struct connectdata *existing)
{
- /* 'local_ip' and 'local_port' get filled with local's numerical
- ip address and port number whenever an outgoing connection is
- **established** from the primary socket to a remote address. */
- char local_ip[MAX_IPADR_LEN] = "";
- int local_port = -1;
-
- /* get the user+password information from the old_conn struct since it may
+ /* get the user+password information from the temp struct since it may
* be new for this request even when we re-use an existing connection */
- if(old_conn->user) {
+ if(temp->user) {
/* use the new user name and password though */
- Curl_safefree(conn->user);
- Curl_safefree(conn->passwd);
- conn->user = old_conn->user;
- conn->passwd = old_conn->passwd;
- old_conn->user = NULL;
- old_conn->passwd = NULL;
+ Curl_safefree(existing->user);
+ Curl_safefree(existing->passwd);
+ existing->user = temp->user;
+ existing->passwd = temp->passwd;
+ temp->user = NULL;
+ temp->passwd = NULL;
}
#ifndef CURL_DISABLE_PROXY
- conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
- if(conn->bits.proxy_user_passwd) {
+ existing->bits.proxy_user_passwd = temp->bits.proxy_user_passwd;
+ if(existing->bits.proxy_user_passwd) {
/* use the new proxy user name and proxy password though */
- Curl_safefree(conn->http_proxy.user);
- Curl_safefree(conn->socks_proxy.user);
- Curl_safefree(conn->http_proxy.passwd);
- Curl_safefree(conn->socks_proxy.passwd);
- conn->http_proxy.user = old_conn->http_proxy.user;
- conn->socks_proxy.user = old_conn->socks_proxy.user;
- conn->http_proxy.passwd = old_conn->http_proxy.passwd;
- conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
- old_conn->http_proxy.user = NULL;
- old_conn->socks_proxy.user = NULL;
- old_conn->http_proxy.passwd = NULL;
- old_conn->socks_proxy.passwd = NULL;
+ Curl_safefree(existing->http_proxy.user);
+ Curl_safefree(existing->socks_proxy.user);
+ Curl_safefree(existing->http_proxy.passwd);
+ Curl_safefree(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;
+ existing->socks_proxy.passwd = temp->socks_proxy.passwd;
+ temp->http_proxy.user = NULL;
+ temp->socks_proxy.user = NULL;
+ temp->http_proxy.passwd = NULL;
+ temp->socks_proxy.passwd = NULL;
}
#endif
- Curl_free_idnconverted_hostname(&conn->host);
- Curl_free_idnconverted_hostname(&conn->conn_to_host);
- Curl_safefree(conn->host.rawalloc);
- Curl_safefree(conn->conn_to_host.rawalloc);
- conn->host = old_conn->host;
- old_conn->host.rawalloc = NULL;
- old_conn->host.encalloc = NULL;
- conn->conn_to_host = old_conn->conn_to_host;
- old_conn->conn_to_host.rawalloc = NULL;
- conn->conn_to_port = old_conn->conn_to_port;
- conn->remote_port = old_conn->remote_port;
- Curl_safefree(conn->hostname_resolve);
+ /* Finding a connection for reuse in the cache matches, among other
+ * things on the "remote-relevant" hostname. This is not necessarily
+ * the authority of the URL, e.g. conn->host. For example:
+ * - we use a proxy (not tunneling). we want to send all requests
+ * that use the same proxy on this connection.
+ * - we have a "connect-to" setting that may redirect the hostname of
+ * a new request to the same remote endpoint of an existing conn.
+ * We want to reuse an existing conn to the remote endpoint.
+ * Since connection reuse does not match on conn->host necessarily, we
+ * switch `existing` conn to `temp` conn's host settings.
+ * TODO: is this correct in the case of TLS connections that have
+ * used the original hostname in SNI to negotiate? Do we send
+ * requests for another host through the different SNI?
+ */
+ Curl_free_idnconverted_hostname(&existing->host);
+ Curl_free_idnconverted_hostname(&existing->conn_to_host);
+ Curl_safefree(existing->host.rawalloc);
+ Curl_safefree(existing->conn_to_host.rawalloc);
+ existing->host = temp->host;
+ temp->host.rawalloc = NULL;
+ temp->host.encalloc = NULL;
+ existing->conn_to_host = temp->conn_to_host;
+ temp->conn_to_host.rawalloc = NULL;
+ existing->conn_to_port = temp->conn_to_port;
+ existing->remote_port = temp->remote_port;
+ Curl_safefree(existing->hostname_resolve);
- conn->hostname_resolve = old_conn->hostname_resolve;
- old_conn->hostname_resolve = NULL;
-
- /* persist connection info in session handle */
- if(conn->transport == TRNSPRT_TCP) {
- Curl_conninfo_local(data, conn->sock[FIRSTSOCKET],
- local_ip, &local_port);
- }
- Curl_persistconninfo(data, conn, local_ip, local_port);
-
- conn_reset_all_postponed_data(old_conn); /* free buffers */
+ existing->hostname_resolve = temp->hostname_resolve;
+ temp->hostname_resolve = NULL;
/* re-use init */
- conn->bits.reuse = TRUE; /* yes, we're re-using here */
+ existing->bits.reuse = TRUE; /* yes, we're re-using here */
- conn_free(old_conn);
+ conn_free(data, temp);
}
/**
@@ -3648,7 +3365,7 @@
{
CURLcode result = CURLE_OK;
struct connectdata *conn;
- struct connectdata *conn_temp = NULL;
+ struct connectdata *existing = NULL;
bool reuse;
bool connections_available = TRUE;
bool force_reuse = FALSE;
@@ -3755,28 +3472,25 @@
goto out;
/*************************************************************
- * IDN-convert the hostnames
+ * IDN-convert the proxy hostnames
*************************************************************/
- result = Curl_idnconvert_hostname(data, &conn->host);
- if(result)
- goto out;
- if(conn->bits.conn_to_host) {
- result = Curl_idnconvert_hostname(data, &conn->conn_to_host);
- if(result)
- goto out;
- }
#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy) {
- result = Curl_idnconvert_hostname(data, &conn->http_proxy.host);
+ result = Curl_idnconvert_hostname(&conn->http_proxy.host);
if(result)
- goto out;
+ return result;
}
if(conn->bits.socksproxy) {
- result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host);
+ result = Curl_idnconvert_hostname(&conn->socks_proxy.host);
if(result)
- goto out;
+ return result;
}
#endif
+ if(conn->bits.conn_to_host) {
+ result = Curl_idnconvert_hostname(&conn->conn_to_host);
+ if(result)
+ return result;
+ }
/*************************************************************
* Check whether the host and the "connect to host" are equal.
@@ -3813,13 +3527,6 @@
if(result)
goto out;
- conn->recv[FIRSTSOCKET] = Curl_recv_plain;
- conn->send[FIRSTSOCKET] = Curl_send_plain;
- conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
- conn->send[SECONDARYSOCKET] = Curl_send_plain;
-
- conn->bits.tcp_fastopen = data->set.tcp_fastopen;
-
/***********************************************************************
* file: is a special case in that it doesn't need a network connection
***********************************************************************/
@@ -3834,8 +3541,6 @@
/* Setup a "faked" transfer that'll do nothing */
if(!result) {
- conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
-
Curl_attach_connection(data, conn);
result = Curl_conncache_add_conn(data);
if(result)
@@ -3861,6 +3566,13 @@
}
#endif
+ /* Setup filter for network connections */
+ conn->recv[FIRSTSOCKET] = Curl_conn_recv;
+ conn->send[FIRSTSOCKET] = Curl_conn_send;
+ conn->recv[SECONDARYSOCKET] = Curl_conn_recv;
+ conn->send[SECONDARYSOCKET] = Curl_conn_send;
+ conn->bits.tcp_fastopen = data->set.tcp_fastopen;
+
/* Get a cloned copy of the SSL config situation stored in the
connection struct. But to get this going nicely, we must first make
sure that the strings in the master copy are pointing to the correct
@@ -3954,34 +3666,33 @@
/* reuse_fresh is TRUE if we are told to use a new connection by force, but
we only acknowledge this option if this is not a re-used connection
- already (which happens due to follow-location or during a HTTP
+ already (which happens due to follow-location or during an HTTP
authentication phase). CONNECT_ONLY transfers also refuse reuse. */
- if((data->set.reuse_fresh && !data->state.this_is_a_follow) ||
+ if((data->set.reuse_fresh && !data->state.followlocation) ||
data->set.connect_only)
reuse = FALSE;
else
- reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
+ reuse = ConnectionExists(data, conn, &existing, &force_reuse, &waitpipe);
if(reuse) {
/*
* We already have a connection for this, we got the former connection in
- * the conn_temp variable and thus we need to cleanup the one we just
- * allocated before we can move along and use the previously existing one.
+ * `existing` and thus we need to cleanup the one we just
+ * allocated before we can move along and use `existing`.
*/
- reuse_conn(data, conn, conn_temp);
- conn = conn_temp;
+ reuse_conn(data, conn, existing);
+ conn = existing;
*in_connect = conn;
#ifndef CURL_DISABLE_PROXY
- infof(data, "Re-using existing connection #%ld with %s %s",
- conn->connection_id,
+ infof(data, "Re-using existing connection with %s %s",
conn->bits.proxy?"proxy":"host",
conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
conn->host.dispname);
#else
- infof(data, "Re-using existing connection #%ld with host %s",
- conn->connection_id, conn->host.dispname);
+ infof(data, "Re-using existing connection with host %s",
+ conn->host.dispname);
#endif
}
else {
@@ -3989,13 +3700,11 @@
be able to do that if we have reached the limit of how many
connections we are allowed to open. */
- if(conn->handler->flags & PROTOPT_ALPN_NPN) {
+ if(conn->handler->flags & PROTOPT_ALPN) {
/* The protocol wants it, so set the bits if enabled in the easy handle
(default) */
if(data->set.ssl_enable_alpn)
conn->bits.tls_enable_alpn = TRUE;
- if(data->set.ssl_enable_npn)
- conn->bits.tls_enable_npn = TRUE;
}
if(waitpipe)
@@ -4046,7 +3755,7 @@
if(!connections_available) {
infof(data, "No connections available.");
- conn_free(conn);
+ conn_free(data, conn);
*in_connect = NULL;
result = CURLE_NO_CONNECTION_AVAILABLE;
@@ -4106,6 +3815,13 @@
* Resolve the address of the server or proxy
*************************************************************/
result = resolve_server(data, conn, async);
+ if(result)
+ goto out;
+
+ /* Everything general done, inform filters that they need
+ * to prepare for a data transfer.
+ */
+ result = Curl_conn_ev_data_setup(data);
out:
return result;
@@ -4129,7 +3845,6 @@
*protocol_done = TRUE;
return result;
}
- *protocol_done = FALSE; /* default to not done */
#ifndef CURL_DISABLE_PROXY
/* set proxy_connect_closed to false unconditionally already here since it
@@ -4146,26 +3861,11 @@
/* set start time here for timeout purposes in the connect procedure, it
is later set again for the progress meter purpose */
conn->now = Curl_now();
-
- if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
- conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
- result = Curl_connecthost(data, conn, conn->dns_entry);
- if(result)
- return result;
- }
- else {
- Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
- if(conn->ssl[FIRSTSOCKET].use ||
- (conn->handler->protocol & PROTO_FAMILY_SSH))
- Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
- conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
- *protocol_done = TRUE;
- Curl_updateconninfo(data, conn, conn->sock[FIRSTSOCKET]);
- Curl_verboseconnect(data, conn);
- }
-
- conn->now = Curl_now(); /* time this *after* the connect is done, we set
- this here perhaps a second time */
+ if(!conn->bits.reuse)
+ result = Curl_conn_setup(data, conn, FIRSTSOCKET, conn->dns_entry,
+ CURL_CF_SSL_DEFAULT);
+ /* not sure we need this flag to be passed around any more */
+ *protocol_done = FALSE;
return result;
}
@@ -4182,6 +3882,7 @@
Curl_free_request_state(data);
memset(&data->req, 0, sizeof(struct SingleRequest));
data->req.size = data->req.maxdownload = -1;
+ data->req.no_body = data->set.opt_no_body;
/* call the stuff that needs to be called */
result = create_conn(data, &conn, asyncp);
@@ -4243,12 +3944,11 @@
data->state.done = FALSE; /* *_done() is not called yet */
data->state.expect100header = FALSE;
- if(data->set.opt_no_body)
+ if(data->req.no_body)
/* in HTTP lingo, no body means using the HEAD request... */
data->state.httpreq = HTTPREQ_HEAD;
k->start = Curl_now(); /* start time */
- k->now = k->start; /* current time is now */
k->header = TRUE; /* assume header */
k->bytecount = 0;
k->ignorebody = FALSE;
@@ -4259,3 +3959,102 @@
return CURLE_OK;
}
+
+#if defined(USE_HTTP2) || defined(USE_HTTP3)
+
+#ifdef USE_NGHTTP2
+
+static void priority_remove_child(struct Curl_easy *parent,
+ struct Curl_easy *child)
+{
+ struct Curl_data_prio_node **pnext = &parent->set.priority.children;
+ struct Curl_data_prio_node *pnode = parent->set.priority.children;
+
+ DEBUGASSERT(child->set.priority.parent == parent);
+ while(pnode && pnode->data != child) {
+ pnext = &pnode->next;
+ pnode = pnode->next;
+ }
+
+ DEBUGASSERT(pnode);
+ if(pnode) {
+ *pnext = pnode->next;
+ free(pnode);
+ }
+
+ child->set.priority.parent = 0;
+ child->set.priority.exclusive = FALSE;
+}
+
+CURLcode Curl_data_priority_add_child(struct Curl_easy *parent,
+ struct Curl_easy *child,
+ bool exclusive)
+{
+ if(child->set.priority.parent) {
+ priority_remove_child(child->set.priority.parent, child);
+ }
+
+ if(parent) {
+ struct Curl_data_prio_node **tail;
+ struct Curl_data_prio_node *pnode;
+
+ pnode = calloc(1, sizeof(*pnode));
+ if(!pnode)
+ return CURLE_OUT_OF_MEMORY;
+ pnode->data = child;
+
+ if(parent->set.priority.children && exclusive) {
+ /* exclusive: move all existing children underneath the new child */
+ struct Curl_data_prio_node *node = parent->set.priority.children;
+ while(node) {
+ node->data->set.priority.parent = child;
+ node = node->next;
+ }
+
+ tail = &child->set.priority.children;
+ while(*tail)
+ tail = &(*tail)->next;
+
+ DEBUGASSERT(!*tail);
+ *tail = parent->set.priority.children;
+ parent->set.priority.children = 0;
+ }
+
+ tail = &parent->set.priority.children;
+ while(*tail) {
+ (*tail)->data->set.priority.exclusive = FALSE;
+ tail = &(*tail)->next;
+ }
+
+ DEBUGASSERT(!*tail);
+ *tail = pnode;
+ }
+
+ child->set.priority.parent = parent;
+ child->set.priority.exclusive = exclusive;
+ return CURLE_OK;
+}
+
+#endif /* USE_NGHTTP2 */
+
+#ifdef USE_NGHTTP2
+static void data_priority_cleanup(struct Curl_easy *data)
+{
+ while(data->set.priority.children) {
+ struct Curl_easy *tmp = data->set.priority.children->data;
+ priority_remove_child(data, tmp);
+ if(data->set.priority.parent)
+ Curl_data_priority_add_child(data->set.priority.parent, tmp, FALSE);
+ }
+
+ if(data->set.priority.parent)
+ priority_remove_child(data->set.priority.parent, data);
+}
+#endif
+
+void Curl_data_priority_clear_state(struct Curl_easy *data)
+{
+ memset(&data->state.priority, 0, sizeof(data->state.priority));
+}
+
+#endif /* defined(USE_HTTP2) || defined(USE_HTTP3) */
diff --git a/lib/url.h b/lib/url.h
index e3b2940..f6a5b25 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -46,12 +46,8 @@
char **userptr, char **passwdptr,
char **optionsptr);
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme);
-
-bool Curl_is_ASCII_name(const char *hostname);
-CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
- struct hostname *host);
-void Curl_free_idnconverted_hostname(struct hostname *host);
+const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
+ size_t schemelen);
#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
@@ -63,21 +59,18 @@
void Curl_verboseconnect(struct Curl_easy *data, struct connectdata *conn);
#endif
-#ifdef CURL_DISABLE_PROXY
-#define CONNECT_PROXY_SSL() FALSE
+#if defined(USE_HTTP2) || defined(USE_HTTP3)
+void Curl_data_priority_clear_state(struct Curl_easy *data);
#else
+#define Curl_data_priority_clear_state(x)
+#endif /* !(defined(USE_HTTP2) || defined(USE_HTTP3)) */
-#define CONNECT_PROXY_SSL()\
- (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
- !conn->bits.proxy_ssl_connected[sockindex])
-
-#define CONNECT_FIRSTSOCKET_PROXY_SSL()\
- (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
- !conn->bits.proxy_ssl_connected[FIRSTSOCKET])
-
-#define CONNECT_SECONDARYSOCKET_PROXY_SSL()\
- (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
- !conn->bits.proxy_ssl_connected[SECONDARYSOCKET])
-#endif /* !CURL_DISABLE_PROXY */
+#ifdef USE_NGHTTP2
+CURLcode Curl_data_priority_add_child(struct Curl_easy *parent,
+ struct Curl_easy *child,
+ bool exclusive);
+#else
+#define Curl_data_priority_add_child(x, y, z) CURLE_NOT_BUILT_IN
+#endif
#endif /* HEADER_CURL_URL_H */
diff --git a/lib/urlapi-int.h b/lib/urlapi-int.h
index a03aa88..d6e240a 100644
--- a/lib/urlapi-int.h
+++ b/lib/urlapi-int.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,10 +25,15 @@
***************************************************************************/
#include "curl_setup.h"
-bool Curl_is_absolute_url(const char *url, char *scheme, size_t buflen);
+size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
+ bool guess_scheme);
+
+CURLUcode Curl_url_set_authority(CURLU *u, const char *authority,
+ unsigned int flags);
#ifdef DEBUGBUILD
-CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname, bool);
+CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
+ bool has_scheme);
#endif
#endif /* HEADER_CURL_URLAPI_INT_H */
diff --git a/lib/urlapi.c b/lib/urlapi.c
index dee4b5a..e0c5476 100644
--- a/lib/urlapi.c
+++ b/lib/urlapi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,12 +27,14 @@
#include "urldata.h"
#include "urlapi-int.h"
#include "strcase.h"
-#include "dotdot.h"
#include "url.h"
#include "escape.h"
#include "curl_ctype.h"
#include "inet_pton.h"
#include "inet_ntop.h"
+#include "strdup.h"
+#include "idn.h"
+#include "curl_memrchr.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -56,6 +58,15 @@
/* scheme is not URL encoded, the longest libcurl supported ones are... */
#define MAX_SCHEME_LEN 40
+/*
+ * If ENABLE_IPV6 is disabled, we still want to parse IPv6 addresses, so make
+ * sure we have _some_ value for AF_INET6 without polluting our fake value
+ * everywhere.
+ */
+#if !defined(ENABLE_IPV6) && !defined(AF_INET6)
+#define AF_INET6 (AF_INET + 1)
+#endif
+
/* Internal representation of CURLU. Point to URL-encoded strings. */
struct Curl_URL {
char *scheme;
@@ -68,9 +79,6 @@
char *path;
char *query;
char *fragment;
-
- char *scratch; /* temporary scratch area */
- char *temppath; /* temporary path pointer */
long portnum; /* the numerical version */
};
@@ -88,8 +96,6 @@
free(u->path);
free(u->query);
free(u->fragment);
- free(u->scratch);
- free(u->temppath);
}
/*
@@ -121,95 +127,47 @@
}
/*
- * Decide in an encoding-independent manner whether a character in an
- * URL must be escaped. The same criterion must be used in strlen_url()
- * and strcpy_url().
+ * Decide whether a character in a URL must be escaped.
*/
-static bool urlchar_needs_escaping(int c)
-{
- return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c));
-}
+#define urlchar_needs_escaping(c) (!(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c)))
-/*
- * strlen_url() returns the length of the given URL if the spaces within the
- * URL were properly URL encoded.
- * URL encoding should be skipped for host names, otherwise IDN resolution
- * will fail.
- */
-static size_t strlen_url(const char *url, bool relative)
-{
- const unsigned char *ptr;
- size_t newlen = 0;
- bool left = TRUE; /* left side of the ? */
- const unsigned char *host_sep = (const unsigned char *) url;
-
- if(!relative)
- host_sep = (const unsigned char *) find_host_sep(url);
-
- for(ptr = (unsigned char *)url; *ptr; ptr++) {
-
- if(ptr < host_sep) {
- ++newlen;
- continue;
- }
-
- if(*ptr == ' ') {
- if(left)
- newlen += 3;
- else
- newlen++;
- continue;
- }
-
- if (*ptr == '?')
- left = FALSE;
-
- if(urlchar_needs_escaping(*ptr))
- newlen += 2;
-
- newlen++;
- }
-
- return newlen;
-}
-
-/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in
- * the source URL accordingly.
- * URL encoding should be skipped for host names, otherwise IDN resolution
- * will fail.
+static const char hexdigits[] = "0123456789abcdef";
+/* urlencode_str() writes data into an output dynbuf and URL-encodes the
+ * spaces in the source URL accordingly.
*
- * Returns TRUE if something was updated.
+ * URL encoding should be skipped for host names, otherwise IDN resolution
+ * will fail.
*/
-static bool strcpy_url(char *output, const char *url, bool relative)
+static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
+ size_t len, bool relative,
+ bool query)
{
/* we must add this with whitespace-replacing */
- bool left = TRUE;
+ bool left = !query;
const unsigned char *iptr;
- char *optr = output;
const unsigned char *host_sep = (const unsigned char *) url;
- bool changed = FALSE;
if(!relative)
host_sep = (const unsigned char *) find_host_sep(url);
for(iptr = (unsigned char *)url; /* read from here */
- *iptr; /* until zero byte */
- iptr++) {
+ len; iptr++, len--) {
if(iptr < host_sep) {
- *optr++ = *iptr;
+ if(Curl_dyn_addn(o, iptr, 1))
+ return CURLUE_OUT_OF_MEMORY;
continue;
}
if(*iptr == ' ') {
if(left) {
- *optr++='%'; /* add a '%' */
- *optr++='2'; /* add a '2' */
- *optr++='0'; /* add a '0' */
+ if(Curl_dyn_addn(o, "%20", 3))
+ return CURLUE_OUT_OF_MEMORY;
}
- else
- *optr++='+'; /* add a '+' here */
- changed = TRUE;
+ else {
+ if(Curl_dyn_addn(o, "+", 1))
+ return CURLUE_OUT_OF_MEMORY;
+ }
continue;
}
@@ -217,55 +175,69 @@
left = FALSE;
if(urlchar_needs_escaping(*iptr)) {
- msnprintf(optr, 4, "%%%02x", *iptr);
- changed = TRUE;
- optr += 3;
+ char out[3]={'%'};
+ out[1] = hexdigits[*iptr>>4];
+ out[2] = hexdigits[*iptr & 0xf];
+ if(Curl_dyn_addn(o, out, 3))
+ return CURLUE_OUT_OF_MEMORY;
}
- else
- *optr++ = *iptr;
+ else {
+ if(Curl_dyn_addn(o, iptr, 1))
+ return CURLUE_OUT_OF_MEMORY;
+ }
}
- *optr = 0; /* null-terminate output buffer */
- return changed;
+ return CURLUE_OK;
}
/*
- * Returns true if the given URL is absolute (as opposed to relative). Returns
- * the scheme in the buffer if TRUE and 'buf' is non-NULL. The buflen must
- * be larger than MAX_SCHEME_LEN if buf is set.
+ * Returns the length of the scheme if the given URL is absolute (as opposed
+ * to relative). Stores the scheme in the buffer if TRUE and 'buf' is
+ * non-NULL. The buflen must be larger than MAX_SCHEME_LEN if buf is set.
+ *
+ * If 'guess_scheme' is TRUE, it means the URL might be provided without
+ * scheme.
*/
-bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
+size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
+ bool guess_scheme)
{
- int i;
+ int i = 0;
DEBUGASSERT(!buf || (buflen > MAX_SCHEME_LEN));
(void)buflen; /* only used in debug-builds */
if(buf)
buf[0] = 0; /* always leave a defined value in buf */
#ifdef WIN32
- if(STARTS_WITH_DRIVE_PREFIX(url))
- return FALSE;
+ if(guess_scheme && STARTS_WITH_DRIVE_PREFIX(url))
+ return 0;
#endif
- for(i = 0; i < MAX_SCHEME_LEN; ++i) {
- char s = url[i];
- if(s && (ISALNUM(s) || (s == '+') || (s == '-') || (s == '.') )) {
- /* RFC 3986 3.1 explains:
- scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
- */
+ if(ISALPHA(url[0]))
+ for(i = 1; i < MAX_SCHEME_LEN; ++i) {
+ char s = url[i];
+ if(s && (ISALNUM(s) || (s == '+') || (s == '-') || (s == '.') )) {
+ /* RFC 3986 3.1 explains:
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ */
+ }
+ else {
+ break;
+ }
}
- else {
- break;
- }
- }
- if(i && (url[i] == ':') && (url[i + 1] == '/')) {
+ if(i && (url[i] == ':') && ((url[i + 1] == '/') || !guess_scheme)) {
+ /* If this does not guess scheme, the scheme always ends with the colon so
+ that this also detects data: URLs etc. In guessing mode, data: could
+ be the host name "data" with a specified port number. */
+
+ /* the length of the scheme is the name part only */
+ size_t len = i;
if(buf) {
buf[i] = 0;
while(i--) {
- buf[i] = (char)TOLOWER(url[i]);
+ buf[i] = Curl_raw_tolower(url[i]);
}
}
- return TRUE;
+ return len;
}
- return FALSE;
+ return 0;
}
/*
@@ -273,34 +245,26 @@
* URL-encodes any spaces.
* The returned pointer must be freed by the caller unless NULL
* (returns NULL on out of memory).
+ *
+ * Note that this function destroys the 'base' string.
*/
-static char *concat_url(const char *base, const char *relurl)
+static char *concat_url(char *base, const char *relurl)
{
/***
TRY to append this new path to the old URL
to the right of the host part. Oh crap, this is doomed to cause
problems in the future...
*/
- char *newest;
+ struct dynbuf newest;
char *protsep;
char *pathsep;
- size_t newlen;
bool host_changed = FALSE;
-
const char *useurl = relurl;
- size_t urllen;
-
- /* we must make our own copy of the URL to play with, as it may
- point to read-only data */
- char *url_clone = strdup(base);
-
- if(!url_clone)
- return NULL; /* skip out of this NOW */
/* protsep points to the start of the host name */
- protsep = strstr(url_clone, "//");
+ protsep = strstr(base, "//");
if(!protsep)
- protsep = url_clone;
+ protsep = base;
else
protsep += 2; /* pass the slashes */
@@ -393,61 +357,50 @@
}
}
- /* If the new part contains a space, this is a mighty stupid redirect
- but we still make an effort to do "right". To the left of a '?'
- letter we replace each space with %20 while it is replaced with '+'
- on the right side of the '?' letter.
- */
- newlen = strlen_url(useurl, !host_changed);
-
- urllen = strlen(url_clone);
-
- newest = malloc(urllen + 1 + /* possible slash */
- newlen + 1 /* zero byte */);
-
- if(!newest) {
- free(url_clone); /* don't leak this */
- return NULL;
- }
+ Curl_dyn_init(&newest, CURL_MAX_INPUT_LENGTH);
/* copy over the root url part */
- memcpy(newest, url_clone, urllen);
+ if(Curl_dyn_add(&newest, base))
+ return NULL;
/* check if we need to append a slash */
if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
;
- else
- newest[urllen++]='/';
+ else {
+ if(Curl_dyn_addn(&newest, "/", 1))
+ return NULL;
+ }
/* then append the new piece on the right side */
- strcpy_url(&newest[urllen], useurl, !host_changed);
+ urlencode_str(&newest, useurl, strlen(useurl), !host_changed, FALSE);
- free(url_clone);
-
- return newest;
+ return Curl_dyn_ptr(&newest);
}
-/* scan for byte values < 31 or 127 */
-static bool junkscan(const char *part, unsigned int flags)
+/* scan for byte values <= 31, 127 and sometimes space */
+static CURLUcode junkscan(const char *url, size_t *urllen, unsigned int flags)
{
- if(part) {
- static const char badbytes[]={
- /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x7f, 0x00 /* null-terminate */
- };
- size_t n = strlen(part);
- size_t nfine = strcspn(part, badbytes);
- if(nfine != n)
- /* since we don't know which part is scanned, return a generic error
- code */
- return TRUE;
- if(!(flags & CURLU_ALLOW_SPACE) && strchr(part, ' '))
- return TRUE;
- }
- return FALSE;
+ static const char badbytes[]={
+ /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x7f, 0x00 /* null-terminate */
+ };
+ size_t n = strlen(url);
+ size_t nfine;
+
+ if(n > CURL_MAX_INPUT_LENGTH)
+ /* excessive input length */
+ return CURLUE_MALFORMED_INPUT;
+
+ nfine = strcspn(url, badbytes);
+ if((nfine != n) ||
+ (!(flags & CURLU_ALLOW_SPACE) && strchr(url, ' ')))
+ return CURLUE_MALFORMED_INPUT;
+
+ *urllen = n;
+ return CURLUE_OK;
}
/*
@@ -458,8 +411,10 @@
*
*/
static CURLUcode parse_hostname_login(struct Curl_URL *u,
- char **hostname,
- unsigned int flags)
+ const char *login,
+ size_t len,
+ unsigned int flags,
+ size_t *offset) /* to the host name */
{
CURLUcode result = CURLUE_OK;
CURLcode ccode;
@@ -468,27 +423,30 @@
char *optionsp = NULL;
const struct Curl_handler *h = NULL;
- /* At this point, we're hoping all the other special cases have
- * been taken care of, so conn->host.name is at most
- * [user[:password][;options]]@]hostname
+ /* At this point, we assume all the other special cases have been taken
+ * care of, so the host is at most
+ *
+ * [user[:password][;options]]@]hostname
*
* We need somewhere to put the embedded details, so do that first.
*/
+ char *ptr;
- char *ptr = strchr(*hostname, '@');
- char *login = *hostname;
+ DEBUGASSERT(login);
+ *offset = 0;
+ ptr = memchr(login, '@', len);
if(!ptr)
goto out;
/* We will now try to extract the
* possible login information in a string like:
* ftp://user:password@ftp.my.site:8021/README */
- *hostname = ++ptr;
+ ptr++;
/* if this is a known scheme, get some details */
if(u->scheme)
- h = Curl_builtin_scheme(u->scheme);
+ h = Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
/* We could use the login information in the URL so extract it. Only parse
options if the handler says we should. Note that 'h' might be NULL! */
@@ -507,31 +465,25 @@
result = CURLUE_USER_NOT_ALLOWED;
goto out;
}
- if(junkscan(userp, flags)) {
- result = CURLUE_BAD_USER;
- goto out;
- }
+ free(u->user);
u->user = userp;
}
if(passwdp) {
- if(junkscan(passwdp, flags)) {
- result = CURLUE_BAD_PASSWORD;
- goto out;
- }
+ free(u->password);
u->password = passwdp;
}
if(optionsp) {
- if(junkscan(optionsp, flags)) {
- result = CURLUE_BAD_LOGIN;
- goto out;
- }
+ free(u->options);
u->options = optionsp;
}
+ /* the host name starts at this offset */
+ *offset = ptr - login;
return CURLUE_OK;
- out:
+
+out:
free(userp);
free(passwdp);
@@ -543,38 +495,23 @@
return result;
}
-UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
+UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
bool has_scheme)
{
- char *portptr = NULL;
- char endbracket;
- int len;
-
+ char *portptr;
+ char *hostname = Curl_dyn_ptr(host);
/*
- * Find the end of an IPv6 address, either on the ']' ending bracket or
- * a percent-encoded zone index.
+ * Find the end of an IPv6 address on the ']' ending bracket.
*/
- if(1 == sscanf(hostname, "[%*45[0123456789abcdefABCDEF:.]%c%n",
- &endbracket, &len)) {
- if(']' == endbracket)
- portptr = &hostname[len];
- else if('%' == endbracket) {
- int zonelen = len;
- if(1 == sscanf(hostname + zonelen, "%*[^]]%c%n", &endbracket, &len)) {
- if(']' != endbracket)
- return CURLUE_BAD_IPV6;
- portptr = &hostname[--zonelen + len + 1];
- }
- else
- return CURLUE_BAD_IPV6;
- }
- else
+ if(hostname[0] == '[') {
+ portptr = strchr(hostname, ']');
+ if(!portptr)
return CURLUE_BAD_IPV6;
-
+ portptr++;
/* this is a RFC2732-style specified IP-address */
- if(portptr && *portptr) {
+ if(*portptr) {
if(*portptr != ':')
- return CURLUE_BAD_IPV6;
+ return CURLUE_BAD_PORT_NUMBER;
}
else
portptr = NULL;
@@ -585,7 +522,7 @@
if(portptr) {
char *rest;
long port;
- char portbuf[7];
+ size_t keep = portptr - hostname;
/* Browser behavior adaptation. If there's a colon with no digits after,
just cut off the name there which makes us ignore the colon and just
@@ -594,15 +531,15 @@
Don't do it if the URL has no scheme, to make something that looks like
a scheme not work!
*/
- if(!portptr[1]) {
- *portptr = '\0';
+ Curl_dyn_setlen(host, keep);
+ portptr++;
+ if(!*portptr)
return has_scheme ? CURLUE_OK : CURLUE_BAD_PORT_NUMBER;
- }
- if(!ISDIGIT(portptr[1]))
+ if(!ISDIGIT(*portptr))
return CURLUE_BAD_PORT_NUMBER;
- port = strtol(portptr + 1, &rest, 10); /* Port number must be decimal */
+ port = strtol(portptr, &rest, 10); /* Port number must be decimal */
if(port > 0xffff)
return CURLUE_BAD_PORT_NUMBER;
@@ -610,12 +547,10 @@
if(rest[0])
return CURLUE_BAD_PORT_NUMBER;
- *portptr++ = '\0'; /* cut off the name there */
- *rest = 0;
- /* generate a new port number string to get rid of leading zeroes etc */
- msnprintf(portbuf, sizeof(portbuf), "%ld", port);
u->portnum = port;
- u->port = strdup(portbuf);
+ /* generate a new port number string to get rid of leading zeroes etc */
+ free(u->port);
+ u->port = aprintf("%ld", port);
if(!u->port)
return CURLUE_OUT_OF_MEMORY;
}
@@ -623,124 +558,132 @@
return CURLUE_OK;
}
-static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
+/* this assumes 'hostname' now starts with [ */
+static CURLUcode ipv6_parse(struct Curl_URL *u, char *hostname,
+ size_t hlen) /* length of hostname */
{
size_t len;
- size_t hlen = strlen(hostname);
+ DEBUGASSERT(*hostname == '[');
+ if(hlen < 4) /* '[::]' is the shortest possible valid string */
+ return CURLUE_BAD_IPV6;
+ hostname++;
+ hlen -= 2;
- if(hostname[0] == '[') {
- const char *l = "0123456789abcdefABCDEF:.";
- if(hlen < 4) /* '[::]' is the shortest possible valid string */
- return CURLUE_BAD_IPV6;
- hostname++;
- hlen -= 2;
+ /* only valid IPv6 letters are ok */
+ len = strspn(hostname, "0123456789abcdefABCDEF:.");
- if(hostname[hlen] != ']')
- return CURLUE_BAD_IPV6;
-
- /* only valid letters are ok */
- len = strspn(hostname, l);
- if(hlen != len) {
- hlen = len;
- if(hostname[len] == '%') {
- /* this could now be '%[zone id]' */
- char zoneid[16];
- int i = 0;
- char *h = &hostname[len + 1];
- /* pass '25' if present and is a url encoded percent sign */
- if(!strncmp(h, "25", 2) && h[2] && (h[2] != ']'))
- h += 2;
- while(*h && (*h != ']') && (i < 15))
- zoneid[i++] = *h++;
- if(!i || (']' != *h))
- /* impossible to reach? */
- return CURLUE_MALFORMED_INPUT;
- zoneid[i] = 0;
- u->zoneid = strdup(zoneid);
- if(!u->zoneid)
- return CURLUE_OUT_OF_MEMORY;
- hostname[len] = ']'; /* insert end bracket */
- hostname[len + 1] = 0; /* terminate the hostname */
- }
- else
+ if(hlen != len) {
+ hlen = len;
+ if(hostname[len] == '%') {
+ /* this could now be '%[zone id]' */
+ char zoneid[16];
+ int i = 0;
+ char *h = &hostname[len + 1];
+ /* pass '25' if present and is a url encoded percent sign */
+ if(!strncmp(h, "25", 2) && h[2] && (h[2] != ']'))
+ h += 2;
+ while(*h && (*h != ']') && (i < 15))
+ zoneid[i++] = *h++;
+ if(!i || (']' != *h))
return CURLUE_BAD_IPV6;
- /* hostname is fine */
+ zoneid[i] = 0;
+ u->zoneid = strdup(zoneid);
+ if(!u->zoneid)
+ return CURLUE_OUT_OF_MEMORY;
+ hostname[len] = ']'; /* insert end bracket */
+ hostname[len + 1] = 0; /* terminate the hostname */
}
-#ifdef ENABLE_IPV6
- {
- char dest[16]; /* fits a binary IPv6 address */
- char norm[MAX_IPADR_LEN];
- hostname[hlen] = 0; /* end the address there */
- if(1 != Curl_inet_pton(AF_INET6, hostname, dest))
- return CURLUE_BAD_IPV6;
-
- /* check if it can be done shorter */
- if(Curl_inet_ntop(AF_INET6, dest, norm, sizeof(norm)) &&
- (strlen(norm) < hlen)) {
- strcpy(hostname, norm);
- hlen = strlen(norm);
- hostname[hlen + 1] = 0;
- }
- hostname[hlen] = ']'; /* restore ending bracket */
- }
-#endif
+ else
+ return CURLUE_BAD_IPV6;
+ /* hostname is fine */
}
+
+ /* Check the IPv6 address. */
+ {
+ char dest[16]; /* fits a binary IPv6 address */
+ char norm[MAX_IPADR_LEN];
+ hostname[hlen] = 0; /* end the address there */
+ if(1 != Curl_inet_pton(AF_INET6, hostname, dest))
+ return CURLUE_BAD_IPV6;
+
+ /* check if it can be done shorter */
+ if(Curl_inet_ntop(AF_INET6, dest, norm, sizeof(norm)) &&
+ (strlen(norm) < hlen)) {
+ strcpy(hostname, norm);
+ hlen = strlen(norm);
+ hostname[hlen + 1] = 0;
+ }
+ hostname[hlen] = ']'; /* restore ending bracket */
+ }
+ return CURLUE_OK;
+}
+
+static CURLUcode hostname_check(struct Curl_URL *u, char *hostname,
+ size_t hlen) /* length of hostname */
+{
+ size_t len;
+ DEBUGASSERT(hostname);
+
+ if(!hlen)
+ return CURLUE_NO_HOST;
+ else if(hostname[0] == '[')
+ return ipv6_parse(u, hostname, hlen);
else {
/* letters from the second string are not ok */
- len = strcspn(hostname, " \r\n\t/:#?!@");
+ len = strcspn(hostname, " \r\n\t/:#?!@{}[]\\$\'\"^`*<>=;,+&()%");
if(hlen != len)
/* hostname with bad content */
return CURLUE_BAD_HOSTNAME;
}
- if(!hostname[0])
- return CURLUE_NO_HOST;
return CURLUE_OK;
}
-#define HOSTNAME_END(x) (((x) == '/') || ((x) == '?') || ((x) == '#'))
-
/*
* Handle partial IPv4 numerical addresses and different bases, like
* '16843009', '0x7f', '0x7f.1' '0177.1.1.1' etc.
*
- * If the given input string is syntactically wrong or any part for example is
- * too big, this function returns FALSE and doesn't create any output.
+ * If the given input string is syntactically wrong IPv4 or any part for
+ * example is too big, this function returns HOST_NAME.
*
* Output the "normalized" version of that input string in plain quad decimal
- * integers and return TRUE.
+ * integers.
+ *
+ * Returns the host type.
*/
-static bool ipv4_normalize(const char *hostname, char *outp, size_t olen)
+
+#define HOST_ERROR -1 /* out of memory */
+#define HOST_BAD -2 /* bad IPv4 address */
+
+#define HOST_NAME 1
+#define HOST_IPV4 2
+#define HOST_IPV6 3
+
+static int ipv4_normalize(struct dynbuf *host)
{
bool done = FALSE;
int n = 0;
- const char *c = hostname;
+ const char *c = Curl_dyn_ptr(host);
unsigned long parts[4] = {0, 0, 0, 0};
+ CURLcode result = CURLE_OK;
+
+ if(*c == '[')
+ return HOST_IPV6;
while(!done) {
char *endp;
unsigned long l;
- if((*c < '0') || (*c > '9'))
+ if(!ISDIGIT(*c))
/* most importantly this doesn't allow a leading plus or minus */
- return FALSE;
+ return HOST_NAME;
l = strtoul(c, &endp, 0);
- /* overflow or nothing parsed at all */
- if(((l == ULONG_MAX) && (errno == ERANGE)) || (endp == c))
- return FALSE;
-
-#if SIZEOF_LONG > 4
- /* a value larger than 32 bits */
- if(l > UINT_MAX)
- return FALSE;
-#endif
-
parts[n] = l;
c = endp;
- switch (*c) {
- case '.' :
+ switch(*c) {
+ case '.':
if(n == 3)
- return FALSE;
+ return HOST_NAME;
n++;
c++;
break;
@@ -750,116 +693,331 @@
break;
default:
- return FALSE;
+ return HOST_NAME;
}
- }
- /* this is deemed a valid IPv4 numerical address */
+ /* overflow */
+ if((l == ULONG_MAX) && (errno == ERANGE))
+ return HOST_NAME;
+
+#if SIZEOF_LONG > 4
+ /* a value larger than 32 bits */
+ if(l > UINT_MAX)
+ return HOST_NAME;
+#endif
+ }
switch(n) {
case 0: /* a -- 32 bits */
- msnprintf(outp, olen, "%u.%u.%u.%u",
- parts[0] >> 24, (parts[0] >> 16) & 0xff,
- (parts[0] >> 8) & 0xff, parts[0] & 0xff);
+ Curl_dyn_reset(host);
+
+ result = Curl_dyn_addf(host, "%u.%u.%u.%u",
+ parts[0] >> 24, (parts[0] >> 16) & 0xff,
+ (parts[0] >> 8) & 0xff, parts[0] & 0xff);
break;
case 1: /* a.b -- 8.24 bits */
if((parts[0] > 0xff) || (parts[1] > 0xffffff))
- return FALSE;
- msnprintf(outp, olen, "%u.%u.%u.%u",
- parts[0], (parts[1] >> 16) & 0xff,
- (parts[1] >> 8) & 0xff, parts[1] & 0xff);
+ return HOST_NAME;
+ Curl_dyn_reset(host);
+ result = Curl_dyn_addf(host, "%u.%u.%u.%u",
+ parts[0], (parts[1] >> 16) & 0xff,
+ (parts[1] >> 8) & 0xff, parts[1] & 0xff);
break;
case 2: /* a.b.c -- 8.8.16 bits */
if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xffff))
- return FALSE;
- msnprintf(outp, olen, "%u.%u.%u.%u",
- parts[0], parts[1], (parts[2] >> 8) & 0xff,
- parts[2] & 0xff);
+ return HOST_NAME;
+ Curl_dyn_reset(host);
+ result = Curl_dyn_addf(host, "%u.%u.%u.%u",
+ parts[0], parts[1], (parts[2] >> 8) & 0xff,
+ parts[2] & 0xff);
break;
case 3: /* a.b.c.d -- 8.8.8.8 bits */
if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff) ||
(parts[3] > 0xff))
- return FALSE;
- msnprintf(outp, olen, "%u.%u.%u.%u",
- parts[0], parts[1], parts[2], parts[3]);
+ return HOST_NAME;
+ Curl_dyn_reset(host);
+ result = Curl_dyn_addf(host, "%u.%u.%u.%u",
+ parts[0], parts[1], parts[2], parts[3]);
break;
}
- return TRUE;
+ if(result)
+ return HOST_ERROR;
+ return HOST_IPV4;
}
-/* return strdup'ed version in 'outp', possibly percent decoded */
-static CURLUcode decode_host(char *hostname, char **outp)
+/* if necessary, replace the host content with a URL decoded version */
+static CURLUcode urldecode_host(struct dynbuf *host)
{
char *per = NULL;
- if(hostname[0] != '[')
- /* only decode if not an ipv6 numerical */
- per = strchr(hostname, '%');
- if(!per) {
- *outp = strdup(hostname);
- if(!*outp)
- return CURLUE_OUT_OF_MEMORY;
- }
+ const char *hostname = Curl_dyn_ptr(host);
+ per = strchr(hostname, '%');
+ if(!per)
+ /* nothing to decode */
+ return CURLUE_OK;
else {
- /* might be encoded */
+ /* encoded */
size_t dlen;
- CURLcode result = Curl_urldecode(hostname, 0, outp, &dlen, REJECT_CTRL);
+ char *decoded;
+ CURLcode result = Curl_urldecode(hostname, 0, &decoded, &dlen,
+ REJECT_CTRL);
if(result)
return CURLUE_BAD_HOSTNAME;
+ Curl_dyn_reset(host);
+ result = Curl_dyn_addn(host, decoded, dlen);
+ free(decoded);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
}
return CURLUE_OK;
}
-static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
+static CURLUcode parse_authority(struct Curl_URL *u,
+ const char *auth, size_t authlen,
+ unsigned int flags,
+ struct dynbuf *host,
+ bool has_scheme)
{
- char *path;
- bool path_alloced = FALSE;
- bool uncpath = FALSE;
- char *hostname;
+ size_t offset;
+ CURLUcode result;
+
+ /*
+ * Parse the login details and strip them out of the host name.
+ */
+ result = parse_hostname_login(u, auth, authlen, flags, &offset);
+ if(result)
+ goto out;
+
+ if(Curl_dyn_addn(host, auth + offset, authlen - offset)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ result = Curl_parse_port(u, host, has_scheme);
+ if(result)
+ goto out;
+
+ if(!Curl_dyn_len(host))
+ return CURLUE_NO_HOST;
+
+ switch(ipv4_normalize(host)) {
+ case HOST_IPV4:
+ break;
+ case HOST_IPV6:
+ result = ipv6_parse(u, Curl_dyn_ptr(host), Curl_dyn_len(host));
+ break;
+ case HOST_NAME:
+ result = urldecode_host(host);
+ if(!result)
+ result = hostname_check(u, Curl_dyn_ptr(host), Curl_dyn_len(host));
+ break;
+ case HOST_ERROR:
+ result = CURLUE_OUT_OF_MEMORY;
+ break;
+ case HOST_BAD:
+ default:
+ result = CURLUE_BAD_HOSTNAME; /* Bad IPv4 address even */
+ break;
+ }
+
+out:
+ return result;
+}
+
+CURLUcode Curl_url_set_authority(CURLU *u, const char *authority,
+ unsigned int flags)
+{
+ CURLUcode result;
+ struct dynbuf host;
+
+ DEBUGASSERT(authority);
+ Curl_dyn_init(&host, CURL_MAX_INPUT_LENGTH);
+
+ result = parse_authority(u, authority, strlen(authority), flags,
+ &host, !!u->scheme);
+ if(result)
+ Curl_dyn_free(&host);
+ else {
+ free(u->host);
+ u->host = Curl_dyn_ptr(&host);
+ }
+ return result;
+}
+
+/*
+ * "Remove Dot Segments"
+ * https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4
+ */
+
+/*
+ * dedotdotify()
+ * @unittest: 1395
+ *
+ * This function gets a null-terminated path with dot and dotdot sequences
+ * passed in and strips them off according to the rules in RFC 3986 section
+ * 5.2.4.
+ *
+ * The function handles a query part ('?' + stuff) appended but it expects
+ * that fragments ('#' + stuff) have already been cut off.
+ *
+ * RETURNS
+ *
+ * Zero for success and 'out' set to an allocated dedotdotified string.
+ */
+UNITTEST int dedotdotify(const char *input, size_t clen, char **outp);
+UNITTEST int dedotdotify(const char *input, size_t clen, char **outp)
+{
+ char *outptr;
+ const char *endp = &input[clen];
+ char *out;
+
+ *outp = NULL;
+ /* the path always starts with a slash, and a slash has not dot */
+ if((clen < 2) || !memchr(input, '.', clen))
+ return 0;
+
+ out = malloc(clen + 1);
+ if(!out)
+ return 1; /* out of memory */
+
+ *out = 0; /* null-terminates, for inputs like "./" */
+ outptr = out;
+
+ do {
+ bool dotdot = TRUE;
+ if(*input == '.') {
+ /* A. If the input buffer begins with a prefix of "../" or "./", then
+ remove that prefix from the input buffer; otherwise, */
+
+ if(!strncmp("./", input, 2)) {
+ input += 2;
+ clen -= 2;
+ }
+ else if(!strncmp("../", input, 3)) {
+ input += 3;
+ clen -= 3;
+ }
+ /* D. if the input buffer consists only of "." or "..", then remove
+ that from the input buffer; otherwise, */
+
+ else if(!strcmp(".", input) || !strcmp("..", input) ||
+ !strncmp(".?", input, 2) || !strncmp("..?", input, 3)) {
+ *out = 0;
+ break;
+ }
+ else
+ dotdot = FALSE;
+ }
+ else if(*input == '/') {
+ /* B. if the input buffer begins with a prefix of "/./" or "/.", where
+ "." is a complete path segment, then replace that prefix with "/" in
+ the input buffer; otherwise, */
+ if(!strncmp("/./", input, 3)) {
+ input += 2;
+ clen -= 2;
+ }
+ else if(!strcmp("/.", input) || !strncmp("/.?", input, 3)) {
+ *outptr++ = '/';
+ *outptr = 0;
+ break;
+ }
+
+ /* C. if the input buffer begins with a prefix of "/../" or "/..",
+ where ".." is a complete path segment, then replace that prefix with
+ "/" in the input buffer and remove the last segment and its
+ preceding "/" (if any) from the output buffer; otherwise, */
+
+ else if(!strncmp("/../", input, 4)) {
+ input += 3;
+ clen -= 3;
+ /* remove the last segment from the output buffer */
+ while(outptr > out) {
+ outptr--;
+ if(*outptr == '/')
+ break;
+ }
+ *outptr = 0; /* null-terminate where it stops */
+ }
+ else if(!strcmp("/..", input) || !strncmp("/..?", input, 4)) {
+ /* remove the last segment from the output buffer */
+ while(outptr > out) {
+ outptr--;
+ if(*outptr == '/')
+ break;
+ }
+ *outptr++ = '/';
+ *outptr = 0; /* null-terminate where it stops */
+ break;
+ }
+ else
+ dotdot = FALSE;
+ }
+ else
+ dotdot = FALSE;
+
+ if(!dotdot) {
+ /* E. move the first path segment in the input buffer to the end of
+ the output buffer, including the initial "/" character (if any) and
+ any subsequent characters up to, but not including, the next "/"
+ character or the end of the input buffer. */
+
+ do {
+ *outptr++ = *input++;
+ clen--;
+ } while(*input && (*input != '/') && (*input != '?'));
+ *outptr = 0;
+ }
+
+ /* continue until end of path */
+ } while(input < endp);
+
+ *outp = out;
+ return 0; /* success */
+}
+
+static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
+{
+ const char *path;
+ size_t pathlen;
char *query = NULL;
char *fragment = NULL;
- CURLUcode result;
- bool url_has_scheme = FALSE;
char schemebuf[MAX_SCHEME_LEN + 1];
- const char *schemep = NULL;
size_t schemelen = 0;
size_t urllen;
+ CURLUcode result = CURLUE_OK;
+ size_t fraglen = 0;
+ struct dynbuf host;
DEBUGASSERT(url);
- /*************************************************************
- * Parse the URL.
- ************************************************************/
- /* allocate scratch area */
- urllen = strlen(url);
- if(urllen > CURL_MAX_INPUT_LENGTH)
- /* excessive input length */
- return CURLUE_MALFORMED_INPUT;
+ Curl_dyn_init(&host, CURL_MAX_INPUT_LENGTH);
- path = u->scratch = malloc(urllen * 2 + 2);
- if(!path)
- return CURLUE_OUT_OF_MEMORY;
+ result = junkscan(url, &urllen, flags);
+ if(result)
+ goto fail;
- hostname = &path[urllen + 1];
- hostname[0] = 0;
-
- if(Curl_is_absolute_url(url, schemebuf, sizeof(schemebuf))) {
- url_has_scheme = TRUE;
- schemelen = strlen(schemebuf);
- }
+ schemelen = Curl_is_absolute_url(url, schemebuf, sizeof(schemebuf),
+ flags & (CURLU_GUESS_SCHEME|
+ CURLU_DEFAULT_SCHEME));
/* handle the file: scheme */
- if(url_has_scheme && !strcmp(schemebuf, "file")) {
- if(urllen <= 6)
+ if(schemelen && !strcmp(schemebuf, "file")) {
+ bool uncpath = FALSE;
+ if(urllen <= 6) {
/* file:/ is not enough to actually be a complete file: URL */
- return CURLUE_BAD_FILE_URL;
+ result = CURLUE_BAD_FILE_URL;
+ goto fail;
+ }
/* path has been allocated large enough to hold this */
- strcpy(path, &url[5]);
+ path = (char *)&url[5];
+ pathlen = urllen - 5;
u->scheme = strdup("file");
- if(!u->scheme)
- return CURLUE_OUT_OF_MEMORY;
+ if(!u->scheme) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
/* Extra handling URLs with an authority component (i.e. that start with
* "file://")
@@ -869,7 +1027,7 @@
*/
if(path[0] == '/' && path[1] == '/') {
/* swallow the two slashes */
- char *ptr = &path[2];
+ const char *ptr = &path[2];
/*
* According to RFC 8089, a file: URL can be reliably dereferenced if:
@@ -905,13 +1063,17 @@
chars, and the delimiting slash character must be appended to the
host name */
path = strpbrk(ptr, "/\\:*?\"<>|");
- if(!path || *path != '/')
- return CURLUE_BAD_FILE_URL;
+ if(!path || *path != '/') {
+ result = CURLUE_BAD_FILE_URL;
+ goto fail;
+ }
len = path - ptr;
if(len) {
- memcpy(hostname, ptr, len);
- hostname[len] = 0;
+ if(Curl_dyn_addn(&host, ptr, len)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
uncpath = TRUE;
}
@@ -919,16 +1081,19 @@
#else
/* Invalid file://hostname/, expected localhost or 127.0.0.1 or
none */
- return CURLUE_BAD_FILE_URL;
+ result = CURLUE_BAD_FILE_URL;
+ goto fail;
#endif
}
}
path = ptr;
+ pathlen = urllen - (ptr - url);
}
if(!uncpath)
- hostname = NULL; /* no host for file: URLs by default */
+ /* no host for file: URLs by default */
+ Curl_dyn_reset(&host);
#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
/* Don't allow Windows drive letters when not in Windows.
@@ -936,218 +1101,232 @@
if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
STARTS_WITH_URL_DRIVE_PREFIX(path)) {
/* File drive letters are only accepted in MSDOS/Windows */
- return CURLUE_BAD_FILE_URL;
+ result = CURLUE_BAD_FILE_URL;
+ goto fail;
}
#else
/* If the path starts with a slash and a drive letter, ditch the slash */
if('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) {
/* This cannot be done with strcpy, as the memory chunks overlap! */
- memmove(path, &path[1], strlen(&path[1]) + 1);
+ path++;
}
#endif
}
else {
/* clear path */
- const char *p;
+ const char *schemep = NULL;
const char *hostp;
- size_t len;
- path[0] = 0;
+ size_t hostlen;
- if(url_has_scheme) {
+ if(schemelen) {
int i = 0;
- p = &url[schemelen + 1];
- while(p && (*p == '/') && (i < 4)) {
+ const char *p = &url[schemelen + 1];
+ while((*p == '/') && (i < 4)) {
p++;
i++;
}
- if((i < 1) || (i>3))
- /* less than one or more than three slashes */
- return CURLUE_BAD_SLASHES;
schemep = schemebuf;
- if(!Curl_builtin_scheme(schemep) &&
- !(flags & CURLU_NON_SUPPORT_SCHEME))
- return CURLUE_UNSUPPORTED_SCHEME;
+ if(!Curl_builtin_scheme(schemep, CURL_ZERO_TERMINATED) &&
+ !(flags & CURLU_NON_SUPPORT_SCHEME)) {
+ result = CURLUE_UNSUPPORTED_SCHEME;
+ goto fail;
+ }
- if(junkscan(schemep, flags))
- return CURLUE_BAD_SCHEME;
+ if((i < 1) || (i > 3)) {
+ /* less than one or more than three slashes */
+ result = CURLUE_BAD_SLASHES;
+ goto fail;
+ }
+ hostp = p; /* host name starts here */
}
else {
/* no scheme! */
- if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME)))
- return CURLUE_BAD_SCHEME;
+ if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME))) {
+ result = CURLUE_BAD_SCHEME;
+ goto fail;
+ }
if(flags & CURLU_DEFAULT_SCHEME)
schemep = DEFAULT_SCHEME;
/*
* The URL was badly formatted, let's try without scheme specified.
*/
- p = url;
+ hostp = url;
}
- hostp = p; /* host name starts here */
-
- /* find the end of the host name + port number */
- while(*p && !HOSTNAME_END(*p))
- p++;
-
- len = p - hostp;
- if(len) {
- memcpy(hostname, hostp, len);
- hostname[len] = 0;
- }
- else {
- if(!(flags & CURLU_NO_AUTHORITY))
- return CURLUE_NO_HOST;
- }
-
- strcpy(path, p);
if(schemep) {
u->scheme = strdup(schemep);
- if(!u->scheme)
- return CURLUE_OUT_OF_MEMORY;
+ if(!u->scheme) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
}
- }
- if((flags & CURLU_URLENCODE) && path[0]) {
- /* worst case output length is 3x the original! */
- char *newp = malloc(strlen(path) * 3);
- if(!newp)
- return CURLUE_OUT_OF_MEMORY;
- path_alloced = TRUE;
- strcpy_url(newp, path, TRUE); /* consider it relative */
- u->temppath = path = newp;
+ /* find the end of the host name + port number */
+ hostlen = strcspn(hostp, "/?#");
+ path = &hostp[hostlen];
+
+ /* this pathlen also contains the query and the fragment */
+ pathlen = urllen - (path - url);
+ if(hostlen) {
+
+ result = parse_authority(u, hostp, hostlen, flags, &host, schemelen);
+ if(result)
+ goto fail;
+
+ if((flags & CURLU_GUESS_SCHEME) && !schemep) {
+ const char *hostname = Curl_dyn_ptr(&host);
+ /* legacy curl-style guess based on host name */
+ if(checkprefix("ftp.", hostname))
+ schemep = "ftp";
+ else if(checkprefix("dict.", hostname))
+ schemep = "dict";
+ else if(checkprefix("ldap.", hostname))
+ schemep = "ldap";
+ else if(checkprefix("imap.", hostname))
+ schemep = "imap";
+ else if(checkprefix("smtp.", hostname))
+ schemep = "smtp";
+ else if(checkprefix("pop3.", hostname))
+ schemep = "pop3";
+ else
+ schemep = "http";
+
+ u->scheme = strdup(schemep);
+ if(!u->scheme) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ }
+ }
+ else if(flags & CURLU_NO_AUTHORITY) {
+ /* allowed to be empty. */
+ if(Curl_dyn_add(&host, "")) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ }
+ else {
+ result = CURLUE_NO_HOST;
+ goto fail;
+ }
}
fragment = strchr(path, '#');
if(fragment) {
- *fragment++ = 0;
- if(junkscan(fragment, flags))
- return CURLUE_BAD_FRAGMENT;
- if(fragment[0]) {
- u->fragment = strdup(fragment);
- if(!u->fragment)
- return CURLUE_OUT_OF_MEMORY;
- }
- }
-
- query = strchr(path, '?');
- if(query) {
- *query++ = 0;
- if(junkscan(query, flags))
- return CURLUE_BAD_QUERY;
- /* done even if the query part is a blank string */
- u->query = strdup(query);
- if(!u->query)
- return CURLUE_OUT_OF_MEMORY;
- }
-
- if(junkscan(path, flags))
- return CURLUE_BAD_PATH;
-
- if(!path[0])
- /* if there's no path left set, unset */
- path = NULL;
- else {
- if(!(flags & CURLU_PATH_AS_IS)) {
- /* remove ../ and ./ sequences according to RFC3986 */
- char *newp = Curl_dedotdotify(path);
- if(!newp)
- return CURLUE_OUT_OF_MEMORY;
-
- if(strcmp(newp, path)) {
- /* if we got a new version */
- if(path_alloced)
- Curl_safefree(u->temppath);
- u->temppath = path = newp;
- path_alloced = TRUE;
+ fraglen = pathlen - (fragment - path);
+ if(fraglen > 1) {
+ /* skip the leading '#' in the copy but include the terminating null */
+ if(flags & CURLU_URLENCODE) {
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ if(urlencode_str(&enc, fragment + 1, fraglen, TRUE, FALSE)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ u->fragment = Curl_dyn_ptr(&enc);
}
- else
- free(newp);
+ else {
+ u->fragment = Curl_memdup(fragment + 1, fraglen);
+ if(!u->fragment) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ }
}
-
- u->path = path_alloced?path:strdup(path);
- if(!u->path)
- return CURLUE_OUT_OF_MEMORY;
- u->temppath = NULL; /* used now */
+ /* after this, pathlen still contains the query */
+ pathlen -= fraglen;
}
- if(hostname) {
- char normalized_ipv4[sizeof("255.255.255.255") + 1];
-
- /*
- * Parse the login details and strip them out of the host name.
- */
- result = parse_hostname_login(u, &hostname, flags);
- if(result)
- return result;
-
- result = Curl_parse_port(u, hostname, url_has_scheme);
- if(result)
- return result;
-
- if(junkscan(hostname, flags))
- return CURLUE_BAD_HOSTNAME;
-
- if(0 == strlen(hostname) && (flags & CURLU_NO_AUTHORITY)) {
- /* Skip hostname check, it's allowed to be empty. */
- u->host = strdup("");
+ DEBUGASSERT(pathlen < urllen);
+ query = memchr(path, '?', pathlen);
+ if(query) {
+ size_t qlen = fragment ? (size_t)(fragment - query) :
+ pathlen - (query - path);
+ pathlen -= qlen;
+ if(qlen > 1) {
+ if(flags & CURLU_URLENCODE) {
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ /* skip the leading question mark */
+ if(urlencode_str(&enc, query + 1, qlen - 1, TRUE, TRUE)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ u->query = Curl_dyn_ptr(&enc);
+ }
+ else {
+ u->query = Curl_memdup(query + 1, qlen);
+ if(!u->query) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ u->query[qlen - 1] = 0;
+ }
}
else {
- if(ipv4_normalize(hostname, normalized_ipv4, sizeof(normalized_ipv4)))
- u->host = strdup(normalized_ipv4);
- else {
- result = decode_host(hostname, &u->host);
- if(result)
- return result;
- result = hostname_check(u, u->host);
- if(result)
- return result;
+ /* single byte query */
+ u->query = strdup("");
+ if(!u->query) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
}
}
- if(!u->host)
- return CURLUE_OUT_OF_MEMORY;
- if((flags & CURLU_GUESS_SCHEME) && !schemep) {
- /* legacy curl-style guess based on host name */
- if(checkprefix("ftp.", hostname))
- schemep = "ftp";
- else if(checkprefix("dict.", hostname))
- schemep = "dict";
- else if(checkprefix("ldap.", hostname))
- schemep = "ldap";
- else if(checkprefix("imap.", hostname))
- schemep = "imap";
- else if(checkprefix("smtp.", hostname))
- schemep = "smtp";
- else if(checkprefix("pop3.", hostname))
- schemep = "pop3";
- else
- schemep = "http";
+ }
- u->scheme = strdup(schemep);
- if(!u->scheme)
- return CURLUE_OUT_OF_MEMORY;
+ if(pathlen && (flags & CURLU_URLENCODE)) {
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ if(urlencode_str(&enc, path, pathlen, TRUE, FALSE)) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ pathlen = Curl_dyn_len(&enc);
+ path = u->path = Curl_dyn_ptr(&enc);
+ }
+
+ if(pathlen <= 1) {
+ /* there is no path left or just the slash, unset */
+ path = NULL;
+ }
+ else {
+ if(!u->path) {
+ u->path = Curl_memdup(path, pathlen + 1);
+ if(!u->path) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ u->path[pathlen] = 0;
+ path = u->path;
+ }
+ else if(flags & CURLU_URLENCODE)
+ /* it might have encoded more than just the path so cut it */
+ u->path[pathlen] = 0;
+
+ if(!(flags & CURLU_PATH_AS_IS)) {
+ /* remove ../ and ./ sequences according to RFC3986 */
+ char *dedot;
+ int err = dedotdotify((char *)path, pathlen, &dedot);
+ if(err) {
+ result = CURLUE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ if(dedot) {
+ free(u->path);
+ u->path = dedot;
+ }
}
}
- Curl_safefree(u->scratch);
- Curl_safefree(u->temppath);
+ u->host = Curl_dyn_ptr(&host);
- return CURLUE_OK;
-}
-
-/*
- * Parse the URL and set the relevant members of the Curl_URL struct.
- */
-static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
-{
- CURLUcode result = seturl(url, u, flags);
- if(result) {
- free_urlhandle(u);
- memset(u, 0, sizeof(struct Curl_URL));
- }
+ return result;
+fail:
+ Curl_dyn_free(&host);
+ free_urlhandle(u);
return result;
}
@@ -1165,8 +1344,6 @@
free_urlhandle(u);
*u = tmpurl;
}
- else
- free_urlhandle(&tmpurl);
return result;
}
@@ -1194,7 +1371,7 @@
} \
} while(0)
-CURLU *curl_url_dup(CURLU *in)
+CURLU *curl_url_dup(const CURLU *in)
{
struct Curl_URL *u = calloc(sizeof(struct Curl_URL), 1);
if(u) {
@@ -1210,19 +1387,20 @@
u->portnum = in->portnum;
}
return u;
- fail:
+fail:
curl_url_cleanup(u);
return NULL;
}
-CURLUcode curl_url_get(CURLU *u, CURLUPart what,
+CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
char **part, unsigned int flags)
{
- char *ptr;
+ const char *ptr;
CURLUcode ifmissing = CURLUE_UNKNOWN_PART;
char portbuf[7];
bool urldecode = (flags & CURLU_URLDECODE)?1:0;
bool urlencode = (flags & CURLU_URLENCODE)?1:0;
+ bool punycode = FALSE;
bool plusdecode = FALSE;
(void)flags;
if(!u)
@@ -1252,6 +1430,7 @@
case CURLUPART_HOST:
ptr = u->host;
ifmissing = CURLUE_NO_HOST;
+ punycode = (flags & CURLU_PUNYCODE)?1:0;
break;
case CURLUPART_ZONEID:
ptr = u->zoneid;
@@ -1265,7 +1444,7 @@
/* there's no stored port number, but asked to deliver
a default one for the scheme */
const struct Curl_handler *h =
- Curl_builtin_scheme(u->scheme);
+ Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
if(h) {
msnprintf(portbuf, sizeof(portbuf), "%u", h->defport);
ptr = portbuf;
@@ -1275,7 +1454,7 @@
/* there is a stored port number, but ask to inhibit if
it matches the default one for the scheme */
const struct Curl_handler *h =
- Curl_builtin_scheme(u->scheme);
+ Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
if(h && (h->defport == u->portnum) &&
(flags & CURLU_NO_DEFAULT_PORT))
ptr = NULL;
@@ -1283,11 +1462,8 @@
break;
case CURLUPART_PATH:
ptr = u->path;
- if(!ptr) {
- ptr = u->path = strdup("/");
- if(!u->path)
- return CURLUE_OUT_OF_MEMORY;
- }
+ if(!ptr)
+ ptr = "/";
break;
case CURLUPART_QUERY:
ptr = u->query;
@@ -1304,6 +1480,7 @@
char *options = u->options;
char *port = u->port;
char *allochost = NULL;
+ punycode = (flags & CURLU_PUNYCODE)?1:0;
if(u->scheme && strcasecompare("file", u->scheme)) {
url = aprintf("file://%s%s%s",
u->path,
@@ -1321,7 +1498,7 @@
else
return CURLUE_NO_SCHEME;
- h = Curl_builtin_scheme(scheme);
+ h = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED);
if(!port && (flags & CURLU_DEFAULT_PORT)) {
/* there's no stored port number, but asked to deliver
a default one for the scheme */
@@ -1344,14 +1521,13 @@
if(u->host[0] == '[') {
if(u->zoneid) {
/* make it '[ host %25 zoneid ]' */
+ struct dynbuf enc;
size_t hostlen = strlen(u->host);
- size_t alen = hostlen + 3 + strlen(u->zoneid) + 1;
- allochost = malloc(alen);
- if(!allochost)
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ if(Curl_dyn_addf(&enc, "%.*s%%25%s]", (int)hostlen - 1, u->host,
+ u->zoneid))
return CURLUE_OUT_OF_MEMORY;
- memcpy(allochost, u->host, hostlen - 1);
- msnprintf(&allochost[hostlen - 1], alen - hostlen + 1,
- "%%25%s]", u->zoneid);
+ allochost = Curl_dyn_ptr(&enc);
}
}
else if(urlencode) {
@@ -1359,39 +1535,19 @@
if(!allochost)
return CURLUE_OUT_OF_MEMORY;
}
- else {
- /* only encode '%' in output host name */
- char *host = u->host;
- size_t pcount = 0;
- /* first, count number of percents present in the name */
- while(*host) {
- if(*host == '%')
- pcount++;
- host++;
- }
- /* if there were percents, encode the host name */
- if(pcount) {
- size_t hostlen = strlen(u->host);
- size_t alen = hostlen + 2 * pcount + 1;
- char *o = allochost = malloc(alen);
+ else if(punycode) {
+ if(!Curl_is_ASCII_name(u->host)) {
+#ifndef USE_IDN
+ return CURLUE_LACKS_IDN;
+#else
+ allochost = Curl_idn_decode(u->host);
if(!allochost)
return CURLUE_OUT_OF_MEMORY;
-
- host = u->host;
- while(*host) {
- if(*host == '%') {
- memcpy(o, "%25", 3);
- o += 3;
- host++;
- continue;
- }
- *o++ = *host++;
- }
- *o = '\0';
+#endif
}
}
- url = aprintf("%s://%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ url = aprintf("%s://%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
scheme,
u->user ? u->user : "",
u->password ? ":": "",
@@ -1402,7 +1558,6 @@
allochost ? allochost : u->host,
port ? ":": "",
port ? port : "",
- (u->path && (u->path[0] != '/')) ? "/": "",
u->path ? u->path : "/",
(u->query && u->query[0]) ? "?": "",
(u->query && u->query[0]) ? u->query : "",
@@ -1420,13 +1575,15 @@
break;
}
if(ptr) {
- *part = strdup(ptr);
+ size_t partlen = strlen(ptr);
+ size_t i = 0;
+ *part = Curl_memdup(ptr, partlen + 1);
if(!*part)
return CURLUE_OUT_OF_MEMORY;
if(plusdecode) {
/* convert + to space */
- char *plus;
- for(plus = *part; *plus; ++plus) {
+ char *plus = *part;
+ for(i = 0; i < partlen; ++plus, i++) {
if(*plus == '+')
*plus = ' ';
}
@@ -1443,18 +1600,29 @@
return CURLUE_URLDECODE;
}
*part = decoded;
+ partlen = dlen;
}
if(urlencode) {
- /* worst case output length is 3x the original! */
- char *newp = malloc(strlen(*part) * 3);
- if(!newp)
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ if(urlencode_str(&enc, *part, partlen, TRUE,
+ what == CURLUPART_QUERY))
return CURLUE_OUT_OF_MEMORY;
- if(strcpy_url(newp, *part, TRUE)) { /* consider it relative */
+ free(*part);
+ *part = Curl_dyn_ptr(&enc);
+ }
+ else if(punycode) {
+ if(!Curl_is_ASCII_name(u->host)) {
+#ifndef USE_IDN
+ return CURLUE_LACKS_IDN;
+#else
+ char *allochost = Curl_idn_decode(*part);
+ if(!allochost)
+ return CURLUE_OUT_OF_MEMORY;
free(*part);
- *part = newp;
+ *part = allochost;
+#endif
}
- else
- free(newp);
}
return CURLUE_OK;
@@ -1471,8 +1639,10 @@
bool urlencode = (flags & CURLU_URLENCODE)? 1 : 0;
bool plusencode = FALSE;
bool urlskipslash = FALSE;
+ bool leadingslash = FALSE;
bool appendquery = FALSE;
bool equalsencode = FALSE;
+ size_t nalloc;
if(!u)
return CURLUE_BAD_HANDLE;
@@ -1525,18 +1695,37 @@
return CURLUE_OK;
}
+ nalloc = strlen(part);
+ if(nalloc > CURL_MAX_INPUT_LENGTH)
+ /* excessive input length */
+ return CURLUE_MALFORMED_INPUT;
+
switch(what) {
- case CURLUPART_SCHEME:
- if(strlen(part) > MAX_SCHEME_LEN)
- /* too long */
+ case CURLUPART_SCHEME: {
+ size_t plen = strlen(part);
+ const char *s = part;
+ if((plen > MAX_SCHEME_LEN) || (plen < 1))
+ /* too long or too short */
return CURLUE_BAD_SCHEME;
if(!(flags & CURLU_NON_SUPPORT_SCHEME) &&
/* verify that it is a fine scheme */
- !Curl_builtin_scheme(part))
+ !Curl_builtin_scheme(part, CURL_ZERO_TERMINATED))
return CURLUE_UNSUPPORTED_SCHEME;
storep = &u->scheme;
urlencode = FALSE; /* never */
+ if(ISALPHA(*s)) {
+ /* ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
+ while(--plen) {
+ if(ISALNUM(*s) || (*s == '+') || (*s == '-') || (*s == '.'))
+ s++; /* fine */
+ else
+ return CURLUE_BAD_SCHEME;
+ }
+ }
+ else
+ return CURLUE_BAD_SCHEME;
break;
+ }
case CURLUPART_USER:
storep = &u->user;
break;
@@ -1546,15 +1735,10 @@
case CURLUPART_OPTIONS:
storep = &u->options;
break;
- case CURLUPART_HOST: {
- size_t len = strcspn(part, " \r\n");
- if(strlen(part) != len)
- /* hostname with bad content */
- return CURLUE_BAD_HOSTNAME;
+ case CURLUPART_HOST:
storep = &u->host;
Curl_safefree(u->zoneid);
break;
- }
case CURLUPART_ZONEID:
storep = &u->zoneid;
break;
@@ -1573,6 +1757,7 @@
break;
case CURLUPART_PATH:
urlskipslash = TRUE;
+ leadingslash = TRUE; /* enforce */
storep = &u->path;
break;
case CURLUPART_QUERY:
@@ -1598,7 +1783,9 @@
/* 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(Curl_is_absolute_url(part, NULL, 0)
+ if(Curl_is_absolute_url(part, NULL, 0,
+ flags & (CURLU_GUESS_SCHEME|
+ CURLU_DEFAULT_SCHEME))
|| curl_url_get(u, CURLUPART_URL, &oldurl, flags)) {
return parseurl_and_replace(part, u, flags);
}
@@ -1619,23 +1806,24 @@
}
DEBUGASSERT(storep);
{
- const char *newp = part;
- size_t nalloc = strlen(part);
+ const char *newp;
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, nalloc * 3 + 1 + leadingslash);
- if(nalloc > CURL_MAX_INPUT_LENGTH)
- /* excessive input length */
- return CURLUE_MALFORMED_INPUT;
-
+ if(leadingslash && (part[0] != '/')) {
+ CURLcode result = Curl_dyn_addn(&enc, "/", 1);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
+ }
if(urlencode) {
const unsigned char *i;
- char *o;
- char *enc = malloc(nalloc * 3 + 1); /* for worst case! */
- if(!enc)
- return CURLUE_OUT_OF_MEMORY;
- for(i = (const unsigned char *)part, o = enc; *i; i++) {
+
+ for(i = (const unsigned char *)part; *i; i++) {
+ CURLcode result;
if((*i == ' ') && plusencode) {
- *o = '+';
- o++;
+ result = Curl_dyn_addn(&enc, "+", 1);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
}
else if(Curl_isunreserved(*i) ||
((*i == '/') && urlskipslash) ||
@@ -1643,66 +1831,77 @@
if((*i == '=') && equalsencode)
/* only skip the first equals sign */
equalsencode = FALSE;
- *o = *i;
- o++;
+ result = Curl_dyn_addn(&enc, i, 1);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
}
else {
- msnprintf(o, 4, "%%%02x", *i);
- o += 3;
+ char out[3]={'%'};
+ out[1] = hexdigits[*i>>4];
+ out[2] = hexdigits[*i & 0xf];
+ result = Curl_dyn_addn(&enc, out, 3);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
}
}
- *o = 0; /* null-terminate */
- newp = enc;
}
else {
char *p;
- newp = strdup(part);
- if(!newp)
+ CURLcode result = Curl_dyn_add(&enc, part);
+ if(result)
return CURLUE_OUT_OF_MEMORY;
- p = (char *)newp;
+ p = Curl_dyn_ptr(&enc);
while(*p) {
/* make sure percent encoded are lower case */
if((*p == '%') && ISXDIGIT(p[1]) && ISXDIGIT(p[2]) &&
(ISUPPER(p[1]) || ISUPPER(p[2]))) {
- p[1] = (char)TOLOWER(p[1]);
- p[2] = (char)TOLOWER(p[2]);
+ p[1] = Curl_raw_tolower(p[1]);
+ p[2] = Curl_raw_tolower(p[2]);
p += 3;
}
else
p++;
}
}
+ newp = Curl_dyn_ptr(&enc);
if(appendquery) {
- /* Append the string onto the old query. Add a '&' separator if none is
- present at the end of the exsting query already */
+ /* Append the 'newp' string onto the old query. Add a '&' separator if
+ 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] != '&');
if(querylen) {
- size_t newplen = strlen(newp);
- char *p = malloc(querylen + addamperand + newplen + 1);
- if(!p) {
- free((char *)newp);
- return CURLUE_OUT_OF_MEMORY;
+ struct dynbuf qbuf;
+ Curl_dyn_init(&qbuf, CURL_MAX_INPUT_LENGTH);
+
+ if(Curl_dyn_addn(&qbuf, u->query, querylen)) /* add original query */
+ goto nomem;
+
+ if(addamperand) {
+ if(Curl_dyn_addn(&qbuf, "&", 1))
+ goto nomem;
}
- strcpy(p, u->query); /* original query */
- if(addamperand)
- p[querylen] = '&'; /* ampersand */
- strcpy(&p[querylen + addamperand], newp); /* new suffix */
- free((char *)newp);
+ if(Curl_dyn_add(&qbuf, newp))
+ goto nomem;
+ Curl_dyn_free(&enc);
free(*storep);
- *storep = p;
+ *storep = Curl_dyn_ptr(&qbuf);
return CURLUE_OK;
+nomem:
+ Curl_dyn_free(&enc);
+ return CURLUE_OUT_OF_MEMORY;
}
}
if(what == CURLUPART_HOST) {
- if(0 == strlen(newp) && (flags & CURLU_NO_AUTHORITY)) {
+ size_t n = strlen(newp);
+ if(!n && (flags & CURLU_NO_AUTHORITY)) {
/* Skip hostname check, it's allowed to be empty. */
}
else {
- if(hostname_check(u, (char *)newp)) {
- free((char *)newp);
+ if(!n || hostname_check(u, (char *)newp, n)) {
+ Curl_dyn_free(&enc);
return CURLUE_BAD_HOSTNAME;
}
}
diff --git a/lib/urldata.h b/lib/urldata.h
index bcb4d46..c45913b 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -53,6 +53,33 @@
#define PORT_GOPHER 70
#define PORT_MQTT 1883
+#ifdef USE_WEBSOCKETS
+/* CURLPROTO_GOPHERS (29) is the highest publicly used protocol bit number,
+ * the rest are internal information. If we use higher bits we only do this on
+ * 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 (1<<30)
+#define CURLPROTO_WSS ((curl_prot_t)1<<31)
+#else
+#define CURLPROTO_WS 0
+#define CURLPROTO_WSS 0
+#endif
+
+/* This should be undefined once we need bit 32 or higher */
+#define PROTO_TYPE_SMALL
+
+#ifndef PROTO_TYPE_SMALL
+typedef curl_off_t curl_prot_t;
+#else
+typedef unsigned int curl_prot_t;
+#endif
+
+/* This mask is for all the old protocols that are provided and defined in the
+ public header and shall exclude protocols added since which are not exposed
+ in the API */
+#define CURLPROTO_MASK (0x3ffffff)
+
#define DICT_MATCH "/MATCH:"
#define DICT_MATCH2 "/M:"
#define DICT_MATCH3 "/FIND:"
@@ -66,7 +93,8 @@
/* 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)
+#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)
@@ -85,6 +113,7 @@
input easier and better. */
#define CURL_MAX_INPUT_LENGTH 8000000
+
#include "cookie.h"
#include "psl.h"
#include "formdata.h"
@@ -105,6 +134,7 @@
#include "hash.h"
#include "splay.h"
#include "dynbuf.h"
+#include "dynhds.h"
/* return the count of bytes sent, or -1 on error */
typedef ssize_t (Curl_send)(struct Curl_easy *data, /* transfer */
@@ -139,10 +169,10 @@
#include "rtsp.h"
#include "smb.h"
#include "mqtt.h"
-#include "wildcard.h"
+#include "ftplistparser.h"
#include "multihandle.h"
-#include "quic.h"
#include "c-hyper.h"
+#include "cf-socket.h"
#ifdef HAVE_GSSAPI
# ifdef HAVE_GSSGNU
@@ -157,10 +187,10 @@
# endif
#endif
-#ifdef HAVE_LIBSSH2_H
+#ifdef USE_LIBSSH2
#include <libssh2.h>
#include <libssh2_sftp.h>
-#endif /* HAVE_LIBSSH2_H */
+#endif /* USE_LIBSSH2 */
#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
#define READBUFFER_MAX CURL_MAX_READ_SIZE
@@ -179,8 +209,17 @@
#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE
#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU
+#ifdef DEBUGBUILD
+/* On a debug build, we want to fail hard on easy handles that
+ * 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: \
+ (DEBUGASSERT(!(x)), FALSE))
+#else
#define GOOD_EASY_HANDLE(x) \
((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))
+#endif
#ifdef HAVE_GSSAPI
/* Types needed for krb5-ftp connections */
@@ -221,22 +260,7 @@
/* SSL backend-specific data; declared differently by each SSL backend */
struct ssl_backend_data;
-/* struct for data related to each SSL connection */
-struct ssl_connect_data {
- ssl_connection_state state;
- ssl_connect_state connecting_state;
-#if defined(USE_SSL)
- struct ssl_backend_data *backend;
-#endif
- /* Use ssl encrypted communications TRUE/FALSE. The library is not
- necessarily using ssl at the moment but at least asked to or means to use
- it. See 'state' for the exact current state of the connection. */
- BIT(use);
-};
-
struct ssl_primary_config {
- long version; /* what version the client wants to use */
- long version_max; /* max supported version the client wants to use*/
char *CApath; /* certificate dir (doesn't work on windows) */
char *CAfile; /* certificate to verify peer against */
char *issuercert; /* optional issuer certificate filename */
@@ -251,10 +275,11 @@
#ifdef USE_TLS_SRP
char *username; /* TLS username (for, e.g., SRP) */
char *password; /* TLS password (for, e.g., SRP) */
- enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */
#endif
char *curves; /* list of curves to use */
unsigned char ssl_options; /* the CURLOPT_SSL_OPTIONS bitmask */
+ unsigned int version_max; /* max supported version the client wants to use */
+ unsigned char version; /* what version the client wants to use */
BIT(verifypeer); /* set TRUE if this is desired */
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
BIT(verifystatus); /* set TRUE if certificate status must be checked */
@@ -273,7 +298,7 @@
char *key_passwd; /* plain text private key password */
BIT(certinfo); /* gather lots of certificate info */
BIT(falsestart);
- BIT(enable_beast); /* allow this flaw for interoperability's sake*/
+ BIT(enable_beast); /* allow this flaw for interoperability's sake */
BIT(no_revoke); /* disable SSL certificate revocation checks */
BIT(no_partialchain); /* don't accept partial certificate chains */
BIT(revoke_best_effort); /* ignore SSL revocation offline/missing revocation
@@ -285,6 +310,7 @@
struct ssl_general_config {
size_t max_ssl_sessions; /* SSL session id cache size */
+ int ca_cache_timeout; /* Certificate store cache timeout (seconds) */
};
/* information stored about one single SSL session */
@@ -318,11 +344,11 @@
char *nonce;
char *cnonce;
char *realm;
- int algo;
char *opaque;
char *qop;
char *algorithm;
int nc; /* nonce count */
+ unsigned char algo;
BIT(stale); /* set true for re-negotiation */
BIT(userhash);
#endif
@@ -448,12 +474,8 @@
* Boolean values that concerns this connection.
*/
struct ConnectBits {
- bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set
- the first time on the first connect function call */
#ifndef CURL_DISABLE_PROXY
- bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy
- is complete */
- BIT(httpproxy); /* if set, this transfer is done through a http proxy */
+ BIT(httpproxy); /* if set, this transfer is done through an HTTP proxy */
BIT(socksproxy); /* if set, this transfer is done through a socks proxy */
BIT(proxy_user_passwd); /* user+password for the proxy? */
BIT(tunnel_proxy); /* if CONNECT is used to "tunnel" through the proxy.
@@ -486,10 +508,6 @@
that we are creating a request with an auth header,
but it is not the final request in the auth
negotiation. */
- BIT(rewindaftersend);/* TRUE when the sending couldn't be stopped even
- though it will be discarded. When the whole send
- operation is done, we must call the data rewind
- callback. */
#ifndef CURL_DISABLE_FTP
BIT(ftp_use_epsv); /* As set with CURLOPT_FTP_USE_EPSV, but if we find out
EPSV doesn't work we disable it for the forthcoming
@@ -507,9 +525,7 @@
connection */
BIT(multiplex); /* connection is multiplexed */
BIT(tcp_fastopen); /* use TCP Fast Open */
- BIT(tls_enable_npn); /* TLS NPN extension? */
BIT(tls_enable_alpn); /* TLS ALPN extension? */
- BIT(connect_only);
#ifndef CURL_DISABLE_DOH
BIT(doh);
#endif
@@ -554,7 +570,7 @@
struct Curl_dns_entry *dns;
struct thread_data *tdata;
void *resolver; /* resolver state, if it is used in the URL state -
- ares_channel f.e. */
+ ares_channel e.g. */
int port;
int status; /* if done is TRUE, this is the status from the callback */
BIT(done); /* set TRUE when the lookup is complete */
@@ -575,8 +591,9 @@
enum upgrade101 {
UPGR101_INIT, /* default state */
- UPGR101_REQUESTED, /* upgrade requested */
- UPGR101_RECEIVED, /* response received */
+ UPGR101_WS, /* upgrade to WebSockets requested */
+ UPGR101_H2, /* upgrade to HTTP/2 requested */
+ UPGR101_RECEIVED, /* 101 response received */
UPGR101_WORKING /* talking upgraded protocol */
};
@@ -598,23 +615,6 @@
DOH_PROBE_SLOTS
};
-/* one of these for each DoH request */
-struct dnsprobe {
- CURL *easy;
- int dnstype;
- unsigned char dohbuffer[512];
- size_t dohlen;
- struct dynbuf serverdoh;
-};
-
-struct dohdata {
- struct curl_slist *headers;
- struct dnsprobe probe[DOH_PROBE_SLOTS];
- unsigned int pending; /* still outstanding requests */
- int port;
- const char *host;
-};
-
/*
* Request specific data in the easy handle (Curl_easy). Previously,
* these members were on the connectdata struct but since a conn struct may
@@ -640,7 +640,6 @@
curl_off_t pendingheader; /* this many bytes left to send is actually
header and not body */
struct curltime start; /* transfer started at this time */
- struct curltime now; /* current time */
enum {
HEADER_NORMAL, /* no bad header at all */
HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest
@@ -698,7 +697,12 @@
#ifndef CURL_DISABLE_DOH
struct dohdata *doh; /* DoH specific data for this request */
#endif
+#if defined(WIN32) && defined(USE_WINSOCK)
+ struct curltime last_sndbuf_update; /* last time readwrite_upload called
+ win_update_buffer_size */
+#endif
unsigned char setcookies;
+ unsigned char writer_stack_depth; /* Unencoding stack depth. */
BIT(header); /* incoming data has HTTP header */
BIT(content_range); /* set TRUE if Content-Range: was found */
BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding
@@ -714,6 +718,7 @@
BIT(forbidchunk); /* used only to explicitly forbid chunk-upload for
specific upload buffers. See readmoredata() in http.c
for details. */
+ BIT(no_body); /* the response has no body */
};
/*
@@ -774,8 +779,8 @@
/* This function *MAY* be set to a protocol-dependent function that is run
* by the curl_disconnect(), as a step in the disconnection. If the handler
* is called because the connection has been considered dead,
- * dead_connection is set to TRUE. The connection is already disassociated
- * from the transfer here.
+ * dead_connection is set to TRUE. The connection is (again) associated with
+ * the transfer here.
*/
CURLcode (*disconnect)(struct Curl_easy *, struct connectdata *,
bool dead_connection);
@@ -796,10 +801,10 @@
void (*attach)(struct Curl_easy *data, struct connectdata *conn);
int defport; /* Default port. */
- unsigned int protocol; /* See CURLPROTO_* - this needs to be the single
- specific protocol bit */
- unsigned int family; /* single bit for protocol family; basically the
- non-TLS name of the protocol this is */
+ 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_* */
};
@@ -820,8 +825,8 @@
url query strings (?foo=bar) ! */
#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per
request instead of per connection */
-#define PROTOPT_ALPN_NPN (1<<8) /* set ALPN and/or NPN for this */
-#define PROTOPT_STREAM (1<<9) /* a protocol with individual logical streams */
+#define PROTOPT_ALPN (1<<8) /* set ALPN for this */
+/* (1<<9) was PROTOPT_STREAM, now free */
#define PROTOPT_URLOPTIONS (1<<10) /* allow options part in the userinfo field
of the URL */
#define PROTOPT_PROXY_AS_HTTP (1<<11) /* allow this non-HTTP scheme over a
@@ -839,73 +844,32 @@
#define CONNRESULT_NONE 0 /* No extra information. */
#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */
-#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
-struct postponed_data {
- char *buffer; /* Temporal store for received data during
- sending, must be freed */
- size_t allocated_size; /* Size of temporal store */
- size_t recv_size; /* Size of received data during sending */
- size_t recv_processed; /* Size of processed part of postponed data */
-#ifdef DEBUGBUILD
- curl_socket_t bindsock;/* Structure must be bound to specific socket,
- used only for DEBUGASSERT */
-#endif /* DEBUGBUILD */
-};
-#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
-
struct proxy_info {
struct hostname host;
- long port;
- curl_proxytype proxytype; /* what kind of proxy that is in use */
+ int port;
+ unsigned char proxytype; /* curl_proxytype: what kind of proxy that is in
+ use */
char *user; /* proxy user name string, allocated */
char *passwd; /* proxy password string, allocated */
};
struct ldapconninfo;
-struct http_connect_state;
-/* for the (SOCKS) connect state machine */
-enum connect_t {
- CONNECT_INIT,
- CONNECT_SOCKS_INIT, /* 1 */
- CONNECT_SOCKS_SEND, /* 2 waiting to send more first data */
- CONNECT_SOCKS_READ_INIT, /* 3 set up read */
- CONNECT_SOCKS_READ, /* 4 read server response */
- CONNECT_GSSAPI_INIT, /* 5 */
- CONNECT_AUTH_INIT, /* 6 setup outgoing auth buffer */
- CONNECT_AUTH_SEND, /* 7 send auth */
- CONNECT_AUTH_READ, /* 8 read auth response */
- CONNECT_REQ_INIT, /* 9 init SOCKS "request" */
- CONNECT_RESOLVING, /* 10 */
- CONNECT_RESOLVED, /* 11 */
- CONNECT_RESOLVE_REMOTE, /* 12 */
- CONNECT_REQ_SEND, /* 13 */
- CONNECT_REQ_SENDING, /* 14 */
- CONNECT_REQ_READ, /* 15 */
- CONNECT_REQ_READ_MORE, /* 16 */
- CONNECT_DONE /* 17 connected fine to the remote or the SOCKS proxy */
-};
-
-#define SOCKS_STATE(x) (((x) >= CONNECT_SOCKS_INIT) && \
- ((x) < CONNECT_DONE))
-
-struct connstate {
- enum connect_t state;
- ssize_t outstanding; /* send this many bytes more */
- unsigned char *outp; /* send from this pointer */
-};
+#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.
*/
struct connectdata {
- struct connstate cnnct;
struct Curl_llist_element bundle_node; /* conncache */
/* chunk is for HTTP chunked encoding, but is in the general connectdata
- struct only because we can do just about any protocol through a HTTP proxy
- and a HTTP proxy may in fact respond using chunked encoding */
+ struct only because we can do just about any protocol through an HTTP
+ proxy and an HTTP proxy may in fact respond using chunked encoding */
struct Curl_chunker chunk;
curl_closesocket_callback fclosesocket; /* function closing the socket(s) */
@@ -918,8 +882,8 @@
#define CONN_INUSE(c) ((c)->easyq.size)
/**** Fields set when inited and not modified again */
- long connection_id; /* Contains a unique number to make it easier to
- track the connections in the log output */
+ curl_off_t connection_id; /* Contains a unique number to make it easier to
+ track the connections in the log output */
/* 'dns_entry' is the particular host we use. This points to an entry in the
DNS cache and it will not get pruned while locked. It gets unlocked in
@@ -927,25 +891,9 @@
there is no name resolve done. */
struct Curl_dns_entry *dns_entry;
- /* 'ip_addr' is the particular IP we connected to. It points to a struct
- within the DNS cache, so this pointer is only valid as long as the DNS
- cache entry remains locked. It gets unlocked in multi_done() */
- struct Curl_addrinfo *ip_addr;
- struct Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */
-#ifdef ENABLE_IPV6
- unsigned int scope_id; /* Scope id for IPv6 */
-#endif
-
- enum {
- TRNSPRT_TCP = 3,
- TRNSPRT_UDP = 4,
- TRNSPRT_QUIC = 5
- } transport;
-
-#ifdef ENABLE_QUIC
- struct quicsocket hequic[2]; /* two, for happy eyeballs! */
- struct quicsocket *quic;
-#endif
+ /* 'remote_addr' is the particular IP we connected to. it is owned, set
+ * and NULLed by the connected socket filter (if there is one). */
+ const struct Curl_sockaddr_ex *remote_addr;
struct hostname host;
char *hostname_resolve; /* host name to resolve to address, allocated */
@@ -956,13 +904,6 @@
struct proxy_info socks_proxy;
struct proxy_info http_proxy;
#endif
- int port; /* which port to use locally - to connect to */
- 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 */
- unsigned short secondary_port; /* secondary socket remote port to connect to
- (ftp) */
-
/* 'primary_ip' and 'primary_port' get filled with peer's numerical
ip address and port number whenever an outgoing connection is
*attempted* from the primary socket to a remote address. When more
@@ -971,52 +912,26 @@
these are updated with data which comes directly from the socket. */
char primary_ip[MAX_IPADR_LEN];
- unsigned char ip_version; /* copied from the Curl_easy at creation time */
-
char *user; /* user name string, allocated */
char *passwd; /* password string, allocated */
char *options; /* options string, allocated */
char *sasl_authzid; /* authorization identity string, allocated */
char *oauth_bearer; /* OAUTH2 bearer, allocated */
- unsigned char httpversion; /* the HTTP version*10 reported by the server */
struct curltime now; /* "current" time */
struct curltime created; /* creation time */
struct curltime lastused; /* when returned to the connection cache */
curl_socket_t sock[2]; /* two sockets, the second is used for the data
transfer when doing FTP */
- curl_socket_t tempsock[2]; /* temporary sockets for happy eyeballs */
- int tempfamily[2]; /* family used for the temp sockets */
Curl_recv *recv[2];
Curl_send *send[2];
+ struct Curl_cfilter *cfilter[2]; /* connection filters */
-#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
- struct postponed_data postponed[2]; /* two buffers for two sockets */
-#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
- struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
-#ifndef CURL_DISABLE_PROXY
- struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */
-#endif
-#ifdef USE_SSL
- void *ssl_extra; /* separately allocated backend-specific data */
-#endif
struct ssl_primary_config ssl_config;
#ifndef CURL_DISABLE_PROXY
struct ssl_primary_config proxy_ssl_config;
#endif
struct ConnectBits bits; /* various state-flags for this connection */
- /* The field below gets set in Curl_connecthost */
- int num_addr; /* number of addresses to try to connect to */
- /* connecttime: when connect() is called on the current IP address. Used to
- be able to track when to move on to try next IP - but only when the multi
- interface is used. */
- struct curltime connecttime;
-
- /* The field below gets set in Curl_connecthost */
- /* how long time in milliseconds to spend on trying to connect to each IP
- address, per family */
- timediff_t timeoutms_per_addr[2];
-
const struct Curl_handler *handler; /* Connection's protocol handler */
const struct Curl_handler *given; /* The protocol first given */
@@ -1034,9 +949,9 @@
#ifdef HAVE_GSSAPI
BIT(sec_complete); /* if Kerberos is enabled for this connection */
- enum protection_level command_prot;
- enum protection_level data_prot;
- enum protection_level request_data_prot;
+ unsigned char command_prot; /* enum protection_level */
+ unsigned char data_prot; /* enum protection_level */
+ unsigned char request_data_prot; /* enum protection_level */
size_t buffer_size;
struct krb5buffer in_buffer;
void *app_data;
@@ -1079,16 +994,15 @@
struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
#endif
+#ifndef CURL_DISABLE_HTTP
/* for chunked-encoded trailer */
struct dynbuf trailer;
+#endif
union {
#ifndef CURL_DISABLE_FTP
struct ftp_conn ftpc;
#endif
-#ifndef CURL_DISABLE_HTTP
- struct http_conn httpc;
-#endif
#ifdef USE_SSH
struct ssh_conn sshc;
#endif
@@ -1115,9 +1029,11 @@
#ifndef CURL_DISABLE_MQTT
struct mqtt_conn mqtt;
#endif
+#ifdef USE_WEBSOCKETS
+ struct websocket *ws;
+#endif
} proto;
- struct http_connect_state *connect_state; /* for HTTP CONNECT */
struct connectbundle *bundle; /* The bundle we are member of */
#ifdef USE_UNIX_SOCKETS
char *unix_domain_socket;
@@ -1132,15 +1048,33 @@
that subsequent bound-requested connections aren't accidentally re-using
wrong connections. */
char *localdev;
- int localportrange;
- int cselect_bits; /* bitmask of socket events */
+ unsigned short localportrange;
int waitfor; /* current READ/WRITE bits to wait for */
- int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
-
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
int socks5_gssapi_enctype;
#endif
+ /* The field below gets set in connect.c:connecthost() */
+ int port; /* which port to use locally - to connect to */
+ 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 */
+#ifdef ENABLE_IPV6
+ unsigned int scope_id; /* Scope id for IPv6 */
+#endif
unsigned short localport;
+ unsigned short secondary_port; /* secondary socket remote port to connect to
+ (ftp) */
+ unsigned char cselect_bits; /* bitmask of socket events */
+ unsigned char alpn; /* APLN TLS negotiated protocol, a CURL_HTTP_VERSION*
+ value */
+#ifndef CURL_DISABLE_PROXY
+ unsigned char proxy_alpn; /* APLN of proxy tunnel, CURL_HTTP_VERSION* */
+#endif
+ unsigned char transport; /* one of the TRNSPRT_* defines */
+ unsigned char ip_version; /* copied from the Curl_easy at creation time */
+ unsigned char httpversion; /* the HTTP version*10 reported by the server */
+ unsigned char connect_only;
+ unsigned char gssapi_delegation; /* inherited from set.gssapi_delegation */
};
/* The end of connectdata. */
@@ -1269,10 +1203,29 @@
should be RFC compliant */
};
-struct Curl_http2_dep {
- struct Curl_http2_dep *next;
+#ifdef USE_NGHTTP2
+struct Curl_data_prio_node {
+ struct Curl_data_prio_node *next;
struct Curl_easy *data;
};
+#endif
+
+/**
+ * Priority information for an easy handle in relation to others
+ * on the same connection.
+ * TODO: we need to adapt it to the new priority scheme as defined in RFC 9218
+ */
+struct Curl_data_priority {
+#ifdef USE_NGHTTP2
+ /* tree like dependencies only implemented in nghttp2 */
+ struct Curl_easy *parent;
+ struct Curl_data_prio_node *children;
+#endif
+ int weight;
+#ifdef USE_NGHTTP2
+ BIT(exclusive);
+#endif
+};
/*
* This struct is for holding data that was attempted to get sent to the user's
@@ -1300,6 +1253,8 @@
EXPIRE_TIMEOUT,
EXPIRE_TOOFAST,
EXPIRE_QUIC,
+ EXPIRE_FTP_ACCEPT,
+ EXPIRE_ALPN_EYEBALLS,
EXPIRE_LAST /* not an actual timer, used as a marker only */
} expire_id;
@@ -1339,7 +1294,9 @@
/* buffers to store authentication data in, as parsed from input options */
struct curltime keeps_speed; /* for the progress meter really */
- long lastconnect_id; /* The last connection, -1 if undefined */
+ curl_off_t lastconnect_id; /* The last connection, -1 if undefined */
+ curl_off_t recent_conn_id; /* The most recent connection used, might no
+ * longer exist */
struct dynbuf headerb; /* buffer to store headers in */
char *buffer; /* download buffer */
@@ -1353,7 +1310,7 @@
This is strdup()ed data. */
char *first_host;
int first_remote_port;
- unsigned int first_remote_protocol;
+ curl_prot_t first_remote_protocol;
int retrycount; /* number of retries on a new connection */
struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
@@ -1389,11 +1346,6 @@
/* a place to store the most recently set (S)FTP entrypath */
char *most_recent_ftp_entrypath;
- unsigned char httpwant; /* when non-zero, a specific HTTP version requested
- to be used in the library's request(s) */
- unsigned char httpversion; /* the lowest HTTP version*10 reported by any
- server involved in this request */
-
#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__)
/* do FTP line-end conversions on most platforms */
#define CURL_DO_LINEEND_CONV
@@ -1411,31 +1363,23 @@
long rtsp_next_client_CSeq; /* the session's next client CSeq */
long rtsp_next_server_CSeq; /* the session's next server CSeq */
long rtsp_CSeq_recv; /* most recent CSeq received */
+
+ unsigned char rtp_channel_mask[32]; /* for the correctness checking of the
+ interleaved data */
#endif
curl_off_t infilesize; /* size of file to upload, -1 means unknown.
Copied from set.filesize at start of operation */
#if defined(USE_HTTP2) || defined(USE_HTTP3)
- size_t drain; /* Increased when this stream has data to read, even if its
- socket is not necessarily is readable. Decreased when
- checked. */
+ struct Curl_data_priority priority; /* shallow copy of data->set */
#endif
curl_read_callback fread_func; /* read callback/function */
void *in; /* CURLOPT_READDATA */
-#ifdef USE_HTTP2
- struct Curl_easy *stream_depends_on;
- int stream_weight;
-#endif
CURLU *uh; /* URL handle for the current parsed URL */
struct urlpieces up;
- Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
char *url; /* work URL, copied from UserDefined */
char *referer; /* referer string */
-#ifndef CURL_DISABLE_COOKIES
- struct curl_slist *cookielist; /* list of cookie files set by
- curl_easy_setopt(COOKIEFILE) calls */
-#endif
struct curl_slist *resolve; /* set to point to the set.resolve list when
this should be dealt with in pretransfer */
#ifndef CURL_DISABLE_HTTP
@@ -1443,7 +1387,7 @@
struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
headers */
struct Curl_llist httphdrs; /* received headers */
- struct curl_header headerout; /* for external purposes */
+ struct curl_header headerout[2]; /* for external purposes */
struct Curl_header_store *prevhead; /* the latest added header */
trailers_state trailers_state; /* whether we are sending trailers
and what stage are we at */
@@ -1474,6 +1418,15 @@
char *proxypasswd;
} aptr;
+ unsigned char httpwant; /* when non-zero, a specific HTTP version requested
+ to be used in the library's request(s) */
+ unsigned char httpversion; /* the lowest HTTP version*10 reported by any
+ server involved in this request */
+ unsigned char httpreq; /* Curl_HttpReq; what kind of HTTP request (if any)
+ is this */
+ unsigned char dselect_bits; /* != 0 -> bitmask of socket events for this
+ transfer overriding anything the socket may
+ report */
#ifdef CURLDEBUG
BIT(conncache_lock);
#endif
@@ -1500,7 +1453,6 @@
BIT(done); /* set to FALSE when Curl_init_do() is called and set to TRUE
when multi_done() is called, to prevent multi_done() to get
invoked twice when the multi interface is used. */
- BIT(stream_depends_e); /* set or don't set the Exclusive bit */
BIT(previouslypending); /* this transfer WAS in the multi->pending queue */
BIT(cookie_engine);
BIT(prefer_ascii); /* ASCII rather than binary */
@@ -1508,6 +1460,10 @@
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(rewindbeforesend);/* TRUE when the sending couldn't be stopped even
+ though it will be discarded. We must call the data
+ rewind callback before trying to send again. */
+ BIT(upload); /* upload request */
};
/*
@@ -1519,7 +1475,7 @@
* Character pointer fields point to dynamic storage, unless otherwise stated.
*/
-struct Curl_multi; /* declared and used only in multi.c */
+struct Curl_multi; /* declared in multihandle.c */
/*
* This enumeration MUST not use conditional directives (#ifdefs), new
@@ -1608,6 +1564,8 @@
STRING_DNS_LOCAL_IP4,
STRING_DNS_LOCAL_IP6,
STRING_SSL_EC_CURVES,
+ STRING_AWS_SIGV4, /* Parameters for V4 signature */
+ STRING_HAPROXY_CLIENT_IP, /* CURLOPT_HAPROXY_CLIENT_IP */
/* -- end of null-terminated strings -- */
@@ -1617,8 +1575,6 @@
STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */
- STRING_AWS_SIGV4, /* Parameters for V4 signature */
-
STRING_LAST /* not used, just an end-of-list marker */
};
@@ -1643,18 +1599,12 @@
FILE *err; /* the stderr user data goes here */
void *debugdata; /* the data that will be passed to fdebug */
char *errorbuffer; /* (Static) store failure messages in here */
- long proxyport; /* If non-zero, use this port number by default. If the
- proxy string features a ":[port]" that one will override
- this. */
void *out; /* CURLOPT_WRITEDATA */
void *in_set; /* CURLOPT_READDATA */
void *writeheader; /* write the header to this if non-NULL */
- long use_port; /* which port to use (when not using default) */
+ unsigned short use_port; /* which port to use (when not using default) */
unsigned long httpauth; /* kind of HTTP authentication to use (bitmask) */
unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */
-#ifndef CURL_DISABLE_PROXY
- unsigned long socks5auth;/* kind of SOCKS5 authentication to use (bitmask) */
-#endif
long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1
for infinity */
@@ -1664,8 +1614,9 @@
of strlen(), and then the data *may* be binary
(contain zero bytes) */
unsigned short localport; /* local port number to bind to */
- int localportrange; /* number of additional port numbers to test in case the
- 'localport' one can't be bind()ed */
+ unsigned short localportrange; /* number of additional port numbers to test
+ in case the 'localport' one can't be
+ bind()ed */
curl_write_callback fwrite_func; /* function that stores the output */
curl_write_callback fwrite_header; /* function that stores headers */
curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */
@@ -1687,7 +1638,13 @@
void *prereq_userp; /* pre-initial request user data */
void *seek_client; /* pointer to pass to the seek callback */
+#ifndef CURL_DISABLE_COOKIES
+ struct curl_slist *cookielist; /* list of cookie files set by
+ curl_easy_setopt(COOKIEFILE) calls */
+#endif
#ifndef CURL_DISABLE_HSTS
+ struct curl_slist *hstslist; /* list of HSTS files set by
+ curl_easy_setopt(HSTS) calls */
curl_hstsread_callback hsts_read;
void *hsts_read_userp;
curl_hstswrite_callback hsts_write;
@@ -1695,10 +1652,10 @@
#endif
void *progress_client; /* pointer to pass to the progress callback */
void *ioctl_client; /* pointer to pass to the ioctl callback */
- long timeout; /* in milliseconds, 0 means no timeout */
- long connecttimeout; /* in milliseconds, 0 means no timeout */
- long happy_eyeballs_timeout; /* in milliseconds, 0 is a valid value */
- long server_response_timeout; /* in milliseconds, 0 means no timeout */
+ unsigned int timeout; /* ms, 0 means no timeout */
+ unsigned int connecttimeout; /* ms, 0 means no timeout */
+ unsigned int happy_eyeballs_timeout; /* ms, 0 is a valid value */
+ unsigned int server_response_timeout; /* ms, 0 means no timeout */
long maxage_conn; /* in seconds, max idle time to allow a connection that
is to be reused */
long maxlifetime_conn; /* in seconds, max time since creation to allow a
@@ -1714,17 +1671,8 @@
download */
curl_off_t set_resume_from; /* continue [ftp] transfer from here */
struct curl_slist *headers; /* linked list of extra headers */
- struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */
struct curl_httppost *httppost; /* linked list of old POST data */
curl_mimepart mimepost; /* MIME/POST data. */
- struct curl_slist *quote; /* after connection is established */
- struct curl_slist *postquote; /* after the transfer */
- struct curl_slist *prequote; /* before the transfer, after type */
- struct curl_slist *source_quote; /* 3rd party quote */
- struct curl_slist *source_prequote; /* in 3rd party transfer mode - before
- the transfer on source host */
- struct curl_slist *source_postquote; /* in 3rd party transfer mode - after
- the transfer on source host */
#ifndef CURL_DISABLE_TELNET
struct curl_slist *telnet_options; /* linked list of telnet options */
#endif
@@ -1732,65 +1680,77 @@
DNS cache */
struct curl_slist *connect_to; /* list of host:port mappings to override
the hostname and port to connect to */
- curl_TimeCond timecondition; /* kind of time/date comparison */
- curl_proxytype proxytype; /* what kind of proxy that is in use */
time_t timevalue; /* what time to compare with */
- Curl_HttpReq method; /* what kind of HTTP request (if any) is this */
+ unsigned char timecondition; /* kind of time comparison: curl_TimeCond */
+ unsigned char method; /* what kind of HTTP request: Curl_HttpReq */
unsigned char httpwant; /* when non-zero, a specific HTTP version requested
to be used in the library's request(s) */
struct ssl_config_data ssl; /* user defined SSL stuff */
#ifndef CURL_DISABLE_PROXY
struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */
+ struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */
+ unsigned short 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: curl_proxytype */
+ unsigned char socks5auth;/* kind of SOCKS5 authentication to use (bitmask) */
#endif
struct ssl_general_config general_ssl; /* general user defined SSL stuff */
- long dns_cache_timeout; /* DNS cache timeout */
- long buffer_size; /* size of receive buffer to use */
+ int dns_cache_timeout; /* DNS cache timeout (seconds) */
+ unsigned int buffer_size; /* size of receive buffer to use */
unsigned int upload_buffer_size; /* size of upload buffer to use,
keep it >= CURL_MAX_WRITE_SIZE */
void *private_data; /* application-private data */
+#ifndef CURL_DISABLE_HTTP
struct curl_slist *http200aliases; /* linked list of aliases for http200 */
+#endif
unsigned char ipver; /* the CURL_IPRESOLVE_* defines in the public header
file 0 - whatever, 1 - v2, 2 - v6 */
curl_off_t max_filesize; /* Maximum file size to download */
#ifndef CURL_DISABLE_FTP
- curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */
- curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */
- curl_ftpccc ftp_ccc; /* FTP CCC options */
- long accepttimeout; /* in milliseconds, 0 means no timeout */
+ unsigned char ftp_filemethod; /* how to get to a file: curl_ftpfile */
+ unsigned char ftpsslauth; /* what AUTH XXX to try: curl_ftpauth */
+ unsigned char ftp_ccc; /* FTP CCC options: curl_ftpccc */
+ unsigned int accepttimeout; /* in milliseconds, 0 means no timeout */
#endif
- int ftp_create_missing_dirs; /* 1 - create directories that don't exist
- 2 - the same but also allow MKD to fail once
- */
+#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
+ struct curl_slist *quote; /* after connection is established */
+ struct curl_slist *postquote; /* after the transfer */
+ struct curl_slist *prequote; /* before the transfer, after type */
+ /* Despite the name, ftp_create_missing_dirs is for FTP(S) and SFTP
+ 1 - create directories that don't exist
+ 2 - the same but also allow MKD to fail once
+ */
+ unsigned char ftp_create_missing_dirs;
+#endif
#ifdef USE_LIBSSH2
curl_sshhostkeycallback ssh_hostkeyfunc; /* hostkey check callback */
void *ssh_hostkeyfunc_userp; /* custom pointer to callback */
#endif
-
+#ifdef USE_SSH
curl_sshkeycallback ssh_keyfunc; /* key matching callback */
void *ssh_keyfunc_userp; /* custom pointer to callback */
-#ifndef CURL_DISABLE_NETRC
- enum CURL_NETRC_OPTION
- use_netrc; /* defined in include/curl.h */
-#endif
- curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
- IMAP or POP3 or others! */
- unsigned int new_file_perms; /* when creating remote files */
- unsigned int new_directory_perms; /* when creating remote dirs */
int ssh_auth_types; /* allowed SSH auth types */
+ unsigned int new_directory_perms; /* when creating remote dirs */
+#endif
+#ifndef CURL_DISABLE_NETRC
+ unsigned char use_netrc; /* enum CURL_NETRC_OPTION values */
+#endif
+ unsigned int new_file_perms; /* when creating remote files */
char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
struct curl_blob *blobs[BLOB_LAST];
#ifdef ENABLE_IPV6
unsigned int scope_id; /* Scope id for IPv6 */
#endif
- unsigned int allowed_protocols;
- unsigned int redir_protocols;
+ curl_prot_t allowed_protocols;
+ curl_prot_t redir_protocols;
+#ifndef CURL_DISABLE_MIME
unsigned int mime_options; /* Mime option flags. */
-
+#endif
#ifndef CURL_DISABLE_RTSP
void *rtp_out; /* write RTP to this if non-NULL */
/* Common RTSP header options */
Curl_RtspReq rtspreq; /* RTSP request type */
- long rtspversion; /* like httpversion, for RTSP */
#endif
#ifndef CURL_DISABLE_FTP
curl_chunk_bgn_callback chunk_bgn; /* called before part of transfer
@@ -1800,9 +1760,11 @@
curl_fnmatch_callback fnmatch; /* callback to decide which file corresponds
to pattern (e.g. if WILDCARDMATCH is on) */
void *fnmatch_data;
+ void *wildcardptr;
#endif
- long gssapi_delegation; /* GSS-API credential delegation, see the
- documentation of CURLOPT_GSSAPI_DELEGATION */
+ /* GSS-API credential delegation, see the documentation of
+ CURLOPT_GSSAPI_DELEGATION */
+ unsigned char gssapi_delegation;
int tcp_keepidle; /* seconds in idle before sending keepalive probe */
int tcp_keepintvl; /* seconds between TCP keepalive probes */
@@ -1810,10 +1772,8 @@
size_t maxconnects; /* Max idle connections in the connection cache */
long expect_100_timeout; /* in milliseconds */
-#ifdef USE_HTTP2
- struct Curl_easy *stream_depends_on;
- int stream_weight;
- struct Curl_http2_dep *stream_dependents;
+#if defined(USE_HTTP2) || defined(USE_HTTP3)
+ struct Curl_data_priority priority;
#endif
curl_resolver_start_callback resolver_start; /* optional callback called
before resolver start */
@@ -1824,8 +1784,10 @@
struct Curl_easy *dohfor; /* this is a DoH request for that transfer */
#endif
CURLU *uh; /* URL handle for the current parsed URL */
+#ifndef CURL_DISABLE_HTTP
void *trailer_data; /* pointer to pass to trailer data callback */
curl_trailer_callback trailer_callback; /* trailing data callback */
+#endif
char keep_post; /* keep POSTs as POSTs after a 30x request; each
bit represents a request, from 301 to 303 */
#ifndef CURL_DISABLE_SMTP
@@ -1833,6 +1795,10 @@
BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
recipients */
#endif
+ unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
+ IMAP or POP3 or others! (type: curl_usessl)*/
+ unsigned char connect_only; /* make connection/request, then let
+ application use the socket */
BIT(is_fread_set); /* has read callback been set to non-NULL? */
#ifndef CURL_DISABLE_TFTP
BIT(tftp_no_options); /* do not send TFTP options requests */
@@ -1845,8 +1811,12 @@
/* Here follows boolean settings that define how to behave during
this session. They are STATIC, set by libcurl users or at least initially
and they don't change during operations. */
+ BIT(quick_exit); /* set 1L when it is okay to leak things (like
+ threads), as we're about to exit() anyway and
+ don't want lengthy cleanups to delay termination,
+ e.g. after a DNS timeout */
BIT(get_filetime); /* get the time and get of the remote file */
- BIT(tunnel_thru_httpproxy); /* use CONNECT through a HTTP proxy */
+ BIT(tunnel_thru_httpproxy); /* use CONNECT through an HTTP proxy */
BIT(prefer_ascii); /* ASCII rather than binary */
BIT(remote_append); /* append, not overwrite, on upload */
BIT(list_only); /* list directory */
@@ -1870,7 +1840,6 @@
BIT(http_auto_referer); /* set "correct" referer when following
location: */
BIT(opt_no_body); /* as set with CURLOPT_NOBODY */
- BIT(upload); /* upload request */
BIT(verbose); /* output verbosity */
BIT(krb); /* Kerberos connection requested */
BIT(reuse_forbid); /* forbidden to be reused, close after use */
@@ -1878,7 +1847,6 @@
BIT(no_signal); /* do not use any signal/alarm handler */
BIT(tcp_nodelay); /* whether to enable TCP_NODELAY or not */
BIT(ignorecl); /* ignore content length */
- BIT(connect_only); /* make connection, let application use the socket */
BIT(http_te_skip); /* pass the raw body data to the user, even when
transfer-encoded (chunked, compressed) */
BIT(http_ce_skip); /* pass the raw body data to the user, even when
@@ -1891,7 +1859,6 @@
BIT(sasl_ir); /* Enable/disable SASL initial response */
BIT(tcp_keepalive); /* use TCP keepalives */
BIT(tcp_fastopen); /* use TCP Fast Open */
- BIT(ssl_enable_npn); /* TLS NPN extension? */
BIT(ssl_enable_alpn);/* TLS ALPN extension? */
BIT(path_as_is); /* allow dotdots? */
BIT(pipewait); /* wait for multiplex status before starting a new
@@ -1899,7 +1866,6 @@
BIT(suppress_connect_headers); /* suppress proxy CONNECT response headers
from user callbacks */
BIT(dns_shuffle_addresses); /* whether to shuffle addresses before use */
- BIT(stream_depends_e); /* set or don't set the Exclusive bit */
BIT(haproxyprotocol); /* whether to send HAProxy PROXY protocol v1
header */
BIT(abstract_unix_socket);
@@ -1911,6 +1877,9 @@
BIT(doh_verifystatus); /* DoH certificate status verification */
#endif
BIT(http09_allowed); /* allow HTTP/0.9 responses */
+#ifdef USE_WEBSOCKETS
+ BIT(ws_raw_mode);
+#endif
};
struct Names {
@@ -1936,13 +1905,21 @@
/* First a simple identifier to easier detect if a user mix up this easy
handle with a multi handle. Set this to CURLEASY_MAGIC_NUMBER */
unsigned int magic;
+ /* once an easy handle is tied to a connection cache
+ a non-negative number to distinguish this transfer from
+ other using the same cache. For easier tracking
+ in log output.
+ This may wrap around after LONG_MAX to 0 again, so it
+ has no uniqueness guarantuee for very large processings. */
+ curl_off_t id;
/* first, two fields for the linked list of these */
struct Curl_easy *next;
struct Curl_easy *prev;
struct connectdata *conn;
- struct Curl_llist_element connect_queue;
+ struct Curl_llist_element connect_queue; /* for the pending and msgsent
+ lists */
struct Curl_llist_element conn_queue; /* list per connectdata */
CURLMstate mstate; /* the handle's state */
@@ -1988,7 +1965,7 @@
struct UrlState state; /* struct for fields used for state info and
other dynamic purposes */
#ifndef CURL_DISABLE_FTP
- struct WildcardData wildcard; /* wildcard download state info */
+ struct WildcardData *wildcard; /* wildcard download state info */
#endif
struct PureInfo info; /* stats, reports and info data */
struct curl_tlssessioninfo tsi; /* Information about the TLS session, only
diff --git a/lib/vauth/cleartext.c b/lib/vauth/cleartext.c
index b82b171..c651fc5 100644
--- a/lib/vauth/cleartext.c
+++ b/lib/vauth/cleartext.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,7 +28,8 @@
#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 <curl/curl.h>
#include "urldata.h"
diff --git a/lib/vauth/cram.c b/lib/vauth/cram.c
index 475d31b..5894ed4 100644
--- a/lib/vauth/cram.c
+++ b/lib/vauth/cram.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c
index 355cd74..fda2d91 100644
--- a/lib/vauth/digest.c
+++ b/lib/vauth/digest.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -49,6 +49,15 @@
#include "curl_memory.h"
#include "memdebug.h"
+#define SESSION_ALGO 1 /* for algos with this bit set */
+
+#define ALGO_MD5 0
+#define ALGO_MD5SESS (ALGO_MD5 | SESSION_ALGO)
+#define ALGO_SHA256 2
+#define ALGO_SHA256SESS (ALGO_SHA256 | SESSION_ALGO)
+#define ALGO_SHA512_256 4
+#define ALGO_SHA512_256SESS (ALGO_SHA512_256 | SESSION_ALGO)
+
#if !defined(USE_WINDOWS_SSPI)
#define DIGEST_QOP_VALUE_AUTH (1 << 0)
#define DIGEST_QOP_VALUE_AUTH_INT (1 << 1)
@@ -133,7 +142,7 @@
}
#if !defined(USE_WINDOWS_SSPI)
-/* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/
+/* 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 */
{
@@ -142,7 +151,7 @@
msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
}
-/* Convert sha256 chunk to RFC7616 -suitable ascii string*/
+/* Convert sha256 chunk to RFC7616 -suitable ascii string */
static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */
unsigned char *dest) /* 65 bytes */
{
@@ -177,7 +186,7 @@
}
*d++ = *s++;
}
- *d = 0;
+ *d = '\0';
}
return dest;
@@ -373,7 +382,7 @@
if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
return CURLE_BAD_CONTENT_ENCODING;
- /* Generate 32 random hex chars, 32 bytes + 1 zero termination */
+ /* Generate 32 random hex chars, 32 bytes + 1 null-termination */
result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce));
if(result)
return result;
@@ -481,7 +490,7 @@
/*
* Curl_auth_decode_digest_http_message()
*
- * This is used to decode a HTTP DIGEST challenge message into the separate
+ * This is used to decode an HTTP DIGEST challenge message into the separate
* attributes.
*
* Parameters:
@@ -512,7 +521,7 @@
char content[DIGEST_MAX_CONTENT_LENGTH];
/* Pass all additional spaces here */
- while(*chlg && ISSPACE(*chlg))
+ while(*chlg && ISBLANK(*chlg))
chlg++;
/* Extract a value=content pair */
@@ -551,6 +560,9 @@
token = strtok_r(tmp, ",", &tok_buf);
while(token) {
+ /* Pass additional spaces here */
+ while(*token && ISBLANK(*token))
+ token++;
if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH)) {
foundAuth = TRUE;
}
@@ -583,17 +595,17 @@
return CURLE_OUT_OF_MEMORY;
if(strcasecompare(content, "MD5-sess"))
- digest->algo = CURLDIGESTALGO_MD5SESS;
+ digest->algo = ALGO_MD5SESS;
else if(strcasecompare(content, "MD5"))
- digest->algo = CURLDIGESTALGO_MD5;
+ digest->algo = ALGO_MD5;
else if(strcasecompare(content, "SHA-256"))
- digest->algo = CURLDIGESTALGO_SHA256;
+ digest->algo = ALGO_SHA256;
else if(strcasecompare(content, "SHA-256-SESS"))
- digest->algo = CURLDIGESTALGO_SHA256SESS;
+ digest->algo = ALGO_SHA256SESS;
else if(strcasecompare(content, "SHA-512-256"))
- digest->algo = CURLDIGESTALGO_SHA512_256;
+ digest->algo = ALGO_SHA512_256;
else if(strcasecompare(content, "SHA-512-256-SESS"))
- digest->algo = CURLDIGESTALGO_SHA512_256SESS;
+ digest->algo = ALGO_SHA512_256SESS;
else
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -610,7 +622,7 @@
break; /* We're done here */
/* Pass all additional spaces here */
- while(*chlg && ISSPACE(*chlg))
+ while(*chlg && ISBLANK(*chlg))
chlg++;
/* Allow the list to be comma-separated */
@@ -628,13 +640,17 @@
if(!digest->nonce)
return CURLE_BAD_CONTENT_ENCODING;
+ /* "<algo>-sess" protocol versions require "auth" or "auth-int" qop */
+ if(!digest->qop && (digest->algo & SESSION_ALGO))
+ return CURLE_BAD_CONTENT_ENCODING;
+
return CURLE_OK;
}
/*
* auth_create_digest_http_message()
*
- * This is used to generate a HTTP DIGEST response message ready for sending
+ * This is used to generate an HTTP DIGEST response message ready for sending
* to the recipient.
*
* Parameters:
@@ -678,6 +694,7 @@
char *hashthis = NULL;
char *tmp = NULL;
+ memset(hashbuf, 0, sizeof(hashbuf));
if(!digest->nc)
digest->nc = 1;
@@ -726,9 +743,7 @@
free(hashthis);
convert_to_ascii(hashbuf, ha1);
- if(digest->algo == CURLDIGESTALGO_MD5SESS ||
- digest->algo == CURLDIGESTALGO_SHA256SESS ||
- digest->algo == CURLDIGESTALGO_SHA512_256SESS) {
+ if(digest->algo & SESSION_ALGO) {
/* nonce and cnonce are OUTSIDE the hash */
tmp = aprintf("%s:%s:%s", ha1, digest->nonce, digest->cnonce);
if(!tmp)
@@ -843,10 +858,8 @@
digest->qop,
request_digest);
- if(strcasecompare(digest->qop, "auth"))
- digest->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0
- padded which tells to the server how many times you are
- using the same nonce in the qop=auth mode */
+ /* Increment nonce-count to use another nc value for the next request */
+ digest->nc++;
}
else {
response = aprintf("username=\"%s\", "
@@ -875,8 +888,9 @@
free(response);
return CURLE_OUT_OF_MEMORY;
}
- tmp = aprintf("%s, opaque=\"%s\"", response, digest->opaque);
+ tmp = aprintf("%s, opaque=\"%s\"", response, opaque_quoted);
free(response);
+ free(opaque_quoted);
if(!tmp)
return CURLE_OUT_OF_MEMORY;
@@ -913,7 +927,7 @@
/*
* Curl_auth_create_digest_http_message()
*
- * This is used to generate a HTTP DIGEST response message ready for sending
+ * This is used to generate an HTTP DIGEST response message ready for sending
* to the recipient.
*
* Parameters:
@@ -938,28 +952,18 @@
struct digestdata *digest,
char **outptr, size_t *outlen)
{
- switch(digest->algo) {
- case CURLDIGESTALGO_MD5:
- case CURLDIGESTALGO_MD5SESS:
+ if(digest->algo <= ALGO_MD5SESS)
return auth_create_digest_http_message(data, userp, passwdp,
request, uripath, digest,
outptr, outlen,
auth_digest_md5_to_ascii,
Curl_md5it);
-
- case CURLDIGESTALGO_SHA256:
- case CURLDIGESTALGO_SHA256SESS:
- case CURLDIGESTALGO_SHA512_256:
- case CURLDIGESTALGO_SHA512_256SESS:
- return auth_create_digest_http_message(data, userp, passwdp,
- request, uripath, digest,
- outptr, outlen,
- auth_digest_sha256_to_ascii,
- Curl_sha256it);
-
- default:
- return CURLE_UNSUPPORTED_PROTOCOL;
- }
+ DEBUGASSERT(digest->algo <= ALGO_SHA512_256SESS);
+ return auth_create_digest_http_message(data, userp, passwdp,
+ request, uripath, digest,
+ outptr, outlen,
+ auth_digest_sha256_to_ascii,
+ Curl_sha256it);
}
/*
@@ -982,7 +986,7 @@
Curl_safefree(digest->algorithm);
digest->nc = 0;
- digest->algo = CURLDIGESTALGO_MD5; /* default algorithm */
+ digest->algo = ALGO_MD5; /* default algorithm */
digest->stale = FALSE; /* default means normal, not stale */
digest->userhash = FALSE;
}
diff --git a/lib/vauth/digest.h b/lib/vauth/digest.h
index 6a2f565..68fdb28 100644
--- a/lib/vauth/digest.h
+++ b/lib/vauth/digest.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,15 +31,6 @@
#define DIGEST_MAX_VALUE_LENGTH 256
#define DIGEST_MAX_CONTENT_LENGTH 1024
-enum {
- CURLDIGESTALGO_MD5,
- CURLDIGESTALGO_MD5SESS,
- CURLDIGESTALGO_SHA256,
- CURLDIGESTALGO_SHA256SESS,
- CURLDIGESTALGO_SHA512_256,
- CURLDIGESTALGO_SHA512_256SESS
-};
-
/* This is used to extract the realm from a challenge message */
bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
const char **endptr);
diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c
index af46384..8fb8669 100644
--- a/lib/vauth/digest_sspi.c
+++ b/lib/vauth/digest_sspi.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2016, Steve Holme, <steve_holme@hotmail.com>.
- * Copyright (C) 2015 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -259,7 +259,7 @@
char content[DIGEST_MAX_CONTENT_LENGTH];
/* Pass all additional spaces here */
- while(*chlg && ISSPACE(*chlg))
+ while(*chlg && ISBLANK(*chlg))
chlg++;
/* Extract a value=content pair */
@@ -292,7 +292,7 @@
break; /* We're done here */
/* Pass all additional spaces here */
- while(*chlg && ISSPACE(*chlg))
+ while(*chlg && ISBLANK(*chlg))
chlg++;
/* Allow the list to be comma-separated */
@@ -307,7 +307,7 @@
/*
* Curl_auth_decode_digest_http_message()
*
- * This is used to decode a HTTP DIGEST challenge message into the separate
+ * This is used to decode an HTTP DIGEST challenge message into the separate
* attributes.
*
* Parameters:
@@ -333,7 +333,7 @@
char value[DIGEST_MAX_VALUE_LENGTH];
char content[DIGEST_MAX_CONTENT_LENGTH];
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(!Curl_auth_digest_get_pair(p, value, content, &p))
@@ -345,7 +345,7 @@
break;
}
- while(*p && ISSPACE(*p))
+ while(*p && ISBLANK(*p))
p++;
if(',' == *p)
@@ -371,7 +371,7 @@
/*
* Curl_auth_create_digest_http_message()
*
- * This is used to generate a HTTP DIGEST response message ready for sending
+ * This is used to generate an HTTP DIGEST response message ready for sending
* to the recipient.
*
* Parameters:
@@ -431,8 +431,8 @@
has changed then delete that context. */
if((userp && !digest->user) || (!userp && digest->user) ||
(passwdp && !digest->passwd) || (!passwdp && digest->passwd) ||
- (userp && digest->user && strcmp(userp, digest->user)) ||
- (passwdp && digest->passwd && strcmp(passwdp, digest->passwd))) {
+ (userp && digest->user && Curl_timestrcmp(userp, digest->user)) ||
+ (passwdp && digest->passwd && Curl_timestrcmp(passwdp, digest->passwd))) {
if(digest->http_context) {
s_pSecFn->DeleteSecurityContext(digest->http_context);
Curl_safefree(digest->http_context);
diff --git a/lib/vauth/gsasl.c b/lib/vauth/gsasl.c
index 9d137b7..c7d0a8d 100644
--- a/lib/vauth/gsasl.c
+++ b/lib/vauth/gsasl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Simon Josefsson, <simon@josefsson.org>, et al.
+ * Copyright (C) Simon Josefsson, <simon@josefsson.org>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,7 +36,8 @@
#include <gsasl.h>
-/* The last #include files should be: */
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
diff --git a/lib/vauth/krb5_gssapi.c b/lib/vauth/krb5_gssapi.c
index bac7804..65eb3e1 100644
--- a/lib/vauth/krb5_gssapi.c
+++ b/lib/vauth/krb5_gssapi.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2019, Steve Holme, <steve_holme@hotmail.com>.
- * Copyright (C) 2015 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vauth/krb5_sspi.c b/lib/vauth/krb5_sspi.c
index 895b4a1..c487149 100644
--- a/lib/vauth/krb5_sspi.c
+++ b/lib/vauth/krb5_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -471,4 +471,4 @@
krb5->token_max = 0;
}
-#endif /* USE_WINDOWS_SSPI && USE_KERBEROS5*/
+#endif /* USE_WINDOWS_SSPI && USE_KERBEROS5 */
diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c
index edaacbb..93096ba 100644
--- a/lib/vauth/ntlm.c
+++ b/lib/vauth/ntlm.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,7 +29,7 @@
/*
* NTLM details:
*
- * https://davenport.sourceforge.io/ntlm.html
+ * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
@@ -88,8 +88,6 @@
fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
- if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
- fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
if(flags & (1<<10))
@@ -382,8 +380,8 @@
(void)data;
(void)userp;
(void)passwdp;
- (void)service,
- (void)hostname,
+ (void)service;
+ (void)hostname;
/* Clean up any former leftovers and initialise to defaults */
Curl_auth_cleanup_ntlm(ntlm);
@@ -513,6 +511,8 @@
size_t userlen = 0;
size_t domlen = 0;
+ memset(lmresp, 0, sizeof(lmresp));
+ memset(ntresp, 0, sizeof(ntresp));
user = strchr(userp, '\\');
if(!user)
user = strchr(userp, '/');
@@ -600,7 +600,7 @@
/* A safer but less compatible alternative is:
* Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
- * See https://davenport.sourceforge.io/ntlm.html#ntlmVersion2 */
+ * See https://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
}
if(unicode) {
@@ -658,7 +658,7 @@
/* LanManager response */
/* NT response */
- 0, /* zero termination */
+ 0, /* null-termination */
0, 0, 0, /* type-3 long, the 24 upper bits */
SHORTPAIR(0x18), /* LanManager response length, twice */
diff --git a/lib/vauth/ntlm.h b/lib/vauth/ntlm.h
index 97325d9..31ce921 100644
--- a/lib/vauth/ntlm.h
+++ b/lib/vauth/ntlm.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,7 +34,8 @@
/* Stuff only required for curl_ntlm_msgs.c */
#ifdef BUILDING_CURL_NTLM_MSGS_C
-/* Flag bits definitions based on https://davenport.sourceforge.io/ntlm.html */
+/* Flag bits definitions based on
+ https://davenport.sourceforge.net/ntlm.html */
#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
/* Indicates that Unicode strings are supported for use in security buffer
@@ -63,9 +64,6 @@
/* Indicates that the LAN Manager session key should be used for signing and
sealing authenticated communications. */
-#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8)
-/* unknown purpose */
-
#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9)
/* Indicates that NTLM authentication is being used. */
diff --git a/lib/vauth/ntlm_sspi.c b/lib/vauth/ntlm_sspi.c
index 193576a..5118963 100644
--- a/lib/vauth/ntlm_sspi.c
+++ b/lib/vauth/ntlm_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vauth/oauth2.c b/lib/vauth/oauth2.c
index 1604b30..a4adbdc 100644
--- a/lib/vauth/oauth2.c
+++ b/lib/vauth/oauth2.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,7 +27,8 @@
#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 <curl/curl.h>
#include "urldata.h"
diff --git a/lib/vauth/spnego_gssapi.c b/lib/vauth/spnego_gssapi.c
index 25dff96..e1d52b7 100644
--- a/lib/vauth/spnego_gssapi.c
+++ b/lib/vauth/spnego_gssapi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vauth/spnego_sspi.c b/lib/vauth/spnego_sspi.c
index d845cac..d3245d0 100644
--- a/lib/vauth/spnego_sspi.c
+++ b/lib/vauth/spnego_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vauth/vauth.c b/lib/vauth/vauth.c
index 9d6363d..62fc7c4 100644
--- a/lib/vauth/vauth.c
+++ b/lib/vauth/vauth.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,6 +27,8 @@
#include <curl/curl.h>
#include "vauth.h"
+#include "urldata.h"
+#include "strcase.h"
#include "curl_multibyte.h"
#include "curl_printf.h"
@@ -144,3 +146,18 @@
return valid;
}
+
+/*
+ * Curl_auth_ollowed_to_host() tells if authentication, cookies or other
+ * "sensitive data" can (still) be sent to this host.
+ */
+bool Curl_auth_allowed_to_host(struct Curl_easy *data)
+{
+ struct connectdata *conn = data->conn;
+ return (!data->state.this_is_a_follow ||
+ data->set.allow_auth_to_other_hosts ||
+ (data->state.first_host &&
+ strcasecompare(data->state.first_host, conn->host.name) &&
+ (data->state.first_remote_port == conn->remote_port) &&
+ (data->state.first_remote_protocol == conn->handler->protocol)));
+}
diff --git a/lib/vauth/vauth.h b/lib/vauth/vauth.h
index 1c4b5b5..d8cff24 100644
--- a/lib/vauth/vauth.h
+++ b/lib/vauth/vauth.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -54,6 +54,12 @@
#define GSS_ERROR(status) ((status) & 0x80000000)
#endif
+/*
+ * Curl_auth_allowed_to_host() tells if authentication, cookies or other
+ * "sensitive data" can (still) be sent to this host.
+ */
+bool Curl_auth_allowed_to_host(struct Curl_easy *data);
+
/* This is used to build a SPN string */
#if !defined(USE_WINDOWS_SSPI)
char *Curl_auth_build_spn(const char *service, const char *host,
@@ -98,11 +104,11 @@
const char *service,
struct bufref *out);
-/* This is used to decode a HTTP DIGEST challenge message */
+/* This is used to decode an HTTP DIGEST challenge message */
CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
struct digestdata *digest);
-/* This is used to generate a HTTP DIGEST response message */
+/* This is used to generate an HTTP DIGEST response message */
CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
@@ -213,7 +219,7 @@
message */
CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
const char *user,
- const char *passwood,
+ const char *password,
const char *service,
const char *host,
const char *chlg64,
@@ -224,7 +230,7 @@
CURLcode Curl_auth_create_spnego_message(struct negotiatedata *nego,
char **outptr, size_t *outlen);
-/* This is used to clean up the SPNEGO specifiec data */
+/* This is used to clean up the SPNEGO specific data */
void Curl_auth_cleanup_spnego(struct negotiatedata *nego);
#endif /* USE_SPNEGO */
diff --git a/lib/version.c b/lib/version.c
index 4672182..4730425 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,12 +24,16 @@
#include "curl_setup.h"
+#ifdef USE_NGHTTP2
+#include <nghttp2/nghttp2.h>
+#endif
+
#include <curl/curl.h>
#include "urldata.h"
#include "vtls/vtls.h"
#include "http2.h"
#include "vssh/ssh.h"
-#include "quic.h"
+#include "vquic/vquic.h"
#include "curl_printf.h"
#include "easy_lock.h"
@@ -53,12 +57,20 @@
#include <librtmp/rtmp.h>
#endif
-#ifdef HAVE_ZLIB_H
+#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
#ifdef HAVE_BROTLI
+#if defined(__GNUC__)
+/* Ignore -Wvla warnings in brotli headers */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wvla"
+#endif
#include <brotli/decode.h>
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
#endif
#ifdef HAVE_ZSTD
@@ -288,7 +300,7 @@
protocol line has its own #if line to make things easier on the eye.
*/
-static const char * const protocols[] = {
+static const char * const supported_protocols[] = {
#ifndef CURL_DISABLE_DICT
"dict",
#endif
@@ -338,6 +350,11 @@
#endif
#ifdef USE_LIBRTMP
"rtmp",
+ "rtmpe",
+ "rtmps",
+ "rtmpt",
+ "rtmpte",
+ "rtmpts",
#endif
#ifndef CURL_DISABLE_RTSP
"rtsp",
@@ -348,8 +365,7 @@
#ifdef USE_SSH
"sftp",
#endif
-#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
- (SIZEOF_CURL_OFF_T > 4)
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE)
"smb",
# ifdef USE_SSL
"smbs",
@@ -367,101 +383,159 @@
#ifndef CURL_DISABLE_TFTP
"tftp",
#endif
+#ifdef USE_WEBSOCKETS
+ "ws",
+#endif
+#if defined(USE_SSL) && defined(USE_WEBSOCKETS)
+ "wss",
+#endif
NULL
};
+/*
+ * Feature presence run-time check functions.
+ *
+ * Warning: the value returned by these should not change between
+ * curl_global_init() and curl_global_cleanup() calls.
+ */
+
+#if defined(USE_LIBIDN2)
+static int idn_present(curl_version_info_data *info)
+{
+ return info->libidn != NULL;
+}
+#else
+#define idn_present NULL
+#endif
+
+#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY)
+static int https_proxy_present(curl_version_info_data *info)
+{
+ (void) info;
+ return Curl_ssl_supports(NULL, SSLSUPP_HTTPS_PROXY);
+}
+#endif
+
+/*
+ * Features table.
+ *
+ * Keep the features alphabetically sorted.
+ * Use FEATURE() macro to define an entry: this allows documentation check.
+ */
+
+#define FEATURE(name, present, bitmask) {(name), (present), (bitmask)}
+
+struct feat {
+ const char *name;
+ int (*present)(curl_version_info_data *info);
+ int bitmask;
+};
+
+static const struct feat features_table[] = {
+#ifndef CURL_DISABLE_ALTSVC
+ FEATURE("alt-svc", NULL, CURL_VERSION_ALTSVC),
+#endif
+#ifdef CURLRES_ASYNCH
+ FEATURE("AsynchDNS", NULL, CURL_VERSION_ASYNCHDNS),
+#endif
+#ifdef HAVE_BROTLI
+ FEATURE("brotli", NULL, CURL_VERSION_BROTLI),
+#endif
+#ifdef DEBUGBUILD
+ FEATURE("Debug", NULL, CURL_VERSION_DEBUG),
+#endif
+#ifdef USE_GSASL
+ FEATURE("gsasl", NULL, CURL_VERSION_GSASL),
+#endif
+#ifdef HAVE_GSSAPI
+ FEATURE("GSS-API", NULL, CURL_VERSION_GSSAPI),
+#endif
+#ifndef CURL_DISABLE_HSTS
+ FEATURE("HSTS", NULL, CURL_VERSION_HSTS),
+#endif
+#if defined(USE_NGHTTP2) || defined(USE_HYPER)
+ FEATURE("HTTP2", NULL, CURL_VERSION_HTTP2),
+#endif
+#if defined(ENABLE_QUIC)
+ FEATURE("HTTP3", NULL, CURL_VERSION_HTTP3),
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY)
+ FEATURE("HTTPS-proxy", https_proxy_present, CURL_VERSION_HTTPS_PROXY),
+#endif
+#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
+ FEATURE("IDN", idn_present, CURL_VERSION_IDN),
+#endif
+#ifdef ENABLE_IPV6
+ FEATURE("IPv6", NULL, CURL_VERSION_IPV6),
+#endif
+#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) )
+ FEATURE("Largefile", NULL, CURL_VERSION_LARGEFILE),
+#endif
+#ifdef HAVE_LIBZ
+ FEATURE("libz", NULL, CURL_VERSION_LIBZ),
+#endif
+#ifdef CURL_WITH_MULTI_SSL
+ FEATURE("MultiSSL", NULL, CURL_VERSION_MULTI_SSL),
+#endif
+#ifdef USE_NTLM
+ FEATURE("NTLM", NULL, CURL_VERSION_NTLM),
+#endif
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
+ defined(NTLM_WB_ENABLED)
+ FEATURE("NTLM_WB", NULL, CURL_VERSION_NTLM_WB),
+#endif
+#if defined(USE_LIBPSL)
+ FEATURE("PSL", NULL, CURL_VERSION_PSL),
+#endif
+#ifdef USE_SPNEGO
+ FEATURE("SPNEGO", NULL, CURL_VERSION_SPNEGO),
+#endif
+#ifdef USE_SSL
+ FEATURE("SSL", NULL, CURL_VERSION_SSL),
+#endif
+#ifdef USE_WINDOWS_SSPI
+ FEATURE("SSPI", NULL, CURL_VERSION_SSPI),
+#endif
+#ifdef GLOBAL_INIT_IS_THREADSAFE
+ FEATURE("threadsafe", NULL, CURL_VERSION_THREADSAFE),
+#endif
+#ifdef USE_TLS_SRP
+ FEATURE("TLS-SRP", NULL, CURL_VERSION_TLSAUTH_SRP),
+#endif
+#ifdef CURLDEBUG
+ FEATURE("TrackMemory", NULL, CURL_VERSION_CURLDEBUG),
+#endif
+#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE)
+ FEATURE("Unicode", NULL, CURL_VERSION_UNICODE),
+#endif
+#ifdef USE_UNIX_SOCKETS
+ FEATURE("UnixSockets", NULL, CURL_VERSION_UNIX_SOCKETS),
+#endif
+#ifdef HAVE_ZSTD
+ FEATURE("zstd", NULL, CURL_VERSION_ZSTD),
+#endif
+ {NULL, NULL, 0}
+};
+
+static const char *feature_names[sizeof(features_table) /
+ sizeof(features_table[0])] = {NULL};
+
+
static curl_version_info_data version_info = {
CURLVERSION_NOW,
LIBCURL_VERSION,
LIBCURL_VERSION_NUM,
- OS, /* as found by configure or set by hand at build-time */
- 0 /* features is 0 by default */
-#ifdef ENABLE_IPV6
- | CURL_VERSION_IPV6
-#endif
-#ifdef USE_SSL
- | CURL_VERSION_SSL
-#endif
-#ifdef USE_NTLM
- | CURL_VERSION_NTLM
-#endif
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
- defined(NTLM_WB_ENABLED)
- | CURL_VERSION_NTLM_WB
-#endif
-#ifdef USE_SPNEGO
- | CURL_VERSION_SPNEGO
-#endif
-#ifdef USE_KERBEROS5
- | CURL_VERSION_KERBEROS5
-#endif
-#ifdef HAVE_GSSAPI
- | CURL_VERSION_GSSAPI
-#endif
-#ifdef USE_WINDOWS_SSPI
- | CURL_VERSION_SSPI
-#endif
-#ifdef HAVE_LIBZ
- | CURL_VERSION_LIBZ
-#endif
-#ifdef DEBUGBUILD
- | CURL_VERSION_DEBUG
-#endif
-#ifdef CURLDEBUG
- | CURL_VERSION_CURLDEBUG
-#endif
-#ifdef CURLRES_ASYNCH
- | CURL_VERSION_ASYNCHDNS
-#endif
-#if (SIZEOF_CURL_OFF_T > 4) && \
- ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) )
- | CURL_VERSION_LARGEFILE
-#endif
-#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE)
- | CURL_VERSION_UNICODE
-#endif
-#if defined(USE_TLS_SRP)
- | CURL_VERSION_TLSAUTH_SRP
-#endif
-#if defined(USE_NGHTTP2) || defined(USE_HYPER)
- | CURL_VERSION_HTTP2
-#endif
-#if defined(ENABLE_QUIC)
- | CURL_VERSION_HTTP3
-#endif
-#if defined(USE_UNIX_SOCKETS)
- | CURL_VERSION_UNIX_SOCKETS
-#endif
-#if defined(USE_LIBPSL)
- | CURL_VERSION_PSL
-#endif
-#if defined(CURL_WITH_MULTI_SSL)
- | CURL_VERSION_MULTI_SSL
-#endif
-#if defined(HAVE_BROTLI)
- | CURL_VERSION_BROTLI
-#endif
-#if defined(HAVE_ZSTD)
- | CURL_VERSION_ZSTD
-#endif
-#ifndef CURL_DISABLE_ALTSVC
- | CURL_VERSION_ALTSVC
-#endif
-#ifndef CURL_DISABLE_HSTS
- | CURL_VERSION_HSTS
-#endif
-#if defined(USE_GSASL)
- | CURL_VERSION_GSASL
-#endif
-#if defined(GLOBAL_INIT_IS_THREADSAFE)
- | CURL_VERSION_THREADSAFE
-#endif
- ,
+ OS, /* as found by configure or set by hand at build-time */
+ 0, /* features bitmask is built at run-time */
NULL, /* ssl_version */
0, /* ssl_version_num, this is kept at zero */
NULL, /* zlib_version */
- protocols,
+ supported_protocols,
NULL, /* c-ares version */
0, /* c-ares version numerical */
NULL, /* libidn version */
@@ -485,11 +559,16 @@
0, /* zstd_ver_num */
NULL, /* zstd version */
NULL, /* Hyper version */
- NULL /* gsasl version */
+ NULL, /* gsasl version */
+ feature_names
};
curl_version_info_data *curl_version_info(CURLversion stamp)
{
+ size_t n;
+ const struct feat *p;
+ int features = 0;
+
#if defined(USE_SSH)
static char ssh_buffer[80];
#endif
@@ -507,15 +586,11 @@
static char zstd_buffer[80];
#endif
+ (void)stamp; /* avoid compiler warnings, we don't use this */
+
#ifdef USE_SSL
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
version_info.ssl_version = ssl_buffer;
-#ifndef CURL_DISABLE_PROXY
- if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)
- version_info.features |= CURL_VERSION_HTTPS_PROXY;
- else
- version_info.features &= ~CURL_VERSION_HTTPS_PROXY;
-#endif
#endif
#ifdef HAVE_LIBZ
@@ -533,10 +608,6 @@
/* This returns a version string if we use the given version or later,
otherwise it returns NULL */
version_info.libidn = idn2_check_version(IDN2_VERSION);
- if(version_info.libidn)
- version_info.features |= CURL_VERSION_IDN;
-#elif defined(USE_WIN32_IDN)
- version_info.features |= CURL_VERSION_IDN;
#endif
#if defined(USE_SSH)
@@ -586,6 +657,16 @@
}
#endif
- (void)stamp; /* avoid compiler warnings, we don't use this */
+ /* Get available features, build bitmask and names array. */
+ n = 0;
+ for(p = features_table; p->name; p++)
+ if(!p->present || p->present(&version_info)) {
+ features |= p->bitmask;
+ feature_names[n++] = p->name;
+ }
+
+ feature_names[n] = NULL; /* Terminate array. */
+ version_info.features = features;
+
return &version_info;
}
diff --git a/lib/version_win32.c b/lib/version_win32.c
index e8f14f9..872d5b4 100644
--- a/lib/version_win32.c
+++ b/lib/version_win32.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2016 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/version_win32.h b/lib/version_win32.h
index 7a9a6a1..3899174 100644
--- a/lib/version_win32.h
+++ b/lib/version_win32.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2016 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vquic/curl_msh3.c b/lib/vquic/curl_msh3.c
new file mode 100644
index 0000000..02b5334
--- /dev/null
+++ b/lib/vquic/curl_msh3.c
@@ -0,0 +1,1087 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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"
+
+#ifdef USE_MSH3
+
+#include "urldata.h"
+#include "timeval.h"
+#include "multiif.h"
+#include "sendf.h"
+#include "curl_log.h"
+#include "cfilters.h"
+#include "cf-socket.h"
+#include "connect.h"
+#include "progress.h"
+#include "http1.h"
+#include "curl_msh3.h"
+#include "socketpair.h"
+#include "vquic/vquic.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define H3_STREAM_WINDOW_SIZE (128 * 1024)
+#define H3_STREAM_CHUNK_SIZE (16 * 1024)
+#define H3_STREAM_RECV_CHUNKS \
+ (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
+
+#ifdef _WIN32
+#define msh3_lock CRITICAL_SECTION
+#define msh3_lock_initialize(lock) InitializeCriticalSection(lock)
+#define msh3_lock_uninitialize(lock) DeleteCriticalSection(lock)
+#define msh3_lock_acquire(lock) EnterCriticalSection(lock)
+#define msh3_lock_release(lock) LeaveCriticalSection(lock)
+#else /* !_WIN32 */
+#include <pthread.h>
+#define msh3_lock pthread_mutex_t
+#define msh3_lock_initialize(lock) do { \
+ pthread_mutexattr_t attr; \
+ pthread_mutexattr_init(&attr); \
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \
+ pthread_mutex_init(lock, &attr); \
+ pthread_mutexattr_destroy(&attr); \
+}while(0)
+#define msh3_lock_uninitialize(lock) pthread_mutex_destroy(lock)
+#define msh3_lock_acquire(lock) pthread_mutex_lock(lock)
+#define msh3_lock_release(lock) pthread_mutex_unlock(lock)
+#endif /* _WIN32 */
+
+
+static void MSH3_CALL msh3_conn_connected(MSH3_CONNECTION *Connection,
+ void *IfContext);
+static void MSH3_CALL msh3_conn_shutdown_complete(MSH3_CONNECTION *Connection,
+ void *IfContext);
+static void MSH3_CALL msh3_conn_new_request(MSH3_CONNECTION *Connection,
+ void *IfContext,
+ MSH3_REQUEST *Request);
+static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request,
+ void *IfContext,
+ const MSH3_HEADER *Header);
+static bool MSH3_CALL msh3_data_received(MSH3_REQUEST *Request,
+ void *IfContext, uint32_t *Length,
+ const uint8_t *Data);
+static void MSH3_CALL msh3_complete(MSH3_REQUEST *Request, void *IfContext,
+ bool Aborted, uint64_t AbortError);
+static void MSH3_CALL msh3_shutdown_complete(MSH3_REQUEST *Request,
+ void *IfContext);
+static void MSH3_CALL msh3_data_sent(MSH3_REQUEST *Request,
+ void *IfContext, void *SendContext);
+
+
+void Curl_msh3_ver(char *p, size_t len)
+{
+ uint32_t v[4];
+ MsH3Version(v);
+ (void)msnprintf(p, len, "msh3/%d.%d.%d.%d", v[0], v[1], v[2], v[3]);
+}
+
+#define SP_LOCAL 0
+#define SP_REMOTE 1
+
+struct cf_msh3_ctx {
+ MSH3_API *api;
+ MSH3_CONNECTION *qconn;
+ struct Curl_sockaddr_ex addr;
+ curl_socket_t sock[2]; /* fake socket pair until we get support in msh3 */
+ char l_ip[MAX_IPADR_LEN]; /* local IP as string */
+ int l_port; /* local port number */
+ struct cf_call_data call_data;
+ struct curltime connect_started; /* time the current attempt started */
+ struct curltime handshake_at; /* time connect handshake finished */
+ /* Flags written by msh3/msquic thread */
+ bool handshake_complete;
+ bool handshake_succeeded;
+ bool connected;
+ /* Flags written by curl thread */
+ BIT(verbose);
+ BIT(active);
+};
+
+/* How to access `call_data` from a cf_msh3 filter */
+#undef CF_CTX_CALL_DATA
+#define CF_CTX_CALL_DATA(cf) \
+ ((struct cf_msh3_ctx *)(cf)->ctx)->call_data
+
+/**
+ * All about the H3 internals of a stream
+ */
+struct stream_ctx {
+ struct MSH3_REQUEST *req;
+ struct bufq recvbuf; /* h3 response */
+#ifdef _WIN32
+ CRITICAL_SECTION recv_lock;
+#else /* !_WIN32 */
+ pthread_mutex_t recv_lock;
+#endif /* _WIN32 */
+ uint64_t error3; /* HTTP/3 stream error code */
+ int status_code; /* HTTP status code */
+ CURLcode recv_error;
+ bool closed;
+ bool reset;
+ bool upload_done;
+ bool firstheader; /* FALSE until headers arrive */
+ bool recv_header_complete;
+};
+
+#define H3_STREAM_CTX(d) ((struct stream_ctx *)(((d) && (d)->req.p.http)? \
+ ((struct HTTP *)(d)->req.p.http)->h3_ctx \
+ : NULL))
+#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h3_ctx
+#define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \
+ H3_STREAM_CTX(d)->id : -2)
+
+
+static CURLcode h3_data_setup(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+
+ if(stream)
+ return CURLE_OK;
+
+ stream = calloc(1, sizeof(*stream));
+ if(!stream)
+ return CURLE_OUT_OF_MEMORY;
+
+ H3_STREAM_LCTX(data) = stream;
+ stream->req = ZERO_NULL;
+ msh3_lock_initialize(&stream->recv_lock);
+ Curl_bufq_init2(&stream->recvbuf, H3_STREAM_CHUNK_SIZE,
+ H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
+ DEBUGF(LOG_CF(data, cf, "data setup"));
+ return CURLE_OK;
+}
+
+static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+
+ (void)cf;
+ if(stream) {
+ DEBUGF(LOG_CF(data, cf, "easy handle is done"));
+ Curl_bufq_free(&stream->recvbuf);
+ free(stream);
+ H3_STREAM_LCTX(data) = NULL;
+ }
+}
+
+static void drain_stream_from_other_thread(struct Curl_easy *data,
+ struct stream_ctx *stream)
+{
+ unsigned char bits;
+
+ /* risky */
+ bits = CURL_CSELECT_IN;
+ if(stream && !stream->upload_done)
+ bits |= CURL_CSELECT_OUT;
+ if(data->state.dselect_bits != bits) {
+ data->state.dselect_bits = bits;
+ /* cannot expire from other thread */
+ }
+}
+
+static void drain_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ unsigned char bits;
+
+ (void)cf;
+ bits = CURL_CSELECT_IN;
+ if(stream && !stream->upload_done)
+ bits |= CURL_CSELECT_OUT;
+ if(data->state.dselect_bits != bits) {
+ data->state.dselect_bits = bits;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+}
+
+static const MSH3_CONNECTION_IF msh3_conn_if = {
+ msh3_conn_connected,
+ msh3_conn_shutdown_complete,
+ msh3_conn_new_request
+};
+
+static void MSH3_CALL msh3_conn_connected(MSH3_CONNECTION *Connection,
+ void *IfContext)
+{
+ struct Curl_cfilter *cf = IfContext;
+ struct cf_msh3_ctx *ctx = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ (void)Connection;
+
+ DEBUGF(LOG_CF(data, cf, "[MSH3] connected"));
+ ctx->handshake_succeeded = true;
+ ctx->connected = true;
+ ctx->handshake_complete = true;
+}
+
+static void MSH3_CALL msh3_conn_shutdown_complete(MSH3_CONNECTION *Connection,
+ void *IfContext)
+{
+ struct Curl_cfilter *cf = IfContext;
+ struct cf_msh3_ctx *ctx = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+
+ (void)Connection;
+ DEBUGF(LOG_CF(data, cf, "[MSH3] shutdown complete"));
+ ctx->connected = false;
+ ctx->handshake_complete = true;
+}
+
+static void MSH3_CALL msh3_conn_new_request(MSH3_CONNECTION *Connection,
+ void *IfContext,
+ MSH3_REQUEST *Request)
+{
+ (void)Connection;
+ (void)IfContext;
+ (void)Request;
+}
+
+static const MSH3_REQUEST_IF msh3_request_if = {
+ msh3_header_received,
+ msh3_data_received,
+ msh3_complete,
+ msh3_shutdown_complete,
+ msh3_data_sent
+};
+
+/* Decode HTTP status code. Returns -1 if no valid status code was
+ decoded. (duplicate from http2.c) */
+static int decode_status_code(const char *value, size_t len)
+{
+ int i;
+ int res;
+
+ if(len != 3) {
+ return -1;
+ }
+
+ res = 0;
+
+ for(i = 0; i < 3; ++i) {
+ char c = value[i];
+
+ if(c < '0' || c > '9') {
+ return -1;
+ }
+
+ res *= 10;
+ res += c - '0';
+ }
+
+ return res;
+}
+
+/*
+ * 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_easy *data,
+ const void *mem, size_t memlen)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ CURLcode result = CURLE_OK;
+ ssize_t nwritten;
+
+ if(!stream)
+ return CURLE_RECV_ERROR;
+
+ nwritten = Curl_bufq_write(&stream->recvbuf, mem, memlen, &result);
+ if(nwritten < 0) {
+ return result;
+ }
+
+ if((size_t)nwritten < memlen) {
+ /* This MUST not happen. Our recbuf is dimensioned to hold the
+ * full max_stream_window and then some for this very reason. */
+ DEBUGASSERT(0);
+ return CURLE_RECV_ERROR;
+ }
+ return result;
+}
+
+static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request,
+ void *userp,
+ const MSH3_HEADER *hd)
+{
+ struct Curl_easy *data = userp;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ CURLcode result;
+ (void)Request;
+
+ if(!stream || stream->recv_header_complete) {
+ return;
+ }
+
+ msh3_lock_acquire(&stream->recv_lock);
+
+ if((hd->NameLength == 7) &&
+ !strncmp(HTTP_PSEUDO_STATUS, (char *)hd->Name, 7)) {
+ char line[14]; /* status line is always 13 characters long */
+ size_t ncopy;
+
+ DEBUGASSERT(!stream->firstheader);
+ stream->status_code = decode_status_code(hd->Value, hd->ValueLength);
+ DEBUGASSERT(stream->status_code != -1);
+ ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n",
+ stream->status_code);
+ result = write_resp_raw(data, line, ncopy);
+ if(result)
+ stream->recv_error = result;
+ stream->firstheader = TRUE;
+ }
+ else {
+ /* store as an HTTP1-style header */
+ DEBUGASSERT(stream->firstheader);
+ result = write_resp_raw(data, hd->Name, hd->NameLength);
+ if(!result)
+ result = write_resp_raw(data, ": ", 2);
+ if(!result)
+ result = write_resp_raw(data, hd->Value, hd->ValueLength);
+ if(!result)
+ result = write_resp_raw(data, "\r\n", 2);
+ if(result) {
+ stream->recv_error = result;
+ }
+ }
+
+ drain_stream_from_other_thread(data, stream);
+ msh3_lock_release(&stream->recv_lock);
+}
+
+static bool MSH3_CALL msh3_data_received(MSH3_REQUEST *Request,
+ void *IfContext, uint32_t *buflen,
+ const uint8_t *buf)
+{
+ struct Curl_easy *data = IfContext;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ CURLcode result;
+ bool rv = FALSE;
+
+ /* TODO: we would like to limit the amount of data we are buffer here.
+ * There seems to be no mechanism in msh3 to adjust flow control and
+ * it is undocumented what happens if we return FALSE here or less
+ * length (buflen is an inout parameter).
+ */
+ (void)Request;
+ if(!stream)
+ return FALSE;
+
+ msh3_lock_acquire(&stream->recv_lock);
+
+ if(!stream->recv_header_complete) {
+ result = write_resp_raw(data, "\r\n", 2);
+ if(result) {
+ stream->recv_error = result;
+ goto out;
+ }
+ stream->recv_header_complete = true;
+ }
+
+ result = write_resp_raw(data, buf, *buflen);
+ if(result) {
+ stream->recv_error = result;
+ }
+ rv = TRUE;
+
+out:
+ msh3_lock_release(&stream->recv_lock);
+ return rv;
+}
+
+static void MSH3_CALL msh3_complete(MSH3_REQUEST *Request, void *IfContext,
+ bool aborted, uint64_t error)
+{
+ struct Curl_easy *data = IfContext;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+
+ (void)Request;
+ if(!stream)
+ return;
+ msh3_lock_acquire(&stream->recv_lock);
+ stream->closed = TRUE;
+ stream->recv_header_complete = true;
+ if(error)
+ stream->error3 = error;
+ if(aborted)
+ stream->reset = TRUE;
+ msh3_lock_release(&stream->recv_lock);
+}
+
+static void MSH3_CALL msh3_shutdown_complete(MSH3_REQUEST *Request,
+ void *IfContext)
+{
+ struct Curl_easy *data = IfContext;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+
+ if(!stream)
+ return;
+ (void)Request;
+ (void)stream;
+}
+
+static void MSH3_CALL msh3_data_sent(MSH3_REQUEST *Request,
+ void *IfContext, void *SendContext)
+{
+ struct Curl_easy *data = IfContext;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ if(!stream)
+ return;
+ (void)Request;
+ (void)stream;
+ (void)SendContext;
+}
+
+static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ CURLcode *err)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ ssize_t nread = -1;
+
+ if(!stream) {
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+ (void)cf;
+ if(stream->reset) {
+ failf(data, "HTTP/3 stream reset by server");
+ *err = CURLE_PARTIAL_FILE;
+ DEBUGF(LOG_CF(data, cf, "cf_recv, was reset -> %d", *err));
+ goto out;
+ }
+ else if(stream->error3) {
+ failf(data, "HTTP/3 stream was not closed cleanly: (error %zd)",
+ (ssize_t)stream->error3);
+ *err = CURLE_HTTP3;
+ DEBUGF(LOG_CF(data, cf, "cf_recv, closed uncleanly -> %d", *err));
+ goto out;
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "cf_recv, closed ok -> %d", *err));
+ }
+ *err = CURLE_OK;
+ nread = 0;
+
+out:
+ return nread;
+}
+
+static void set_quic_expire(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+
+ /* we have no indication from msh3 when it would be a good time
+ * to juggle the connection again. So, we compromise by calling
+ * us again every some milliseconds. */
+ (void)cf;
+ if(stream && stream->req && !stream->closed) {
+ Curl_expire(data, 10, EXPIRE_QUIC);
+ }
+ else {
+ Curl_expire(data, 50, EXPIRE_QUIC);
+ }
+}
+
+static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ ssize_t nread = -1;
+ struct cf_call_data save;
+
+ (void)cf;
+ if(!stream) {
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+ CF_DATA_SAVE(save, cf, data);
+ DEBUGF(LOG_CF(data, cf, "req: recv with %zu byte buffer", len));
+
+ msh3_lock_acquire(&stream->recv_lock);
+
+ if(stream->recv_error) {
+ failf(data, "request aborted");
+ *err = stream->recv_error;
+ goto out;
+ }
+
+ *err = CURLE_OK;
+
+ if(!Curl_bufq_is_empty(&stream->recvbuf)) {
+ nread = Curl_bufq_read(&stream->recvbuf,
+ (unsigned char *)buf, len, err);
+ DEBUGF(LOG_CF(data, cf, "read recvbuf(len=%zu) -> %zd, %d",
+ len, nread, *err));
+ if(nread < 0)
+ goto out;
+ if(stream->closed)
+ drain_stream(cf, data);
+ }
+ else if(stream->closed) {
+ nread = recv_closed_stream(cf, data, err);
+ goto out;
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "req: nothing here, call again"));
+ *err = CURLE_AGAIN;
+ }
+
+out:
+ msh3_lock_release(&stream->recv_lock);
+ set_quic_expire(cf, data);
+ CF_DATA_RESTORE(cf, save);
+ return nread;
+}
+
+static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err)
+{
+ struct cf_msh3_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h1_req_parser h1;
+ struct dynhds h2_headers;
+ MSH3_HEADER *nva = NULL;
+ size_t nheader, i;
+ ssize_t nwritten = -1;
+ struct cf_call_data save;
+ bool eos;
+
+ CF_DATA_SAVE(save, cf, data);
+
+ Curl_h1_req_parse_init(&h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
+ Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
+
+ /* Sizes must match for cast below to work" */
+ DEBUGASSERT(stream);
+ DEBUGF(LOG_CF(data, cf, "req: send %zu bytes", len));
+
+ if(!stream->req) {
+ /* The first send on the request contains the headers and possibly some
+ data. Parse out the headers and create the request, then if there is
+ any data left over go ahead and send it too. */
+ nwritten = Curl_h1_req_parse_read(&h1, buf, len, NULL, 0, err);
+ if(nwritten < 0)
+ goto out;
+ DEBUGASSERT(h1.done);
+ DEBUGASSERT(h1.req);
+
+ *err = Curl_http_req_to_h2(&h2_headers, h1.req, data);
+ if(*err) {
+ nwritten = -1;
+ goto out;
+ }
+
+ nheader = Curl_dynhds_count(&h2_headers);
+ nva = malloc(sizeof(MSH3_HEADER) * nheader);
+ if(!nva) {
+ *err = CURLE_OUT_OF_MEMORY;
+ nwritten = -1;
+ goto out;
+ }
+
+ for(i = 0; i < nheader; ++i) {
+ struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
+ nva[i].Name = e->name;
+ nva[i].NameLength = e->namelen;
+ nva[i].Value = e->value;
+ nva[i].ValueLength = e->valuelen;
+ }
+
+ switch(data->state.httpreq) {
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ case HTTPREQ_POST_MIME:
+ case HTTPREQ_PUT:
+ /* known request body size or -1 */
+ eos = FALSE;
+ break;
+ default:
+ /* there is not request body */
+ eos = TRUE;
+ stream->upload_done = TRUE;
+ break;
+ }
+
+ DEBUGF(LOG_CF(data, cf, "req: send %zu headers", nheader));
+ stream->req = MsH3RequestOpen(ctx->qconn, &msh3_request_if, data,
+ nva, nheader,
+ eos ? MSH3_REQUEST_FLAG_FIN :
+ MSH3_REQUEST_FLAG_NONE);
+ if(!stream->req) {
+ failf(data, "request open failed");
+ *err = CURLE_SEND_ERROR;
+ goto out;
+ }
+ *err = CURLE_OK;
+ nwritten = len;
+ goto out;
+ }
+ else {
+ /* request is open */
+ DEBUGF(LOG_CF(data, cf, "req: send %zu body bytes", len));
+ if(len > 0xFFFFFFFF) {
+ len = 0xFFFFFFFF;
+ }
+
+ if(!MsH3RequestSend(stream->req, MSH3_REQUEST_FLAG_NONE, buf,
+ (uint32_t)len, stream)) {
+ *err = CURLE_SEND_ERROR;
+ goto out;
+ }
+
+ /* TODO - msh3/msquic will hold onto this memory until the send complete
+ event. How do we make sure curl doesn't free it until then? */
+ *err = CURLE_OK;
+ nwritten = len;
+ }
+
+out:
+ set_quic_expire(cf, data);
+ free(nva);
+ Curl_h1_req_parse_free(&h1);
+ Curl_dynhds_free(&h2_headers);
+ CF_DATA_RESTORE(cf, save);
+ return nwritten;
+}
+
+static int cf_msh3_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ struct cf_msh3_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ int bitmap = GETSOCK_BLANK;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ if(stream && ctx->sock[SP_LOCAL] != CURL_SOCKET_BAD) {
+ socks[0] = ctx->sock[SP_LOCAL];
+
+ if(stream->recv_error) {
+ bitmap |= GETSOCK_READSOCK(0);
+ drain_stream(cf, data);
+ }
+ else if(stream->req) {
+ bitmap |= GETSOCK_READSOCK(0);
+ drain_stream(cf, data);
+ }
+ }
+ DEBUGF(LOG_CF(data, cf, "select_sock -> %d", bitmap));
+ CF_DATA_RESTORE(cf, save);
+ return bitmap;
+}
+
+static bool cf_msh3_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct cf_call_data save;
+ bool pending = FALSE;
+
+ CF_DATA_SAVE(save, cf, data);
+
+ (void)cf;
+ if(stream && stream->req) {
+ msh3_lock_acquire(&stream->recv_lock);
+ DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "data pending = %zu",
+ Curl_bufq_len(&stream->recvbuf)));
+ pending = !Curl_bufq_is_empty(&stream->recvbuf);
+ msh3_lock_release(&stream->recv_lock);
+ if(pending)
+ drain_stream(cf, (struct Curl_easy *)data);
+ }
+
+ CF_DATA_RESTORE(cf, save);
+ return pending;
+}
+
+static void cf_msh3_active(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_msh3_ctx *ctx = cf->ctx;
+
+ /* use this socket from now on */
+ cf->conn->sock[cf->sockindex] = ctx->sock[SP_LOCAL];
+ /* the first socket info gets set at conn and data */
+ if(cf->sockindex == FIRSTSOCKET) {
+ cf->conn->remote_addr = &ctx->addr;
+ #ifdef ENABLE_IPV6
+ cf->conn->bits.ipv6 = (ctx->addr.family == AF_INET6)? TRUE : FALSE;
+ #endif
+ Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port);
+ }
+ ctx->active = TRUE;
+}
+
+static CURLcode h3_data_pause(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool pause)
+{
+ if(!pause) {
+ drain_stream(cf, data);
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode cf_msh3_data_event(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct cf_call_data save;
+ CURLcode result = CURLE_OK;
+
+ CF_DATA_SAVE(save, cf, data);
+
+ (void)arg1;
+ (void)arg2;
+ switch(event) {
+ case CF_CTRL_DATA_SETUP:
+ result = h3_data_setup(cf, data);
+ break;
+ case CF_CTRL_DATA_PAUSE:
+ result = h3_data_pause(cf, data, (arg1 != 0));
+ break;
+ case CF_CTRL_DATA_DONE:
+ h3_data_done(cf, data);
+ break;
+ case CF_CTRL_DATA_DONE_SEND:
+ DEBUGF(LOG_CF(data, cf, "req: send done"));
+ if(stream) {
+ stream->upload_done = TRUE;
+ if(stream->req) {
+ char buf[1];
+ if(!MsH3RequestSend(stream->req, MSH3_REQUEST_FLAG_FIN,
+ buf, 0, data)) {
+ result = CURLE_SEND_ERROR;
+ }
+ }
+ }
+ break;
+ case CF_CTRL_CONN_INFO_UPDATE:
+ DEBUGF(LOG_CF(data, cf, "req: update info"));
+ cf_msh3_active(cf, data);
+ break;
+ default:
+ break;
+ }
+
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static CURLcode cf_connect_start(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_msh3_ctx *ctx = cf->ctx;
+ bool verify = !!cf->conn->ssl_config.verifypeer;
+ MSH3_ADDR addr = {0};
+ CURLcode result;
+
+ memcpy(&addr, &ctx->addr.sa_addr, ctx->addr.addrlen);
+ MSH3_SET_PORT(&addr, (uint16_t)cf->conn->remote_port);
+
+ if(verify && (cf->conn->ssl_config.CAfile || cf->conn->ssl_config.CApath)) {
+ /* TODO: need a way to provide trust anchors to MSH3 */
+#ifdef DEBUGBUILD
+ /* we need this for our test cases to run */
+ DEBUGF(LOG_CF(data, cf, "non-standard CA not supported, "
+ "switching off verifypeer in DEBUG mode"));
+ verify = 0;
+#else
+ DEBUGF(LOG_CF(data, cf, "non-standard CA not supported, "
+ "attempting with built-in verification"));
+#endif
+ }
+
+ DEBUGF(LOG_CF(data, cf, "connecting to %s:%d (verify=%d)",
+ cf->conn->host.name, (int)cf->conn->remote_port, verify));
+
+ ctx->api = MsH3ApiOpen();
+ if(!ctx->api) {
+ failf(data, "can't create msh3 api");
+ return CURLE_FAILED_INIT;
+ }
+
+ ctx->qconn = MsH3ConnectionOpen(ctx->api,
+ &msh3_conn_if,
+ cf,
+ cf->conn->host.name,
+ &addr,
+ !verify);
+ if(!ctx->qconn) {
+ failf(data, "can't create msh3 connection");
+ if(ctx->api) {
+ MsH3ApiClose(ctx->api);
+ ctx->api = NULL;
+ }
+ return CURLE_FAILED_INIT;
+ }
+
+ result = h3_data_setup(cf, data);
+ if(result)
+ return result;
+
+ return CURLE_OK;
+}
+
+static CURLcode cf_msh3_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct cf_msh3_ctx *ctx = cf->ctx;
+ struct cf_call_data save;
+ CURLcode result = CURLE_OK;
+
+ (void)blocking;
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ CF_DATA_SAVE(save, cf, data);
+
+ if(ctx->sock[SP_LOCAL] == CURL_SOCKET_BAD) {
+ if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx->sock[0]) < 0) {
+ ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
+ ctx->sock[SP_REMOTE] = CURL_SOCKET_BAD;
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+
+ *done = FALSE;
+ if(!ctx->qconn) {
+ ctx->connect_started = Curl_now();
+ result = cf_connect_start(cf, data);
+ if(result)
+ goto out;
+ }
+
+ if(ctx->handshake_complete) {
+ ctx->handshake_at = Curl_now();
+ if(ctx->handshake_succeeded) {
+ DEBUGF(LOG_CF(data, cf, "handshake succeeded"));
+ cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+ cf->conn->httpversion = 30;
+ cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+ cf->connected = TRUE;
+ cf->conn->alpn = CURL_HTTP_VERSION_3;
+ *done = TRUE;
+ connkeep(cf->conn, "HTTP/3 default");
+ Curl_pgrsTime(data, TIMER_APPCONNECT);
+ }
+ else {
+ failf(data, "failed to connect, handshake failed");
+ result = CURLE_COULDNT_CONNECT;
+ }
+ }
+
+out:
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static void cf_msh3_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_msh3_ctx *ctx = cf->ctx;
+ struct cf_call_data save;
+
+ (void)data;
+ CF_DATA_SAVE(save, cf, data);
+
+ if(ctx) {
+ DEBUGF(LOG_CF(data, cf, "destroying"));
+ if(ctx->qconn) {
+ MsH3ConnectionClose(ctx->qconn);
+ ctx->qconn = NULL;
+ }
+ if(ctx->api) {
+ MsH3ApiClose(ctx->api);
+ ctx->api = NULL;
+ }
+
+ if(ctx->active) {
+ /* We share our socket at cf->conn->sock[cf->sockindex] when active.
+ * If it is no longer there, someone has stolen (and hopefully
+ * closed it) and we just forget about it.
+ */
+ ctx->active = FALSE;
+ if(ctx->sock[SP_LOCAL] == cf->conn->sock[cf->sockindex]) {
+ DEBUGF(LOG_CF(data, cf, "cf_msh3_close(%d) active",
+ (int)ctx->sock[SP_LOCAL]));
+ cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "cf_socket_close(%d) no longer at "
+ "conn->sock[], discarding", (int)ctx->sock[SP_LOCAL]));
+ ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
+ }
+ if(cf->sockindex == FIRSTSOCKET)
+ cf->conn->remote_addr = NULL;
+ }
+ if(ctx->sock[SP_LOCAL] != CURL_SOCKET_BAD) {
+ sclose(ctx->sock[SP_LOCAL]);
+ }
+ if(ctx->sock[SP_REMOTE] != CURL_SOCKET_BAD) {
+ sclose(ctx->sock[SP_REMOTE]);
+ }
+ ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
+ ctx->sock[SP_REMOTE] = CURL_SOCKET_BAD;
+ }
+ CF_DATA_RESTORE(cf, save);
+}
+
+static void cf_msh3_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ cf_msh3_close(cf, data);
+ free(cf->ctx);
+ cf->ctx = NULL;
+ /* no CF_DATA_RESTORE(cf, save); its gone */
+
+}
+
+static CURLcode cf_msh3_query(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query, int *pres1, void *pres2)
+{
+ struct cf_msh3_ctx *ctx = cf->ctx;
+
+ switch(query) {
+ case CF_QUERY_MAX_CONCURRENT: {
+ /* TODO: we do not have access to this so far, fake it */
+ (void)ctx;
+ *pres1 = 100;
+ return CURLE_OK;
+ }
+ case CF_QUERY_TIMER_CONNECT: {
+ struct curltime *when = pres2;
+ /* we do not know when the first byte arrived */
+ if(cf->connected)
+ *when = ctx->handshake_at;
+ return CURLE_OK;
+ }
+ case CF_QUERY_TIMER_APPCONNECT: {
+ struct curltime *when = pres2;
+ if(cf->connected)
+ *when = ctx->handshake_at;
+ return CURLE_OK;
+ }
+ default:
+ break;
+ }
+ return cf->next?
+ cf->next->cft->query(cf->next, data, query, pres1, pres2) :
+ CURLE_UNKNOWN_OPTION;
+}
+
+static bool cf_msh3_conn_is_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending)
+{
+ struct cf_msh3_ctx *ctx = cf->ctx;
+
+ (void)data;
+ *input_pending = FALSE;
+ return ctx && ctx->sock[SP_LOCAL] != CURL_SOCKET_BAD && ctx->qconn &&
+ ctx->connected;
+}
+
+struct Curl_cftype Curl_cft_http3 = {
+ "HTTP/3",
+ CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
+ 0,
+ cf_msh3_destroy,
+ cf_msh3_connect,
+ cf_msh3_close,
+ Curl_cf_def_get_host,
+ cf_msh3_get_select_socks,
+ cf_msh3_data_pending,
+ cf_msh3_send,
+ cf_msh3_recv,
+ cf_msh3_data_event,
+ cf_msh3_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ cf_msh3_query,
+};
+
+CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai)
+{
+ struct cf_msh3_ctx *ctx = NULL;
+ struct Curl_cfilter *cf = NULL;
+ CURLcode result;
+
+ (void)data;
+ (void)conn;
+ (void)ai; /* TODO: msh3 resolves itself? */
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ Curl_sock_assign_addr(&ctx->addr, ai, TRNSPRT_QUIC);
+ ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
+ ctx->sock[SP_REMOTE] = CURL_SOCKET_BAD;
+
+ result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
+
+out:
+ *pcf = (!result)? cf : NULL;
+ if(result) {
+ Curl_safefree(cf);
+ Curl_safefree(ctx);
+ }
+
+ return result;
+}
+
+bool Curl_conn_is_msh3(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 /* USE_MSH3 */
diff --git a/lib/vquic/msh3.h b/lib/vquic/curl_msh3.h
similarity index 64%
copy from lib/vquic/msh3.h
copy to lib/vquic/curl_msh3.h
index ce884d9..33931f5 100644
--- a/lib/vquic/msh3.h
+++ b/lib/vquic/curl_msh3.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_VQUIC_MSH3_H
-#define HEADER_CURL_VQUIC_MSH3_H
+#ifndef HEADER_CURL_VQUIC_CURL_MSH3_H
+#define HEADER_CURL_VQUIC_CURL_MSH3_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,11 +30,17 @@
#include <msh3.h>
-struct quicsocket {
- MSH3_API* api;
- MSH3_CONNECTION* conn;
-};
+void Curl_msh3_ver(char *p, size_t len);
+
+CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai);
+
+bool Curl_conn_is_msh3(const struct Curl_easy *data,
+ const struct connectdata *conn,
+ int sockindex);
#endif /* USE_MSQUIC */
-#endif /* HEADER_CURL_VQUIC_MSH3_H */
+#endif /* HEADER_CURL_VQUIC_CURL_MSH3_H */
diff --git a/lib/vquic/curl_ngtcp2.c b/lib/vquic/curl_ngtcp2.c
new file mode 100644
index 0000000..a430aa1
--- /dev/null
+++ b/lib/vquic/curl_ngtcp2.c
@@ -0,0 +1,2698 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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_NGTCP2) && defined(USE_NGHTTP3)
+#include <ngtcp2/ngtcp2.h>
+#include <nghttp3/nghttp3.h>
+
+#ifdef USE_OPENSSL
+#include <openssl/err.h>
+#ifdef OPENSSL_IS_BORINGSSL
+#include <ngtcp2/ngtcp2_crypto_boringssl.h>
+#else
+#include <ngtcp2/ngtcp2_crypto_quictls.h>
+#endif
+#include "vtls/openssl.h"
+#elif defined(USE_GNUTLS)
+#include <ngtcp2/ngtcp2_crypto_gnutls.h>
+#include "vtls/gtls.h"
+#elif defined(USE_WOLFSSL)
+#include <ngtcp2/ngtcp2_crypto_wolfssl.h>
+#include "vtls/wolfssl.h"
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "strdup.h"
+#include "rand.h"
+#include "multiif.h"
+#include "strcase.h"
+#include "cfilters.h"
+#include "cf-socket.h"
+#include "connect.h"
+#include "progress.h"
+#include "strerror.h"
+#include "dynbuf.h"
+#include "http1.h"
+#include "select.h"
+#include "vquic.h"
+#include "vquic_int.h"
+#include "vtls/keylog.h"
+#include "vtls/vtls.h"
+#include "curl_ngtcp2.h"
+
+#include "warnless.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+
+#define H3_ALPN_H3_29 "\x5h3-29"
+#define H3_ALPN_H3 "\x2h3"
+
+#define QUIC_MAX_STREAMS (256*1024)
+#define QUIC_MAX_DATA (1*1024*1024)
+#define QUIC_IDLE_TIMEOUT (60*NGTCP2_SECONDS)
+#define QUIC_HANDSHAKE_TIMEOUT (10*NGTCP2_SECONDS)
+
+/* A stream window is the maximum amount we need to buffer for
+ * each active transfer. We use HTTP/3 flow control and only ACK
+ * when we take things out of the buffer.
+ * Chunk size is large enough to take a full DATA frame */
+#define H3_STREAM_WINDOW_SIZE (128 * 1024)
+#define H3_STREAM_CHUNK_SIZE (16 * 1024)
+/* The pool keeps spares around and half of a full stream windows
+ * seems good. More does not seem to improve performance.
+ * The benefit of the pool is that stream buffer to not keep
+ * spares. So memory consumption goes down when streams run empty,
+ * have a large upload done, etc. */
+#define H3_STREAM_POOL_SPARES \
+ (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE ) / 2
+/* Receive and Send max number of chunks just follows from the
+ * chunk size and window size */
+#define H3_STREAM_RECV_CHUNKS \
+ (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
+#define H3_STREAM_SEND_CHUNKS \
+ (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
+
+
+#ifdef USE_OPENSSL
+#define QUIC_CIPHERS \
+ "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
+ "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
+#define QUIC_GROUPS "P-256:X25519:P-384:P-521"
+#elif defined(USE_GNUTLS)
+#define QUIC_PRIORITY \
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
+ "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
+ "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
+ "%DISABLE_TLS13_COMPAT_MODE"
+#elif defined(USE_WOLFSSL)
+#define QUIC_CIPHERS \
+ "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
+ "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
+#define QUIC_GROUPS "P-256:P-384:P-521"
+#endif
+
+
+/*
+ * Store ngtcp2 version info in this buffer.
+ */
+void Curl_ngtcp2_ver(char *p, size_t len)
+{
+ const ngtcp2_info *ng2 = ngtcp2_version(0);
+ const nghttp3_info *ht3 = nghttp3_version(0);
+ (void)msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
+ ng2->version_str, ht3->version_str);
+}
+
+struct cf_ngtcp2_ctx {
+ struct cf_quic_ctx q;
+ ngtcp2_path connected_path;
+ ngtcp2_conn *qconn;
+ ngtcp2_cid dcid;
+ ngtcp2_cid scid;
+ uint32_t version;
+ ngtcp2_settings settings;
+ ngtcp2_transport_params transport_params;
+ ngtcp2_ccerr last_error;
+ ngtcp2_crypto_conn_ref conn_ref;
+#ifdef USE_OPENSSL
+ SSL_CTX *sslctx;
+ SSL *ssl;
+#elif defined(USE_GNUTLS)
+ struct gtls_instance *gtls;
+#elif defined(USE_WOLFSSL)
+ WOLFSSL_CTX *sslctx;
+ WOLFSSL *ssl;
+#endif
+ struct cf_call_data call_data;
+ nghttp3_conn *h3conn;
+ nghttp3_settings h3settings;
+ struct curltime started_at; /* time the current attempt started */
+ struct curltime handshake_at; /* time connect handshake finished */
+ struct curltime first_byte_at; /* when first byte was recvd */
+ struct curltime reconnect_at; /* time the next attempt should start */
+ struct bufc_pool stream_bufcp; /* chunk pool for streams */
+ size_t max_stream_window; /* max flow window for one stream */
+ int qlogfd;
+ BIT(got_first_byte); /* if first byte was received */
+};
+
+/* 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
+
+/**
+ * All about the H3 internals of a stream
+ */
+struct h3_stream_ctx {
+ int64_t id; /* HTTP/3 protocol identifier */
+ struct bufq sendbuf; /* h3 request body */
+ struct bufq recvbuf; /* h3 response body */
+ size_t sendbuf_len_in_flight; /* sendbuf amount "in flight" */
+ size_t upload_blocked_len; /* the amount written last and EGAINed */
+ size_t recv_buf_nonflow; /* buffered bytes, not counting for flow control */
+ uint64_t error3; /* HTTP/3 stream error code */
+ curl_off_t upload_left; /* number of request bytes left to upload */
+ int status_code; /* HTTP status code */
+ bool resp_hds_complete; /* we have a complete, final response */
+ bool closed; /* TRUE on stream close */
+ bool reset; /* TRUE on stream reset */
+ bool send_closed; /* stream is local closed */
+};
+
+#define H3_STREAM_CTX(d) ((struct h3_stream_ctx *)(((d) && (d)->req.p.http)? \
+ ((struct HTTP *)(d)->req.p.http)->h3_ctx \
+ : NULL))
+#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h3_ctx
+#define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \
+ H3_STREAM_CTX(d)->id : -2)
+
+static CURLcode h3_data_setup(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+
+ if(!data || !data->req.p.http) {
+ failf(data, "initialization failure, transfer not http initialized");
+ return CURLE_FAILED_INIT;
+ }
+
+ if(stream)
+ return CURLE_OK;
+
+ stream = calloc(1, sizeof(*stream));
+ if(!stream)
+ return CURLE_OUT_OF_MEMORY;
+
+ stream->id = -1;
+ /* on send, we control how much we put into the buffer */
+ Curl_bufq_initp(&stream->sendbuf, &ctx->stream_bufcp,
+ H3_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE);
+ stream->sendbuf_len_in_flight = 0;
+ /* on recv, we need a flexible buffer limit since we also write
+ * headers to it that are not counted against the nghttp3 flow limits. */
+ Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
+ H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
+ stream->recv_buf_nonflow = 0;
+
+ H3_STREAM_LCTX(data) = stream;
+ DEBUGF(LOG_CF(data, cf, "data setup"));
+ return CURLE_OK;
+}
+
+static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+
+ (void)cf;
+ if(stream) {
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] easy handle is done",
+ stream->id));
+ Curl_bufq_free(&stream->sendbuf);
+ Curl_bufq_free(&stream->recvbuf);
+ free(stream);
+ H3_STREAM_LCTX(data) = NULL;
+ }
+}
+
+/* ngtcp2 default congestion controller does not perform pacing. Limit
+ the maximum packet burst to MAX_PKT_BURST packets. */
+#define MAX_PKT_BURST 10
+
+struct pkt_io_ctx {
+ struct Curl_cfilter *cf;
+ struct Curl_easy *data;
+ ngtcp2_tstamp ts;
+ size_t pkt_count;
+ ngtcp2_path_storage ps;
+};
+
+static ngtcp2_tstamp timestamp(void)
+{
+ struct curltime ct = Curl_now();
+ return ct.tv_sec * NGTCP2_SECONDS + ct.tv_usec * NGTCP2_MICROSECONDS;
+}
+
+static void pktx_init(struct pkt_io_ctx *pktx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ pktx->cf = cf;
+ pktx->data = data;
+ pktx->ts = timestamp();
+ pktx->pkt_count = 0;
+ ngtcp2_path_storage_zero(&pktx->ps);
+}
+
+static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx);
+static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx);
+static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
+ uint64_t datalen, void *user_data,
+ void *stream_user_data);
+
+static ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref)
+{
+ struct Curl_cfilter *cf = conn_ref->user_data;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ return ctx->qconn;
+}
+
+#ifdef DEBUG_NGTCP2
+static void quic_printf(void *user_data, const char *fmt, ...)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+
+ (void)ctx; /* TODO: need an easy handle to infof() message */
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+#endif
+
+static void qlog_callback(void *user_data, uint32_t flags,
+ const void *data, size_t datalen)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ (void)flags;
+ if(ctx->qlogfd != -1) {
+ ssize_t rc = write(ctx->qlogfd, data, datalen);
+ if(rc == -1) {
+ /* on write error, stop further write attempts */
+ close(ctx->qlogfd);
+ ctx->qlogfd = -1;
+ }
+ }
+
+}
+
+static void quic_settings(struct cf_ngtcp2_ctx *ctx,
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx)
+{
+ ngtcp2_settings *s = &ctx->settings;
+ ngtcp2_transport_params *t = &ctx->transport_params;
+
+ ngtcp2_settings_default(s);
+ ngtcp2_transport_params_default(t);
+#ifdef DEBUG_NGTCP2
+ s->log_printf = quic_printf;
+#else
+ s->log_printf = NULL;
+#endif
+
+ (void)data;
+ s->initial_ts = pktx->ts;
+ s->handshake_timeout = QUIC_HANDSHAKE_TIMEOUT;
+ s->max_window = 100 * ctx->max_stream_window;
+ s->max_stream_window = ctx->max_stream_window;
+
+ 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_streams_bidi = QUIC_MAX_STREAMS;
+ t->initial_max_streams_uni = QUIC_MAX_STREAMS;
+ t->max_idle_timeout = QUIC_IDLE_TIMEOUT;
+ if(ctx->qlogfd != -1) {
+ s->qlog_write = qlog_callback;
+ }
+}
+
+#ifdef USE_OPENSSL
+static void keylog_callback(const SSL *ssl, const char *line)
+{
+ (void)ssl;
+ Curl_tls_keylog_write_line(line);
+}
+#elif defined(USE_GNUTLS)
+static int keylog_callback(gnutls_session_t session, const char *label,
+ const gnutls_datum_t *secret)
+{
+ gnutls_datum_t crandom;
+ gnutls_datum_t srandom;
+
+ gnutls_session_get_random(session, &crandom, &srandom);
+ if(crandom.size != 32) {
+ return -1;
+ }
+
+ Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
+ return 0;
+}
+#elif defined(USE_WOLFSSL)
+#if defined(HAVE_SECRET_CALLBACK)
+static void keylog_callback(const WOLFSSL *ssl, const char *line)
+{
+ (void)ssl;
+ Curl_tls_keylog_write_line(line);
+}
+#endif
+#endif
+
+static int init_ngh3_conn(struct Curl_cfilter *cf);
+
+#ifdef USE_OPENSSL
+static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
+ struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct connectdata *conn = cf->conn;
+ CURLcode result = CURLE_FAILED_INIT;
+ SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
+
+ if(!ssl_ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+#ifdef OPENSSL_IS_BORINGSSL
+ if(ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) {
+ failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
+ goto out;
+ }
+#else
+ if(ngtcp2_crypto_quictls_configure_client_context(ssl_ctx) != 0) {
+ failf(data, "ngtcp2_crypto_quictls_configure_client_context failed");
+ goto out;
+ }
+#endif
+
+ SSL_CTX_set_default_verify_paths(ssl_ctx);
+
+#ifdef OPENSSL_IS_BORINGSSL
+ if(SSL_CTX_set1_curves_list(ssl_ctx, QUIC_GROUPS) != 1) {
+ failf(data, "SSL_CTX_set1_curves_list failed");
+ goto out;
+ }
+#else
+ if(SSL_CTX_set_ciphersuites(ssl_ctx, QUIC_CIPHERS) != 1) {
+ char error_buffer[256];
+ ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
+ failf(data, "SSL_CTX_set_ciphersuites: %s", error_buffer);
+ goto out;
+ }
+
+ if(SSL_CTX_set1_groups_list(ssl_ctx, QUIC_GROUPS) != 1) {
+ failf(data, "SSL_CTX_set1_groups_list failed");
+ goto out;
+ }
+#endif
+
+ /* Open the file if a TLS or QUIC backend has not done this before. */
+ Curl_tls_keylog_open();
+ if(Curl_tls_keylog_enabled()) {
+ SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
+ }
+
+ result = Curl_ssl_setup_x509_store(cf, data, ssl_ctx);
+ if(result)
+ goto out;
+
+ /* OpenSSL always tries to verify the peer, this only says whether it should
+ * fail to connect if the verification fails, or if it should continue
+ * anyway. In the latter case the result of the verification is checked with
+ * SSL_get_verify_result() below. */
+ SSL_CTX_set_verify(ssl_ctx, conn->ssl_config.verifypeer ?
+ SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
+
+ /* give application a chance to interfere with SSL set up. */
+ if(data->set.ssl.fsslctx) {
+ Curl_set_in_callback(data, true);
+ result = (*data->set.ssl.fsslctx)(data, ssl_ctx,
+ data->set.ssl.fsslctxp);
+ Curl_set_in_callback(data, false);
+ if(result) {
+ failf(data, "error signaled by ssl ctx callback");
+ goto out;
+ }
+ }
+ result = CURLE_OK;
+
+out:
+ *pssl_ctx = result? NULL : ssl_ctx;
+ if(result && ssl_ctx)
+ SSL_CTX_free(ssl_ctx);
+ return result;
+}
+
+static CURLcode quic_set_client_cert(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ SSL_CTX *ssl_ctx = ctx->sslctx;
+ const struct ssl_config_data *ssl_config;
+
+ ssl_config = Curl_ssl_get_config(data, FIRSTSOCKET);
+ DEBUGASSERT(ssl_config);
+
+ if(ssl_config->primary.clientcert || ssl_config->primary.cert_blob
+ || ssl_config->cert_type) {
+ return Curl_ossl_set_client_cert(
+ data, ssl_ctx, ssl_config->primary.clientcert,
+ ssl_config->primary.cert_blob, ssl_config->cert_type,
+ ssl_config->key, ssl_config->key_blob,
+ ssl_config->key_type, ssl_config->key_passwd);
+ }
+
+ return CURLE_OK;
+}
+
+/** SSL callbacks ***/
+
+static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ const uint8_t *alpn = NULL;
+ size_t alpnlen = 0;
+
+ (void)data;
+ DEBUGASSERT(!ctx->ssl);
+ ctx->ssl = SSL_new(ctx->sslctx);
+
+ SSL_set_app_data(ctx->ssl, &ctx->conn_ref);
+ SSL_set_connect_state(ctx->ssl);
+ SSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
+
+ alpn = (const uint8_t *)H3_ALPN_H3_29 H3_ALPN_H3;
+ alpnlen = sizeof(H3_ALPN_H3_29) - 1 + sizeof(H3_ALPN_H3) - 1;
+ if(alpn)
+ SSL_set_alpn_protos(ctx->ssl, alpn, (int)alpnlen);
+
+ /* set SNI */
+ SSL_set_tlsext_host_name(ctx->ssl, cf->conn->host.name);
+ return CURLE_OK;
+}
+#elif defined(USE_GNUTLS)
+static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ CURLcode result;
+ gnutls_datum_t alpn[2];
+ /* this will need some attention when HTTPS proxy over QUIC get fixed */
+ const char * const hostname = cf->conn->host.name;
+ long * const pverifyresult = &data->set.ssl.certverifyresult;
+ int rc;
+
+ DEBUGASSERT(ctx->gtls == NULL);
+ ctx->gtls = calloc(1, sizeof(*(ctx->gtls)));
+ if(!ctx->gtls)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = gtls_client_init(data, &cf->conn->ssl_config, &data->set.ssl,
+ hostname, ctx->gtls, pverifyresult);
+ if(result)
+ return result;
+
+ gnutls_session_set_ptr(ctx->gtls->session, &ctx->conn_ref);
+
+ if(ngtcp2_crypto_gnutls_configure_client_session(ctx->gtls->session) != 0) {
+ DEBUGF(LOG_CF(data, cf,
+ "ngtcp2_crypto_gnutls_configure_client_session failed\n"));
+ return CURLE_QUIC_CONNECT_ERROR;
+ }
+
+ rc = gnutls_priority_set_direct(ctx->gtls->session, QUIC_PRIORITY, NULL);
+ if(rc < 0) {
+ DEBUGF(LOG_CF(data, cf, "gnutls_priority_set_direct failed: %s\n",
+ gnutls_strerror(rc)));
+ return CURLE_QUIC_CONNECT_ERROR;
+ }
+
+ /* Open the file if a TLS or QUIC backend has not done this before. */
+ Curl_tls_keylog_open();
+ if(Curl_tls_keylog_enabled()) {
+ gnutls_session_set_keylog_function(ctx->gtls->session, keylog_callback);
+ }
+
+ /* strip the first byte (the length) from NGHTTP3_ALPN_H3 */
+ alpn[0].data = (unsigned char *)H3_ALPN_H3_29 + 1;
+ alpn[0].size = sizeof(H3_ALPN_H3_29) - 2;
+ alpn[1].data = (unsigned char *)H3_ALPN_H3 + 1;
+ alpn[1].size = sizeof(H3_ALPN_H3) - 2;
+
+ gnutls_alpn_set_protocols(ctx->gtls->session,
+ alpn, 2, GNUTLS_ALPN_MANDATORY);
+ return CURLE_OK;
+}
+#elif defined(USE_WOLFSSL)
+
+static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
+ struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct connectdata *conn = cf->conn;
+ CURLcode result = CURLE_FAILED_INIT;
+ WOLFSSL_CTX *ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
+
+ if(!ssl_ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ if(ngtcp2_crypto_wolfssl_configure_client_context(ssl_ctx) != 0) {
+ failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed");
+ goto out;
+ }
+
+ wolfSSL_CTX_set_default_verify_paths(ssl_ctx);
+
+ if(wolfSSL_CTX_set_cipher_list(ssl_ctx, QUIC_CIPHERS) != 1) {
+ char error_buffer[256];
+ ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
+ failf(data, "SSL_CTX_set_ciphersuites: %s", error_buffer);
+ goto out;
+ }
+
+ if(wolfSSL_CTX_set1_groups_list(ssl_ctx, (char *)QUIC_GROUPS) != 1) {
+ failf(data, "SSL_CTX_set1_groups_list failed");
+ goto out;
+ }
+
+ /* Open the file if a TLS or QUIC backend has not done this before. */
+ Curl_tls_keylog_open();
+ if(Curl_tls_keylog_enabled()) {
+#if defined(HAVE_SECRET_CALLBACK)
+ wolfSSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
+#else
+ failf(data, "wolfSSL was built without keylog callback");
+ goto out;
+#endif
+ }
+
+ if(conn->ssl_config.verifypeer) {
+ const char * const ssl_cafile = conn->ssl_config.CAfile;
+ const char * const ssl_capath = conn->ssl_config.CApath;
+
+ wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
+ if(conn->ssl_config.CAfile || conn->ssl_config.CApath) {
+ /* tell wolfSSL where to find CA certificates that are used to verify
+ the server's certificate. */
+ if(!wolfSSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ goto out;
+ }
+ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+ }
+#ifdef CURL_CA_FALLBACK
+ else {
+ /* verifying the peer without any CA certificates won't work so
+ use wolfssl's built-in default as fallback */
+ wolfSSL_CTX_set_default_verify_paths(ssl_ctx);
+ }
+#endif
+ }
+ else {
+ wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
+ }
+
+ /* give application a chance to interfere with SSL set up. */
+ if(data->set.ssl.fsslctx) {
+ Curl_set_in_callback(data, true);
+ result = (*data->set.ssl.fsslctx)(data, ssl_ctx,
+ data->set.ssl.fsslctxp);
+ Curl_set_in_callback(data, false);
+ if(result) {
+ failf(data, "error signaled by ssl ctx callback");
+ goto out;
+ }
+ }
+ result = CURLE_OK;
+
+out:
+ *pssl_ctx = result? NULL : ssl_ctx;
+ if(result && ssl_ctx)
+ SSL_CTX_free(ssl_ctx);
+ return result;
+}
+
+/** SSL callbacks ***/
+
+static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ const uint8_t *alpn = NULL;
+ size_t alpnlen = 0;
+ /* this will need some attention when HTTPS proxy over QUIC get fixed */
+ const char * const hostname = cf->conn->host.name;
+
+ (void)data;
+ DEBUGASSERT(!ctx->ssl);
+ ctx->ssl = wolfSSL_new(ctx->sslctx);
+
+ wolfSSL_set_app_data(ctx->ssl, &ctx->conn_ref);
+ wolfSSL_set_connect_state(ctx->ssl);
+ wolfSSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
+
+ alpn = (const uint8_t *)H3_ALPN_H3_29 H3_ALPN_H3;
+ alpnlen = sizeof(H3_ALPN_H3_29) - 1 + sizeof(H3_ALPN_H3) - 1;
+ if(alpn)
+ wolfSSL_set_alpn_protos(ctx->ssl, alpn, (int)alpnlen);
+
+ /* set SNI */
+ wolfSSL_UseSNI(ctx->ssl, WOLFSSL_SNI_HOST_NAME,
+ hostname, (unsigned short)strlen(hostname));
+
+ return CURLE_OK;
+}
+#endif /* defined(USE_WOLFSSL) */
+
+static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
+{
+ (void)user_data;
+ (void)tconn;
+ return 0;
+}
+
+static void report_consumed_data(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ size_t consumed)
+{
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+
+ if(!stream)
+ return;
+ /* the HTTP/1.1 response headers are written to the buffer, but
+ * consuming those does not count against flow control. */
+ if(stream->recv_buf_nonflow) {
+ if(consumed >= stream->recv_buf_nonflow) {
+ consumed -= stream->recv_buf_nonflow;
+ stream->recv_buf_nonflow = 0;
+ }
+ else {
+ stream->recv_buf_nonflow -= consumed;
+ consumed = 0;
+ }
+ }
+ if(consumed > 0) {
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] consumed %zu DATA bytes",
+ stream->id, consumed));
+ ngtcp2_conn_extend_max_stream_offset(ctx->qconn, stream->id,
+ consumed);
+ ngtcp2_conn_extend_max_offset(ctx->qconn, consumed);
+ }
+}
+
+static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
+ int64_t stream_id, uint64_t offset,
+ const uint8_t *buf, size_t buflen,
+ void *user_data, void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ nghttp3_ssize nconsumed;
+ int fin = (flags & NGTCP2_STREAM_DATA_FLAG_FIN) ? 1 : 0;
+ struct Curl_easy *data = stream_user_data;
+ (void)offset;
+ (void)data;
+
+ nconsumed =
+ nghttp3_conn_read_stream(ctx->h3conn, stream_id, buf, buflen, fin);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read_stream(len=%zu) -> %zd",
+ stream_id, buflen, nconsumed));
+ if(nconsumed < 0) {
+ ngtcp2_ccerr_set_application_error(
+ &ctx->last_error,
+ nghttp3_err_infer_quic_app_error_code((int)nconsumed), NULL, 0);
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ /* number of bytes inside buflen which consists of framing overhead
+ * including QPACK HEADERS. In other words, it does not consume payload of
+ * DATA frame. */
+ ngtcp2_conn_extend_max_stream_offset(tconn, stream_id, nconsumed);
+ ngtcp2_conn_extend_max_offset(tconn, nconsumed);
+
+ 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)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ int rv;
+ (void)stream_id;
+ (void)tconn;
+ (void)offset;
+ (void)datalen;
+ (void)stream_user_data;
+
+ rv = nghttp3_conn_add_ack_offset(ctx->h3conn, stream_id, datalen);
+ if(rv) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags,
+ int64_t stream3_id, uint64_t app_error_code,
+ void *user_data, void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ int rv;
+
+ (void)tconn;
+ (void)data;
+ /* stream is closed... */
+
+ if(!(flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET)) {
+ app_error_code = NGHTTP3_H3_NO_ERROR;
+ }
+
+ rv = nghttp3_conn_close_stream(ctx->h3conn, stream3_id,
+ app_error_code);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] quic close(err=%"
+ PRIu64 ") -> %d", stream3_id, app_error_code, rv));
+ if(rv) {
+ ngtcp2_ccerr_set_application_error(
+ &ctx->last_error, nghttp3_err_infer_quic_app_error_code(rv), NULL, 0);
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+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;
+ struct Curl_easy *data = stream_user_data;
+ int rv;
+ (void)tconn;
+ (void)final_size;
+ (void)app_error_code;
+ (void)data;
+
+ rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] reset -> %d", stream_id, rv));
+ if(rv) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static int cb_stream_stop_sending(ngtcp2_conn *tconn, 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;
+ int rv;
+ (void)tconn;
+ (void)app_error_code;
+ (void)stream_user_data;
+
+ rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
+ if(rv) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static int cb_extend_max_local_streams_bidi(ngtcp2_conn *tconn,
+ uint64_t max_streams,
+ void *user_data)
+{
+ (void)tconn;
+ (void)max_streams;
+ (void)user_data;
+
+ return 0;
+}
+
+static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id,
+ uint64_t max_data, void *user_data,
+ void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ int rv;
+ (void)tconn;
+ (void)max_data;
+ (void)stream_user_data;
+
+ rv = nghttp3_conn_unblock_stream(ctx->h3conn, stream_id);
+ if(rv) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static void cb_rand(uint8_t *dest, size_t destlen,
+ const ngtcp2_rand_ctx *rand_ctx)
+{
+ CURLcode result;
+ (void)rand_ctx;
+
+ result = Curl_rand(NULL, dest, destlen);
+ if(result) {
+ /* cb_rand is only used for non-cryptographic context. If Curl_rand
+ failed, just fill 0 and call it *random*. */
+ memset(dest, 0, destlen);
+ }
+}
+
+static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
+ uint8_t *token, size_t cidlen,
+ void *user_data)
+{
+ CURLcode result;
+ (void)tconn;
+ (void)user_data;
+
+ result = Curl_rand(NULL, cid->data, cidlen);
+ if(result)
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ cid->datalen = cidlen;
+
+ result = Curl_rand(NULL, token, NGTCP2_STATELESS_RESET_TOKENLEN);
+ if(result)
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+
+ return 0;
+}
+
+static int cb_recv_rx_key(ngtcp2_conn *tconn, ngtcp2_encryption_level level,
+ void *user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ (void)tconn;
+
+ if(level != NGTCP2_ENCRYPTION_LEVEL_1RTT) {
+ return 0;
+ }
+
+ if(init_ngh3_conn(cf) != CURLE_OK) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static ngtcp2_callbacks ng_callbacks = {
+ ngtcp2_crypto_client_initial_cb,
+ NULL, /* recv_client_initial */
+ ngtcp2_crypto_recv_crypto_data_cb,
+ cb_handshake_completed,
+ NULL, /* recv_version_negotiation */
+ ngtcp2_crypto_encrypt_cb,
+ ngtcp2_crypto_decrypt_cb,
+ ngtcp2_crypto_hp_mask_cb,
+ cb_recv_stream_data,
+ cb_acked_stream_data_offset,
+ NULL, /* stream_open */
+ cb_stream_close,
+ NULL, /* recv_stateless_reset */
+ ngtcp2_crypto_recv_retry_cb,
+ cb_extend_max_local_streams_bidi,
+ NULL, /* extend_max_local_streams_uni */
+ cb_rand,
+ cb_get_new_connection_id,
+ NULL, /* remove_connection_id */
+ ngtcp2_crypto_update_key_cb, /* update_key */
+ NULL, /* path_validation */
+ NULL, /* select_preferred_addr */
+ cb_stream_reset,
+ NULL, /* extend_max_remote_streams_bidi */
+ NULL, /* extend_max_remote_streams_uni */
+ cb_extend_max_stream_data,
+ NULL, /* dcid_status */
+ NULL, /* handshake_confirmed */
+ NULL, /* recv_new_token */
+ ngtcp2_crypto_delete_crypto_aead_ctx_cb,
+ ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
+ NULL, /* recv_datagram */
+ NULL, /* ack_datagram */
+ NULL, /* lost_datagram */
+ ngtcp2_crypto_get_path_challenge_data_cb,
+ cb_stream_stop_sending,
+ NULL, /* version_negotiation */
+ cb_recv_rx_key,
+ NULL, /* recv_tx_key */
+ NULL, /* early_data_rejected */
+};
+
+/**
+ * Connection maintenance like timeouts on packet ACKs etc. are done by us, not
+ * the OS like for TCP. POLL events on the socket therefore are not
+ * sufficient.
+ * ngtcp2 tells us when it wants to be invoked again. We handle that via
+ * the `Curl_expire()` mechanisms.
+ */
+static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct pkt_io_ctx local_pktx;
+ ngtcp2_tstamp expiry;
+
+ if(!pktx) {
+ pktx_init(&local_pktx, cf, data);
+ pktx = &local_pktx;
+ }
+ else {
+ pktx->ts = timestamp();
+ }
+
+ expiry = ngtcp2_conn_get_expiry(ctx->qconn);
+ if(expiry != UINT64_MAX) {
+ if(expiry <= pktx->ts) {
+ CURLcode result;
+ int rv = ngtcp2_conn_handle_expiry(ctx->qconn, pktx->ts);
+ if(rv) {
+ failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
+ ngtcp2_strerror(rv));
+ ngtcp2_ccerr_set_liberr(&ctx->last_error, rv, NULL, 0);
+ return CURLE_SEND_ERROR;
+ }
+ result = cf_progress_ingress(cf, data, pktx);
+ if(result)
+ return result;
+ result = cf_progress_egress(cf, data, pktx);
+ if(result)
+ return result;
+ /* ask again, things might have changed */
+ expiry = ngtcp2_conn_get_expiry(ctx->qconn);
+ }
+
+ if(expiry > pktx->ts) {
+ ngtcp2_duration timeout = expiry - pktx->ts;
+ if(timeout % NGTCP2_MILLISECONDS) {
+ timeout += NGTCP2_MILLISECONDS;
+ }
+ Curl_expire(data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
+ }
+ }
+ return CURLE_OK;
+}
+
+static int cf_ngtcp2_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct SingleRequest *k = &data->req;
+ int rv = GETSOCK_BLANK;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ socks[0] = ctx->q.sockfd;
+
+ /* in HTTP/3 we can always get a frame, so check read */
+ rv |= GETSOCK_READSOCK(0);
+
+ /* we're still uploading or the HTTP/2 layer wants to send data */
+ if((k->keepon & KEEP_SENDBITS) == KEEP_SEND &&
+ ngtcp2_conn_get_cwnd_left(ctx->qconn) &&
+ ngtcp2_conn_get_max_data_left(ctx->qconn) &&
+ stream && nghttp3_conn_is_stream_writable(ctx->h3conn, stream->id))
+ rv |= GETSOCK_WRITESOCK(0);
+
+ /* DEBUGF(LOG_CF(data, cf, "get_select_socks -> %x (sock=%d)",
+ rv, (int)socks[0])); */
+ CF_DATA_RESTORE(cf, save);
+ return rv;
+}
+
+static void h3_drain_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ unsigned char bits;
+
+ (void)cf;
+ bits = CURL_CSELECT_IN;
+ if(stream && stream->upload_left && !stream->send_closed)
+ bits |= CURL_CSELECT_OUT;
+ if(data->state.dselect_bits != bits) {
+ data->state.dselect_bits = bits;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+}
+
+static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
+ uint64_t app_error_code, void *user_data,
+ void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ (void)conn;
+ (void)stream_id;
+ (void)app_error_code;
+ (void)cf;
+
+ /* we might be called by nghttp3 after we already cleaned up */
+ if(!stream)
+ return 0;
+
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] h3 close(err=%" PRId64 ")",
+ stream_id, app_error_code));
+ stream->closed = TRUE;
+ stream->error3 = app_error_code;
+ if(app_error_code == NGHTTP3_H3_INTERNAL_ERROR) {
+ stream->reset = TRUE;
+ stream->send_closed = TRUE;
+ }
+ h3_drain_stream(cf, data);
+ return 0;
+}
+
+/*
+ * write_resp_raw() copies response data in raw format to the `data`'s
+ * receive buffer. If not enough space is available, it appends to the
+ * `data`'s overflow buffer.
+ */
+static CURLcode write_resp_raw(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const void *mem, size_t memlen,
+ bool flow)
+{
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ CURLcode result = CURLE_OK;
+ ssize_t nwritten;
+
+ (void)cf;
+ if(!stream) {
+ return CURLE_RECV_ERROR;
+ }
+ nwritten = Curl_bufq_write(&stream->recvbuf, mem, memlen, &result);
+ /* DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] add recvbuf(len=%zu) "
+ "-> %zd, %d", stream->id, memlen, nwritten, result));
+ */
+ if(nwritten < 0) {
+ return result;
+ }
+
+ if(!flow)
+ stream->recv_buf_nonflow += (size_t)nwritten;
+
+ if((size_t)nwritten < memlen) {
+ /* This MUST not happen. Our recbuf is dimensioned to hold the
+ * full max_stream_window and then some for this very reason. */
+ DEBUGASSERT(0);
+ return CURLE_RECV_ERROR;
+ }
+ return result;
+}
+
+static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id,
+ const uint8_t *buf, size_t buflen,
+ void *user_data, void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ CURLcode result;
+
+ (void)conn;
+ (void)stream3_id;
+
+ result = write_resp_raw(cf, data, buf, buflen, TRUE);
+ h3_drain_stream(cf, data);
+ return result? -1 : 0;
+}
+
+static int cb_h3_deferred_consume(nghttp3_conn *conn, int64_t stream3_id,
+ size_t consumed, void *user_data,
+ void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ (void)conn;
+ (void)stream_user_data;
+
+ /* nghttp3 has consumed bytes on the QUIC stream and we need to
+ * tell the QUIC connection to increase its flow control */
+ ngtcp2_conn_extend_max_stream_offset(ctx->qconn, stream3_id, consumed);
+ ngtcp2_conn_extend_max_offset(ctx->qconn, consumed);
+ return 0;
+}
+
+static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
+ int fin, void *user_data, void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ CURLcode result = CURLE_OK;
+ (void)conn;
+ (void)stream_id;
+ (void)fin;
+ (void)cf;
+
+ if(!stream)
+ return 0;
+ /* add a CRLF only if we've received some headers */
+ result = write_resp_raw(cf, data, "\r\n", 2, FALSE);
+ if(result) {
+ return -1;
+ }
+
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] end_headers(status_code=%d",
+ stream_id, stream->status_code));
+ if(stream->status_code / 100 != 1) {
+ stream->resp_hds_complete = TRUE;
+ }
+ h3_drain_stream(cf, data);
+ return 0;
+}
+
+static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
+ int32_t token, nghttp3_rcbuf *name,
+ nghttp3_rcbuf *value, uint8_t flags,
+ void *user_data, void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ nghttp3_vec h3name = nghttp3_rcbuf_get_buf(name);
+ nghttp3_vec h3val = nghttp3_rcbuf_get_buf(value);
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ CURLcode result = CURLE_OK;
+ (void)conn;
+ (void)stream_id;
+ (void)token;
+ (void)flags;
+ (void)cf;
+
+ /* we might have cleaned up this transfer already */
+ if(!stream)
+ return 0;
+
+ if(token == NGHTTP3_QPACK_TOKEN__STATUS) {
+ char line[14]; /* status line is always 13 characters long */
+ size_t ncopy;
+
+ result = Curl_http_decode_status(&stream->status_code,
+ (const char *)h3val.base, h3val.len);
+ if(result)
+ return -1;
+ ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n",
+ stream->status_code);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] status: %s",
+ stream_id, line));
+ result = write_resp_raw(cf, data, line, ncopy, FALSE);
+ if(result) {
+ return -1;
+ }
+ }
+ else {
+ /* store as an HTTP1-style header */
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] header: %.*s: %.*s",
+ stream_id, (int)h3name.len, h3name.base,
+ (int)h3val.len, h3val.base));
+ result = write_resp_raw(cf, data, h3name.base, h3name.len, FALSE);
+ if(result) {
+ return -1;
+ }
+ result = write_resp_raw(cf, data, ": ", 2, FALSE);
+ if(result) {
+ return -1;
+ }
+ result = write_resp_raw(cf, data, h3val.base, h3val.len, FALSE);
+ if(result) {
+ return -1;
+ }
+ result = write_resp_raw(cf, data, "\r\n", 2, FALSE);
+ if(result) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int cb_h3_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_ngtcp2_ctx *ctx = cf->ctx;
+ int rv;
+ (void)conn;
+ (void)stream_user_data;
+
+ rv = ngtcp2_conn_shutdown_stream_read(ctx->qconn, 0, stream_id,
+ app_error_code);
+ if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t stream_id,
+ uint64_t app_error_code, void *user_data,
+ void *stream_user_data) {
+ struct Curl_cfilter *cf = user_data;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct Curl_easy *data = stream_user_data;
+ int rv;
+ (void)conn;
+ (void)data;
+
+ rv = ngtcp2_conn_shutdown_stream_write(ctx->qconn, 0, stream_id,
+ app_error_code);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] reset -> %d", stream_id, rv));
+ if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static nghttp3_callbacks ngh3_callbacks = {
+ cb_h3_acked_req_body, /* acked_stream_data */
+ cb_h3_stream_close,
+ cb_h3_recv_data,
+ cb_h3_deferred_consume,
+ NULL, /* begin_headers */
+ cb_h3_recv_header,
+ cb_h3_end_headers,
+ NULL, /* begin_trailers */
+ cb_h3_recv_header,
+ NULL, /* end_trailers */
+ cb_h3_stop_sending,
+ NULL, /* end_stream */
+ cb_h3_reset_stream,
+ NULL, /* shutdown */
+ NULL /* recv_settings */
+};
+
+static int init_ngh3_conn(struct Curl_cfilter *cf)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ CURLcode result;
+ int rc;
+ int64_t ctrl_stream_id, qpack_enc_stream_id, qpack_dec_stream_id;
+
+ if(ngtcp2_conn_get_streams_uni_left(ctx->qconn) < 3) {
+ return CURLE_QUIC_CONNECT_ERROR;
+ }
+
+ nghttp3_settings_default(&ctx->h3settings);
+
+ rc = nghttp3_conn_client_new(&ctx->h3conn,
+ &ngh3_callbacks,
+ &ctx->h3settings,
+ nghttp3_mem_default(),
+ cf);
+ if(rc) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
+ }
+
+ rc = ngtcp2_conn_open_uni_stream(ctx->qconn, &ctrl_stream_id, NULL);
+ if(rc) {
+ result = CURLE_QUIC_CONNECT_ERROR;
+ goto fail;
+ }
+
+ rc = nghttp3_conn_bind_control_stream(ctx->h3conn, ctrl_stream_id);
+ if(rc) {
+ result = CURLE_QUIC_CONNECT_ERROR;
+ goto fail;
+ }
+
+ rc = ngtcp2_conn_open_uni_stream(ctx->qconn, &qpack_enc_stream_id, NULL);
+ if(rc) {
+ result = CURLE_QUIC_CONNECT_ERROR;
+ goto fail;
+ }
+
+ rc = ngtcp2_conn_open_uni_stream(ctx->qconn, &qpack_dec_stream_id, NULL);
+ if(rc) {
+ result = CURLE_QUIC_CONNECT_ERROR;
+ goto fail;
+ }
+
+ rc = nghttp3_conn_bind_qpack_streams(ctx->h3conn, qpack_enc_stream_id,
+ qpack_dec_stream_id);
+ if(rc) {
+ result = CURLE_QUIC_CONNECT_ERROR;
+ goto fail;
+ }
+
+ return CURLE_OK;
+fail:
+
+ return result;
+}
+
+static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h3_stream_ctx *stream,
+ CURLcode *err)
+{
+ ssize_t nread = -1;
+
+ (void)cf;
+ if(stream->reset) {
+ failf(data,
+ "HTTP/3 stream %" PRId64 " reset by server", stream->id);
+ *err = CURLE_PARTIAL_FILE;
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, was reset -> %d",
+ stream->id, *err));
+ goto out;
+ }
+ else if(stream->error3 != NGHTTP3_H3_NO_ERROR) {
+ failf(data,
+ "HTTP/3 stream %" PRId64 " was not closed cleanly: "
+ "(err %"PRId64")", stream->id, stream->error3);
+ *err = CURLE_HTTP3;
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, closed uncleanly"
+ " -> %d", stream->id, *err));
+ goto out;
+ }
+
+ if(!stream->resp_hds_complete) {
+ failf(data,
+ "HTTP/3 stream %" PRId64 " was closed cleanly, but before getting"
+ " all response header fields, treated as error",
+ stream->id);
+ *err = CURLE_HTTP3;
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, closed incomplete"
+ " -> %d", stream->id, *err));
+ goto out;
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, closed ok"
+ " -> %d", stream->id, *err));
+ }
+ *err = CURLE_OK;
+ nread = 0;
+
+out:
+ return nread;
+}
+
+/* incoming data frames on the h3 stream */
+static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ ssize_t nread = -1;
+ struct cf_call_data save;
+ struct pkt_io_ctx pktx;
+
+ (void)ctx;
+
+ CF_DATA_SAVE(save, cf, data);
+ DEBUGASSERT(cf->connected);
+ DEBUGASSERT(ctx);
+ DEBUGASSERT(ctx->qconn);
+ DEBUGASSERT(ctx->h3conn);
+ *err = CURLE_OK;
+
+ pktx_init(&pktx, cf, data);
+
+ if(!stream) {
+ *err = CURLE_RECV_ERROR;
+ goto out;
+ }
+
+ if(!Curl_bufq_is_empty(&stream->recvbuf)) {
+ nread = Curl_bufq_read(&stream->recvbuf,
+ (unsigned char *)buf, len, err);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read recvbuf(len=%zu) "
+ "-> %zd, %d", stream->id, len, nread, *err));
+ if(nread < 0)
+ goto out;
+ report_consumed_data(cf, data, nread);
+ }
+
+ if(cf_progress_ingress(cf, data, &pktx)) {
+ *err = CURLE_RECV_ERROR;
+ nread = -1;
+ goto out;
+ }
+
+ /* recvbuf had nothing before, maybe after progressing ingress? */
+ if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) {
+ nread = Curl_bufq_read(&stream->recvbuf,
+ (unsigned char *)buf, len, err);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read recvbuf(len=%zu) "
+ "-> %zd, %d", stream->id, len, nread, *err));
+ if(nread < 0)
+ goto out;
+ report_consumed_data(cf, data, nread);
+ }
+
+ if(nread > 0) {
+ h3_drain_stream(cf, data);
+ }
+ else {
+ if(stream->closed) {
+ nread = recv_closed_stream(cf, data, stream, err);
+ goto out;
+ }
+ *err = CURLE_AGAIN;
+ nread = -1;
+ }
+
+out:
+ if(cf_progress_egress(cf, data, &pktx)) {
+ *err = CURLE_SEND_ERROR;
+ nread = -1;
+ }
+ else {
+ CURLcode result2 = check_and_set_expiry(cf, data, &pktx);
+ if(result2) {
+ *err = result2;
+ nread = -1;
+ }
+ }
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv(len=%zu) -> %zd, %d",
+ stream? stream->id : -1, len, nread, *err));
+ CF_DATA_RESTORE(cf, save);
+ return nread;
+}
+
+static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
+ uint64_t datalen, void *user_data,
+ void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ size_t skiplen;
+
+ (void)cf;
+ if(!stream)
+ return 0;
+ /* The server acknowledged `datalen` of bytes from our request body.
+ * This is a delta. We have kept this data in `sendbuf` for
+ * re-transmissions and can free it now. */
+ if(datalen >= (uint64_t)stream->sendbuf_len_in_flight)
+ skiplen = stream->sendbuf_len_in_flight;
+ else
+ skiplen = (size_t)datalen;
+ Curl_bufq_skip(&stream->sendbuf, skiplen);
+ stream->sendbuf_len_in_flight -= skiplen;
+
+ /* Everything ACKed, we resume upload processing */
+ if(!stream->sendbuf_len_in_flight) {
+ int rv = nghttp3_conn_resume_stream(conn, stream_id);
+ if(rv) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+ if((data->req.keepon & KEEP_SEND_HOLD) &&
+ (data->req.keepon & KEEP_SEND)) {
+ data->req.keepon &= ~KEEP_SEND_HOLD;
+ h3_drain_stream(cf, data);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] unpausing acks",
+ 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)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ ssize_t nwritten = 0;
+ size_t nvecs = 0;
+ (void)cf;
+ (void)conn;
+ (void)stream_id;
+ (void)user_data;
+ (void)veccnt;
+
+ if(!stream)
+ return NGHTTP3_ERR_CALLBACK_FAILURE;
+ /* nghttp3 keeps references to the sendbuf data until it is ACKed
+ * by the server (see `cb_h3_acked_req_body()` for updates).
+ * `sendbuf_len_in_flight` is the amount of bytes in `sendbuf`
+ * that we have already passed to nghttp3, but which have not been
+ * ACKed yet.
+ * Any amount beyond `sendbuf_len_in_flight` we need still to pass
+ * to nghttp3. Do that now, if we can. */
+ if(stream->sendbuf_len_in_flight < Curl_bufq_len(&stream->sendbuf)) {
+ nvecs = 0;
+ while(nvecs < veccnt &&
+ Curl_bufq_peek_at(&stream->sendbuf,
+ stream->sendbuf_len_in_flight,
+ (const unsigned char **)&vec[nvecs].base,
+ &vec[nvecs].len)) {
+ stream->sendbuf_len_in_flight += vec[nvecs].len;
+ nwritten += vec[nvecs].len;
+ ++nvecs;
+ }
+ DEBUGASSERT(nvecs > 0); /* we SHOULD have been be able to peek */
+ }
+
+ if(nwritten > 0 && stream->upload_left != -1)
+ stream->upload_left -= nwritten;
+
+ /* When we stopped sending and everything in `sendbuf` is "in flight",
+ * we are at the end of the request body. */
+ if(stream->upload_left == 0) {
+ *pflags = NGHTTP3_DATA_FLAG_EOF;
+ stream->send_closed = TRUE;
+ }
+ else if(!nwritten) {
+ /* Not EOF, and nothing to give, we signal WOULDBLOCK. */
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read req body -> AGAIN",
+ stream->id));
+ return NGHTTP3_ERR_WOULDBLOCK;
+ }
+
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read req body -> "
+ "%d vecs%s with %zu (buffered=%zu, left=%"
+ CURL_FORMAT_CURL_OFF_T ")",
+ stream->id, (int)nvecs,
+ *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
+ nwritten, Curl_bufq_len(&stream->sendbuf),
+ stream->upload_left));
+ return (nghttp3_ssize)nvecs;
+}
+
+/* Index where :authority header field will appear in request header
+ field list. */
+#define AUTHORITY_DST_IDX 3
+
+static ssize_t h3_stream_open(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const void *buf, size_t len,
+ CURLcode *err)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct h3_stream_ctx *stream = NULL;
+ struct h1_req_parser h1;
+ struct dynhds h2_headers;
+ size_t nheader;
+ nghttp3_nv *nva = NULL;
+ int rc = 0;
+ unsigned int i;
+ ssize_t nwritten = -1;
+ nghttp3_data_reader reader;
+ nghttp3_data_reader *preader = NULL;
+
+ Curl_h1_req_parse_init(&h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
+ Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
+
+ *err = h3_data_setup(cf, data);
+ if(*err)
+ goto out;
+ stream = H3_STREAM_CTX(data);
+ DEBUGASSERT(stream);
+
+ rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &stream->id, NULL);
+ if(rc) {
+ failf(data, "can get bidi streams");
+ *err = CURLE_SEND_ERROR;
+ goto out;
+ }
+
+ nwritten = Curl_h1_req_parse_read(&h1, buf, len, NULL, 0, err);
+ if(nwritten < 0)
+ goto out;
+ DEBUGASSERT(h1.done);
+ DEBUGASSERT(h1.req);
+
+ *err = Curl_http_req_to_h2(&h2_headers, h1.req, data);
+ if(*err) {
+ nwritten = -1;
+ goto out;
+ }
+
+ nheader = Curl_dynhds_count(&h2_headers);
+ nva = malloc(sizeof(nghttp3_nv) * nheader);
+ if(!nva) {
+ *err = CURLE_OUT_OF_MEMORY;
+ nwritten = -1;
+ goto out;
+ }
+
+ for(i = 0; i < nheader; ++i) {
+ struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
+ nva[i].name = (unsigned char *)e->name;
+ nva[i].namelen = e->namelen;
+ nva[i].value = (unsigned char *)e->value;
+ nva[i].valuelen = e->valuelen;
+ nva[i].flags = NGHTTP3_NV_FLAG_NONE;
+ }
+
+ switch(data->state.httpreq) {
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ case HTTPREQ_POST_MIME:
+ case HTTPREQ_PUT:
+ /* known request body size or -1 */
+ if(data->state.infilesize != -1)
+ stream->upload_left = data->state.infilesize;
+ else
+ /* data sending without specifying the data amount up front */
+ stream->upload_left = -1; /* unknown */
+ break;
+ default:
+ /* there is not request body */
+ stream->upload_left = 0; /* no request body */
+ break;
+ }
+
+ stream->send_closed = (stream->upload_left == 0);
+ if(!stream->send_closed) {
+ reader.read_data = cb_h3_read_req_body;
+ preader = &reader;
+ }
+
+ rc = nghttp3_conn_submit_request(ctx->h3conn, stream->id,
+ nva, nheader, preader, data);
+ if(rc) {
+ switch(rc) {
+ case NGHTTP3_ERR_CONN_CLOSING:
+ DEBUGF(LOG_CF(data, cf, "h3sid[%"PRId64"] failed to send, "
+ "connection is closing", stream->id));
+ break;
+ default:
+ DEBUGF(LOG_CF(data, cf, "h3sid[%"PRId64"] failed to send -> %d (%s)",
+ stream->id, rc, ngtcp2_strerror(rc)));
+ break;
+ }
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ goto out;
+ }
+
+ infof(data, "Using HTTP/3 Stream ID: %" PRId64, stream->id);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] opened for %s",
+ stream->id, data->state.url));
+
+out:
+ free(nva);
+ Curl_h1_req_parse_free(&h1);
+ Curl_dynhds_free(&h2_headers);
+ return nwritten;
+}
+
+static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ ssize_t sent = 0;
+ struct cf_call_data save;
+ struct pkt_io_ctx pktx;
+ CURLcode result;
+
+ CF_DATA_SAVE(save, cf, data);
+ DEBUGASSERT(cf->connected);
+ DEBUGASSERT(ctx->qconn);
+ DEBUGASSERT(ctx->h3conn);
+ pktx_init(&pktx, cf, data);
+ *err = CURLE_OK;
+
+ result = cf_progress_ingress(cf, data, &pktx);
+ if(result) {
+ *err = result;
+ sent = -1;
+ }
+
+ if(!stream || stream->id < 0) {
+ sent = h3_stream_open(cf, data, buf, len, err);
+ if(sent < 0) {
+ DEBUGF(LOG_CF(data, cf, "failed to open stream -> %d", *err));
+ goto out;
+ }
+ }
+ else if(stream->upload_blocked_len) {
+ /* the data in `buf` has alread been submitted or added to the
+ * buffers, but have been EAGAINed on the last invocation. */
+ DEBUGASSERT(len >= stream->upload_blocked_len);
+ if(len < stream->upload_blocked_len) {
+ /* Did we get called again with a smaller `len`? This should not
+ * happen. We are not prepared to handle that. */
+ failf(data, "HTTP/3 send again with decreased length");
+ *err = CURLE_HTTP3;
+ sent = -1;
+ goto out;
+ }
+ sent = (ssize_t)stream->upload_blocked_len;
+ stream->upload_blocked_len = 0;
+ }
+ else if(stream->closed) {
+ *err = CURLE_HTTP3;
+ sent = -1;
+ goto out;
+ }
+ else {
+ sent = Curl_bufq_write(&stream->sendbuf, buf, len, err);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_send, add to "
+ "sendbuf(len=%zu) -> %zd, %d",
+ stream->id, len, sent, *err));
+ if(sent < 0) {
+ goto out;
+ }
+
+ (void)nghttp3_conn_resume_stream(ctx->h3conn, stream->id);
+ }
+
+ result = cf_progress_egress(cf, data, &pktx);
+ if(result) {
+ *err = result;
+ sent = -1;
+ }
+
+ if(stream && sent > 0 && stream->sendbuf_len_in_flight) {
+ /* We have unacknowledged DATA and cannot report success to our
+ * caller. Instead we EAGAIN and remember how much we have already
+ * "written" into our various internal connection buffers.
+ * We put the stream upload on HOLD, until this gets ACKed. */
+ stream->upload_blocked_len = sent;
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_send(len=%zu), "
+ "%zu bytes in flight -> EGAIN", stream->id, len,
+ stream->sendbuf_len_in_flight));
+ *err = CURLE_AGAIN;
+ sent = -1;
+ data->req.keepon |= KEEP_SEND_HOLD;
+ }
+
+out:
+ result = check_and_set_expiry(cf, data, &pktx);
+ if(result) {
+ *err = result;
+ sent = -1;
+ }
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_send(len=%zu) -> %zd, %d",
+ stream? stream->id : -1, len, sent, *err));
+ CF_DATA_RESTORE(cf, save);
+ return sent;
+}
+
+static CURLcode qng_verify_peer(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+ const char *hostname, *disp_hostname;
+ int port;
+ char *snihost;
+
+ Curl_conn_get_host(data, cf->sockindex, &hostname, &disp_hostname, &port);
+ snihost = Curl_ssl_snihost(data, hostname, NULL);
+ if(!snihost)
+ return CURLE_PEER_FAILED_VERIFICATION;
+
+ cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+ cf->conn->httpversion = 30;
+ cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+
+ if(cf->conn->ssl_config.verifyhost) {
+#ifdef USE_OPENSSL
+ X509 *server_cert;
+ server_cert = SSL_get_peer_certificate(ctx->ssl);
+ if(!server_cert) {
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ result = Curl_ossl_verifyhost(data, cf->conn, server_cert);
+ X509_free(server_cert);
+ if(result)
+ return result;
+#elif defined(USE_GNUTLS)
+ result = Curl_gtls_verifyserver(data, ctx->gtls->session,
+ &cf->conn->ssl_config, &data->set.ssl,
+ hostname, disp_hostname,
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
+ if(result)
+ return result;
+#elif defined(USE_WOLFSSL)
+ if(wolfSSL_check_domain_name(ctx->ssl, snihost) == SSL_FAILURE)
+ return CURLE_PEER_FAILED_VERIFICATION;
+#endif
+ infof(data, "Verified certificate just fine");
+ }
+ else
+ infof(data, "Skipped certificate verification");
+#ifdef USE_OPENSSL
+ if(data->set.ssl.certinfo)
+ /* asked to gather certificate info */
+ (void)Curl_ossl_certchain(data, ctx->ssl);
+#endif
+ return result;
+}
+
+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 pkt_io_ctx *pktx = userp;
+ struct cf_ngtcp2_ctx *ctx = pktx->cf->ctx;
+ ngtcp2_pkt_info pi;
+ ngtcp2_path path;
+ int rv;
+
+ ++pktx->pkt_count;
+ ngtcp2_addr_init(&path.local, (struct sockaddr *)&ctx->q.local_addr,
+ ctx->q.local_addrlen);
+ ngtcp2_addr_init(&path.remote, (struct sockaddr *)remote_addr,
+ remote_addrlen);
+ pi.ecn = (uint32_t)ecn;
+
+ rv = ngtcp2_conn_read_pkt(ctx->qconn, &path, &pi, pkt, pktlen, pktx->ts);
+ if(rv) {
+ DEBUGF(LOG_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s",
+ ngtcp2_strerror(rv)));
+ if(!ctx->last_error.error_code) {
+ if(rv == NGTCP2_ERR_CRYPTO) {
+ ngtcp2_ccerr_set_tls_alert(&ctx->last_error,
+ ngtcp2_conn_get_tls_alert(ctx->qconn),
+ NULL, 0);
+ }
+ else {
+ ngtcp2_ccerr_set_liberr(&ctx->last_error, rv, NULL, 0);
+ }
+ }
+
+ 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;
+}
+
+static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct pkt_io_ctx local_pktx;
+ size_t pkts_chunk = 128, i;
+ size_t pkts_max = 10 * pkts_chunk;
+ CURLcode result = CURLE_OK;
+
+ if(!pktx) {
+ pktx_init(&local_pktx, cf, data);
+ pktx = &local_pktx;
+ }
+ else {
+ pktx->ts = timestamp();
+ }
+
+ for(i = 0; i < pkts_max; i += pkts_chunk) {
+ pktx->pkt_count = 0;
+ result = vquic_recv_packets(cf, data, &ctx->q, pkts_chunk,
+ recv_pkt, pktx);
+ if(result) /* error */
+ break;
+ if(pktx->pkt_count < pkts_chunk) /* got less than we could */
+ break;
+ /* give egress a chance before we receive more */
+ result = cf_progress_egress(cf, data, pktx);
+ if(result) /* error */
+ break;
+ }
+ return result;
+}
+
+/**
+ * Read a network packet to send from ngtcp2 into `buf`.
+ * Return number of bytes written or -1 with *err set.
+ */
+static ssize_t read_pkt_to_send(void *userp,
+ unsigned char *buf, size_t buflen,
+ CURLcode *err)
+{
+ struct pkt_io_ctx *x = userp;
+ struct cf_ngtcp2_ctx *ctx = x->cf->ctx;
+ nghttp3_vec vec[16];
+ nghttp3_ssize veccnt;
+ ngtcp2_ssize ndatalen;
+ uint32_t flags;
+ int64_t stream_id;
+ int fin;
+ ssize_t nwritten, n;
+ veccnt = 0;
+ stream_id = -1;
+ fin = 0;
+
+ /* ngtcp2 may want to put several frames from different streams into
+ * this packet. `NGTCP2_WRITE_STREAM_FLAG_MORE` tells it to do so.
+ * When `NGTCP2_ERR_WRITE_MORE` is returned, we *need* to make
+ * another iteration.
+ * When ngtcp2 is happy (because it has no other frame that would fit
+ * or it has nothing more to send), it returns the total length
+ * of the assembled packet. This may be 0 if there was nothing to send. */
+ nwritten = 0;
+ *err = CURLE_OK;
+ for(;;) {
+
+ if(ctx->h3conn && ngtcp2_conn_get_max_data_left(ctx->qconn)) {
+ veccnt = nghttp3_conn_writev_stream(ctx->h3conn, &stream_id, &fin, vec,
+ sizeof(vec) / sizeof(vec[0]));
+ if(veccnt < 0) {
+ failf(x->data, "nghttp3_conn_writev_stream returned error: %s",
+ nghttp3_strerror((int)veccnt));
+ ngtcp2_ccerr_set_application_error(
+ &ctx->last_error,
+ nghttp3_err_infer_quic_app_error_code((int)veccnt), NULL, 0);
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+ }
+
+ flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
+ (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
+ n = ngtcp2_conn_writev_stream(ctx->qconn, &x->ps.path,
+ NULL, buf, buflen,
+ &ndatalen, flags, stream_id,
+ (const ngtcp2_vec *)vec, veccnt, x->ts);
+ if(n == 0) {
+ /* nothing to send */
+ *err = CURLE_AGAIN;
+ nwritten = -1;
+ goto out;
+ }
+ else if(n < 0) {
+ switch(n) {
+ case NGTCP2_ERR_STREAM_DATA_BLOCKED:
+ DEBUGASSERT(ndatalen == -1);
+ nghttp3_conn_block_stream(ctx->h3conn, stream_id);
+ n = 0;
+ break;
+ case NGTCP2_ERR_STREAM_SHUT_WR:
+ DEBUGASSERT(ndatalen == -1);
+ nghttp3_conn_shutdown_stream_write(ctx->h3conn, stream_id);
+ n = 0;
+ break;
+ case NGTCP2_ERR_WRITE_MORE:
+ /* ngtcp2 wants to send more. update the flow of the stream whose data
+ * is in the buffer and continue */
+ DEBUGASSERT(ndatalen >= 0);
+ n = 0;
+ break;
+ default:
+ DEBUGASSERT(ndatalen == -1);
+ failf(x->data, "ngtcp2_conn_writev_stream returned error: %s",
+ ngtcp2_strerror((int)n));
+ ngtcp2_ccerr_set_liberr(&ctx->last_error, (int)n, NULL, 0);
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ goto out;
+ }
+ }
+
+ if(ndatalen >= 0) {
+ /* 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",
+ nghttp3_strerror(rv));
+ return CURLE_SEND_ERROR;
+ }
+ }
+
+ if(n > 0) {
+ /* packet assembled, leave */
+ nwritten = n;
+ goto out;
+ }
+ }
+out:
+ return nwritten;
+}
+
+static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ ssize_t nread;
+ size_t max_payload_size, path_max_payload_size, max_pktcnt;
+ size_t pktcnt = 0;
+ size_t gsolen = 0; /* this disables gso until we have a clue */
+ CURLcode curlcode;
+ struct pkt_io_ctx local_pktx;
+
+ if(!pktx) {
+ pktx_init(&local_pktx, cf, data);
+ pktx = &local_pktx;
+ }
+ else {
+ pktx->ts = timestamp();
+ ngtcp2_path_storage_zero(&pktx->ps);
+ }
+
+ curlcode = vquic_flush(cf, data, &ctx->q);
+ if(curlcode) {
+ if(curlcode == CURLE_AGAIN) {
+ Curl_expire(data, 1, EXPIRE_QUIC);
+ return CURLE_OK;
+ }
+ return curlcode;
+ }
+
+ /* In UDP, there is a maximum theoretical packet paload length and
+ * a minimum payload length that is "guarantueed" to work.
+ * To detect if this minimum payload can be increased, ngtcp2 sends
+ * now and then a packet payload larger than the minimum. It that
+ * is ACKed by the peer, both parties know that it works and
+ * the subsequent packets can use a larger one.
+ * This is called PMTUD (Path Maximum Transmission Unit Discovery).
+ * Since a PMTUD might be rejected right on send, we do not want it
+ * be followed by other packets of lesser size. Because those would
+ * also fail then. So, if we detect a PMTUD while buffering, we flush.
+ */
+ 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);
+ /* maximum number of packets buffered before we flush to the socket */
+ max_pktcnt = CURLMIN(MAX_PKT_BURST,
+ ctx->q.sendbuf.chunk_size / max_payload_size);
+
+ for(;;) {
+ /* add the next packet to send, if any, to our buffer */
+ nread = Curl_bufq_sipn(&ctx->q.sendbuf, max_payload_size,
+ read_pkt_to_send, pktx, &curlcode);
+ /* DEBUGF(LOG_CF(data, cf, "sip packet(maxlen=%zu) -> %zd, %d",
+ max_payload_size, nread, curlcode)); */
+ if(nread < 0) {
+ if(curlcode != CURLE_AGAIN)
+ return curlcode;
+ /* Nothing more to add, flush and leave */
+ curlcode = vquic_send(cf, data, &ctx->q, gsolen);
+ if(curlcode) {
+ if(curlcode == CURLE_AGAIN) {
+ Curl_expire(data, 1, EXPIRE_QUIC);
+ return CURLE_OK;
+ }
+ return curlcode;
+ }
+ goto out;
+ }
+
+ DEBUGASSERT(nread > 0);
+ if(pktcnt == 0) {
+ /* first packet in buffer. This is either of a known, "good"
+ * payload size or it is a PMTUD. We'll see. */
+ gsolen = (size_t)nread;
+ }
+ else if((size_t)nread > gsolen ||
+ (gsolen > path_max_payload_size && (size_t)nread != gsolen)) {
+ /* The just added packet is a PMTUD *or* the one(s) before the
+ * just added were PMTUD and the last one is smaller.
+ * Flush the buffer before the last add. */
+ curlcode = vquic_send_tail_split(cf, data, &ctx->q,
+ gsolen, nread, nread);
+ if(curlcode) {
+ if(curlcode == CURLE_AGAIN) {
+ Curl_expire(data, 1, EXPIRE_QUIC);
+ return CURLE_OK;
+ }
+ return curlcode;
+ }
+ pktcnt = 0;
+ continue;
+ }
+
+ if(++pktcnt >= max_pktcnt || (size_t)nread < gsolen) {
+ /* Reached MAX_PKT_BURST *or*
+ * the capacity of our buffer *or*
+ * last add was shorter than the previous ones, flush */
+ curlcode = vquic_send(cf, data, &ctx->q, gsolen);
+ if(curlcode) {
+ if(curlcode == CURLE_AGAIN) {
+ Curl_expire(data, 1, EXPIRE_QUIC);
+ return CURLE_OK;
+ }
+ return curlcode;
+ }
+ /* pktbuf has been completely sent */
+ pktcnt = 0;
+ }
+ }
+
+out:
+ return CURLE_OK;
+}
+
+/*
+ * Called from transfer.c:data_pending to know if we should keep looping
+ * to receive more data from the connection.
+ */
+static bool cf_ngtcp2_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ const struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ (void)cf;
+ return stream && !Curl_bufq_is_empty(&stream->recvbuf);
+}
+
+static CURLcode h3_data_pause(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool pause)
+{
+ /* TODO: there seems right now no API in ngtcp2 to shrink/enlarge
+ * the streams windows. As we do in HTTP/2. */
+ if(!pause) {
+ h3_drain_stream(cf, data);
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ (void)arg1;
+ (void)arg2;
+ switch(event) {
+ case CF_CTRL_DATA_SETUP:
+ break;
+ case CF_CTRL_DATA_PAUSE:
+ result = h3_data_pause(cf, data, (arg1 != 0));
+ break;
+ case CF_CTRL_DATA_DONE: {
+ h3_data_done(cf, data);
+ break;
+ }
+ case CF_CTRL_DATA_DONE_SEND: {
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ if(stream && !stream->send_closed) {
+ stream->send_closed = TRUE;
+ stream->upload_left = Curl_bufq_len(&stream->sendbuf);
+ (void)nghttp3_conn_resume_stream(ctx->h3conn, stream->id);
+ }
+ break;
+ }
+ case CF_CTRL_DATA_IDLE:
+ result = check_and_set_expiry(cf, data, NULL);
+ break;
+ default:
+ break;
+ }
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static void cf_ngtcp2_ctx_clear(struct cf_ngtcp2_ctx *ctx)
+{
+ struct cf_call_data save = ctx->call_data;
+
+ if(ctx->qlogfd != -1) {
+ close(ctx->qlogfd);
+ }
+#ifdef USE_OPENSSL
+ if(ctx->ssl)
+ SSL_free(ctx->ssl);
+ if(ctx->sslctx)
+ SSL_CTX_free(ctx->sslctx);
+#elif defined(USE_GNUTLS)
+ if(ctx->gtls) {
+ if(ctx->gtls->cred)
+ gnutls_certificate_free_credentials(ctx->gtls->cred);
+ if(ctx->gtls->session)
+ gnutls_deinit(ctx->gtls->session);
+ free(ctx->gtls);
+ }
+#elif defined(USE_WOLFSSL)
+ if(ctx->ssl)
+ wolfSSL_free(ctx->ssl);
+ if(ctx->sslctx)
+ wolfSSL_CTX_free(ctx->sslctx);
+#endif
+ vquic_ctx_free(&ctx->q);
+ if(ctx->h3conn)
+ nghttp3_conn_del(ctx->h3conn);
+ if(ctx->qconn)
+ ngtcp2_conn_del(ctx->qconn);
+ Curl_bufcp_free(&ctx->stream_bufcp);
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->qlogfd = -1;
+ ctx->call_data = save;
+}
+
+static void cf_ngtcp2_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ if(ctx && ctx->qconn) {
+ char buffer[NGTCP2_MAX_UDP_PAYLOAD_SIZE];
+ ngtcp2_tstamp ts;
+ ngtcp2_ssize rc;
+
+ DEBUGF(LOG_CF(data, cf, "close"));
+ ts = timestamp();
+ rc = ngtcp2_conn_write_connection_close(ctx->qconn, NULL, /* path */
+ NULL, /* pkt_info */
+ (uint8_t *)buffer, sizeof(buffer),
+ &ctx->last_error, ts);
+ if(rc > 0) {
+ while((send(ctx->q.sockfd, buffer, (SEND_TYPE_ARG3)rc, 0) == -1) &&
+ SOCKERRNO == EINTR);
+ }
+
+ cf_ngtcp2_ctx_clear(ctx);
+ }
+
+ cf->connected = FALSE;
+ CF_DATA_RESTORE(cf, save);
+}
+
+static void cf_ngtcp2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ DEBUGF(LOG_CF(data, cf, "destroy"));
+ if(ctx) {
+ cf_ngtcp2_ctx_clear(ctx);
+ free(ctx);
+ }
+ cf->ctx = NULL;
+ /* No CF_DATA_RESTORE(cf, save) possible */
+ (void)save;
+}
+
+/*
+ * Might be called twice for happy eyeballs.
+ */
+static CURLcode cf_connect_start(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ int rc;
+ int rv;
+ CURLcode result;
+ const struct Curl_sockaddr_ex *sockaddr;
+ int qfd;
+
+ 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);
+
+#ifdef USE_OPENSSL
+ result = quic_ssl_ctx(&ctx->sslctx, cf, data);
+ if(result)
+ return result;
+
+ result = quic_set_client_cert(cf, data);
+ if(result)
+ return result;
+#elif defined(USE_WOLFSSL)
+ result = quic_ssl_ctx(&ctx->sslctx, cf, data);
+ if(result)
+ return result;
+#endif
+
+ result = quic_init_ssl(cf, data);
+ if(result)
+ return result;
+
+ ctx->dcid.datalen = NGTCP2_MAX_CIDLEN;
+ result = Curl_rand(data, ctx->dcid.data, NGTCP2_MAX_CIDLEN);
+ if(result)
+ return result;
+
+ ctx->scid.datalen = NGTCP2_MAX_CIDLEN;
+ result = Curl_rand(data, ctx->scid.data, NGTCP2_MAX_CIDLEN);
+ if(result)
+ return result;
+
+ (void)Curl_qlogdir(data, ctx->scid.data, NGTCP2_MAX_CIDLEN, &qfd);
+ ctx->qlogfd = qfd; /* -1 if failure above */
+ quic_settings(ctx, data, pktx);
+
+ result = vquic_ctx_init(&ctx->q);
+ if(result)
+ return result;
+
+ Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd,
+ &sockaddr, NULL, NULL, NULL, NULL);
+ ctx->q.local_addrlen = sizeof(ctx->q.local_addr);
+ rv = getsockname(ctx->q.sockfd, (struct sockaddr *)&ctx->q.local_addr,
+ &ctx->q.local_addrlen);
+ if(rv == -1)
+ return CURLE_QUIC_CONNECT_ERROR;
+
+ ngtcp2_addr_init(&ctx->connected_path.local,
+ (struct sockaddr *)&ctx->q.local_addr,
+ ctx->q.local_addrlen);
+ ngtcp2_addr_init(&ctx->connected_path.remote,
+ &sockaddr->sa_addr, sockaddr->addrlen);
+
+ rc = ngtcp2_conn_client_new(&ctx->qconn, &ctx->dcid, &ctx->scid,
+ &ctx->connected_path,
+ NGTCP2_PROTO_VER_V1, &ng_callbacks,
+ &ctx->settings, &ctx->transport_params,
+ NULL, cf);
+ if(rc)
+ return CURLE_QUIC_CONNECT_ERROR;
+
+#ifdef USE_GNUTLS
+ ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->gtls->session);
+#else
+ ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->ssl);
+#endif
+
+ ngtcp2_ccerr_default(&ctx->last_error);
+
+ ctx->conn_ref.get_conn = get_conn;
+ ctx->conn_ref.user_data = cf;
+
+ return CURLE_OK;
+}
+
+static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ 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) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ /* Connect the UDP filter first */
+ if(!cf->next->connected) {
+ result = Curl_conn_cf_connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ return result;
+ }
+
+ *done = FALSE;
+ now = Curl_now();
+ pktx_init(&pktx, cf, data);
+
+ CF_DATA_SAVE(save, cf, data);
+
+ if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) {
+ /* Not time yet to attempt the next connect */
+ DEBUGF(LOG_CF(data, cf, "waiting for reconnect time"));
+ goto out;
+ }
+
+ if(!ctx->qconn) {
+ ctx->started_at = now;
+ result = cf_connect_start(cf, data, &pktx);
+ if(result)
+ goto out;
+ result = cf_progress_egress(cf, data, &pktx);
+ /* we do not expect to be able to recv anything yet */
+ goto out;
+ }
+
+ result = cf_progress_ingress(cf, data, &pktx);
+ if(result)
+ goto out;
+
+ result = cf_progress_egress(cf, data, &pktx);
+ if(result)
+ goto out;
+
+ if(ngtcp2_conn_get_handshake_completed(ctx->qconn)) {
+ ctx->handshake_at = now;
+ DEBUGF(LOG_CF(data, cf, "handshake complete after %dms",
+ (int)Curl_timediff(now, ctx->started_at)));
+ result = qng_verify_peer(cf, data);
+ if(!result) {
+ DEBUGF(LOG_CF(data, cf, "peer verified"));
+ cf->connected = TRUE;
+ cf->conn->alpn = CURL_HTTP_VERSION_3;
+ *done = TRUE;
+ connkeep(cf->conn, "HTTP/3 default");
+ }
+ }
+
+out:
+ if(result == CURLE_RECV_ERROR && ctx->qconn &&
+ ngtcp2_conn_in_draining_period(ctx->qconn)) {
+ /* When a QUIC server instance is shutting down, it may send us a
+ * CONNECTION_CLOSE right away. Our connection then enters the DRAINING
+ * state.
+ * This may be a stopping of the service or it may be that the server
+ * is reloading and a new instance will start serving soon.
+ * In any case, we tear down our socket and start over with a new one.
+ * We re-open the underlying UDP cf right now, but do not start
+ * connecting until called again.
+ */
+ int reconn_delay_ms = 200;
+
+ DEBUGF(LOG_CF(data, cf, "connect, remote closed, reconnect after %dms",
+ reconn_delay_ms));
+ Curl_conn_cf_close(cf->next, data);
+ cf_ngtcp2_ctx_clear(ctx);
+ result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
+ if(!result && *done) {
+ *done = FALSE;
+ ctx->reconnect_at = now;
+ ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000;
+ Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC);
+ result = CURLE_OK;
+ }
+ }
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ if(result) {
+ const char *r_ip;
+ int r_port;
+
+ Curl_cf_socket_peek(cf->next, data, NULL, NULL,
+ &r_ip, &r_port, NULL, NULL);
+ infof(data, "QUIC connect to %s port %u failed: %s",
+ r_ip, r_port, curl_easy_strerror(result));
+ }
+#endif
+ if(!result && ctx->qconn) {
+ result = check_and_set_expiry(cf, data, &pktx);
+ }
+ DEBUGF(LOG_CF(data, cf, "connect -> %d, done=%d", result, *done));
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query, int *pres1, void *pres2)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct cf_call_data save;
+
+ switch(query) {
+ case CF_QUERY_MAX_CONCURRENT: {
+ const ngtcp2_transport_params *rp;
+ DEBUGASSERT(pres1);
+
+ CF_DATA_SAVE(save, cf, data);
+ rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn);
+ if(rp)
+ *pres1 = (rp->initial_max_streams_bidi > INT_MAX)?
+ INT_MAX : (int)rp->initial_max_streams_bidi;
+ else /* not arrived yet? */
+ *pres1 = Curl_multi_max_concurrent_streams(data->multi);
+ DEBUGF(LOG_CF(data, cf, "query max_conncurrent -> %d", *pres1));
+ CF_DATA_RESTORE(cf, save);
+ return CURLE_OK;
+ }
+ case CF_QUERY_CONNECT_REPLY_MS:
+ if(ctx->got_first_byte) {
+ timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
+ *pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
+ }
+ else
+ *pres1 = -1;
+ return CURLE_OK;
+ case CF_QUERY_TIMER_CONNECT: {
+ struct curltime *when = pres2;
+ if(ctx->got_first_byte)
+ *when = ctx->first_byte_at;
+ return CURLE_OK;
+ }
+ case CF_QUERY_TIMER_APPCONNECT: {
+ struct curltime *when = pres2;
+ if(cf->connected)
+ *when = ctx->handshake_at;
+ return CURLE_OK;
+ }
+ default:
+ break;
+ }
+ return cf->next?
+ cf->next->cft->query(cf->next, data, query, pres1, pres2) :
+ CURLE_UNKNOWN_OPTION;
+}
+
+static bool cf_ngtcp2_conn_is_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending)
+{
+ bool alive = TRUE;
+
+ *input_pending = FALSE;
+ if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
+ return FALSE;
+
+ if(*input_pending) {
+ /* This happens before we've sent off a request and the connection is
+ not in use by any other transfer, there shouldn't be any data here,
+ only "protocol frames" */
+ *input_pending = FALSE;
+ if(cf_progress_ingress(cf, data, NULL))
+ alive = FALSE;
+ else {
+ alive = TRUE;
+ }
+ }
+
+ return alive;
+}
+
+struct Curl_cftype Curl_cft_http3 = {
+ "HTTP/3",
+ CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
+ 0,
+ cf_ngtcp2_destroy,
+ cf_ngtcp2_connect,
+ cf_ngtcp2_close,
+ Curl_cf_def_get_host,
+ cf_ngtcp2_get_select_socks,
+ cf_ngtcp2_data_pending,
+ cf_ngtcp2_send,
+ cf_ngtcp2_recv,
+ cf_ngtcp2_data_event,
+ cf_ngtcp2_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ cf_ngtcp2_query,
+};
+
+CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai)
+{
+ struct cf_ngtcp2_ctx *ctx = NULL;
+ struct Curl_cfilter *cf = NULL, *udp_cf = NULL;
+ CURLcode result;
+
+ (void)data;
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ ctx->qlogfd = -1;
+ cf_ngtcp2_ctx_clear(ctx);
+
+ result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
+ if(result)
+ goto out;
+
+ result = Curl_cf_udp_create(&udp_cf, data, conn, ai, TRNSPRT_QUIC);
+ if(result)
+ goto out;
+
+ cf->conn = conn;
+ udp_cf->conn = cf->conn;
+ udp_cf->sockindex = cf->sockindex;
+ cf->next = udp_cf;
+
+out:
+ *pcf = (!result)? cf : NULL;
+ if(result) {
+ if(udp_cf)
+ Curl_conn_cf_discard_sub(cf, udp_cf, data, TRUE);
+ Curl_safefree(cf);
+ Curl_safefree(ctx);
+ }
+ return result;
+}
+
+bool Curl_conn_is_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
new file mode 100644
index 0000000..db3e611
--- /dev/null
+++ b/lib/vquic/curl_ngtcp2.h
@@ -0,0 +1,61 @@
+#ifndef HEADER_CURL_VQUIC_CURL_NGTCP2_H
+#define HEADER_CURL_VQUIC_CURL_NGTCP2_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
+
+#ifdef HAVE_NETINET_UDP_H
+#include <netinet/udp.h>
+#endif
+
+#include <ngtcp2/ngtcp2_crypto.h>
+#include <nghttp3/nghttp3.h>
+#ifdef USE_OPENSSL
+#include <openssl/ssl.h>
+#elif defined(USE_WOLFSSL)
+#include <wolfssl/options.h>
+#include <wolfssl/ssl.h>
+#include <wolfssl/quic.h>
+#endif
+
+struct Curl_cfilter;
+
+#include "urldata.h"
+
+void Curl_ngtcp2_ver(char *p, size_t len);
+
+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_quiche.c b/lib/vquic/curl_quiche.c
new file mode 100644
index 0000000..39cc16e
--- /dev/null
+++ b/lib/vquic/curl_quiche.c
@@ -0,0 +1,1637 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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"
+
+#ifdef USE_QUICHE
+#include <quiche.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include "bufq.h"
+#include "urldata.h"
+#include "cfilters.h"
+#include "cf-socket.h"
+#include "sendf.h"
+#include "strdup.h"
+#include "rand.h"
+#include "strcase.h"
+#include "multiif.h"
+#include "connect.h"
+#include "progress.h"
+#include "strerror.h"
+#include "http1.h"
+#include "vquic.h"
+#include "vquic_int.h"
+#include "curl_quiche.h"
+#include "transfer.h"
+#include "vtls/openssl.h"
+#include "vtls/keylog.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* #define DEBUG_QUICHE */
+
+#define QUIC_MAX_STREAMS (100)
+#define QUIC_IDLE_TIMEOUT (5 * 1000) /* milliseconds */
+
+#define H3_STREAM_WINDOW_SIZE (128 * 1024)
+#define H3_STREAM_CHUNK_SIZE (16 * 1024)
+/* The pool keeps spares around and half of a full stream windows
+ * seems good. More does not seem to improve performance.
+ * The benefit of the pool is that stream buffer to not keep
+ * spares. So memory consumption goes down when streams run empty,
+ * have a large upload done, etc. */
+#define H3_STREAM_POOL_SPARES \
+ (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE ) / 2
+/* Receive and Send max number of chunks just follows from the
+ * chunk size and window size */
+#define H3_STREAM_RECV_CHUNKS \
+ (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
+#define H3_STREAM_SEND_CHUNKS \
+ (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
+
+/*
+ * Store quiche version info in this buffer.
+ */
+void Curl_quiche_ver(char *p, size_t len)
+{
+ (void)msnprintf(p, len, "quiche/%s", quiche_version());
+}
+
+static void keylog_callback(const SSL *ssl, const char *line)
+{
+ (void)ssl;
+ Curl_tls_keylog_write_line(line);
+}
+
+static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
+{
+ SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
+
+ SSL_CTX_set_alpn_protos(ssl_ctx,
+ (const uint8_t *)QUICHE_H3_APPLICATION_PROTOCOL,
+ sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1);
+
+ SSL_CTX_set_default_verify_paths(ssl_ctx);
+
+ /* Open the file if a TLS or QUIC backend has not done this before. */
+ Curl_tls_keylog_open();
+ if(Curl_tls_keylog_enabled()) {
+ SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
+ }
+
+ {
+ struct connectdata *conn = data->conn;
+ if(conn->ssl_config.verifypeer) {
+ const char * const ssl_cafile = conn->ssl_config.CAfile;
+ const char * const ssl_capath = conn->ssl_config.CApath;
+ if(ssl_cafile || ssl_capath) {
+ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
+ /* tell OpenSSL where to find CA certificates that are used to verify
+ the server's certificate. */
+ if(!SSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ return NULL;
+ }
+ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+ }
+#ifdef CURL_CA_FALLBACK
+ else {
+ /* verifying the peer without any CA certificates won't work so
+ use openssl's built-in default as fallback */
+ SSL_CTX_set_default_verify_paths(ssl_ctx);
+ }
+#endif
+ }
+ }
+ return ssl_ctx;
+}
+
+struct cf_quiche_ctx {
+ struct cf_quic_ctx q;
+ quiche_conn *qconn;
+ quiche_config *cfg;
+ quiche_h3_conn *h3c;
+ quiche_h3_config *h3config;
+ uint8_t scid[QUICHE_MAX_CONN_ID_LEN];
+ SSL_CTX *sslctx;
+ SSL *ssl;
+ struct curltime started_at; /* time the current attempt started */
+ struct curltime handshake_at; /* time connect handshake finished */
+ struct curltime first_byte_at; /* when first byte was recvd */
+ struct curltime reconnect_at; /* time the next attempt should start */
+ struct bufc_pool stream_bufcp; /* chunk pool for streams */
+ curl_off_t data_recvd;
+ size_t sends_on_hold; /* # of streams with SEND_HOLD set */
+ BIT(goaway); /* got GOAWAY from server */
+ BIT(got_first_byte); /* if first byte was received */
+};
+
+#ifdef DEBUG_QUICHE
+static void quiche_debug_log(const char *line, void *argp)
+{
+ (void)argp;
+ fprintf(stderr, "%s\n", line);
+}
+#endif
+
+static void cf_quiche_ctx_clear(struct cf_quiche_ctx *ctx)
+{
+ if(ctx) {
+ vquic_ctx_free(&ctx->q);
+ if(ctx->qconn)
+ quiche_conn_free(ctx->qconn);
+ if(ctx->h3config)
+ quiche_h3_config_free(ctx->h3config);
+ if(ctx->h3c)
+ quiche_h3_conn_free(ctx->h3c);
+ if(ctx->cfg)
+ quiche_config_free(ctx->cfg);
+ Curl_bufcp_free(&ctx->stream_bufcp);
+ memset(ctx, 0, sizeof(*ctx));
+ }
+}
+
+/**
+ * All about the H3 internals of a stream
+ */
+struct stream_ctx {
+ int64_t id; /* HTTP/3 protocol stream identifier */
+ struct bufq recvbuf; /* h3 response */
+ uint64_t error3; /* HTTP/3 stream error code */
+ curl_off_t upload_left; /* number of request bytes left to upload */
+ bool closed; /* TRUE on stream close */
+ bool reset; /* TRUE on stream reset */
+ bool send_closed; /* stream is locally closed */
+ bool resp_hds_complete; /* complete, final response has been received */
+ bool resp_got_header; /* TRUE when h3 stream has recvd some HEADER */
+};
+
+#define H3_STREAM_CTX(d) ((struct stream_ctx *)(((d) && (d)->req.p.http)? \
+ ((struct HTTP *)(d)->req.p.http)->h3_ctx \
+ : NULL))
+#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h3_ctx
+#define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \
+ H3_STREAM_CTX(d)->id : -2)
+
+static bool stream_send_is_suspended(struct Curl_easy *data)
+{
+ return (data->req.keepon & KEEP_SEND_HOLD);
+}
+
+static void stream_send_suspend(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+
+ if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) {
+ data->req.keepon |= KEEP_SEND_HOLD;
+ ++ctx->sends_on_hold;
+ if(H3_STREAM_ID(data) >= 0)
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] suspend sending",
+ H3_STREAM_ID(data)));
+ else
+ DEBUGF(LOG_CF(data, cf, "[%s] suspend sending",
+ data->state.url));
+ }
+}
+
+static void stream_send_resume(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+
+ if(stream_send_is_suspended(data)) {
+ data->req.keepon &= ~KEEP_SEND_HOLD;
+ --ctx->sends_on_hold;
+ if(H3_STREAM_ID(data) >= 0)
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] resume sending",
+ H3_STREAM_ID(data)));
+ else
+ DEBUGF(LOG_CF(data, cf, "[%s] resume sending",
+ data->state.url));
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+}
+
+static void check_resumes(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ struct Curl_easy *sdata;
+
+ if(ctx->sends_on_hold) {
+ DEBUGASSERT(data->multi);
+ for(sdata = data->multi->easyp;
+ sdata && ctx->sends_on_hold; sdata = sdata->next) {
+ if(stream_send_is_suspended(sdata)) {
+ stream_send_resume(cf, sdata);
+ }
+ }
+ }
+}
+
+static CURLcode h3_data_setup(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+
+ if(stream)
+ return CURLE_OK;
+
+ stream = calloc(1, sizeof(*stream));
+ if(!stream)
+ return CURLE_OUT_OF_MEMORY;
+
+ H3_STREAM_LCTX(data) = stream;
+ stream->id = -1;
+ Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
+ H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
+ DEBUGF(LOG_CF(data, cf, "data setup"));
+ return CURLE_OK;
+}
+
+static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+
+ (void)cf;
+ if(stream) {
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] easy handle is done",
+ stream->id));
+ if(stream_send_is_suspended(data)) {
+ data->req.keepon &= ~KEEP_SEND_HOLD;
+ --ctx->sends_on_hold;
+ }
+ Curl_bufq_free(&stream->recvbuf);
+ free(stream);
+ H3_STREAM_LCTX(data) = NULL;
+ }
+}
+
+static void drain_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ unsigned char bits;
+
+ (void)cf;
+ bits = CURL_CSELECT_IN;
+ if(stream && !stream->send_closed && stream->upload_left)
+ bits |= CURL_CSELECT_OUT;
+ if(data->state.dselect_bits != bits) {
+ data->state.dselect_bits = bits;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+}
+
+static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int64_t stream3_id)
+{
+ struct Curl_easy *sdata;
+
+ (void)cf;
+ if(H3_STREAM_ID(data) == stream3_id) {
+ return data;
+ }
+ else {
+ DEBUGASSERT(data->multi);
+ for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+ if((sdata->conn == data->conn) && H3_STREAM_ID(sdata) == stream3_id) {
+ return sdata;
+ }
+ }
+ }
+ return 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,
+ struct Curl_easy *data,
+ const void *mem, size_t memlen)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ CURLcode result = CURLE_OK;
+ ssize_t nwritten;
+
+ (void)cf;
+ if(!stream)
+ return CURLE_RECV_ERROR;
+ nwritten = Curl_bufq_write(&stream->recvbuf, mem, memlen, &result);
+ if(nwritten < 0)
+ return result;
+
+ if((size_t)nwritten < memlen) {
+ /* This MUST not happen. Our recbuf is dimensioned to hold the
+ * full max_stream_window and then some for this very reason. */
+ DEBUGASSERT(0);
+ return CURLE_RECV_ERROR;
+ }
+ return result;
+}
+
+struct cb_ctx {
+ struct Curl_cfilter *cf;
+ struct Curl_easy *data;
+};
+
+static int cb_each_header(uint8_t *name, size_t name_len,
+ uint8_t *value, size_t value_len,
+ void *argp)
+{
+ struct cb_ctx *x = argp;
+ struct stream_ctx *stream = H3_STREAM_CTX(x->data);
+ CURLcode result;
+
+ (void)stream;
+ if((name_len == 7) && !strncmp(HTTP_PSEUDO_STATUS, (char *)name, 7)) {
+ result = write_resp_raw(x->cf, x->data, "HTTP/3 ", sizeof("HTTP/3 ") - 1);
+ if(!result)
+ result = write_resp_raw(x->cf, x->data, value, value_len);
+ if(!result)
+ result = write_resp_raw(x->cf, x->data, " \r\n", 3);
+ }
+ else {
+ result = write_resp_raw(x->cf, x->data, name, name_len);
+ if(!result)
+ result = write_resp_raw(x->cf, x->data, ": ", 2);
+ if(!result)
+ result = write_resp_raw(x->cf, x->data, value, value_len);
+ if(!result)
+ result = write_resp_raw(x->cf, x->data, "\r\n", 2);
+ }
+ if(result) {
+ DEBUGF(LOG_CF(x->data, x->cf,
+ "[h3sid=%"PRId64"][HEADERS][%.*s: %.*s] error %d",
+ stream? stream->id : -1, (int)name_len, name,
+ (int)value_len, value, result));
+ }
+ return result;
+}
+
+static ssize_t stream_resp_read(void *reader_ctx,
+ unsigned char *buf, size_t len,
+ CURLcode *err)
+{
+ struct cb_ctx *x = reader_ctx;
+ struct cf_quiche_ctx *ctx = x->cf->ctx;
+ struct stream_ctx *stream = H3_STREAM_CTX(x->data);
+ ssize_t nread;
+
+ if(!stream) {
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ nread = quiche_h3_recv_body(ctx->h3c, ctx->qconn, stream->id,
+ buf, len);
+ if(nread >= 0) {
+ *err = CURLE_OK;
+ return nread;
+ }
+ else {
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+}
+
+static CURLcode cf_recv_body(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ ssize_t nwritten;
+ 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;
+ }
+
+ cb_ctx.cf = cf;
+ cb_ctx.data = data;
+ nwritten = Curl_bufq_slurp(&stream->recvbuf,
+ stream_resp_read, &cb_ctx, &result);
+
+ if(nwritten < 0 && result != CURLE_AGAIN) {
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] recv_body error %zd",
+ stream->id, nwritten));
+ failf(data, "Error %d in HTTP/3 response body for stream[%"PRId64"]",
+ 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";
+ }
+}
+#else
+#define cf_ev_name(x) ""
+#endif
+
+static CURLcode h3_process_event(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int64_t stream3_id,
+ quiche_h3_event *ev)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct cb_ctx cb_ctx;
+ CURLcode result = CURLE_OK;
+ int rc;
+
+ if(!stream)
+ return CURLE_OK;
+ DEBUGASSERT(stream3_id == stream->id);
+ switch(quiche_h3_event_type(ev)) {
+ case QUICHE_H3_EVENT_HEADERS:
+ 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[%"PRId64"]",
+ rc, stream3_id);
+ return CURLE_RECV_ERROR;
+ }
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][HEADERS]", stream3_id));
+ break;
+
+ case QUICHE_H3_EVENT_DATA:
+ if(!stream->closed) {
+ result = cf_recv_body(cf, data);
+ }
+ break;
+
+ case QUICHE_H3_EVENT_RESET:
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][RESET]", stream3_id));
+ stream->closed = TRUE;
+ stream->reset = TRUE;
+ stream->send_closed = TRUE;
+ streamclose(cf->conn, "Reset of stream");
+ break;
+
+ case QUICHE_H3_EVENT_FINISHED:
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][FINISHED]", stream3_id));
+ if(!stream->resp_hds_complete) {
+ result = write_resp_raw(cf, data, "\r\n", 2);
+ if(result)
+ return result;
+ stream->resp_hds_complete = TRUE;
+ }
+ stream->closed = TRUE;
+ streamclose(cf->conn, "End of stream");
+ break;
+
+ case QUICHE_H3_EVENT_GOAWAY:
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][GOAWAY]", stream3_id));
+ break;
+
+ default:
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] recv, unhandled event %d",
+ stream3_id, quiche_h3_event_type(ev)));
+ break;
+ }
+ return result;
+}
+
+static CURLcode cf_poll_events(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct Curl_easy *sdata;
+ quiche_h3_event *ev;
+ CURLcode result;
+
+ /* Take in the events and distribute them to the transfers. */
+ while(ctx->h3c) {
+ int64_t stream3_id = quiche_h3_conn_poll(ctx->h3c, ctx->qconn, &ev);
+ if(stream3_id == QUICHE_H3_ERR_DONE) {
+ break;
+ }
+ else if(stream3_id < 0) {
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] error poll: %"PRId64,
+ stream? stream->id : -1, stream3_id));
+ return CURLE_HTTP3;
+ }
+
+ sdata = get_stream_easy(cf, data, stream3_id);
+ if(!sdata) {
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] discard event %s for "
+ "unknown [h3sid=%"PRId64"]",
+ stream? stream->id : -1, cf_ev_name(ev),
+ stream3_id));
+ }
+ else {
+ result = h3_process_event(cf, sdata, stream3_id, ev);
+ drain_stream(cf, sdata);
+ if(result) {
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] error processing event %s "
+ "for [h3sid=%"PRId64"] -> %d",
+ stream? stream->id : -1, cf_ev_name(ev),
+ stream3_id, result));
+ if(data == sdata) {
+ /* Only report this error to the caller if it is about the
+ * transfer we were called with. Otherwise we fail a transfer
+ * due to a problem in another one. */
+ quiche_h3_event_free(ev);
+ return result;
+ }
+ }
+ quiche_h3_event_free(ev);
+ }
+ }
+ return CURLE_OK;
+}
+
+struct recv_ctx {
+ struct Curl_cfilter *cf;
+ struct Curl_easy *data;
+ 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)
+{
+ struct recv_ctx *r = userp;
+ struct cf_quiche_ctx *ctx = r->cf->ctx;
+ quiche_recv_info recv_info;
+ ssize_t nread;
+
+ (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 *)pkt, pktlen,
+ &recv_info);
+ if(nread < 0) {
+ if(QUICHE_ERR_DONE == nread) {
+ DEBUGF(LOG_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->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_conn_recv() == %zd", nread);
+ return CURLE_RECV_ERROR;
+ }
+ }
+ else if((size_t)nread < pktlen) {
+ DEBUGF(LOG_CF(r->data, r->cf, "ingress, quiche only read %zd/%zu bytes",
+ nread, pktlen));
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode cf_process_ingress(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ struct recv_ctx rctx;
+ CURLcode result;
+
+ DEBUGASSERT(ctx->qconn);
+ rctx.cf = cf;
+ rctx.data = data;
+ rctx.pkts = 0;
+
+ result = vquic_recv_packets(cf, data, &ctx->q, 1000, recv_pkt, &rctx);
+ if(result)
+ return result;
+
+ if(rctx.pkts > 0) {
+ /* quiche digested ingress packets. It might have opened flow control
+ * windows again. */
+ check_resumes(cf, data);
+ }
+ return cf_poll_events(cf, data);
+}
+
+struct read_ctx {
+ struct Curl_cfilter *cf;
+ struct Curl_easy *data;
+ quiche_send_info send_info;
+};
+
+static ssize_t read_pkt_to_send(void *userp,
+ unsigned char *buf, size_t buflen,
+ CURLcode *err)
+{
+ struct read_ctx *x = userp;
+ struct cf_quiche_ctx *ctx = x->cf->ctx;
+ ssize_t nwritten;
+
+ nwritten = quiche_conn_send(ctx->qconn, buf, buflen, &x->send_info);
+ if(nwritten == QUICHE_ERR_DONE) {
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+
+ if(nwritten < 0) {
+ failf(x->data, "quiche_conn_send returned %zd", nwritten);
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+ *err = CURLE_OK;
+ return nwritten;
+}
+
+/*
+ * flush_egress drains the buffers and sends off data.
+ * Calls failf() on errors.
+ */
+static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ ssize_t nread;
+ CURLcode result;
+ int64_t timeout_ns;
+ struct read_ctx readx;
+ size_t pkt_count, gsolen;
+
+ result = vquic_flush(cf, data, &ctx->q);
+ if(result) {
+ if(result == CURLE_AGAIN) {
+ Curl_expire(data, 1, EXPIRE_QUIC);
+ return CURLE_OK;
+ }
+ return result;
+ }
+
+ readx.cf = cf;
+ readx.data = data;
+ memset(&readx.send_info, 0, sizeof(readx.send_info));
+ pkt_count = 0;
+ gsolen = quiche_conn_max_send_udp_payload_size(ctx->qconn);
+ for(;;) {
+ /* add the next packet to send, if any, to our buffer */
+ nread = Curl_bufq_sipn(&ctx->q.sendbuf, 0,
+ read_pkt_to_send, &readx, &result);
+ /* DEBUGF(LOG_CF(data, cf, "sip packet(maxlen=%zu) -> %zd, %d",
+ (size_t)0, nread, result)); */
+
+ if(nread < 0) {
+ if(result != CURLE_AGAIN)
+ return result;
+ /* Nothing more to add, flush and leave */
+ result = vquic_send(cf, data, &ctx->q, gsolen);
+ if(result) {
+ if(result == CURLE_AGAIN) {
+ Curl_expire(data, 1, EXPIRE_QUIC);
+ return CURLE_OK;
+ }
+ return result;
+ }
+ goto out;
+ }
+
+ ++pkt_count;
+ if((size_t)nread < gsolen || pkt_count >= MAX_PKT_BURST) {
+ result = vquic_send(cf, data, &ctx->q, gsolen);
+ if(result) {
+ if(result == CURLE_AGAIN) {
+ Curl_expire(data, 1, EXPIRE_QUIC);
+ return CURLE_OK;
+ }
+ goto out;
+ }
+ pkt_count = 0;
+ }
+ }
+
+out:
+ timeout_ns = quiche_conn_timeout_as_nanos(ctx->qconn);
+ if(timeout_ns % 1000000)
+ timeout_ns += 1000000;
+ /* expire resolution is milliseconds */
+ Curl_expire(data, (timeout_ns / 1000000), EXPIRE_QUIC);
+ return result;
+}
+
+static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ CURLcode *err)
+{
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ ssize_t nread = -1;
+
+ DEBUGASSERT(stream);
+ if(stream->reset) {
+ failf(data,
+ "HTTP/3 stream %" PRId64 " reset by server", stream->id);
+ *err = stream->resp_got_header? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, was reset -> %d",
+ stream->id, *err));
+ }
+ else if(!stream->resp_got_header) {
+ failf(data,
+ "HTTP/3 stream %" PRId64 " was closed cleanly, but before getting"
+ " all response header fields, treated as error",
+ stream->id);
+ /* *err = CURLE_PARTIAL_FILE; */
+ *err = CURLE_RECV_ERROR;
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, closed incomplete"
+ " -> %d", stream->id, *err));
+ }
+ else {
+ *err = CURLE_OK;
+ nread = 0;
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, closed ok"
+ " -> %d", stream->id, *err));
+ }
+ return nread;
+}
+
+static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ ssize_t nread = -1;
+ CURLcode result;
+
+ if(!stream) {
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ if(!Curl_bufq_is_empty(&stream->recvbuf)) {
+ nread = Curl_bufq_read(&stream->recvbuf,
+ (unsigned char *)buf, len, err);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read recvbuf(len=%zu) "
+ "-> %zd, %d", stream->id, len, nread, *err));
+ if(nread < 0)
+ goto out;
+ }
+
+ if(cf_process_ingress(cf, data)) {
+ DEBUGF(LOG_CF(data, cf, "cf_recv, error on ingress"));
+ *err = CURLE_RECV_ERROR;
+ nread = -1;
+ goto out;
+ }
+
+ /* recvbuf had nothing before, maybe after progressing ingress? */
+ if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) {
+ nread = Curl_bufq_read(&stream->recvbuf,
+ (unsigned char *)buf, len, err);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read recvbuf(len=%zu) "
+ "-> %zd, %d", stream->id, len, nread, *err));
+ if(nread < 0)
+ goto out;
+ }
+
+ if(nread > 0) {
+ if(stream->closed)
+ drain_stream(cf, data);
+ }
+ else {
+ if(stream->closed) {
+ nread = recv_closed_stream(cf, data, err);
+ goto out;
+ }
+ else if(quiche_conn_is_draining(ctx->qconn)) {
+ failf(data, "QUIC connection is draining");
+ *err = CURLE_HTTP3;
+ nread = -1;
+ goto out;
+ }
+ *err = CURLE_AGAIN;
+ nread = -1;
+ }
+
+out:
+ result = cf_flush_egress(cf, data);
+ if(result) {
+ DEBUGF(LOG_CF(data, cf, "cf_recv, flush egress failed"));
+ *err = result;
+ nread = -1;
+ }
+ if(nread > 0)
+ ctx->data_recvd += nread;
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] cf_recv(total=%"
+ CURL_FORMAT_CURL_OFF_T ") -> %zd, %d",
+ stream ? stream->id : (int64_t)0,
+ ctx->data_recvd, nread, *err));
+ return nread;
+}
+
+/* Index where :authority header field will appear in request header
+ field list. */
+#define AUTHORITY_DST_IDX 3
+
+static ssize_t h3_open_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const void *buf, size_t len,
+ CURLcode *err)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ size_t nheader, i;
+ int64_t stream3_id;
+ struct h1_req_parser h1;
+ struct dynhds h2_headers;
+ quiche_h3_header *nva = NULL;
+ ssize_t nwritten;
+
+ if(!stream) {
+ *err = h3_data_setup(cf, data);
+ if(*err) {
+ return -1;
+ }
+ stream = H3_STREAM_CTX(data);
+ DEBUGASSERT(stream);
+ }
+
+ Curl_h1_req_parse_init(&h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
+ Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
+
+ DEBUGASSERT(stream);
+ nwritten = Curl_h1_req_parse_read(&h1, buf, len, NULL, 0, err);
+ if(nwritten < 0)
+ goto out;
+ DEBUGASSERT(h1.done);
+ DEBUGASSERT(h1.req);
+
+ *err = Curl_http_req_to_h2(&h2_headers, h1.req, data);
+ if(*err) {
+ nwritten = -1;
+ goto out;
+ }
+
+ nheader = Curl_dynhds_count(&h2_headers);
+ nva = malloc(sizeof(quiche_h3_header) * nheader);
+ if(!nva) {
+ *err = CURLE_OUT_OF_MEMORY;
+ nwritten = -1;
+ goto out;
+ }
+
+ for(i = 0; i < nheader; ++i) {
+ struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
+ nva[i].name = (unsigned char *)e->name;
+ nva[i].name_len = e->namelen;
+ nva[i].value = (unsigned char *)e->value;
+ nva[i].value_len = e->valuelen;
+ }
+
+ switch(data->state.httpreq) {
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ case HTTPREQ_POST_MIME:
+ case HTTPREQ_PUT:
+ if(data->state.infilesize != -1)
+ stream->upload_left = data->state.infilesize;
+ else
+ /* data sending without specifying the data amount up front */
+ stream->upload_left = -1; /* unknown */
+ break;
+ default:
+ stream->upload_left = 0; /* no request body */
+ break;
+ }
+
+ if(stream->upload_left == 0)
+ stream->send_closed = TRUE;
+
+ stream3_id = quiche_h3_send_request(ctx->h3c, ctx->qconn, nva, nheader,
+ stream->send_closed);
+ if(stream3_id < 0) {
+ if(QUICHE_H3_ERR_STREAM_BLOCKED == stream3_id) {
+ /* quiche seems to report this error if the connection window is
+ * exhausted. Which happens frequently and intermittent. */
+ DEBUGF(LOG_CF(data, cf, "send_request(%s) rejected with BLOCKED",
+ data->state.url));
+ stream_send_suspend(cf, data);
+ *err = CURLE_AGAIN;
+ nwritten = -1;
+ goto out;
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "send_request(%s) -> %" PRId64,
+ data->state.url, stream3_id));
+ }
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ goto out;
+ }
+
+ DEBUGASSERT(stream->id == -1);
+ *err = CURLE_OK;
+ stream->id = stream3_id;
+ stream->closed = FALSE;
+ stream->reset = FALSE;
+
+ infof(data, "Using HTTP/3 Stream ID: %" PRId64, stream3_id);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] opened for %s",
+ stream3_id, data->state.url));
+
+out:
+ free(nva);
+ Curl_h1_req_parse_free(&h1);
+ Curl_dynhds_free(&h2_headers);
+ return nwritten;
+}
+
+static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ CURLcode result;
+ ssize_t nwritten;
+
+ *err = cf_process_ingress(cf, data);
+ if(*err) {
+ nwritten = -1;
+ goto out;
+ }
+
+ if(!stream || stream->id < 0) {
+ nwritten = h3_open_stream(cf, data, buf, len, err);
+ if(nwritten < 0)
+ goto out;
+ stream = H3_STREAM_CTX(data);
+ }
+ else {
+ bool eof = (stream->upload_left >= 0 &&
+ (curl_off_t)len >= stream->upload_left);
+ nwritten = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream->id,
+ (uint8_t *)buf, len, eof);
+ if(nwritten == QUICHE_H3_ERR_DONE || (nwritten == 0 && len > 0)) {
+ /* TODO: we seem to be blocked on flow control and should HOLD
+ * sending. But when do we open again? */
+ if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) {
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] send_body(len=%zu) "
+ "-> window exhausted", stream->id, len));
+ stream_send_suspend(cf, data);
+ }
+ *err = CURLE_AGAIN;
+ nwritten = -1;
+ goto out;
+ }
+ else if(nwritten == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) {
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] send_body(len=%zu) "
+ "-> exceeds size", stream->id, len));
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ goto out;
+ }
+ else if(nwritten < 0) {
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] send_body(len=%zu) "
+ "-> quiche err %zd", stream->id, len, nwritten));
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ goto out;
+ }
+ else {
+ /* quiche accepted all or at least a part of the buf */
+ if(stream->upload_left > 0) {
+ stream->upload_left = (nwritten < stream->upload_left)?
+ (stream->upload_left - nwritten) : 0;
+ }
+ if(stream->upload_left == 0)
+ stream->send_closed = TRUE;
+
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] send body(len=%zu, "
+ "left=%" CURL_FORMAT_CURL_OFF_T ") -> %zd",
+ stream->id, len, stream->upload_left, nwritten));
+ *err = CURLE_OK;
+ }
+ }
+
+out:
+ result = cf_flush_egress(cf, data);
+ if(result) {
+ *err = result;
+ nwritten = -1;
+ }
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_send(len=%zu) -> %zd, %d",
+ stream? stream->id : -1, len, nwritten, *err));
+ return nwritten;
+}
+
+static bool stream_is_writeable(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+
+ return stream &&
+ quiche_conn_stream_writable(ctx->qconn, (uint64_t)stream->id, 1);
+}
+
+static int cf_quiche_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ struct SingleRequest *k = &data->req;
+ int rv = GETSOCK_BLANK;
+
+ socks[0] = ctx->q.sockfd;
+
+ /* in an HTTP/3 connection we can basically always get a frame so we should
+ always be ready for one */
+ rv |= GETSOCK_READSOCK(0);
+
+ /* we're still uploading or the HTTP/3 layer wants to send data */
+ if(((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
+ && stream_is_writeable(cf, data))
+ rv |= GETSOCK_WRITESOCK(0);
+
+ return rv;
+}
+
+/*
+ * 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)
+{
+ const struct stream_ctx *stream = H3_STREAM_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)
+{
+ /* TODO: there seems right now no API in quiche to shrink/enlarge
+ * the streams windows. As we do in HTTP/2. */
+ if(!pause) {
+ drain_stream(cf, data);
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
+{
+ CURLcode result = CURLE_OK;
+
+ (void)arg1;
+ (void)arg2;
+ switch(event) {
+ case CF_CTRL_DATA_SETUP:
+ break;
+ case CF_CTRL_DATA_PAUSE:
+ result = h3_data_pause(cf, data, (arg1 != 0));
+ break;
+ case CF_CTRL_DATA_DONE: {
+ h3_data_done(cf, data);
+ break;
+ }
+ case CF_CTRL_DATA_DONE_SEND: {
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ if(stream && !stream->send_closed) {
+ unsigned char body[1];
+ ssize_t sent;
+
+ stream->send_closed = TRUE;
+ stream->upload_left = 0;
+ body[0] = 'X';
+ sent = cf_quiche_send(cf, data, body, 0, &result);
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] DONE_SEND -> %zd, %d",
+ stream->id, sent, result));
+ }
+ break;
+ }
+ case CF_CTRL_DATA_IDLE:
+ result = cf_flush_egress(cf, data);
+ if(result)
+ DEBUGF(LOG_CF(data, cf, "data idle, flush egress -> %d", result));
+ break;
+ default:
+ break;
+ }
+ return result;
+}
+
+static CURLcode cf_verify_peer(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+
+ cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+ cf->conn->httpversion = 30;
+ cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+
+ if(cf->conn->ssl_config.verifyhost) {
+ X509 *server_cert;
+ server_cert = SSL_get_peer_certificate(ctx->ssl);
+ if(!server_cert) {
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ goto out;
+ }
+ result = Curl_ossl_verifyhost(data, cf->conn, server_cert);
+ X509_free(server_cert);
+ if(result)
+ goto out;
+ }
+ else
+ DEBUGF(LOG_CF(data, cf, "Skipped certificate verification"));
+
+ ctx->h3config = quiche_h3_config_new();
+ if(!ctx->h3config) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ /* Create a new HTTP/3 connection on the QUIC connection. */
+ ctx->h3c = quiche_h3_conn_new_with_transport(ctx->qconn, ctx->h3config);
+ if(!ctx->h3c) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ if(data->set.ssl.certinfo)
+ /* asked to gather certificate info */
+ (void)Curl_ossl_certchain(data, ctx->ssl);
+
+out:
+ if(result) {
+ if(ctx->h3config) {
+ quiche_h3_config_free(ctx->h3config);
+ ctx->h3config = NULL;
+ }
+ if(ctx->h3c) {
+ quiche_h3_conn_free(ctx->h3c);
+ ctx->h3c = NULL;
+ }
+ }
+ return result;
+}
+
+static CURLcode cf_connect_start(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ int rv;
+ CURLcode result;
+ const struct Curl_sockaddr_ex *sockaddr;
+
+ DEBUGASSERT(ctx->q.sockfd != CURL_SOCKET_BAD);
+
+#ifdef DEBUG_QUICHE
+ /* initialize debug log callback only once */
+ static int debug_log_init = 0;
+ if(!debug_log_init) {
+ quiche_enable_debug_logging(quiche_debug_log, NULL);
+ debug_log_init = 1;
+ }
+#endif
+ Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
+ H3_STREAM_POOL_SPARES);
+ ctx->data_recvd = 0;
+
+ result = vquic_ctx_init(&ctx->q);
+ if(result)
+ return result;
+
+ ctx->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
+ if(!ctx->cfg) {
+ failf(data, "can't create quiche config");
+ return CURLE_FAILED_INIT;
+ }
+ quiche_config_enable_pacing(ctx->cfg, false);
+ quiche_config_set_max_idle_timeout(ctx->cfg, QUIC_IDLE_TIMEOUT);
+ quiche_config_set_initial_max_data(ctx->cfg, (1 * 1024 * 1024)
+ /* (QUIC_MAX_STREAMS/2) * H3_STREAM_WINDOW_SIZE */);
+ quiche_config_set_initial_max_streams_bidi(ctx->cfg, QUIC_MAX_STREAMS);
+ quiche_config_set_initial_max_streams_uni(ctx->cfg, QUIC_MAX_STREAMS);
+ quiche_config_set_initial_max_stream_data_bidi_local(ctx->cfg,
+ H3_STREAM_WINDOW_SIZE);
+ quiche_config_set_initial_max_stream_data_bidi_remote(ctx->cfg,
+ H3_STREAM_WINDOW_SIZE);
+ quiche_config_set_initial_max_stream_data_uni(ctx->cfg,
+ H3_STREAM_WINDOW_SIZE);
+ quiche_config_set_disable_active_migration(ctx->cfg, TRUE);
+
+ quiche_config_set_max_connection_window(ctx->cfg,
+ 10 * QUIC_MAX_STREAMS * H3_STREAM_WINDOW_SIZE);
+ quiche_config_set_max_stream_window(ctx->cfg, 10 * H3_STREAM_WINDOW_SIZE);
+ quiche_config_set_application_protos(ctx->cfg,
+ (uint8_t *)
+ QUICHE_H3_APPLICATION_PROTOCOL,
+ sizeof(QUICHE_H3_APPLICATION_PROTOCOL)
+ - 1);
+
+ DEBUGASSERT(!ctx->ssl);
+ DEBUGASSERT(!ctx->sslctx);
+ ctx->sslctx = quic_ssl_ctx(data);
+ if(!ctx->sslctx)
+ return CURLE_QUIC_CONNECT_ERROR;
+ ctx->ssl = SSL_new(ctx->sslctx);
+ if(!ctx->ssl)
+ return CURLE_QUIC_CONNECT_ERROR;
+
+ SSL_set_app_data(ctx->ssl, cf);
+ SSL_set_tlsext_host_name(ctx->ssl, cf->conn->host.name);
+
+ result = Curl_rand(data, ctx->scid, sizeof(ctx->scid));
+ if(result)
+ return result;
+
+ Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd,
+ &sockaddr, NULL, NULL, NULL, NULL);
+ ctx->q.local_addrlen = sizeof(ctx->q.local_addr);
+ rv = getsockname(ctx->q.sockfd, (struct sockaddr *)&ctx->q.local_addr,
+ &ctx->q.local_addrlen);
+ if(rv == -1)
+ return CURLE_QUIC_CONNECT_ERROR;
+
+ ctx->qconn = quiche_conn_new_with_tls((const uint8_t *)ctx->scid,
+ sizeof(ctx->scid), NULL, 0,
+ (struct sockaddr *)&ctx->q.local_addr,
+ ctx->q.local_addrlen,
+ &sockaddr->sa_addr, sockaddr->addrlen,
+ ctx->cfg, ctx->ssl, false);
+ if(!ctx->qconn) {
+ failf(data, "can't create quiche connection");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Known to not work on Windows */
+#if !defined(WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
+ {
+ 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");
+ }
+#endif
+
+ result = cf_flush_egress(cf, data);
+ if(result)
+ return result;
+
+ {
+ unsigned char alpn_protocols[] = QUICHE_H3_APPLICATION_PROTOCOL;
+ unsigned alpn_len, offset = 0;
+
+ /* Replace each ALPN length prefix by a comma. */
+ while(offset < sizeof(alpn_protocols) - 1) {
+ alpn_len = alpn_protocols[offset];
+ alpn_protocols[offset] = ',';
+ offset += 1 + alpn_len;
+ }
+
+ DEBUGF(LOG_CF(data, cf, "Sent QUIC client Initial, ALPN: %s",
+ alpn_protocols + 1));
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+ struct curltime now;
+
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ /* Connect the UDP filter first */
+ if(!cf->next->connected) {
+ result = Curl_conn_cf_connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ return result;
+ }
+
+ *done = FALSE;
+ now = Curl_now();
+
+ if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) {
+ /* Not time yet to attempt the next connect */
+ DEBUGF(LOG_CF(data, cf, "waiting for reconnect time"));
+ goto out;
+ }
+
+ if(!ctx->qconn) {
+ result = cf_connect_start(cf, data);
+ if(result)
+ goto out;
+ ctx->started_at = now;
+ result = cf_flush_egress(cf, data);
+ /* we do not expect to be able to recv anything yet */
+ goto out;
+ }
+
+ result = cf_process_ingress(cf, data);
+ if(result)
+ goto out;
+
+ result = cf_flush_egress(cf, data);
+ if(result)
+ goto out;
+
+ if(quiche_conn_is_established(ctx->qconn)) {
+ DEBUGF(LOG_CF(data, cf, "handshake complete after %dms",
+ (int)Curl_timediff(now, ctx->started_at)));
+ ctx->handshake_at = now;
+ result = cf_verify_peer(cf, data);
+ if(!result) {
+ DEBUGF(LOG_CF(data, cf, "peer verified"));
+ cf->connected = TRUE;
+ cf->conn->alpn = CURL_HTTP_VERSION_3;
+ *done = TRUE;
+ connkeep(cf->conn, "HTTP/3 default");
+ }
+ }
+ else if(quiche_conn_is_draining(ctx->qconn)) {
+ /* When a QUIC server instance is shutting down, it may send us a
+ * CONNECTION_CLOSE right away. Our connection then enters the DRAINING
+ * state.
+ * This may be a stopping of the service or it may be that the server
+ * is reloading and a new instance will start serving soon.
+ * In any case, we tear down our socket and start over with a new one.
+ * We re-open the underlying UDP cf right now, but do not start
+ * connecting until called again.
+ */
+ int reconn_delay_ms = 200;
+
+ DEBUGF(LOG_CF(data, cf, "connect, remote closed, reconnect after %dms",
+ reconn_delay_ms));
+ Curl_conn_cf_close(cf->next, data);
+ cf_quiche_ctx_clear(ctx);
+ result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
+ if(!result && *done) {
+ *done = FALSE;
+ ctx->reconnect_at = Curl_now();
+ ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000;
+ Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC);
+ result = CURLE_OK;
+ }
+ }
+
+out:
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ if(result && result != CURLE_AGAIN) {
+ const char *r_ip;
+ int r_port;
+
+ Curl_cf_socket_peek(cf->next, data, NULL, NULL,
+ &r_ip, &r_port, NULL, NULL);
+ infof(data, "connect to %s port %u failed: %s",
+ r_ip, r_port, curl_easy_strerror(result));
+ }
+#endif
+ return result;
+}
+
+static void cf_quiche_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+
+ if(ctx) {
+ if(ctx->qconn) {
+ (void)quiche_conn_close(ctx->qconn, TRUE, 0, NULL, 0);
+ /* flushing the egress is not a failsafe way to deliver all the
+ outstanding packets, but we also don't want to get stuck here... */
+ (void)cf_flush_egress(cf, data);
+ }
+ cf_quiche_ctx_clear(ctx);
+ }
+}
+
+static void cf_quiche_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+
+ (void)data;
+ cf_quiche_ctx_clear(ctx);
+ free(ctx);
+ cf->ctx = NULL;
+}
+
+static CURLcode cf_quiche_query(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query, int *pres1, void *pres2)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+
+ switch(query) {
+ case CF_QUERY_MAX_CONCURRENT: {
+ uint64_t max_streams = CONN_INUSE(cf->conn);
+ if(!ctx->goaway) {
+ max_streams += quiche_conn_peer_streams_left_bidi(ctx->qconn);
+ }
+ *pres1 = (max_streams > INT_MAX)? INT_MAX : (int)max_streams;
+ DEBUGF(LOG_CF(data, cf, "query: MAX_CONCURRENT -> %d", *pres1));
+ return CURLE_OK;
+ }
+ case CF_QUERY_CONNECT_REPLY_MS:
+ if(ctx->got_first_byte) {
+ timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
+ *pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
+ }
+ else
+ *pres1 = -1;
+ return CURLE_OK;
+ case CF_QUERY_TIMER_CONNECT: {
+ struct curltime *when = pres2;
+ if(ctx->got_first_byte)
+ *when = ctx->first_byte_at;
+ return CURLE_OK;
+ }
+ case CF_QUERY_TIMER_APPCONNECT: {
+ struct curltime *when = pres2;
+ if(cf->connected)
+ *when = ctx->handshake_at;
+ return CURLE_OK;
+ }
+ default:
+ break;
+ }
+ return cf->next?
+ cf->next->cft->query(cf->next, data, query, pres1, pres2) :
+ CURLE_UNKNOWN_OPTION;
+}
+
+static bool cf_quiche_conn_is_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending)
+{
+ bool alive = TRUE;
+
+ *input_pending = FALSE;
+ if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
+ return FALSE;
+
+ if(*input_pending) {
+ /* This happens before we've sent off a request and the connection is
+ not in use by any other transfer, there shouldn't be any data here,
+ only "protocol frames" */
+ *input_pending = FALSE;
+ if(cf_process_ingress(cf, data))
+ alive = FALSE;
+ else {
+ alive = TRUE;
+ }
+ }
+
+ return alive;
+}
+
+struct Curl_cftype Curl_cft_http3 = {
+ "HTTP/3",
+ CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
+ 0,
+ cf_quiche_destroy,
+ cf_quiche_connect,
+ cf_quiche_close,
+ Curl_cf_def_get_host,
+ cf_quiche_get_select_socks,
+ cf_quiche_data_pending,
+ cf_quiche_send,
+ cf_quiche_recv,
+ cf_quiche_data_event,
+ cf_quiche_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ cf_quiche_query,
+};
+
+CURLcode Curl_cf_quiche_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai)
+{
+ struct cf_quiche_ctx *ctx = NULL;
+ struct Curl_cfilter *cf = NULL, *udp_cf = NULL;
+ CURLcode result;
+
+ (void)data;
+ (void)conn;
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
+ if(result)
+ goto out;
+
+ result = Curl_cf_udp_create(&udp_cf, data, conn, ai, TRNSPRT_QUIC);
+ if(result)
+ goto out;
+
+ udp_cf->conn = cf->conn;
+ udp_cf->sockindex = cf->sockindex;
+ cf->next = udp_cf;
+
+out:
+ *pcf = (!result)? cf : NULL;
+ if(result) {
+ if(udp_cf)
+ Curl_conn_cf_discard_sub(cf, udp_cf, data, TRUE);
+ Curl_safefree(cf);
+ Curl_safefree(ctx);
+ }
+
+ return result;
+}
+
+bool Curl_conn_is_quiche(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/quiche.h b/lib/vquic/curl_quiche.h
similarity index 60%
rename from lib/vquic/quiche.h
rename to lib/vquic/curl_quiche.h
index de68089..bce781c 100644
--- a/lib/vquic/quiche.h
+++ b/lib/vquic/curl_quiche.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_VQUIC_QUICHE_H
-#define HEADER_CURL_VQUIC_QUICHE_H
+#ifndef HEADER_CURL_VQUIC_CURL_QUICHE_H
+#define HEADER_CURL_VQUIC_CURL_QUICHE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,26 +31,20 @@
#include <quiche.h>
#include <openssl/ssl.h>
-struct quic_handshake {
- char *buf; /* pointer to the buffer */
- size_t alloclen; /* size of allocation */
- size_t len; /* size of content in buffer */
- size_t nread; /* how many bytes have been read */
-};
+struct Curl_cfilter;
+struct Curl_easy;
-struct quicsocket {
- quiche_config *cfg;
- quiche_conn *conn;
- quiche_h3_conn *h3c;
- quiche_h3_config *h3config;
- uint8_t scid[QUICHE_MAX_CONN_ID_LEN];
- curl_socket_t sockfd;
- uint32_t version;
- SSL_CTX *sslctx;
- SSL *ssl;
- bool h3_recving; /* TRUE when in h3-body-reading state */
-};
+void Curl_quiche_ver(char *p, size_t len);
+
+CURLcode Curl_cf_quiche_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai);
+
+bool Curl_conn_is_quiche(const struct Curl_easy *data,
+ const struct connectdata *conn,
+ int sockindex);
#endif
-#endif /* HEADER_CURL_VQUIC_QUICHE_H */
+#endif /* HEADER_CURL_VQUIC_CURL_QUICHE_H */
diff --git a/lib/vquic/msh3.c b/lib/vquic/msh3.c
deleted file mode 100644
index 296943b..0000000
--- a/lib/vquic/msh3.c
+++ /dev/null
@@ -1,517 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the 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"
-
-#ifdef USE_MSH3
-
-#include "urldata.h"
-#include "curl_printf.h"
-#include "timeval.h"
-#include "multiif.h"
-#include "sendf.h"
-#include "connect.h"
-#include "h2h3.h"
-#include "msh3.h"
-
-/* #define DEBUG_HTTP3 1 */
-#ifdef DEBUG_HTTP3
-#define H3BUGF(x) x
-#else
-#define H3BUGF(x) do { } while(0)
-#endif
-
-#define MSH3_REQ_INIT_BUF_LEN 8192
-
-static CURLcode msh3_do_it(struct Curl_easy *data, bool *done);
-static int msh3_getsock(struct Curl_easy *data,
- struct connectdata *conn, curl_socket_t *socks);
-static CURLcode msh3_disconnect(struct Curl_easy *data,
- struct connectdata *conn,
- bool dead_connection);
-static unsigned int msh3_conncheck(struct Curl_easy *data,
- struct connectdata *conn,
- unsigned int checks_to_perform);
-static Curl_recv msh3_stream_recv;
-static Curl_send msh3_stream_send;
-static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request,
- void *IfContext,
- const MSH3_HEADER *Header);
-static void MSH3_CALL msh3_data_received(MSH3_REQUEST *Request,
- void *IfContext, uint32_t Length,
- const uint8_t *Data);
-static void MSH3_CALL msh3_complete(MSH3_REQUEST *Request, void *IfContext,
- bool Aborted, uint64_t AbortError);
-static void MSH3_CALL msh3_shutdown(MSH3_REQUEST *Request, void *IfContext);
-
-static const struct Curl_handler msh3_curl_handler_http3 = {
- "HTTPS", /* scheme */
- ZERO_NULL, /* setup_connection */
- msh3_do_it, /* do_it */
- Curl_http_done, /* done */
- ZERO_NULL, /* do_more */
- ZERO_NULL, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- msh3_getsock, /* proto_getsock */
- msh3_getsock, /* doing_getsock */
- ZERO_NULL, /* domore_getsock */
- msh3_getsock, /* perform_getsock */
- msh3_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
- msh3_conncheck, /* connection_check */
- ZERO_NULL, /* attach connection */
- PORT_HTTP, /* defport */
- CURLPROTO_HTTPS, /* protocol */
- CURLPROTO_HTTP, /* family */
- PROTOPT_SSL | PROTOPT_STREAM /* flags */
-};
-
-static const MSH3_REQUEST_IF msh3_request_if = {
- msh3_header_received,
- msh3_data_received,
- msh3_complete,
- msh3_shutdown
-};
-
-void Curl_quic_ver(char *p, size_t len)
-{
- uint32_t v[4];
- MsH3Version(v);
- (void)msnprintf(p, len, "msh3/%d.%d.%d.%d", v[0], v[1], v[2], v[3]);
-}
-
-CURLcode Curl_quic_connect(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t sockfd,
- int sockindex,
- const struct sockaddr *addr,
- socklen_t addrlen)
-{
- struct quicsocket *qs = &conn->hequic[sockindex];
- bool unsecure = !conn->ssl_config.verifypeer;
- memset(qs, 0, sizeof(*qs));
-
- (void)sockfd;
- (void)addr; /* TODO - Pass address along */
- (void)addrlen;
-
- H3BUGF(infof(data, "creating new api/connection"));
-
- qs->api = MsH3ApiOpen();
- if(!qs->api) {
- failf(data, "can't create msh3 api");
- return CURLE_FAILED_INIT;
- }
-
- qs->conn = MsH3ConnectionOpen(qs->api,
- conn->host.name,
- (uint16_t)conn->remote_port,
- unsecure);
- if(!qs->conn) {
- failf(data, "can't create msh3 connection");
- if(qs->api) {
- MsH3ApiClose(qs->api);
- }
- return CURLE_FAILED_INIT;
- }
-
- return CURLE_OK;
-}
-
-CURLcode Curl_quic_is_connected(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
- bool *connected)
-{
- struct quicsocket *qs = &conn->hequic[sockindex];
- MSH3_CONNECTION_STATE state;
-
- state = MsH3ConnectionGetState(qs->conn, false);
- if(state == MSH3_CONN_HANDSHAKE_FAILED || state == MSH3_CONN_DISCONNECTED) {
- failf(data, "failed to connect, state=%u", (uint32_t)state);
- return CURLE_COULDNT_CONNECT;
- }
-
- if(state == MSH3_CONN_CONNECTED) {
- H3BUGF(infof(data, "connection connected"));
- *connected = true;
- conn->quic = qs;
- conn->recv[sockindex] = msh3_stream_recv;
- conn->send[sockindex] = msh3_stream_send;
- conn->handler = &msh3_curl_handler_http3;
- conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
- conn->httpversion = 30;
- conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- /* TODO - Clean up other happy-eyeballs connection(s)? */
- }
-
- return CURLE_OK;
-}
-
-static int msh3_getsock(struct Curl_easy *data,
- struct connectdata *conn, curl_socket_t *socks)
-{
- struct HTTP *stream = data->req.p.http;
- int bitmap = GETSOCK_BLANK;
-
- socks[0] = conn->sock[FIRSTSOCKET];
-
- if(stream->recv_error) {
- bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
- data->state.drain++;
- }
- else if(stream->recv_header_len || stream->recv_data_len) {
- bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
- data->state.drain++;
- }
-
- H3BUGF(infof(data, "msh3_getsock %u", (uint32_t)data->state.drain));
-
- return bitmap;
-}
-
-static CURLcode msh3_do_it(struct Curl_easy *data, bool *done)
-{
- struct HTTP *stream = data->req.p.http;
- H3BUGF(infof(data, "msh3_do_it"));
- stream->recv_buf = malloc(MSH3_REQ_INIT_BUF_LEN);
- if(!stream->recv_buf) {
- return CURLE_OUT_OF_MEMORY;
- }
- stream->req = ZERO_NULL;
- msh3_lock_initialize(&stream->recv_lock);
- stream->recv_buf_alloc = MSH3_REQ_INIT_BUF_LEN;
- stream->recv_header_len = 0;
- stream->recv_header_complete = false;
- stream->recv_data_len = 0;
- stream->recv_data_complete = false;
- stream->recv_error = CURLE_OK;
- return Curl_http(data, done);
-}
-
-static unsigned int msh3_conncheck(struct Curl_easy *data,
- struct connectdata *conn,
- unsigned int checks_to_perform)
-{
- (void)data;
- (void)conn;
- (void)checks_to_perform;
- H3BUGF(infof(data, "msh3_conncheck"));
- return CONNRESULT_NONE;
-}
-
-static void msh3_cleanup(struct quicsocket *qs, struct HTTP *stream)
-{
- if(stream && stream->recv_buf) {
- free(stream->recv_buf);
- stream->recv_buf = ZERO_NULL;
- msh3_lock_uninitialize(&stream->recv_lock);
- }
- if(qs->conn) {
- MsH3ConnectionClose(qs->conn);
- qs->conn = ZERO_NULL;
- }
- if(qs->api) {
- MsH3ApiClose(qs->api);
- qs->api = ZERO_NULL;
- }
-}
-
-static CURLcode msh3_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead_connection)
-{
- (void)dead_connection;
- H3BUGF(infof(data, "disconnecting (msh3)"));
- msh3_cleanup(conn->quic, data->req.p.http);
- return CURLE_OK;
-}
-
-void Curl_quic_disconnect(struct Curl_easy *data, struct connectdata *conn,
- int tempindex)
-{
- if(conn->transport == TRNSPRT_QUIC) {
- H3BUGF(infof(data, "disconnecting (curl)"));
- msh3_cleanup(&conn->hequic[tempindex], data->req.p.http);
- }
-}
-
-/* Requires stream->recv_lock to be held */
-static bool msh3request_ensure_room(struct HTTP *stream, size_t len)
-{
- uint8_t *new_recv_buf;
- const size_t cur_recv_len = stream->recv_header_len + stream->recv_data_len;
- if(cur_recv_len + len > stream->recv_buf_alloc) {
- size_t new_recv_buf_alloc_len = stream->recv_buf_alloc;
- do {
- new_recv_buf_alloc_len <<= 1; /* TODO - handle overflow */
- } while(cur_recv_len + len > new_recv_buf_alloc_len);
- new_recv_buf = malloc(new_recv_buf_alloc_len);
- if(!new_recv_buf) {
- return false;
- }
- if(cur_recv_len) {
- memcpy(new_recv_buf, stream->recv_buf, cur_recv_len);
- }
- stream->recv_buf_alloc = new_recv_buf_alloc_len;
- free(stream->recv_buf);
- stream->recv_buf = new_recv_buf;
- }
- return true;
-}
-
-static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request,
- void *IfContext,
- const MSH3_HEADER *Header)
-{
- struct HTTP *stream = IfContext;
- size_t total_len;
- (void)Request;
- H3BUGF(printf("* msh3_header_received\n"));
-
- if(stream->recv_header_complete) {
- H3BUGF(printf("* ignoring header after data\n"));
- return;
- }
-
- msh3_lock_acquire(&stream->recv_lock);
-
- if((Header->NameLength == 7) &&
- !strncmp(H2H3_PSEUDO_STATUS, (char *)Header->Name, 7)) {
- total_len = 9 + Header->ValueLength;
- if(!msh3request_ensure_room(stream, total_len)) {
- /* TODO - handle error */
- goto release_lock;
- }
- msnprintf((char *)stream->recv_buf + stream->recv_header_len,
- stream->recv_buf_alloc - stream->recv_header_len,
- "HTTP/3 %.*s\n", (int)Header->ValueLength, Header->Value);
- }
- else {
- total_len = Header->NameLength + 4 + Header->ValueLength;
- if(!msh3request_ensure_room(stream, total_len)) {
- /* TODO - handle error */
- goto release_lock;
- }
- msnprintf((char *)stream->recv_buf + stream->recv_header_len,
- stream->recv_buf_alloc - stream->recv_header_len,
- "%.*s: %.*s\n",
- (int)Header->NameLength, Header->Name,
- (int)Header->ValueLength, Header->Value);
- }
-
- stream->recv_header_len += total_len - 1; /* don't include null-terminator */
-
-release_lock:
- msh3_lock_release(&stream->recv_lock);
-}
-
-static void MSH3_CALL msh3_data_received(MSH3_REQUEST *Request,
- void *IfContext, uint32_t Length,
- const uint8_t *Data)
-{
- struct HTTP *stream = IfContext;
- size_t cur_recv_len = stream->recv_header_len + stream->recv_data_len;
- (void)Request;
- H3BUGF(printf("* msh3_data_received %u. %zu buffered, %zu allocated\n",
- Length, cur_recv_len, stream->recv_buf_alloc));
- msh3_lock_acquire(&stream->recv_lock);
- if(!stream->recv_header_complete) {
- H3BUGF(printf("* Headers complete!\n"));
- if(!msh3request_ensure_room(stream, 2)) {
- /* TODO - handle error */
- goto release_lock;
- }
- stream->recv_buf[stream->recv_header_len++] = '\r';
- stream->recv_buf[stream->recv_header_len++] = '\n';
- stream->recv_header_complete = true;
- cur_recv_len += 2;
- }
- if(!msh3request_ensure_room(stream, Length)) {
- /* TODO - handle error */
- goto release_lock;
- }
- memcpy(stream->recv_buf + cur_recv_len, Data, Length);
- stream->recv_data_len += (size_t)Length;
-release_lock:
- msh3_lock_release(&stream->recv_lock);
-}
-
-static void MSH3_CALL msh3_complete(MSH3_REQUEST *Request, void *IfContext,
- bool Aborted, uint64_t AbortError)
-{
- struct HTTP *stream = IfContext;
- (void)Request;
- (void)AbortError;
- H3BUGF(printf("* msh3_complete, aborted=%s\n", Aborted ? "true" : "false"));
- msh3_lock_acquire(&stream->recv_lock);
- if(Aborted) {
- stream->recv_error = CURLE_HTTP3; /* TODO - how do we pass AbortError? */
- }
- stream->recv_header_complete = true;
- stream->recv_data_complete = true;
- msh3_lock_release(&stream->recv_lock);
-}
-
-static void MSH3_CALL msh3_shutdown(MSH3_REQUEST *Request, void *IfContext)
-{
- struct HTTP *stream = IfContext;
- (void)Request;
- (void)stream;
-}
-
-static_assert(sizeof(MSH3_HEADER) == sizeof(struct h2h3pseudo),
- "Sizes must match for cast below to work");
-
-static ssize_t msh3_stream_send(struct Curl_easy *data,
- int sockindex,
- const void *mem,
- size_t len,
- CURLcode *curlcode)
-{
- struct connectdata *conn = data->conn;
- struct HTTP *stream = data->req.p.http;
- struct quicsocket *qs = conn->quic;
- struct h2h3req *hreq;
-
- (void)sockindex;
- H3BUGF(infof(data, "msh3_stream_send %zu", len));
-
- if(!stream->req) {
- *curlcode = Curl_pseudo_headers(data, mem, len, &hreq);
- if(*curlcode) {
- failf(data, "Curl_pseudo_headers failed");
- return -1;
- }
- H3BUGF(infof(data, "starting request with %zu headers", hreq->entries));
- stream->req = MsH3RequestOpen(qs->conn, &msh3_request_if, stream,
- (MSH3_HEADER*)hreq->header, hreq->entries);
- Curl_pseudo_free(hreq);
- if(!stream->req) {
- failf(data, "request open failed");
- *curlcode = CURLE_SEND_ERROR;
- return -1;
- }
- *curlcode = CURLE_OK;
- return len;
- }
- H3BUGF(infof(data, "send %zd body bytes on request %p", len,
- (void *)stream->req));
- *curlcode = CURLE_SEND_ERROR;
- return -1;
-}
-
-static ssize_t msh3_stream_recv(struct Curl_easy *data,
- int sockindex,
- char *buf,
- size_t buffersize,
- CURLcode *curlcode)
-{
- struct HTTP *stream = data->req.p.http;
- size_t outsize = 0;
- (void)sockindex;
- H3BUGF(infof(data, "msh3_stream_recv %zu", buffersize));
-
- if(stream->recv_error) {
- failf(data, "request aborted");
- *curlcode = stream->recv_error;
- return -1;
- }
-
- msh3_lock_acquire(&stream->recv_lock);
-
- if(stream->recv_header_len) {
- outsize = buffersize;
- if(stream->recv_header_len < outsize) {
- outsize = stream->recv_header_len;
- }
- memcpy(buf, stream->recv_buf, outsize);
- if(outsize < stream->recv_header_len + stream->recv_data_len) {
- memmove(stream->recv_buf, stream->recv_buf + outsize,
- stream->recv_header_len + stream->recv_data_len - outsize);
- }
- stream->recv_header_len -= outsize;
- H3BUGF(infof(data, "returned %zu bytes of headers", outsize));
- }
- else if(stream->recv_data_len) {
- outsize = buffersize;
- if(stream->recv_data_len < outsize) {
- outsize = stream->recv_data_len;
- }
- memcpy(buf, stream->recv_buf, outsize);
- if(outsize < stream->recv_data_len) {
- memmove(stream->recv_buf, stream->recv_buf + outsize,
- stream->recv_data_len - outsize);
- }
- stream->recv_data_len -= outsize;
- H3BUGF(infof(data, "returned %zu bytes of data", outsize));
- }
- else if(stream->recv_data_complete) {
- H3BUGF(infof(data, "receive complete"));
- }
-
- msh3_lock_release(&stream->recv_lock);
-
- return (ssize_t)outsize;
-}
-
-CURLcode Curl_quic_done_sending(struct Curl_easy *data)
-{
- struct connectdata *conn = data->conn;
- H3BUGF(infof(data, "Curl_quic_done_sending"));
- if(conn->handler == &msh3_curl_handler_http3) {
- struct HTTP *stream = data->req.p.http;
- stream->upload_done = TRUE;
- }
-
- return CURLE_OK;
-}
-
-void Curl_quic_done(struct Curl_easy *data, bool premature)
-{
- (void)data;
- (void)premature;
- H3BUGF(infof(data, "Curl_quic_done"));
-}
-
-bool Curl_quic_data_pending(const struct Curl_easy *data)
-{
- struct HTTP *stream = data->req.p.http;
- H3BUGF(infof((struct Curl_easy *)data, "Curl_quic_data_pending"));
- return stream->recv_header_len || stream->recv_data_len;
-}
-
-/*
- * Called from transfer.c:Curl_readwrite when neither HTTP level read
- * nor write is performed. It is a good place to handle timer expiry
- * for QUIC transport.
- */
-CURLcode Curl_quic_idle(struct Curl_easy *data)
-{
- (void)data;
- H3BUGF(infof(data, "Curl_quic_idle"));
- return CURLE_OK;
-}
-
-#endif /* USE_MSH3 */
diff --git a/lib/vquic/ngtcp2.c b/lib/vquic/ngtcp2.c
deleted file mode 100644
index ca9c388..0000000
--- a/lib/vquic/ngtcp2.c
+++ /dev/null
@@ -1,2079 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the 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"
-
-#ifdef USE_NGTCP2
-#include <ngtcp2/ngtcp2.h>
-#include <nghttp3/nghttp3.h>
-#ifdef USE_OPENSSL
-#include <openssl/err.h>
-#ifdef OPENSSL_IS_BORINGSSL
-#include <ngtcp2/ngtcp2_crypto_boringssl.h>
-#else
-#include <ngtcp2/ngtcp2_crypto_openssl.h>
-#endif
-#include "vtls/openssl.h"
-#elif defined(USE_GNUTLS)
-#include <ngtcp2/ngtcp2_crypto_gnutls.h>
-#include "vtls/gtls.h"
-#endif
-#include "urldata.h"
-#include "sendf.h"
-#include "strdup.h"
-#include "rand.h"
-#include "ngtcp2.h"
-#include "multiif.h"
-#include "strcase.h"
-#include "connect.h"
-#include "strerror.h"
-#include "dynbuf.h"
-#include "vquic.h"
-#include "h2h3.h"
-#include "vtls/keylog.h"
-#include "vtls/vtls.h"
-
-/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
-
-/* #define DEBUG_NGTCP2 */
-#ifdef CURLDEBUG
-#define DEBUG_HTTP3
-#endif
-#ifdef DEBUG_HTTP3
-#define H3BUGF(x) x
-#else
-#define H3BUGF(x) do { } while(0)
-#endif
-
-#define H3_ALPN_H3_29 "\x5h3-29"
-#define H3_ALPN_H3 "\x2h3"
-
-/*
- * This holds outgoing HTTP/3 stream data that is used by nghttp3 until acked.
- * It is used as a circular buffer. Add new bytes at the end until it reaches
- * the far end, then start over at index 0 again.
- */
-
-#define H3_SEND_SIZE (256*1024)
-struct h3out {
- uint8_t buf[H3_SEND_SIZE];
- size_t used; /* number of bytes used in the buffer */
- size_t windex; /* index in the buffer where to start writing the next
- data block */
-};
-
-#define QUIC_MAX_STREAMS (256*1024)
-#define QUIC_MAX_DATA (1*1024*1024)
-#define QUIC_IDLE_TIMEOUT (60*NGTCP2_SECONDS)
-
-#ifdef USE_OPENSSL
-#define QUIC_CIPHERS \
- "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
- "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
-#define QUIC_GROUPS "P-256:X25519:P-384:P-521"
-#elif defined(USE_GNUTLS)
-#define QUIC_PRIORITY \
- "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
- "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
- "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
- "%DISABLE_TLS13_COMPAT_MODE"
-#endif
-
-/* ngtcp2 default congestion controller does not perform pacing. Limit
- the maximum packet burst to MAX_PKT_BURST packets. */
-#define MAX_PKT_BURST 10
-
-static CURLcode ng_process_ingress(struct Curl_easy *data,
- curl_socket_t sockfd,
- struct quicsocket *qs);
-static CURLcode ng_flush_egress(struct Curl_easy *data, int sockfd,
- struct quicsocket *qs);
-static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
- size_t datalen, void *user_data,
- void *stream_user_data);
-
-static ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref)
-{
- struct quicsocket *qs = conn_ref->user_data;
- return qs->qconn;
-}
-
-static ngtcp2_tstamp timestamp(void)
-{
- struct curltime ct = Curl_now();
- return ct.tv_sec * NGTCP2_SECONDS + ct.tv_usec * NGTCP2_MICROSECONDS;
-}
-
-#ifdef DEBUG_NGTCP2
-static void quic_printf(void *user_data, const char *fmt, ...)
-{
- va_list ap;
- (void)user_data; /* TODO, use this to do infof() instead long-term */
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- fprintf(stderr, "\n");
-}
-#endif
-
-static void qlog_callback(void *user_data, uint32_t flags,
- const void *data, size_t datalen)
-{
- struct quicsocket *qs = (struct quicsocket *)user_data;
- (void)flags;
- if(qs->qlogfd != -1) {
- ssize_t rc = write(qs->qlogfd, data, datalen);
- if(rc == -1) {
- /* on write error, stop further write attempts */
- close(qs->qlogfd);
- qs->qlogfd = -1;
- }
- }
-
-}
-
-static void quic_settings(struct quicsocket *qs,
- uint64_t stream_buffer_size)
-{
- ngtcp2_settings *s = &qs->settings;
- ngtcp2_transport_params *t = &qs->transport_params;
- ngtcp2_settings_default(s);
- ngtcp2_transport_params_default(t);
-#ifdef DEBUG_NGTCP2
- s->log_printf = quic_printf;
-#else
- s->log_printf = NULL;
-#endif
- s->initial_ts = timestamp();
- t->initial_max_stream_data_bidi_local = stream_buffer_size;
- t->initial_max_stream_data_bidi_remote = QUIC_MAX_STREAMS;
- t->initial_max_stream_data_uni = QUIC_MAX_STREAMS;
- t->initial_max_data = QUIC_MAX_DATA;
- t->initial_max_streams_bidi = 1;
- t->initial_max_streams_uni = 3;
- t->max_idle_timeout = QUIC_IDLE_TIMEOUT;
- if(qs->qlogfd != -1) {
- s->qlog.write = qlog_callback;
- }
-}
-
-#ifdef USE_OPENSSL
-static void keylog_callback(const SSL *ssl, const char *line)
-{
- (void)ssl;
- Curl_tls_keylog_write_line(line);
-}
-#elif defined(USE_GNUTLS)
-static int keylog_callback(gnutls_session_t session, const char *label,
- const gnutls_datum_t *secret)
-{
- gnutls_datum_t crandom;
- gnutls_datum_t srandom;
-
- gnutls_session_get_random(session, &crandom, &srandom);
- if(crandom.size != 32) {
- return -1;
- }
-
- Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
- return 0;
-}
-#endif
-
-static int init_ngh3_conn(struct quicsocket *qs);
-
-#ifdef USE_OPENSSL
-static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
-{
- struct connectdata *conn = data->conn;
- SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
-
-#ifdef OPENSSL_IS_BORINGSSL
- if(ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) {
- failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
- return NULL;
- }
-#else
- if(ngtcp2_crypto_openssl_configure_client_context(ssl_ctx) != 0) {
- failf(data, "ngtcp2_crypto_openssl_configure_client_context failed");
- return NULL;
- }
-#endif
-
- SSL_CTX_set_default_verify_paths(ssl_ctx);
-
-#ifdef OPENSSL_IS_BORINGSSL
- if(SSL_CTX_set1_curves_list(ssl_ctx, QUIC_GROUPS) != 1) {
- failf(data, "SSL_CTX_set1_curves_list failed");
- return NULL;
- }
-#else
- if(SSL_CTX_set_ciphersuites(ssl_ctx, QUIC_CIPHERS) != 1) {
- char error_buffer[256];
- ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
- failf(data, "SSL_CTX_set_ciphersuites: %s", error_buffer);
- return NULL;
- }
-
- if(SSL_CTX_set1_groups_list(ssl_ctx, QUIC_GROUPS) != 1) {
- failf(data, "SSL_CTX_set1_groups_list failed");
- return NULL;
- }
-#endif
-
- /* Open the file if a TLS or QUIC backend has not done this before. */
- Curl_tls_keylog_open();
- if(Curl_tls_keylog_enabled()) {
- SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
- }
-
- if(conn->ssl_config.verifypeer) {
- const char * const ssl_cafile = conn->ssl_config.CAfile;
- const char * const ssl_capath = conn->ssl_config.CApath;
-
- if(ssl_cafile || ssl_capath) {
- SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
- /* tell OpenSSL where to find CA certificates that are used to verify
- the server's certificate. */
- if(!SSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:"
- " CAfile: %s CApath: %s",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
- return NULL;
- }
- infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
- infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
- }
-#ifdef CURL_CA_FALLBACK
- else {
- /* verifying the peer without any CA certificates won't work so
- use openssl's built-in default as fallback */
- SSL_CTX_set_default_verify_paths(ssl_ctx);
- }
-#endif
- }
- return ssl_ctx;
-}
-
-static CURLcode quic_set_client_cert(struct Curl_easy *data,
- struct quicsocket *qs)
-{
- struct connectdata *conn = data->conn;
- SSL_CTX *ssl_ctx = qs->sslctx;
- char *const ssl_cert = SSL_SET_OPTION(primary.clientcert);
- const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
- const char *const ssl_cert_type = SSL_SET_OPTION(cert_type);
-
- if(ssl_cert || ssl_cert_blob || ssl_cert_type) {
- return Curl_ossl_set_client_cert(
- data, ssl_ctx, ssl_cert, ssl_cert_blob, ssl_cert_type,
- SSL_SET_OPTION(key), SSL_SET_OPTION(key_blob),
- SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd));
- }
-
- return CURLE_OK;
-}
-
-/** SSL callbacks ***/
-
-static int quic_init_ssl(struct quicsocket *qs)
-{
- const uint8_t *alpn = NULL;
- size_t alpnlen = 0;
- /* this will need some attention when HTTPS proxy over QUIC get fixed */
- const char * const hostname = qs->conn->host.name;
-
- DEBUGASSERT(!qs->ssl);
- qs->ssl = SSL_new(qs->sslctx);
-
- SSL_set_app_data(qs->ssl, &qs->conn_ref);
- SSL_set_connect_state(qs->ssl);
- SSL_set_quic_use_legacy_codepoint(qs->ssl, 0);
-
- alpn = (const uint8_t *)H3_ALPN_H3_29 H3_ALPN_H3;
- alpnlen = sizeof(H3_ALPN_H3_29) - 1 + sizeof(H3_ALPN_H3) - 1;
- if(alpn)
- SSL_set_alpn_protos(qs->ssl, alpn, (int)alpnlen);
-
- /* set SNI */
- SSL_set_tlsext_host_name(qs->ssl, hostname);
- return 0;
-}
-#elif defined(USE_GNUTLS)
-static int quic_init_ssl(struct quicsocket *qs)
-{
- gnutls_datum_t alpn[2];
- /* this will need some attention when HTTPS proxy over QUIC get fixed */
- const char * const hostname = qs->conn->host.name;
- int rc;
-
- DEBUGASSERT(!qs->ssl);
-
- gnutls_init(&qs->ssl, GNUTLS_CLIENT);
- gnutls_session_set_ptr(qs->ssl, &qs->conn_ref);
-
- if(ngtcp2_crypto_gnutls_configure_client_session(qs->ssl) != 0) {
- H3BUGF(fprintf(stderr,
- "ngtcp2_crypto_gnutls_configure_client_session failed\n"));
- return 1;
- }
-
- rc = gnutls_priority_set_direct(qs->ssl, QUIC_PRIORITY, NULL);
- if(rc < 0) {
- H3BUGF(fprintf(stderr, "gnutls_priority_set_direct failed: %s\n",
- gnutls_strerror(rc)));
- return 1;
- }
-
- /* Open the file if a TLS or QUIC backend has not done this before. */
- Curl_tls_keylog_open();
- if(Curl_tls_keylog_enabled()) {
- gnutls_session_set_keylog_function(qs->ssl, keylog_callback);
- }
-
- if(qs->cred)
- gnutls_certificate_free_credentials(qs->cred);
-
- rc = gnutls_certificate_allocate_credentials(&qs->cred);
- if(rc < 0) {
- H3BUGF(fprintf(stderr,
- "gnutls_certificate_allocate_credentials failed: %s\n",
- gnutls_strerror(rc)));
- return 1;
- }
-
- rc = gnutls_certificate_set_x509_system_trust(qs->cred);
- if(rc < 0) {
- H3BUGF(fprintf(stderr,
- "gnutls_certificate_set_x509_system_trust failed: %s\n",
- gnutls_strerror(rc)));
- return 1;
- }
-
- rc = gnutls_credentials_set(qs->ssl, GNUTLS_CRD_CERTIFICATE, qs->cred);
- if(rc < 0) {
- H3BUGF(fprintf(stderr, "gnutls_credentials_set failed: %s\n",
- gnutls_strerror(rc)));
- return 1;
- }
-
- /* strip the first byte (the length) from NGHTTP3_ALPN_H3 */
- alpn[0].data = (unsigned char *)H3_ALPN_H3_29 + 1;
- alpn[0].size = sizeof(H3_ALPN_H3_29) - 2;
- alpn[1].data = (unsigned char *)H3_ALPN_H3 + 1;
- alpn[1].size = sizeof(H3_ALPN_H3) - 2;
-
- gnutls_alpn_set_protocols(qs->ssl, alpn, 2, GNUTLS_ALPN_MANDATORY);
-
- /* set SNI */
- gnutls_server_name_set(qs->ssl, GNUTLS_NAME_DNS, hostname, strlen(hostname));
- return 0;
-}
-#endif
-
-static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
-{
- (void)user_data;
- (void)tconn;
- return 0;
-}
-
-static void extend_stream_window(ngtcp2_conn *tconn,
- struct HTTP *stream)
-{
- size_t thismuch = stream->unacked_window;
- ngtcp2_conn_extend_max_stream_offset(tconn, stream->stream3_id, thismuch);
- ngtcp2_conn_extend_max_offset(tconn, thismuch);
- stream->unacked_window = 0;
-}
-
-
-static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
- int64_t stream_id, uint64_t offset,
- const uint8_t *buf, size_t buflen,
- void *user_data, void *stream_user_data)
-{
- struct quicsocket *qs = (struct quicsocket *)user_data;
- nghttp3_ssize nconsumed;
- int fin = (flags & NGTCP2_STREAM_DATA_FLAG_FIN) ? 1 : 0;
- (void)offset;
- (void)stream_user_data;
-
- nconsumed =
- nghttp3_conn_read_stream(qs->h3conn, stream_id, buf, buflen, fin);
- if(nconsumed < 0) {
- ngtcp2_connection_close_error_set_application_error(
- &qs->last_error, nghttp3_err_infer_quic_app_error_code((int)nconsumed),
- NULL, 0);
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- /* number of bytes inside buflen which consists of framing overhead
- * including QPACK HEADERS. In other words, it does not consume payload of
- * DATA frame. */
- ngtcp2_conn_extend_max_stream_offset(tconn, stream_id, nconsumed);
- ngtcp2_conn_extend_max_offset(tconn, nconsumed);
-
- 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)
-{
- struct quicsocket *qs = (struct quicsocket *)user_data;
- int rv;
- (void)stream_id;
- (void)tconn;
- (void)offset;
- (void)datalen;
- (void)stream_user_data;
-
- rv = nghttp3_conn_add_ack_offset(qs->h3conn, stream_id, datalen);
- if(rv) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags,
- int64_t stream_id, uint64_t app_error_code,
- void *user_data, void *stream_user_data)
-{
- struct quicsocket *qs = (struct quicsocket *)user_data;
- int rv;
- (void)tconn;
- (void)stream_user_data;
- /* stream is closed... */
-
- if(!(flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET)) {
- app_error_code = NGHTTP3_H3_NO_ERROR;
- }
-
- rv = nghttp3_conn_close_stream(qs->h3conn, stream_id,
- app_error_code);
- if(rv) {
- ngtcp2_connection_close_error_set_application_error(
- &qs->last_error, nghttp3_err_infer_quic_app_error_code(rv), NULL, 0);
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-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 quicsocket *qs = (struct quicsocket *)user_data;
- int rv;
- (void)tconn;
- (void)final_size;
- (void)app_error_code;
- (void)stream_user_data;
-
- rv = nghttp3_conn_shutdown_stream_read(qs->h3conn, stream_id);
- if(rv) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int cb_stream_stop_sending(ngtcp2_conn *tconn, int64_t stream_id,
- uint64_t app_error_code, void *user_data,
- void *stream_user_data)
-{
- struct quicsocket *qs = (struct quicsocket *)user_data;
- int rv;
- (void)tconn;
- (void)app_error_code;
- (void)stream_user_data;
-
- rv = nghttp3_conn_shutdown_stream_read(qs->h3conn, stream_id);
- if(rv) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int cb_extend_max_local_streams_bidi(ngtcp2_conn *tconn,
- uint64_t max_streams,
- void *user_data)
-{
- (void)tconn;
- (void)max_streams;
- (void)user_data;
-
- return 0;
-}
-
-static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id,
- uint64_t max_data, void *user_data,
- void *stream_user_data)
-{
- struct quicsocket *qs = (struct quicsocket *)user_data;
- int rv;
- (void)tconn;
- (void)max_data;
- (void)stream_user_data;
-
- rv = nghttp3_conn_unblock_stream(qs->h3conn, stream_id);
- if(rv) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static void cb_rand(uint8_t *dest, size_t destlen,
- const ngtcp2_rand_ctx *rand_ctx)
-{
- CURLcode result;
- (void)rand_ctx;
-
- result = Curl_rand(NULL, dest, destlen);
- if(result) {
- /* cb_rand is only used for non-cryptographic context. If Curl_rand
- failed, just fill 0 and call it *random*. */
- memset(dest, 0, destlen);
- }
-}
-
-static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
- uint8_t *token, size_t cidlen,
- void *user_data)
-{
- CURLcode result;
- (void)tconn;
- (void)user_data;
-
- result = Curl_rand(NULL, cid->data, cidlen);
- if(result)
- return NGTCP2_ERR_CALLBACK_FAILURE;
- cid->datalen = cidlen;
-
- result = Curl_rand(NULL, token, NGTCP2_STATELESS_RESET_TOKENLEN);
- if(result)
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- return 0;
-}
-
-static int cb_recv_rx_key(ngtcp2_conn *tconn, ngtcp2_crypto_level level,
- void *user_data)
-{
- struct quicsocket *qs = (struct quicsocket *)user_data;
- (void)tconn;
-
- if(level != NGTCP2_CRYPTO_LEVEL_APPLICATION) {
- return 0;
- }
-
- if(init_ngh3_conn(qs) != CURLE_OK) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static ngtcp2_callbacks ng_callbacks = {
- ngtcp2_crypto_client_initial_cb,
- NULL, /* recv_client_initial */
- ngtcp2_crypto_recv_crypto_data_cb,
- cb_handshake_completed,
- NULL, /* recv_version_negotiation */
- ngtcp2_crypto_encrypt_cb,
- ngtcp2_crypto_decrypt_cb,
- ngtcp2_crypto_hp_mask_cb,
- cb_recv_stream_data,
- cb_acked_stream_data_offset,
- NULL, /* stream_open */
- cb_stream_close,
- NULL, /* recv_stateless_reset */
- ngtcp2_crypto_recv_retry_cb,
- cb_extend_max_local_streams_bidi,
- NULL, /* extend_max_local_streams_uni */
- cb_rand,
- cb_get_new_connection_id,
- NULL, /* remove_connection_id */
- ngtcp2_crypto_update_key_cb, /* update_key */
- NULL, /* path_validation */
- NULL, /* select_preferred_addr */
- cb_stream_reset,
- NULL, /* extend_max_remote_streams_bidi */
- NULL, /* extend_max_remote_streams_uni */
- cb_extend_max_stream_data,
- NULL, /* dcid_status */
- NULL, /* handshake_confirmed */
- NULL, /* recv_new_token */
- ngtcp2_crypto_delete_crypto_aead_ctx_cb,
- ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
- NULL, /* recv_datagram */
- NULL, /* ack_datagram */
- NULL, /* lost_datagram */
- ngtcp2_crypto_get_path_challenge_data_cb,
- cb_stream_stop_sending,
- NULL, /* version_negotiation */
- cb_recv_rx_key,
- NULL, /* recv_tx_key */
-};
-
-/*
- * Might be called twice for happy eyeballs.
- */
-CURLcode Curl_quic_connect(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t sockfd,
- int sockindex,
- const struct sockaddr *addr,
- socklen_t addrlen)
-{
- int rc;
- int rv;
- CURLcode result;
- ngtcp2_path path; /* TODO: this must be initialized properly */
- struct quicsocket *qs = &conn->hequic[sockindex];
- char ipbuf[40];
- int port;
- int qfd;
-
- if(qs->conn)
- Curl_quic_disconnect(data, conn, sockindex);
- qs->conn = conn;
-
- /* extract the used address as a string */
- if(!Curl_addr2string((struct sockaddr*)addr, addrlen, ipbuf, &port)) {
- char buffer[STRERROR_LEN];
- failf(data, "ssrem inet_ntop() failed with errno %d: %s",
- SOCKERRNO, Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- return CURLE_BAD_FUNCTION_ARGUMENT;
- }
-
- infof(data, "Connect socket %d over QUIC to %s:%d",
- sockfd, ipbuf, port);
-
- qs->version = NGTCP2_PROTO_VER_MAX;
-#ifdef USE_OPENSSL
- qs->sslctx = quic_ssl_ctx(data);
- if(!qs->sslctx)
- return CURLE_QUIC_CONNECT_ERROR;
-
- result = quic_set_client_cert(data, qs);
- if(result)
- return result;
-#endif
-
- if(quic_init_ssl(qs))
- return CURLE_QUIC_CONNECT_ERROR;
-
- qs->dcid.datalen = NGTCP2_MAX_CIDLEN;
- result = Curl_rand(data, qs->dcid.data, NGTCP2_MAX_CIDLEN);
- if(result)
- return result;
-
- qs->scid.datalen = NGTCP2_MAX_CIDLEN;
- result = Curl_rand(data, qs->scid.data, NGTCP2_MAX_CIDLEN);
- if(result)
- return result;
-
- (void)Curl_qlogdir(data, qs->scid.data, NGTCP2_MAX_CIDLEN, &qfd);
- qs->qlogfd = qfd; /* -1 if failure above */
- quic_settings(qs, data->set.buffer_size);
-
- qs->local_addrlen = sizeof(qs->local_addr);
- rv = getsockname(sockfd, (struct sockaddr *)&qs->local_addr,
- &qs->local_addrlen);
- if(rv == -1)
- return CURLE_QUIC_CONNECT_ERROR;
-
- ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr,
- qs->local_addrlen);
- ngtcp2_addr_init(&path.remote, addr, addrlen);
-
- rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path,
- NGTCP2_PROTO_VER_V1, &ng_callbacks,
- &qs->settings, &qs->transport_params, NULL, qs);
- if(rc)
- return CURLE_QUIC_CONNECT_ERROR;
-
- ngtcp2_conn_set_tls_native_handle(qs->qconn, qs->ssl);
-
- ngtcp2_connection_close_error_default(&qs->last_error);
-
-#if defined(__linux__) && defined(UDP_SEGMENT) && defined(HAVE_SENDMSG)
- qs->no_gso = FALSE;
-#else
- qs->no_gso = TRUE;
-#endif
-
- qs->num_blocked_pkt = 0;
- qs->num_blocked_pkt_sent = 0;
- memset(&qs->blocked_pkt, 0, sizeof(qs->blocked_pkt));
-
- qs->pktbuflen = NGTCP2_MAX_PMTUD_UDP_PAYLOAD_SIZE * MAX_PKT_BURST;
- qs->pktbuf = malloc(qs->pktbuflen);
- if(!qs->pktbuf) {
- ngtcp2_conn_del(qs->qconn);
- qs->qconn = NULL;
- return CURLE_OUT_OF_MEMORY;
- }
-
- qs->conn_ref.get_conn = get_conn;
- qs->conn_ref.user_data = qs;
-
- return CURLE_OK;
-}
-
-/*
- * Store ngtcp2 version info in this buffer.
- */
-void Curl_quic_ver(char *p, size_t len)
-{
- const ngtcp2_info *ng2 = ngtcp2_version(0);
- const nghttp3_info *ht3 = nghttp3_version(0);
- (void)msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
- ng2->version_str, ht3->version_str);
-}
-
-static int ng_getsock(struct Curl_easy *data, struct connectdata *conn,
- curl_socket_t *socks)
-{
- struct SingleRequest *k = &data->req;
- int bitmap = GETSOCK_BLANK;
- struct HTTP *stream = data->req.p.http;
- struct quicsocket *qs = conn->quic;
-
- socks[0] = conn->sock[FIRSTSOCKET];
-
- /* in a HTTP/2 connection we can basically always get a frame so we should
- always be ready for one */
- bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
-
- /* we're still uploading or the HTTP/2 layer wants to send data */
- if((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND &&
- (!stream->h3out || stream->h3out->used < H3_SEND_SIZE) &&
- ngtcp2_conn_get_cwnd_left(qs->qconn) &&
- ngtcp2_conn_get_max_data_left(qs->qconn) &&
- nghttp3_conn_is_stream_writable(qs->h3conn, stream->stream3_id))
- bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
-
- return bitmap;
-}
-
-static void qs_disconnect(struct quicsocket *qs)
-{
- char buffer[NGTCP2_MAX_UDP_PAYLOAD_SIZE];
- ngtcp2_tstamp ts;
- ngtcp2_ssize rc;
-
- if(!qs->conn) /* already closed */
- return;
- ts = timestamp();
- rc = ngtcp2_conn_write_connection_close(qs->qconn, NULL, /* path */
- NULL, /* pkt_info */
- (uint8_t *)buffer, sizeof(buffer),
- &qs->last_error, ts);
- if(rc > 0) {
- while((send(qs->conn->sock[FIRSTSOCKET], buffer, rc, 0) == -1) &&
- SOCKERRNO == EINTR);
- }
-
- qs->conn = NULL;
- if(qs->qlogfd != -1) {
- close(qs->qlogfd);
- qs->qlogfd = -1;
- }
- if(qs->ssl)
-#ifdef USE_OPENSSL
- SSL_free(qs->ssl);
-#elif defined(USE_GNUTLS)
- gnutls_deinit(qs->ssl);
-#endif
- qs->ssl = NULL;
-#ifdef USE_GNUTLS
- if(qs->cred) {
- gnutls_certificate_free_credentials(qs->cred);
- qs->cred = NULL;
- }
-#endif
- free(qs->pktbuf);
- nghttp3_conn_del(qs->h3conn);
- ngtcp2_conn_del(qs->qconn);
-#ifdef USE_OPENSSL
- SSL_CTX_free(qs->sslctx);
-#endif
-}
-
-void Curl_quic_disconnect(struct Curl_easy *data,
- struct connectdata *conn,
- int tempindex)
-{
- (void)data;
- if(conn->transport == TRNSPRT_QUIC)
- qs_disconnect(&conn->hequic[tempindex]);
-}
-
-static CURLcode ng_disconnect(struct Curl_easy *data,
- struct connectdata *conn,
- bool dead_connection)
-{
- (void)dead_connection;
- Curl_quic_disconnect(data, conn, 0);
- Curl_quic_disconnect(data, conn, 1);
- return CURLE_OK;
-}
-
-static unsigned int ng_conncheck(struct Curl_easy *data,
- struct connectdata *conn,
- unsigned int checks_to_perform)
-{
- (void)data;
- (void)conn;
- (void)checks_to_perform;
- return CONNRESULT_NONE;
-}
-
-static const struct Curl_handler Curl_handler_http3 = {
- "HTTPS", /* scheme */
- ZERO_NULL, /* setup_connection */
- Curl_http, /* do_it */
- Curl_http_done, /* done */
- ZERO_NULL, /* do_more */
- ZERO_NULL, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ng_getsock, /* proto_getsock */
- ng_getsock, /* doing_getsock */
- ZERO_NULL, /* domore_getsock */
- ng_getsock, /* perform_getsock */
- ng_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
- ng_conncheck, /* connection_check */
- ZERO_NULL, /* attach connection */
- PORT_HTTP, /* defport */
- CURLPROTO_HTTPS, /* protocol */
- CURLPROTO_HTTP, /* family */
- PROTOPT_SSL | PROTOPT_STREAM /* flags */
-};
-
-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_easy *data = stream_user_data;
- struct HTTP *stream = data->req.p.http;
- (void)conn;
- (void)stream_id;
- (void)app_error_code;
- (void)user_data;
- H3BUGF(infof(data, "cb_h3_stream_close CALLED"));
-
- stream->closed = TRUE;
- Curl_expire(data, 0, EXPIRE_QUIC);
- /* make sure that ngh3_stream_recv is called again to complete the transfer
- even if there are no more packets to be received from the server. */
- data->state.drain = 1;
- return 0;
-}
-
-/*
- * write_data() copies data to the stream's receive buffer. If not enough
- * space is available in the receive buffer, it copies the rest to the
- * stream's overflow buffer.
- */
-static CURLcode write_data(struct HTTP *stream, const void *mem, size_t memlen)
-{
- CURLcode result = CURLE_OK;
- const char *buf = mem;
- size_t ncopy = memlen;
- /* copy as much as possible to the receive buffer */
- if(stream->len) {
- size_t len = CURLMIN(ncopy, stream->len);
- memcpy(stream->mem, buf, len);
- stream->len -= len;
- stream->memlen += len;
- stream->mem += len;
- buf += len;
- ncopy -= len;
- }
- /* copy the rest to the overflow buffer */
- if(ncopy)
- result = Curl_dyn_addn(&stream->overflow, buf, ncopy);
- return result;
-}
-
-static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream_id,
- const uint8_t *buf, size_t buflen,
- void *user_data, void *stream_user_data)
-{
- struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.p.http;
- CURLcode result = CURLE_OK;
- (void)conn;
-
- result = write_data(stream, buf, buflen);
- if(result) {
- return -1;
- }
- stream->unacked_window += buflen;
- (void)stream_id;
- (void)user_data;
- return 0;
-}
-
-static int cb_h3_deferred_consume(nghttp3_conn *conn, int64_t stream_id,
- size_t consumed, void *user_data,
- void *stream_user_data)
-{
- struct quicsocket *qs = user_data;
- (void)conn;
- (void)stream_user_data;
- (void)stream_id;
-
- ngtcp2_conn_extend_max_stream_offset(qs->qconn, stream_id, consumed);
- ngtcp2_conn_extend_max_offset(qs->qconn, consumed);
- return 0;
-}
-
-/* Decode HTTP status code. Returns -1 if no valid status code was
- decoded. (duplicate from http2.c) */
-static int decode_status_code(const uint8_t *value, size_t len)
-{
- int i;
- int res;
-
- if(len != 3) {
- return -1;
- }
-
- res = 0;
-
- for(i = 0; i < 3; ++i) {
- char c = value[i];
-
- if(c < '0' || c > '9') {
- return -1;
- }
-
- res *= 10;
- res += c - '0';
- }
-
- return res;
-}
-
-static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
- int fin, void *user_data, void *stream_user_data)
-{
- struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.p.http;
- CURLcode result = CURLE_OK;
- (void)conn;
- (void)stream_id;
- (void)user_data;
- (void)fin;
-
- /* add a CRLF only if we've received some headers */
- if(stream->firstheader) {
- result = write_data(stream, "\r\n", 2);
- if(result) {
- return -1;
- }
- }
- return 0;
-}
-
-static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
- int32_t token, nghttp3_rcbuf *name,
- nghttp3_rcbuf *value, uint8_t flags,
- void *user_data, void *stream_user_data)
-{
- nghttp3_vec h3name = nghttp3_rcbuf_get_buf(name);
- nghttp3_vec h3val = nghttp3_rcbuf_get_buf(value);
- struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.p.http;
- CURLcode result = CURLE_OK;
- (void)conn;
- (void)stream_id;
- (void)token;
- (void)flags;
- (void)user_data;
-
- if(token == NGHTTP3_QPACK_TOKEN__STATUS) {
- char line[14]; /* status line is always 13 characters long */
- size_t ncopy;
- int status = decode_status_code(h3val.base, h3val.len);
- DEBUGASSERT(status != -1);
- ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n", status);
- result = write_data(stream, line, ncopy);
- if(result) {
- return -1;
- }
- }
- else {
- /* store as a HTTP1-style header */
- result = write_data(stream, h3name.base, h3name.len);
- if(result) {
- return -1;
- }
- result = write_data(stream, ": ", 2);
- if(result) {
- return -1;
- }
- result = write_data(stream, h3val.base, h3val.len);
- if(result) {
- return -1;
- }
- result = write_data(stream, "\r\n", 2);
- if(result) {
- return -1;
- }
- }
-
- stream->firstheader = TRUE;
- return 0;
-}
-
-static int cb_h3_send_stop_sending(nghttp3_conn *conn, int64_t stream_id,
- uint64_t app_error_code,
- void *user_data,
- void *stream_user_data)
-{
- (void)conn;
- (void)stream_id;
- (void)app_error_code;
- (void)user_data;
- (void)stream_user_data;
- return 0;
-}
-
-static nghttp3_callbacks ngh3_callbacks = {
- cb_h3_acked_stream_data, /* acked_stream_data */
- cb_h3_stream_close,
- cb_h3_recv_data,
- cb_h3_deferred_consume,
- NULL, /* begin_headers */
- cb_h3_recv_header,
- cb_h3_end_headers,
- NULL, /* begin_trailers */
- cb_h3_recv_header,
- NULL, /* end_trailers */
- cb_h3_send_stop_sending,
- NULL, /* end_stream */
- NULL, /* reset_stream */
- NULL /* shutdown */
-};
-
-static int init_ngh3_conn(struct quicsocket *qs)
-{
- CURLcode result;
- int rc;
- int64_t ctrl_stream_id, qpack_enc_stream_id, qpack_dec_stream_id;
-
- if(ngtcp2_conn_get_max_local_streams_uni(qs->qconn) < 3) {
- return CURLE_QUIC_CONNECT_ERROR;
- }
-
- nghttp3_settings_default(&qs->h3settings);
-
- rc = nghttp3_conn_client_new(&qs->h3conn,
- &ngh3_callbacks,
- &qs->h3settings,
- nghttp3_mem_default(),
- qs);
- if(rc) {
- result = CURLE_OUT_OF_MEMORY;
- goto fail;
- }
-
- rc = ngtcp2_conn_open_uni_stream(qs->qconn, &ctrl_stream_id, NULL);
- if(rc) {
- result = CURLE_QUIC_CONNECT_ERROR;
- goto fail;
- }
-
- rc = nghttp3_conn_bind_control_stream(qs->h3conn, ctrl_stream_id);
- if(rc) {
- result = CURLE_QUIC_CONNECT_ERROR;
- goto fail;
- }
-
- rc = ngtcp2_conn_open_uni_stream(qs->qconn, &qpack_enc_stream_id, NULL);
- if(rc) {
- result = CURLE_QUIC_CONNECT_ERROR;
- goto fail;
- }
-
- rc = ngtcp2_conn_open_uni_stream(qs->qconn, &qpack_dec_stream_id, NULL);
- if(rc) {
- result = CURLE_QUIC_CONNECT_ERROR;
- goto fail;
- }
-
- rc = nghttp3_conn_bind_qpack_streams(qs->h3conn, qpack_enc_stream_id,
- qpack_dec_stream_id);
- if(rc) {
- result = CURLE_QUIC_CONNECT_ERROR;
- goto fail;
- }
-
- return CURLE_OK;
- fail:
-
- return result;
-}
-
-static Curl_recv ngh3_stream_recv;
-static Curl_send ngh3_stream_send;
-
-static size_t drain_overflow_buffer(struct HTTP *stream)
-{
- size_t overlen = Curl_dyn_len(&stream->overflow);
- size_t ncopy = CURLMIN(overlen, stream->len);
- if(ncopy > 0) {
- memcpy(stream->mem, Curl_dyn_ptr(&stream->overflow), ncopy);
- stream->len -= ncopy;
- stream->mem += ncopy;
- stream->memlen += ncopy;
- if(ncopy != overlen)
- /* make the buffer only keep the tail */
- (void)Curl_dyn_tail(&stream->overflow, overlen - ncopy);
- else
- Curl_dyn_reset(&stream->overflow);
- }
- return ncopy;
-}
-
-/* incoming data frames on the h3 stream */
-static ssize_t ngh3_stream_recv(struct Curl_easy *data,
- int sockindex,
- char *buf,
- size_t buffersize,
- CURLcode *curlcode)
-{
- struct connectdata *conn = data->conn;
- curl_socket_t sockfd = conn->sock[sockindex];
- struct HTTP *stream = data->req.p.http;
- struct quicsocket *qs = conn->quic;
-
- if(!stream->memlen) {
- /* remember where to store incoming data for this stream and how big the
- buffer is */
- stream->mem = buf;
- stream->len = buffersize;
- }
- /* else, there's data in the buffer already */
-
- /* if there's data in the overflow buffer from a previous call, copy as much
- as possible to the receive buffer before receiving more */
- drain_overflow_buffer(stream);
-
- if(ng_process_ingress(data, sockfd, qs)) {
- *curlcode = CURLE_RECV_ERROR;
- return -1;
- }
- if(ng_flush_egress(data, sockfd, qs)) {
- *curlcode = CURLE_SEND_ERROR;
- return -1;
- }
-
- if(stream->memlen) {
- ssize_t memlen = stream->memlen;
- /* data arrived */
- *curlcode = CURLE_OK;
- /* reset to allow more data to come */
- stream->memlen = 0;
- stream->mem = buf;
- stream->len = buffersize;
- /* extend the stream window with the data we're consuming and send out
- any additional packets to tell the server that we can receive more */
- extend_stream_window(qs->qconn, stream);
- if(ng_flush_egress(data, sockfd, qs)) {
- *curlcode = CURLE_SEND_ERROR;
- return -1;
- }
- return memlen;
- }
-
- if(stream->closed) {
- *curlcode = CURLE_OK;
- return 0;
- }
-
- infof(data, "ngh3_stream_recv returns 0 bytes and EAGAIN");
- *curlcode = CURLE_AGAIN;
- return -1;
-}
-
-/* this amount of data has now been acked on this stream */
-static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
- size_t datalen, void *user_data,
- void *stream_user_data)
-{
- struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.p.http;
- (void)user_data;
-
- if(!data->set.postfields) {
- stream->h3out->used -= datalen;
- H3BUGF(infof(data,
- "cb_h3_acked_stream_data, %zd bytes, %zd left unacked",
- datalen, stream->h3out->used));
- DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE);
-
- if(stream->h3out->used == 0) {
- int rv = nghttp3_conn_resume_stream(conn, stream_id);
- if(rv) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
- }
- }
- return 0;
-}
-
-static nghttp3_ssize cb_h3_readfunction(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_easy *data = stream_user_data;
- size_t nread;
- struct HTTP *stream = data->req.p.http;
- (void)conn;
- (void)stream_id;
- (void)user_data;
- (void)veccnt;
-
- if(data->set.postfields) {
- vec[0].base = data->set.postfields;
- vec[0].len = data->state.infilesize;
- *pflags = NGHTTP3_DATA_FLAG_EOF;
- return 1;
- }
-
- if(stream->upload_len && H3_SEND_SIZE <= stream->h3out->used) {
- return NGHTTP3_ERR_WOULDBLOCK;
- }
-
- nread = CURLMIN(stream->upload_len, H3_SEND_SIZE - stream->h3out->used);
- if(nread > 0) {
- /* nghttp3 wants us to hold on to the data until it tells us it is okay to
- delete it. Append the data at the end of the h3out buffer. Since we can
- only return consecutive data, copy the amount that fits and the next
- part comes in next invoke. */
- struct h3out *out = stream->h3out;
- if(nread + out->windex > H3_SEND_SIZE)
- nread = H3_SEND_SIZE - out->windex;
-
- memcpy(&out->buf[out->windex], stream->upload_mem, nread);
-
- /* that's the chunk we return to nghttp3 */
- vec[0].base = &out->buf[out->windex];
- vec[0].len = nread;
-
- out->windex += nread;
- out->used += nread;
-
- if(out->windex == H3_SEND_SIZE)
- out->windex = 0; /* wrap */
- stream->upload_mem += nread;
- stream->upload_len -= nread;
- if(data->state.infilesize != -1) {
- stream->upload_left -= nread;
- if(!stream->upload_left)
- *pflags = NGHTTP3_DATA_FLAG_EOF;
- }
- H3BUGF(infof(data, "cb_h3_readfunction %zd bytes%s (at %zd unacked)",
- nread, *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
- out->used));
- }
- if(stream->upload_done && !stream->upload_len &&
- (stream->upload_left <= 0)) {
- H3BUGF(infof(data, "cb_h3_readfunction sets EOF"));
- *pflags = NGHTTP3_DATA_FLAG_EOF;
- return nread ? 1 : 0;
- }
- else if(!nread) {
- return NGHTTP3_ERR_WOULDBLOCK;
- }
- return 1;
-}
-
-/* Index where :authority header field will appear in request header
- field list. */
-#define AUTHORITY_DST_IDX 3
-
-static CURLcode http_request(struct Curl_easy *data, const void *mem,
- size_t len)
-{
- struct connectdata *conn = data->conn;
- struct HTTP *stream = data->req.p.http;
- size_t nheader;
- struct quicsocket *qs = conn->quic;
- CURLcode result = CURLE_OK;
- nghttp3_nv *nva = NULL;
- int64_t stream3_id;
- int rc;
- struct h3out *h3out = NULL;
- struct h2h3req *hreq = NULL;
-
- rc = ngtcp2_conn_open_bidi_stream(qs->qconn, &stream3_id, NULL);
- if(rc) {
- failf(data, "can get bidi streams");
- result = CURLE_SEND_ERROR;
- goto fail;
- }
-
- stream->stream3_id = stream3_id;
- stream->h3req = TRUE; /* senf off! */
- Curl_dyn_init(&stream->overflow, CURL_MAX_READ_SIZE);
-
- result = Curl_pseudo_headers(data, mem, len, &hreq);
- if(result)
- goto fail;
- nheader = hreq->entries;
-
- nva = malloc(sizeof(nghttp3_nv) * nheader);
- if(!nva) {
- result = CURLE_OUT_OF_MEMORY;
- goto fail;
- }
- else {
- unsigned int i;
- for(i = 0; i < nheader; i++) {
- nva[i].name = (unsigned char *)hreq->header[i].name;
- nva[i].namelen = hreq->header[i].namelen;
- nva[i].value = (unsigned char *)hreq->header[i].value;
- nva[i].valuelen = hreq->header[i].valuelen;
- }
- }
-
- switch(data->state.httpreq) {
- case HTTPREQ_POST:
- case HTTPREQ_POST_FORM:
- case HTTPREQ_POST_MIME:
- case HTTPREQ_PUT: {
- nghttp3_data_reader data_reader;
- if(data->state.infilesize != -1)
- stream->upload_left = data->state.infilesize;
- else
- /* data sending without specifying the data amount up front */
- stream->upload_left = -1; /* unknown, but not zero */
-
- data_reader.read_data = cb_h3_readfunction;
-
- h3out = calloc(sizeof(struct h3out), 1);
- if(!h3out) {
- result = CURLE_OUT_OF_MEMORY;
- goto fail;
- }
- stream->h3out = h3out;
-
- rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
- nva, nheader, &data_reader, data);
- if(rc) {
- result = CURLE_SEND_ERROR;
- goto fail;
- }
- break;
- }
- default:
- stream->upload_left = 0; /* nothing left to send */
- rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
- nva, nheader, NULL, data);
- if(rc) {
- result = CURLE_SEND_ERROR;
- goto fail;
- }
- break;
- }
-
- Curl_safefree(nva);
-
- infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)",
- stream3_id, (void *)data);
-
- Curl_pseudo_free(hreq);
- return CURLE_OK;
-
-fail:
- free(nva);
- Curl_pseudo_free(hreq);
- return result;
-}
-static ssize_t ngh3_stream_send(struct Curl_easy *data,
- int sockindex,
- const void *mem,
- size_t len,
- CURLcode *curlcode)
-{
- ssize_t sent = 0;
- struct connectdata *conn = data->conn;
- struct quicsocket *qs = conn->quic;
- curl_socket_t sockfd = conn->sock[sockindex];
- struct HTTP *stream = data->req.p.http;
-
- if(!stream->h3req) {
- CURLcode result = http_request(data, mem, len);
- if(result) {
- *curlcode = CURLE_SEND_ERROR;
- return -1;
- }
- /* Assume that mem of length len only includes HTTP/1.1 style
- header fields. In other words, it does not contain request
- body. */
- sent = len;
- }
- else {
- H3BUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes",
- len));
- if(!stream->upload_len) {
- stream->upload_mem = mem;
- stream->upload_len = len;
- (void)nghttp3_conn_resume_stream(qs->h3conn, stream->stream3_id);
- }
- else {
- *curlcode = CURLE_AGAIN;
- return -1;
- }
- }
-
- if(ng_flush_egress(data, sockfd, qs)) {
- *curlcode = CURLE_SEND_ERROR;
- return -1;
- }
-
- /* Reset post upload buffer after resumed. */
- if(stream->upload_mem) {
- if(data->set.postfields) {
- sent = len;
- }
- else {
- sent = len - stream->upload_len;
- }
-
- stream->upload_mem = NULL;
- stream->upload_len = 0;
-
- if(sent == 0) {
- *curlcode = CURLE_AGAIN;
- return -1;
- }
- }
-
- *curlcode = CURLE_OK;
- return sent;
-}
-
-static CURLcode ng_has_connected(struct Curl_easy *data,
- struct connectdata *conn, int tempindex)
-{
- CURLcode result = CURLE_OK;
- conn->recv[FIRSTSOCKET] = ngh3_stream_recv;
- conn->send[FIRSTSOCKET] = ngh3_stream_send;
- conn->handler = &Curl_handler_http3;
- conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
- conn->httpversion = 30;
- conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- conn->quic = &conn->hequic[tempindex];
-
- if(conn->ssl_config.verifyhost) {
-#ifdef USE_OPENSSL
- X509 *server_cert;
- server_cert = SSL_get_peer_certificate(conn->quic->ssl);
- if(!server_cert) {
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- result = Curl_ossl_verifyhost(data, conn, server_cert);
- X509_free(server_cert);
- if(result)
- return result;
- infof(data, "Verified certificate just fine");
-#else
- result = Curl_gtls_verifyserver(data, conn, conn->quic->ssl, FIRSTSOCKET);
-#endif
- }
- else
- infof(data, "Skipped certificate verification");
- return result;
-}
-
-/*
- * There can be multiple connection attempts going on in parallel.
- */
-CURLcode Curl_quic_is_connected(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
- bool *done)
-{
- CURLcode result;
- struct quicsocket *qs = &conn->hequic[sockindex];
- curl_socket_t sockfd = conn->tempsock[sockindex];
-
- result = ng_process_ingress(data, sockfd, qs);
- if(result)
- goto error;
-
- result = ng_flush_egress(data, sockfd, qs);
- if(result)
- goto error;
-
- if(ngtcp2_conn_get_handshake_completed(qs->qconn)) {
- result = ng_has_connected(data, conn, sockindex);
- if(!result)
- *done = TRUE;
- }
-
- return result;
- error:
- (void)qs_disconnect(qs);
- return result;
-
-}
-
-static CURLcode ng_process_ingress(struct Curl_easy *data,
- curl_socket_t sockfd,
- struct quicsocket *qs)
-{
- ssize_t recvd;
- int rv;
- uint8_t buf[65536];
- size_t bufsize = sizeof(buf);
- struct sockaddr_storage remote_addr;
- socklen_t remote_addrlen;
- ngtcp2_path path;
- ngtcp2_tstamp ts = timestamp();
- ngtcp2_pkt_info pi = { 0 };
-
- for(;;) {
- remote_addrlen = sizeof(remote_addr);
- while((recvd = recvfrom(sockfd, (char *)buf, bufsize, 0,
- (struct sockaddr *)&remote_addr,
- &remote_addrlen)) == -1 &&
- SOCKERRNO == EINTR)
- ;
- if(recvd == -1) {
- if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK)
- break;
-
- failf(data, "ngtcp2: recvfrom() unexpectedly returned %zd", recvd);
- return CURLE_RECV_ERROR;
- }
-
- ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr,
- qs->local_addrlen);
- ngtcp2_addr_init(&path.remote, (struct sockaddr *)&remote_addr,
- remote_addrlen);
-
- rv = ngtcp2_conn_read_pkt(qs->qconn, &path, &pi, buf, recvd, ts);
- if(rv) {
- if(!qs->last_error.error_code) {
- if(rv == NGTCP2_ERR_CRYPTO) {
- ngtcp2_connection_close_error_set_transport_error_tls_alert(
- &qs->last_error, ngtcp2_conn_get_tls_alert(qs->qconn), NULL, 0);
- }
- else {
- ngtcp2_connection_close_error_set_transport_error_liberr(
- &qs->last_error, rv, NULL, 0);
- }
- }
-
- 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;
-}
-
-static CURLcode do_sendmsg(size_t *sent, struct Curl_easy *data, int sockfd,
- struct quicsocket *qs, const uint8_t *pkt,
- size_t pktlen, size_t gsolen);
-
-static CURLcode send_packet_no_gso(size_t *psent, struct Curl_easy *data,
- int sockfd, struct quicsocket *qs,
- const uint8_t *pkt, size_t pktlen,
- size_t gsolen)
-{
- const uint8_t *p, *end = pkt + pktlen;
- size_t sent;
-
- *psent = 0;
-
- for(p = pkt; p < end; p += gsolen) {
- size_t len = CURLMIN(gsolen, (size_t)(end - p));
- CURLcode curlcode = do_sendmsg(&sent, data, sockfd, qs, p, len, len);
- if(curlcode != CURLE_OK) {
- return curlcode;
- }
- *psent += sent;
- }
-
- return CURLE_OK;
-}
-
-static CURLcode do_sendmsg(size_t *psent, struct Curl_easy *data, int sockfd,
- struct quicsocket *qs, const uint8_t *pkt,
- size_t pktlen, size_t gsolen)
-{
-#ifdef HAVE_SENDMSG
- struct iovec msg_iov = {(void *)pkt, pktlen};
- struct msghdr msg = {0};
- uint8_t msg_ctrl[32];
- ssize_t sent;
-#if defined(__linux__) && defined(UDP_SEGMENT)
- struct cmsghdr *cm;
-#endif
-
- *psent = 0;
- msg.msg_iov = &msg_iov;
- msg.msg_iovlen = 1;
-
-#if defined(__linux__) && defined(UDP_SEGMENT)
- if(pktlen > gsolen) {
- /* Only set this, when we need it. macOS, for example,
- * does not seem to like a msg_control of length 0. */
- msg.msg_control = msg_ctrl;
- assert(sizeof(msg_ctrl) >= CMSG_SPACE(sizeof(uint16_t)));
- msg.msg_controllen = CMSG_SPACE(sizeof(uint16_t));
- cm = CMSG_FIRSTHDR(&msg);
- cm->cmsg_level = SOL_UDP;
- cm->cmsg_type = UDP_SEGMENT;
- cm->cmsg_len = CMSG_LEN(sizeof(uint16_t));
- *(uint16_t *)(void *)CMSG_DATA(cm) = gsolen & 0xffff;
- }
-#endif
-
-
- while((sent = sendmsg(sockfd, &msg, 0)) == -1 && SOCKERRNO == EINTR)
- ;
-
- if(sent == -1) {
- switch(SOCKERRNO) {
- case EAGAIN:
-#if EAGAIN != EWOULDBLOCK
- case EWOULDBLOCK:
-#endif
- return CURLE_AGAIN;
- case EMSGSIZE:
- /* UDP datagram is too large; caused by PMTUD. Just let it be lost. */
- break;
- case EIO:
- if(pktlen > gsolen) {
- /* GSO failure */
- failf(data, "sendmsg() returned %zd (errno %d); disable GSO", sent,
- SOCKERRNO);
- qs->no_gso = TRUE;
- return send_packet_no_gso(psent, data, sockfd, qs, pkt, pktlen,
- gsolen);
- }
- /* FALLTHROUGH */
- default:
- failf(data, "sendmsg() returned %zd (errno %d)", sent, SOCKERRNO);
- return CURLE_SEND_ERROR;
- }
- }
- else {
- assert(pktlen == (size_t)sent);
- }
-#else
- ssize_t sent;
- (void)qs;
- (void)gsolen;
-
- *psent = 0;
-
- while((sent = send(sockfd, (const char *)pkt, pktlen, 0)) == -1 &&
- SOCKERRNO == EINTR)
- ;
-
- if(sent == -1) {
- if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
- return CURLE_AGAIN;
- }
- else {
- failf(data, "send() returned %zd (errno %d)", sent, SOCKERRNO);
- if(SOCKERRNO != EMSGSIZE) {
- return CURLE_SEND_ERROR;
- }
- /* UDP datagram is too large; caused by PMTUD. Just let it be
- lost. */
- }
- }
-#endif
-
- *psent = pktlen;
-
- return CURLE_OK;
-}
-
-static CURLcode send_packet(size_t *psent, struct Curl_easy *data, int sockfd,
- struct quicsocket *qs, const uint8_t *pkt,
- size_t pktlen, size_t gsolen)
-{
- if(qs->no_gso && pktlen > gsolen) {
- return send_packet_no_gso(psent, data, sockfd, qs, pkt, pktlen, gsolen);
- }
-
- return do_sendmsg(psent, data, sockfd, qs, pkt, pktlen, gsolen);
-}
-
-static void push_blocked_pkt(struct quicsocket *qs, const uint8_t *pkt,
- size_t pktlen, size_t gsolen)
-{
- struct blocked_pkt *blkpkt;
-
- assert(qs->num_blocked_pkt <
- sizeof(qs->blocked_pkt) / sizeof(qs->blocked_pkt[0]));
-
- blkpkt = &qs->blocked_pkt[qs->num_blocked_pkt++];
-
- blkpkt->pkt = pkt;
- blkpkt->pktlen = pktlen;
- blkpkt->gsolen = gsolen;
-}
-
-static CURLcode send_blocked_pkt(struct Curl_easy *data, int sockfd,
- struct quicsocket *qs)
-{
- size_t sent;
- CURLcode curlcode;
- struct blocked_pkt *blkpkt;
-
- for(; qs->num_blocked_pkt_sent < qs->num_blocked_pkt;
- ++qs->num_blocked_pkt_sent) {
- blkpkt = &qs->blocked_pkt[qs->num_blocked_pkt_sent];
- curlcode = send_packet(&sent, data, sockfd, qs, blkpkt->pkt,
- blkpkt->pktlen, blkpkt->gsolen);
-
- if(curlcode) {
- if(curlcode == CURLE_AGAIN) {
- blkpkt->pkt += sent;
- blkpkt->pktlen -= sent;
- }
- return curlcode;
- }
- }
-
- qs->num_blocked_pkt = 0;
- qs->num_blocked_pkt_sent = 0;
-
- return CURLE_OK;
-}
-
-static CURLcode ng_flush_egress(struct Curl_easy *data,
- int sockfd,
- struct quicsocket *qs)
-{
- int rv;
- size_t sent;
- ngtcp2_ssize outlen;
- uint8_t *outpos = qs->pktbuf;
- size_t max_udp_payload_size =
- ngtcp2_conn_get_max_udp_payload_size(qs->qconn);
- size_t path_max_udp_payload_size =
- ngtcp2_conn_get_path_max_udp_payload_size(qs->qconn);
- size_t max_pktcnt =
- CURLMIN(MAX_PKT_BURST, qs->pktbuflen / max_udp_payload_size);
- size_t pktcnt = 0;
- size_t gsolen;
- ngtcp2_path_storage ps;
- ngtcp2_tstamp ts = timestamp();
- ngtcp2_tstamp expiry;
- ngtcp2_duration timeout;
- int64_t stream_id;
- nghttp3_ssize veccnt;
- int fin;
- nghttp3_vec vec[16];
- ngtcp2_ssize ndatalen;
- uint32_t flags;
- CURLcode curlcode;
-
- rv = ngtcp2_conn_handle_expiry(qs->qconn, ts);
- if(rv) {
- failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
- ngtcp2_strerror(rv));
- ngtcp2_connection_close_error_set_transport_error_liberr(&qs->last_error,
- rv, NULL, 0);
- return CURLE_SEND_ERROR;
- }
-
- if(qs->num_blocked_pkt) {
- curlcode = send_blocked_pkt(data, sockfd, qs);
- if(curlcode) {
- if(curlcode == CURLE_AGAIN) {
- Curl_expire(data, 1, EXPIRE_QUIC);
- return CURLE_OK;
- }
- return curlcode;
- }
- }
-
- ngtcp2_path_storage_zero(&ps);
-
- for(;;) {
- veccnt = 0;
- stream_id = -1;
- fin = 0;
-
- if(qs->h3conn && ngtcp2_conn_get_max_data_left(qs->qconn)) {
- veccnt = nghttp3_conn_writev_stream(qs->h3conn, &stream_id, &fin, vec,
- sizeof(vec) / sizeof(vec[0]));
- if(veccnt < 0) {
- failf(data, "nghttp3_conn_writev_stream returned error: %s",
- nghttp3_strerror((int)veccnt));
- ngtcp2_connection_close_error_set_application_error(
- &qs->last_error,
- nghttp3_err_infer_quic_app_error_code((int)veccnt), NULL, 0);
- return CURLE_SEND_ERROR;
- }
- }
-
- flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
- (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
- outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, outpos,
- max_udp_payload_size,
- &ndatalen, flags, stream_id,
- (const ngtcp2_vec *)vec, veccnt, ts);
- if(outlen == 0) {
- if(outpos != qs->pktbuf) {
- curlcode = send_packet(&sent, data, sockfd, qs, qs->pktbuf,
- outpos - qs->pktbuf, gsolen);
- if(curlcode) {
- if(curlcode == CURLE_AGAIN) {
- push_blocked_pkt(qs, qs->pktbuf + sent, outpos - qs->pktbuf - sent,
- gsolen);
- Curl_expire(data, 1, EXPIRE_QUIC);
- return CURLE_OK;
- }
- return curlcode;
- }
- }
-
- break;
- }
- if(outlen < 0) {
- switch(outlen) {
- case NGTCP2_ERR_STREAM_DATA_BLOCKED:
- assert(ndatalen == -1);
- rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
- if(rv) {
- failf(data, "nghttp3_conn_block_stream returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
- continue;
- case NGTCP2_ERR_STREAM_SHUT_WR:
- assert(ndatalen == -1);
- rv = nghttp3_conn_shutdown_stream_write(qs->h3conn, stream_id);
- if(rv) {
- failf(data,
- "nghttp3_conn_shutdown_stream_write returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
- continue;
- case NGTCP2_ERR_WRITE_MORE:
- assert(ndatalen >= 0);
- rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
- if(rv) {
- failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
- continue;
- default:
- assert(ndatalen == -1);
- failf(data, "ngtcp2_conn_writev_stream returned error: %s",
- ngtcp2_strerror((int)outlen));
- ngtcp2_connection_close_error_set_transport_error_liberr(
- &qs->last_error, (int)outlen, NULL, 0);
- return CURLE_SEND_ERROR;
- }
- }
- else if(ndatalen >= 0) {
- rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
- if(rv) {
- failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
- }
-
- outpos += outlen;
-
- if(pktcnt == 0) {
- gsolen = outlen;
- }
- else if((size_t)outlen > gsolen ||
- (gsolen > path_max_udp_payload_size &&
- (size_t)outlen != gsolen)) {
- /* Packet larger than path_max_udp_payload_size is PMTUD probe
- packet and it might not be sent because of EMSGSIZE. Send
- them separately to minimize the loss. */
- curlcode = send_packet(&sent, data, sockfd, qs, qs->pktbuf,
- outpos - outlen - qs->pktbuf, gsolen);
- if(curlcode) {
- if(curlcode == CURLE_AGAIN) {
- push_blocked_pkt(qs, qs->pktbuf + sent,
- outpos - outlen - qs->pktbuf - sent, gsolen);
- push_blocked_pkt(qs, outpos - outlen, outlen, outlen);
- Curl_expire(data, 1, EXPIRE_QUIC);
- return CURLE_OK;
- }
- return curlcode;
- }
- curlcode = send_packet(&sent, data, sockfd, qs, outpos - outlen, outlen,
- outlen);
- if(curlcode) {
- if(curlcode == CURLE_AGAIN) {
- assert(0 == sent);
- push_blocked_pkt(qs, outpos - outlen, outlen, outlen);
- Curl_expire(data, 1, EXPIRE_QUIC);
- return CURLE_OK;
- }
- return curlcode;
- }
-
- pktcnt = 0;
- outpos = qs->pktbuf;
- continue;
- }
-
- if(++pktcnt >= max_pktcnt || (size_t)outlen < gsolen) {
- curlcode = send_packet(&sent, data, sockfd, qs, qs->pktbuf,
- outpos - qs->pktbuf, gsolen);
- if(curlcode) {
- if(curlcode == CURLE_AGAIN) {
- push_blocked_pkt(qs, qs->pktbuf + sent, outpos - qs->pktbuf - sent,
- gsolen);
- Curl_expire(data, 1, EXPIRE_QUIC);
- return CURLE_OK;
- }
- return curlcode;
- }
-
- pktcnt = 0;
- outpos = qs->pktbuf;
- }
- }
-
- expiry = ngtcp2_conn_get_expiry(qs->qconn);
- if(expiry != UINT64_MAX) {
- if(expiry <= ts) {
- timeout = 0;
- }
- else {
- timeout = expiry - ts;
- if(timeout % NGTCP2_MILLISECONDS) {
- timeout += NGTCP2_MILLISECONDS;
- }
- }
- Curl_expire(data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
- }
-
- return CURLE_OK;
-}
-
-/*
- * Called from transfer.c:done_sending when we stop HTTP/3 uploading.
- */
-CURLcode Curl_quic_done_sending(struct Curl_easy *data)
-{
- struct connectdata *conn = data->conn;
- DEBUGASSERT(conn);
- if(conn->handler == &Curl_handler_http3) {
- /* only for HTTP/3 transfers */
- struct HTTP *stream = data->req.p.http;
- struct quicsocket *qs = conn->quic;
- stream->upload_done = TRUE;
- (void)nghttp3_conn_resume_stream(qs->h3conn, stream->stream3_id);
- }
-
- return CURLE_OK;
-}
-
-/*
- * Called from http.c:Curl_http_done when a request completes.
- */
-void Curl_quic_done(struct Curl_easy *data, bool premature)
-{
- (void)premature;
- if(data->conn->handler == &Curl_handler_http3) {
- /* only for HTTP/3 transfers */
- struct HTTP *stream = data->req.p.http;
- Curl_dyn_free(&stream->overflow);
- free(stream->h3out);
- }
-}
-
-/*
- * Called from transfer.c:data_pending to know if we should keep looping
- * to receive more data from the connection.
- */
-bool Curl_quic_data_pending(const struct Curl_easy *data)
-{
- /* We may have received more data than we're able to hold in the receive
- buffer and allocated an overflow buffer. Since it's possible that
- there's no more data coming on the socket, we need to keep reading
- until the overflow buffer is empty. */
- const struct HTTP *stream = data->req.p.http;
- return Curl_dyn_len(&stream->overflow) > 0;
-}
-
-/*
- * Called from transfer.c:Curl_readwrite when neither HTTP level read
- * nor write is performed. It is a good place to handle timer expiry
- * for QUIC transport.
- */
-CURLcode Curl_quic_idle(struct Curl_easy *data)
-{
- struct connectdata *conn = data->conn;
- curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- struct quicsocket *qs = conn->quic;
-
- if(ngtcp2_conn_get_expiry(qs->qconn) > timestamp()) {
- return CURLE_OK;
- }
-
- if(ng_flush_egress(data, sockfd, qs)) {
- return CURLE_SEND_ERROR;
- }
-
- return CURLE_OK;
-}
-
-#endif
diff --git a/lib/vquic/ngtcp2.h b/lib/vquic/ngtcp2.h
deleted file mode 100644
index 23fbcb6..0000000
--- a/lib/vquic/ngtcp2.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef HEADER_CURL_VQUIC_NGTCP2_H
-#define HEADER_CURL_VQUIC_NGTCP2_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the 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"
-
-#ifdef USE_NGTCP2
-
-#ifdef HAVE_NETINET_UDP_H
-#include <netinet/udp.h>
-#endif
-
-#include <ngtcp2/ngtcp2_crypto.h>
-#include <nghttp3/nghttp3.h>
-#ifdef USE_OPENSSL
-#include <openssl/ssl.h>
-#elif defined(USE_GNUTLS)
-#include <gnutls/gnutls.h>
-#endif
-
-struct blocked_pkt {
- const uint8_t *pkt;
- size_t pktlen;
- size_t gsolen;
-};
-
-struct quicsocket {
- struct connectdata *conn; /* point back to the connection */
- ngtcp2_conn *qconn;
- ngtcp2_cid dcid;
- ngtcp2_cid scid;
- uint32_t version;
- ngtcp2_settings settings;
- ngtcp2_transport_params transport_params;
- ngtcp2_connection_close_error last_error;
- ngtcp2_crypto_conn_ref conn_ref;
-#ifdef USE_OPENSSL
- SSL_CTX *sslctx;
- SSL *ssl;
-#elif defined(USE_GNUTLS)
- gnutls_certificate_credentials_t cred;
- gnutls_session_t ssl;
-#endif
- struct sockaddr_storage local_addr;
- socklen_t local_addrlen;
- bool no_gso;
- uint8_t *pktbuf;
- size_t pktbuflen;
- /* the number of entries in blocked_pkt */
- size_t num_blocked_pkt;
- /* the number of processed entries in blocked_pkt */
- size_t num_blocked_pkt_sent;
- /* the packets blocked by sendmsg (EAGAIN or EWOULDBLOCK) */
- struct blocked_pkt blocked_pkt[2];
-
- nghttp3_conn *h3conn;
- nghttp3_settings h3settings;
- int qlogfd;
-};
-
-#include "urldata.h"
-
-#endif
-
-#endif /* HEADER_CURL_VQUIC_NGTCP2_H */
diff --git a/lib/vquic/quiche.c b/lib/vquic/quiche.c
deleted file mode 100644
index 9a2b743..0000000
--- a/lib/vquic/quiche.c
+++ /dev/null
@@ -1,880 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the 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"
-
-#ifdef USE_QUICHE
-#include <quiche.h>
-#include <openssl/err.h>
-#include <openssl/ssl.h>
-#include "urldata.h"
-#include "sendf.h"
-#include "strdup.h"
-#include "rand.h"
-#include "quic.h"
-#include "strcase.h"
-#include "multiif.h"
-#include "connect.h"
-#include "strerror.h"
-#include "vquic.h"
-#include "transfer.h"
-#include "h2h3.h"
-#include "vtls/openssl.h"
-#include "vtls/keylog.h"
-
-/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
-
-#define DEBUG_HTTP3
-/* #define DEBUG_QUICHE */
-#ifdef DEBUG_HTTP3
-#define H3BUGF(x) x
-#else
-#define H3BUGF(x) do { } while(0)
-#endif
-
-#define QUIC_MAX_STREAMS (256*1024)
-#define QUIC_MAX_DATA (1*1024*1024)
-#define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */
-
-static CURLcode process_ingress(struct Curl_easy *data,
- curl_socket_t sockfd,
- struct quicsocket *qs);
-
-static CURLcode flush_egress(struct Curl_easy *data, curl_socket_t sockfd,
- struct quicsocket *qs);
-
-static CURLcode http_request(struct Curl_easy *data, const void *mem,
- size_t len);
-static Curl_recv h3_stream_recv;
-static Curl_send h3_stream_send;
-
-static int quiche_getsock(struct Curl_easy *data,
- struct connectdata *conn, curl_socket_t *socks)
-{
- struct SingleRequest *k = &data->req;
- int bitmap = GETSOCK_BLANK;
-
- socks[0] = conn->sock[FIRSTSOCKET];
-
- /* in a HTTP/2 connection we can basically always get a frame so we should
- always be ready for one */
- bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
-
- /* we're still uploading or the HTTP/2 layer wants to send data */
- if((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND)
- bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
-
- return bitmap;
-}
-
-static CURLcode qs_disconnect(struct Curl_easy *data,
- struct quicsocket *qs)
-{
- DEBUGASSERT(qs);
- if(qs->conn) {
- (void)quiche_conn_close(qs->conn, TRUE, 0, NULL, 0);
- /* flushing the egress is not a failsafe way to deliver all the
- outstanding packets, but we also don't want to get stuck here... */
- (void)flush_egress(data, qs->sockfd, qs);
- quiche_conn_free(qs->conn);
- qs->conn = NULL;
- }
- if(qs->h3config)
- quiche_h3_config_free(qs->h3config);
- if(qs->h3c)
- quiche_h3_conn_free(qs->h3c);
- if(qs->cfg) {
- quiche_config_free(qs->cfg);
- qs->cfg = NULL;
- }
- return CURLE_OK;
-}
-
-static CURLcode quiche_disconnect(struct Curl_easy *data,
- struct connectdata *conn,
- bool dead_connection)
-{
- struct quicsocket *qs = conn->quic;
- (void)dead_connection;
- return qs_disconnect(data, qs);
-}
-
-void Curl_quic_disconnect(struct Curl_easy *data,
- struct connectdata *conn,
- int tempindex)
-{
- if(conn->transport == TRNSPRT_QUIC)
- qs_disconnect(data, &conn->hequic[tempindex]);
-}
-
-static unsigned int quiche_conncheck(struct Curl_easy *data,
- struct connectdata *conn,
- unsigned int checks_to_perform)
-{
- (void)data;
- (void)conn;
- (void)checks_to_perform;
- return CONNRESULT_NONE;
-}
-
-static CURLcode quiche_do(struct Curl_easy *data, bool *done)
-{
- struct HTTP *stream = data->req.p.http;
- stream->h3req = FALSE; /* not sent */
- return Curl_http(data, done);
-}
-
-static const struct Curl_handler Curl_handler_http3 = {
- "HTTPS", /* scheme */
- ZERO_NULL, /* setup_connection */
- quiche_do, /* do_it */
- Curl_http_done, /* done */
- ZERO_NULL, /* do_more */
- ZERO_NULL, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- quiche_getsock, /* proto_getsock */
- quiche_getsock, /* doing_getsock */
- ZERO_NULL, /* domore_getsock */
- quiche_getsock, /* perform_getsock */
- quiche_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
- quiche_conncheck, /* connection_check */
- ZERO_NULL, /* attach connection */
- PORT_HTTP, /* defport */
- CURLPROTO_HTTPS, /* protocol */
- CURLPROTO_HTTP, /* family */
- PROTOPT_SSL | PROTOPT_STREAM /* flags */
-};
-
-#ifdef DEBUG_QUICHE
-static void quiche_debug_log(const char *line, void *argp)
-{
- (void)argp;
- fprintf(stderr, "%s\n", line);
-}
-#endif
-
-static void keylog_callback(const SSL *ssl, const char *line)
-{
- (void)ssl;
- Curl_tls_keylog_write_line(line);
-}
-
-static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
-{
- SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
-
- SSL_CTX_set_alpn_protos(ssl_ctx,
- (const uint8_t *)QUICHE_H3_APPLICATION_PROTOCOL,
- sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1);
-
- SSL_CTX_set_default_verify_paths(ssl_ctx);
-
- /* Open the file if a TLS or QUIC backend has not done this before. */
- Curl_tls_keylog_open();
- if(Curl_tls_keylog_enabled()) {
- SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
- }
-
- {
- struct connectdata *conn = data->conn;
- if(conn->ssl_config.verifypeer) {
- const char * const ssl_cafile = conn->ssl_config.CAfile;
- const char * const ssl_capath = conn->ssl_config.CApath;
- if(ssl_cafile || ssl_capath) {
- SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
- /* tell OpenSSL where to find CA certificates that are used to verify
- the server's certificate. */
- if(!SSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:"
- " CAfile: %s CApath: %s",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
- return NULL;
- }
- infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
- infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
- }
-#ifdef CURL_CA_FALLBACK
- else {
- /* verifying the peer without any CA certificates won't work so
- use openssl's built-in default as fallback */
- SSL_CTX_set_default_verify_paths(ssl_ctx);
- }
-#endif
- }
- }
- return ssl_ctx;
-}
-
-static int quic_init_ssl(struct quicsocket *qs, struct connectdata *conn)
-{
- /* this will need some attention when HTTPS proxy over QUIC get fixed */
- const char * const hostname = conn->host.name;
-
- DEBUGASSERT(!qs->ssl);
- qs->ssl = SSL_new(qs->sslctx);
-
- SSL_set_app_data(qs->ssl, qs);
-
- /* set SNI */
- SSL_set_tlsext_host_name(qs->ssl, hostname);
- return 0;
-}
-
-
-CURLcode Curl_quic_connect(struct Curl_easy *data,
- struct connectdata *conn, curl_socket_t sockfd,
- int sockindex,
- const struct sockaddr *addr, socklen_t addrlen)
-{
- CURLcode result;
- struct quicsocket *qs = &conn->hequic[sockindex];
- char ipbuf[40];
- int port;
-
-#ifdef DEBUG_QUICHE
- /* initialize debug log callback only once */
- static int debug_log_init = 0;
- if(!debug_log_init) {
- quiche_enable_debug_logging(quiche_debug_log, NULL);
- debug_log_init = 1;
- }
-#endif
-
- (void)addr;
- (void)addrlen;
-
- qs->sockfd = sockfd;
- qs->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
- if(!qs->cfg) {
- failf(data, "can't create quiche config");
- return CURLE_FAILED_INIT;
- }
-
- quiche_config_set_max_idle_timeout(qs->cfg, QUIC_IDLE_TIMEOUT);
- quiche_config_set_initial_max_data(qs->cfg, QUIC_MAX_DATA);
- quiche_config_set_initial_max_stream_data_bidi_local(qs->cfg, QUIC_MAX_DATA);
- quiche_config_set_initial_max_stream_data_bidi_remote(qs->cfg,
- QUIC_MAX_DATA);
- quiche_config_set_initial_max_stream_data_uni(qs->cfg, QUIC_MAX_DATA);
- quiche_config_set_initial_max_streams_bidi(qs->cfg, QUIC_MAX_STREAMS);
- quiche_config_set_initial_max_streams_uni(qs->cfg, QUIC_MAX_STREAMS);
- quiche_config_set_application_protos(qs->cfg,
- (uint8_t *)
- QUICHE_H3_APPLICATION_PROTOCOL,
- sizeof(QUICHE_H3_APPLICATION_PROTOCOL)
- - 1);
-
- qs->sslctx = quic_ssl_ctx(data);
- if(!qs->sslctx)
- return CURLE_QUIC_CONNECT_ERROR;
-
- if(quic_init_ssl(qs, conn))
- return CURLE_QUIC_CONNECT_ERROR;
-
- result = Curl_rand(data, qs->scid, sizeof(qs->scid));
- if(result)
- return result;
-
- qs->conn = quiche_conn_new_with_tls((const uint8_t *) qs->scid,
- sizeof(qs->scid), NULL, 0, addr, addrlen,
- qs->cfg, qs->ssl, false);
- if(!qs->conn) {
- failf(data, "can't create quiche connection");
- return CURLE_OUT_OF_MEMORY;
- }
-
- /* Known to not work on Windows */
-#if !defined(WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
- {
- int qfd;
- (void)Curl_qlogdir(data, qs->scid, sizeof(qs->scid), &qfd);
- if(qfd != -1)
- quiche_conn_set_qlog_fd(qs->conn, qfd,
- "qlog title", "curl qlog");
- }
-#endif
-
- result = flush_egress(data, sockfd, qs);
- if(result)
- return result;
-
- /* extract the used address as a string */
- if(!Curl_addr2string((struct sockaddr*)addr, addrlen, ipbuf, &port)) {
- char buffer[STRERROR_LEN];
- failf(data, "ssrem inet_ntop() failed with errno %d: %s",
- SOCKERRNO, Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- return CURLE_BAD_FUNCTION_ARGUMENT;
- }
-
- infof(data, "Connect socket %d over QUIC to %s:%ld",
- sockfd, ipbuf, port);
-
- Curl_persistconninfo(data, conn, NULL, -1);
-
- /* for connection reuse purposes: */
- conn->ssl[FIRSTSOCKET].state = ssl_connection_complete;
-
- {
- unsigned char alpn_protocols[] = QUICHE_H3_APPLICATION_PROTOCOL;
- unsigned alpn_len, offset = 0;
-
- /* Replace each ALPN length prefix by a comma. */
- while(offset < sizeof(alpn_protocols) - 1) {
- alpn_len = alpn_protocols[offset];
- alpn_protocols[offset] = ',';
- offset += 1 + alpn_len;
- }
-
- infof(data, "Sent QUIC client Initial, ALPN: %s",
- alpn_protocols + 1);
- }
-
- return CURLE_OK;
-}
-
-static CURLcode quiche_has_connected(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
- int tempindex)
-{
- CURLcode result;
- struct quicsocket *qs = conn->quic = &conn->hequic[tempindex];
-
- conn->recv[sockindex] = h3_stream_recv;
- conn->send[sockindex] = h3_stream_send;
- conn->handler = &Curl_handler_http3;
- conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
- conn->httpversion = 30;
- conn->bundle->multiuse = BUNDLE_MULTIPLEX;
-
- if(conn->ssl_config.verifyhost) {
- X509 *server_cert;
- server_cert = SSL_get_peer_certificate(qs->ssl);
- if(!server_cert) {
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- result = Curl_ossl_verifyhost(data, conn, server_cert);
- X509_free(server_cert);
- if(result)
- return result;
- infof(data, "Verified certificate just fine");
- }
- else
- infof(data, "Skipped certificate verification");
-
- qs->h3config = quiche_h3_config_new();
- if(!qs->h3config)
- return CURLE_OUT_OF_MEMORY;
-
- /* Create a new HTTP/3 connection on the QUIC connection. */
- qs->h3c = quiche_h3_conn_new_with_transport(qs->conn, qs->h3config);
- if(!qs->h3c) {
- result = CURLE_OUT_OF_MEMORY;
- goto fail;
- }
- if(conn->hequic[1-tempindex].cfg) {
- qs = &conn->hequic[1-tempindex];
- quiche_config_free(qs->cfg);
- quiche_conn_free(qs->conn);
- qs->cfg = NULL;
- qs->conn = NULL;
- }
- return CURLE_OK;
- fail:
- quiche_h3_config_free(qs->h3config);
- quiche_h3_conn_free(qs->h3c);
- return result;
-}
-
-/*
- * This function gets polled to check if this QUIC connection has connected.
- */
-CURLcode Curl_quic_is_connected(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
- bool *done)
-{
- CURLcode result;
- struct quicsocket *qs = &conn->hequic[sockindex];
- curl_socket_t sockfd = conn->tempsock[sockindex];
-
- result = process_ingress(data, sockfd, qs);
- if(result)
- goto error;
-
- result = flush_egress(data, sockfd, qs);
- if(result)
- goto error;
-
- if(quiche_conn_is_established(qs->conn)) {
- *done = TRUE;
- result = quiche_has_connected(data, conn, 0, sockindex);
- DEBUGF(infof(data, "quiche established connection"));
- }
-
- return result;
- error:
- qs_disconnect(data, qs);
- return result;
-}
-
-static CURLcode process_ingress(struct Curl_easy *data, int sockfd,
- struct quicsocket *qs)
-{
- ssize_t recvd;
- uint8_t *buf = (uint8_t *)data->state.buffer;
- size_t bufsize = data->set.buffer_size;
- struct sockaddr_storage from;
- socklen_t from_len;
- quiche_recv_info recv_info;
-
- DEBUGASSERT(qs->conn);
-
- /* in case the timeout expired */
- quiche_conn_on_timeout(qs->conn);
-
- do {
- from_len = sizeof(from);
-
- recvd = recvfrom(sockfd, buf, bufsize, 0,
- (struct sockaddr *)&from, &from_len);
-
- if((recvd < 0) && ((SOCKERRNO == EAGAIN) || (SOCKERRNO == EWOULDBLOCK)))
- break;
-
- if(recvd < 0) {
- failf(data, "quiche: recvfrom() unexpectedly returned %zd "
- "(errno: %d, socket %d)", recvd, SOCKERRNO, sockfd);
- return CURLE_RECV_ERROR;
- }
-
- recv_info.from = (struct sockaddr *) &from;
- recv_info.from_len = from_len;
-
- recvd = quiche_conn_recv(qs->conn, buf, recvd, &recv_info);
- if(recvd == QUICHE_ERR_DONE)
- break;
-
- if(recvd < 0) {
- if(QUICHE_ERR_TLS_FAIL == recvd) {
- long verify_ok = SSL_get_verify_result(qs->ssl);
- if(verify_ok != X509_V_OK) {
- failf(data, "SSL certificate problem: %s",
- X509_verify_cert_error_string(verify_ok));
-
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- }
-
- failf(data, "quiche_conn_recv() == %zd", recvd);
-
- return CURLE_RECV_ERROR;
- }
- } while(1);
-
- return CURLE_OK;
-}
-
-/*
- * flush_egress drains the buffers and sends off data.
- * Calls failf() on errors.
- */
-static CURLcode flush_egress(struct Curl_easy *data, int sockfd,
- struct quicsocket *qs)
-{
- ssize_t sent;
- uint8_t out[1200];
- int64_t timeout_ns;
- quiche_send_info send_info;
-
- do {
- sent = quiche_conn_send(qs->conn, out, sizeof(out), &send_info);
- if(sent == QUICHE_ERR_DONE)
- break;
-
- if(sent < 0) {
- failf(data, "quiche_conn_send returned %zd", sent);
- return CURLE_SEND_ERROR;
- }
-
- sent = send(sockfd, out, sent, 0);
- if(sent < 0) {
- failf(data, "send() returned %zd", sent);
- return CURLE_SEND_ERROR;
- }
- } while(1);
-
- /* time until the next timeout event, as nanoseconds. */
- timeout_ns = quiche_conn_timeout_as_nanos(qs->conn);
- if(timeout_ns)
- /* expire uses milliseconds */
- Curl_expire(data, (timeout_ns + 999999) / 1000000, EXPIRE_QUIC);
-
- return CURLE_OK;
-}
-
-struct h3h1header {
- char *dest;
- size_t destlen; /* left to use */
- size_t nlen; /* used */
-};
-
-static int cb_each_header(uint8_t *name, size_t name_len,
- uint8_t *value, size_t value_len,
- void *argp)
-{
- struct h3h1header *headers = (struct h3h1header *)argp;
- size_t olen = 0;
-
- if((name_len == 7) && !strncmp(H2H3_PSEUDO_STATUS, (char *)name, 7)) {
- msnprintf(headers->dest,
- headers->destlen, "HTTP/3 %.*s\n",
- (int) value_len, value);
- }
- else if(!headers->nlen) {
- return CURLE_HTTP3;
- }
- else {
- msnprintf(headers->dest,
- headers->destlen, "%.*s: %.*s\n",
- (int)name_len, name, (int) value_len, value);
- }
- olen = strlen(headers->dest);
- headers->destlen -= olen;
- headers->nlen += olen;
- headers->dest += olen;
- return 0;
-}
-
-static ssize_t h3_stream_recv(struct Curl_easy *data,
- int sockindex,
- char *buf,
- size_t buffersize,
- CURLcode *curlcode)
-{
- ssize_t recvd = -1;
- ssize_t rcode;
- struct connectdata *conn = data->conn;
- struct quicsocket *qs = conn->quic;
- curl_socket_t sockfd = conn->sock[sockindex];
- quiche_h3_event *ev;
- int rc;
- struct h3h1header headers;
- struct HTTP *stream = data->req.p.http;
- headers.dest = buf;
- headers.destlen = buffersize;
- headers.nlen = 0;
-
- if(process_ingress(data, sockfd, qs)) {
- infof(data, "h3_stream_recv returns on ingress");
- *curlcode = CURLE_RECV_ERROR;
- return -1;
- }
-
- if(qs->h3_recving) {
- /* body receiving state */
- rcode = quiche_h3_recv_body(qs->h3c, qs->conn, stream->stream3_id,
- (unsigned char *)buf, buffersize);
- if(rcode <= 0) {
- recvd = -1;
- qs->h3_recving = FALSE;
- /* fall through into the while loop below */
- }
- else
- recvd = rcode;
- }
-
- while(recvd < 0) {
- int64_t s = quiche_h3_conn_poll(qs->h3c, qs->conn, &ev);
- if(s < 0)
- /* nothing more to do */
- break;
-
- if(s != stream->stream3_id) {
- /* another transfer, ignore for now */
- infof(data, "Got h3 for stream %u, expects %u",
- s, stream->stream3_id);
- continue;
- }
-
- switch(quiche_h3_event_type(ev)) {
- case QUICHE_H3_EVENT_HEADERS:
- rc = quiche_h3_event_for_each_header(ev, cb_each_header, &headers);
- if(rc) {
- *curlcode = rc;
- failf(data, "Error in HTTP/3 response header");
- break;
- }
- recvd = headers.nlen;
- break;
- case QUICHE_H3_EVENT_DATA:
- if(!stream->firstbody) {
- /* add a header-body separator CRLF */
- buf[0] = '\r';
- buf[1] = '\n';
- buf += 2;
- buffersize -= 2;
- stream->firstbody = TRUE;
- recvd = 2; /* two bytes already */
- }
- else
- recvd = 0;
- rcode = quiche_h3_recv_body(qs->h3c, qs->conn, s, (unsigned char *)buf,
- buffersize);
- if(rcode <= 0) {
- recvd = -1;
- break;
- }
- qs->h3_recving = TRUE;
- recvd += rcode;
- break;
-
- case QUICHE_H3_EVENT_RESET:
- streamclose(conn, "Stream reset");
- *curlcode = CURLE_PARTIAL_FILE;
- return -1;
-
- case QUICHE_H3_EVENT_FINISHED:
- streamclose(conn, "End of stream");
- recvd = 0; /* end of stream */
- break;
- default:
- break;
- }
-
- quiche_h3_event_free(ev);
- }
- if(flush_egress(data, sockfd, qs)) {
- *curlcode = CURLE_SEND_ERROR;
- return -1;
- }
-
- *curlcode = (-1 == recvd)? CURLE_AGAIN : CURLE_OK;
- if(recvd >= 0)
- /* Get this called again to drain the event queue */
- Curl_expire(data, 0, EXPIRE_QUIC);
-
- data->state.drain = (recvd >= 0) ? 1 : 0;
- return recvd;
-}
-
-static ssize_t h3_stream_send(struct Curl_easy *data,
- int sockindex,
- const void *mem,
- size_t len,
- CURLcode *curlcode)
-{
- ssize_t sent;
- struct connectdata *conn = data->conn;
- struct quicsocket *qs = conn->quic;
- curl_socket_t sockfd = conn->sock[sockindex];
- struct HTTP *stream = data->req.p.http;
-
- if(!stream->h3req) {
- CURLcode result = http_request(data, mem, len);
- if(result) {
- *curlcode = CURLE_SEND_ERROR;
- return -1;
- }
- sent = len;
- }
- else {
- sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
- (uint8_t *)mem, len, FALSE);
- if(sent == QUICHE_H3_ERR_DONE) {
- sent = 0;
- }
- else if(sent < 0) {
- *curlcode = CURLE_SEND_ERROR;
- return -1;
- }
- }
-
- if(flush_egress(data, sockfd, qs)) {
- *curlcode = CURLE_SEND_ERROR;
- return -1;
- }
-
- *curlcode = CURLE_OK;
- return sent;
-}
-
-/*
- * Store quiche version info in this buffer.
- */
-void Curl_quic_ver(char *p, size_t len)
-{
- (void)msnprintf(p, len, "quiche/%s", quiche_version());
-}
-
-/* Index where :authority header field will appear in request header
- field list. */
-#define AUTHORITY_DST_IDX 3
-
-static CURLcode http_request(struct Curl_easy *data, const void *mem,
- size_t len)
-{
- struct connectdata *conn = data->conn;
- struct HTTP *stream = data->req.p.http;
- size_t nheader;
- int64_t stream3_id;
- quiche_h3_header *nva = NULL;
- struct quicsocket *qs = conn->quic;
- CURLcode result = CURLE_OK;
- struct h2h3req *hreq = NULL;
-
- stream->h3req = TRUE; /* senf off! */
-
- result = Curl_pseudo_headers(data, mem, len, &hreq);
- if(result)
- goto fail;
- nheader = hreq->entries;
-
- nva = malloc(sizeof(quiche_h3_header) * nheader);
- if(!nva) {
- result = CURLE_OUT_OF_MEMORY;
- goto fail;
- }
- else {
- unsigned int i;
- for(i = 0; i < nheader; i++) {
- nva[i].name = (unsigned char *)hreq->header[i].name;
- nva[i].name_len = hreq->header[i].namelen;
- nva[i].value = (unsigned char *)hreq->header[i].value;
- nva[i].value_len = hreq->header[i].valuelen;
- }
- }
-
- switch(data->state.httpreq) {
- case HTTPREQ_POST:
- case HTTPREQ_POST_FORM:
- case HTTPREQ_POST_MIME:
- case HTTPREQ_PUT:
- if(data->state.infilesize != -1)
- stream->upload_left = data->state.infilesize;
- else
- /* data sending without specifying the data amount up front */
- stream->upload_left = -1; /* unknown, but not zero */
-
- stream3_id = quiche_h3_send_request(qs->h3c, qs->conn, nva, nheader,
- stream->upload_left ? FALSE: TRUE);
- if((stream3_id >= 0) && data->set.postfields) {
- ssize_t sent = quiche_h3_send_body(qs->h3c, qs->conn, stream3_id,
- (uint8_t *)data->set.postfields,
- stream->upload_left, TRUE);
- if(sent <= 0) {
- failf(data, "quiche_h3_send_body failed");
- result = CURLE_SEND_ERROR;
- }
- stream->upload_left = 0; /* nothing left to send */
- }
- break;
- default:
- stream3_id = quiche_h3_send_request(qs->h3c, qs->conn, nva, nheader,
- TRUE);
- break;
- }
-
- Curl_safefree(nva);
-
- if(stream3_id < 0) {
- H3BUGF(infof(data, "quiche_h3_send_request returned %d",
- stream3_id));
- result = CURLE_SEND_ERROR;
- goto fail;
- }
-
- infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)",
- stream3_id, (void *)data);
- stream->stream3_id = stream3_id;
-
- Curl_pseudo_free(hreq);
- return CURLE_OK;
-
-fail:
- free(nva);
- Curl_pseudo_free(hreq);
- return result;
-}
-
-/*
- * Called from transfer.c:done_sending when we stop HTTP/3 uploading.
- */
-CURLcode Curl_quic_done_sending(struct Curl_easy *data)
-{
- struct connectdata *conn = data->conn;
- DEBUGASSERT(conn);
- if(conn->handler == &Curl_handler_http3) {
- /* only for HTTP/3 transfers */
- ssize_t sent;
- struct HTTP *stream = data->req.p.http;
- struct quicsocket *qs = conn->quic;
- stream->upload_done = TRUE;
- sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
- NULL, 0, TRUE);
- if(sent < 0)
- return CURLE_SEND_ERROR;
- }
-
- return CURLE_OK;
-}
-
-/*
- * Called from http.c:Curl_http_done when a request completes.
- */
-void Curl_quic_done(struct Curl_easy *data, bool premature)
-{
- (void)data;
- (void)premature;
-}
-
-/*
- * Called from transfer.c:data_pending to know if we should keep looping
- * to receive more data from the connection.
- */
-bool Curl_quic_data_pending(const struct Curl_easy *data)
-{
- (void)data;
- return FALSE;
-}
-
-/*
- * Called from transfer.c:Curl_readwrite when neither HTTP level read
- * nor write is performed. It is a good place to handle timer expiry
- * for QUIC transport.
- */
-CURLcode Curl_quic_idle(struct Curl_easy *data)
-{
- (void)data;
- return CURLE_OK;
-}
-
-#endif
diff --git a/lib/vquic/vquic.c b/lib/vquic/vquic.c
index e52a4f3..399de0b 100644
--- a/lib/vquic/vquic.c
+++ b/lib/vquic/vquic.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,17 +22,41 @@
*
***************************************************************************/
-#include "curl_setup.h"
+/* WIP, experimental: use recvmmsg() on linux
+ * we have no configure check, yet
+ * and also it is only available for _GNU_SOURCE, which
+ * we do not use otherwise.
+#define HAVE_SENDMMSG
+ */
+#if defined(HAVE_SENDMMSG)
+#define _GNU_SOURCE
+#include <sys/socket.h>
+#undef _GNU_SOURCE
+#endif
-#ifdef ENABLE_QUIC
+#include "curl_setup.h"
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include "urldata.h"
+#include "bufq.h"
#include "dynbuf.h"
-#include "curl_printf.h"
+#include "cfilters.h"
+#include "curl_log.h"
+#include "curl_msh3.h"
+#include "curl_ngtcp2.h"
+#include "curl_quiche.h"
#include "vquic.h"
+#include "vquic_int.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+
+#ifdef ENABLE_QUIC
#ifdef O_BINARY
#define QLOGMODE O_WRONLY|O_CREAT|O_BINARY
@@ -40,6 +64,445 @@
#define QLOGMODE O_WRONLY|O_CREAT
#endif
+#define NW_CHUNK_SIZE (64 * 1024)
+#define NW_SEND_CHUNKS 2
+
+
+void Curl_quic_ver(char *p, size_t len)
+{
+#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
+ Curl_ngtcp2_ver(p, len);
+#elif defined(USE_QUICHE)
+ Curl_quiche_ver(p, len);
+#elif defined(USE_MSH3)
+ Curl_msh3_ver(p, len);
+#endif
+}
+
+CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx)
+{
+ Curl_bufq_init2(&qctx->sendbuf, NW_CHUNK_SIZE, NW_SEND_CHUNKS,
+ BUFQ_OPT_SOFT_LIMIT);
+#if defined(__linux__) && defined(UDP_SEGMENT) && defined(HAVE_SENDMSG)
+ qctx->no_gso = FALSE;
+#else
+ qctx->no_gso = TRUE;
+#endif
+
+ return CURLE_OK;
+}
+
+void vquic_ctx_free(struct cf_quic_ctx *qctx)
+{
+ Curl_bufq_free(&qctx->sendbuf);
+}
+
+static CURLcode send_packet_no_gso(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct cf_quic_ctx *qctx,
+ const uint8_t *pkt, size_t pktlen,
+ size_t gsolen, size_t *psent);
+
+static CURLcode do_sendmsg(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct cf_quic_ctx *qctx,
+ const uint8_t *pkt, size_t pktlen, size_t gsolen,
+ size_t *psent)
+{
+#ifdef HAVE_SENDMSG
+ struct iovec msg_iov;
+ struct msghdr msg = {0};
+ ssize_t sent;
+#if defined(__linux__) && defined(UDP_SEGMENT)
+ uint8_t msg_ctrl[32];
+ struct cmsghdr *cm;
+#endif
+
+ *psent = 0;
+ msg_iov.iov_base = (uint8_t *)pkt;
+ msg_iov.iov_len = pktlen;
+ msg.msg_iov = &msg_iov;
+ msg.msg_iovlen = 1;
+
+#if defined(__linux__) && defined(UDP_SEGMENT)
+ if(pktlen > gsolen) {
+ /* Only set this, when we need it. macOS, for example,
+ * does not seem to like a msg_control of length 0. */
+ msg.msg_control = msg_ctrl;
+ assert(sizeof(msg_ctrl) >= CMSG_SPACE(sizeof(uint16_t)));
+ msg.msg_controllen = CMSG_SPACE(sizeof(uint16_t));
+ cm = CMSG_FIRSTHDR(&msg);
+ cm->cmsg_level = SOL_UDP;
+ cm->cmsg_type = UDP_SEGMENT;
+ cm->cmsg_len = CMSG_LEN(sizeof(uint16_t));
+ *(uint16_t *)(void *)CMSG_DATA(cm) = gsolen & 0xffff;
+ }
+#endif
+
+
+ while((sent = sendmsg(qctx->sockfd, &msg, 0)) == -1 && SOCKERRNO == EINTR)
+ ;
+
+ if(sent == -1) {
+ switch(SOCKERRNO) {
+ case EAGAIN:
+#if EAGAIN != EWOULDBLOCK
+ case EWOULDBLOCK:
+#endif
+ return CURLE_AGAIN;
+ case EMSGSIZE:
+ /* UDP datagram is too large; caused by PMTUD. Just let it be lost. */
+ break;
+ case EIO:
+ if(pktlen > gsolen) {
+ /* GSO failure */
+ failf(data, "sendmsg() returned %zd (errno %d); disable GSO", sent,
+ 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);
+ return CURLE_SEND_ERROR;
+ }
+ }
+ else {
+ assert(pktlen == (size_t)sent);
+ }
+#else
+ ssize_t sent;
+ (void)gsolen;
+
+ *psent = 0;
+
+ while((sent = send(qctx->sockfd,
+ (const char *)pkt, (SEND_TYPE_ARG3)pktlen, 0)) == -1 &&
+ SOCKERRNO == EINTR)
+ ;
+
+ if(sent == -1) {
+ if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
+ return CURLE_AGAIN;
+ }
+ else {
+ failf(data, "send() returned %zd (errno %d)", sent, SOCKERRNO);
+ if(SOCKERRNO != EMSGSIZE) {
+ return CURLE_SEND_ERROR;
+ }
+ /* UDP datagram is too large; caused by PMTUD. Just let it be
+ lost. */
+ }
+ }
+#endif
+ (void)cf;
+ *psent = pktlen;
+
+ return CURLE_OK;
+}
+
+static CURLcode send_packet_no_gso(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct cf_quic_ctx *qctx,
+ const uint8_t *pkt, size_t pktlen,
+ size_t gsolen, size_t *psent)
+{
+ const uint8_t *p, *end = pkt + pktlen;
+ size_t sent;
+
+ *psent = 0;
+
+ for(p = pkt; p < end; p += gsolen) {
+ size_t len = CURLMIN(gsolen, (size_t)(end - p));
+ CURLcode curlcode = do_sendmsg(cf, data, qctx, p, len, len, &sent);
+ if(curlcode != CURLE_OK) {
+ return curlcode;
+ }
+ *psent += sent;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode vquic_send_packets(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct cf_quic_ctx *qctx,
+ const uint8_t *pkt, size_t pktlen,
+ size_t gsolen, size_t *psent)
+{
+ if(qctx->no_gso && pktlen > gsolen) {
+ return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);
+ }
+
+ return do_sendmsg(cf, data, qctx, pkt, pktlen, gsolen, psent);
+}
+
+CURLcode vquic_flush(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct cf_quic_ctx *qctx)
+{
+ const unsigned char *buf;
+ size_t blen, sent;
+ CURLcode result;
+ size_t gsolen;
+
+ while(Curl_bufq_peek(&qctx->sendbuf, &buf, &blen)) {
+ gsolen = qctx->gsolen;
+ if(qctx->split_len) {
+ gsolen = qctx->split_gsolen;
+ if(blen > qctx->split_len)
+ blen = qctx->split_len;
+ }
+
+ DEBUGF(LOG_CF(data, cf, "vquic_send(len=%zu, gso=%zu)",
+ blen, gsolen));
+ result = vquic_send_packets(cf, data, qctx, buf, blen, gsolen, &sent);
+ DEBUGF(LOG_CF(data, cf, "vquic_send(len=%zu, gso=%zu) -> %d, sent=%zu",
+ blen, gsolen, result, sent));
+ if(result) {
+ if(result == CURLE_AGAIN) {
+ Curl_bufq_skip(&qctx->sendbuf, sent);
+ if(qctx->split_len)
+ qctx->split_len -= sent;
+ }
+ return result;
+ }
+ Curl_bufq_skip(&qctx->sendbuf, sent);
+ if(qctx->split_len)
+ qctx->split_len -= sent;
+ }
+ return CURLE_OK;
+}
+
+CURLcode vquic_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct cf_quic_ctx *qctx, size_t gsolen)
+{
+ qctx->gsolen = gsolen;
+ return vquic_flush(cf, data, qctx);
+}
+
+CURLcode vquic_send_tail_split(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct cf_quic_ctx *qctx, size_t gsolen,
+ size_t tail_len, size_t tail_gsolen)
+{
+ DEBUGASSERT(Curl_bufq_len(&qctx->sendbuf) > tail_len);
+ qctx->split_len = Curl_bufq_len(&qctx->sendbuf) - tail_len;
+ qctx->split_gsolen = gsolen;
+ qctx->gsolen = tail_gsolen;
+ DEBUGF(LOG_CF(data, cf, "vquic_send_tail_split: [%zu gso=%zu][%zu gso=%zu]",
+ qctx->split_len, qctx->split_gsolen,
+ tail_len, qctx->gsolen));
+ return vquic_flush(cf, data, qctx);
+}
+
+#ifdef HAVE_SENDMMSG
+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)
+{
+#define MMSG_NUM 64
+ struct iovec msg_iov[MMSG_NUM];
+ struct mmsghdr mmsg[MMSG_NUM];
+ uint8_t bufs[MMSG_NUM][2*1024];
+ struct sockaddr_storage remote_addr[MMSG_NUM];
+ size_t total_nread, pkts;
+ int mcount, i, n;
+ CURLcode result = CURLE_OK;
+
+ DEBUGASSERT(max_pkts > 0);
+ pkts = 0;
+ total_nread = 0;
+ while(pkts < max_pkts) {
+ n = (int)CURLMIN(MMSG_NUM, max_pkts);
+ memset(&mmsg, 0, sizeof(mmsg));
+ for(i = 0; i < n; ++i) {
+ msg_iov[i].iov_base = bufs[i];
+ msg_iov[i].iov_len = (int)sizeof(bufs[i]);
+ mmsg[i].msg_hdr.msg_iov = &msg_iov[i];
+ mmsg[i].msg_hdr.msg_iovlen = 1;
+ mmsg[i].msg_hdr.msg_name = &remote_addr[i];
+ mmsg[i].msg_hdr.msg_namelen = sizeof(remote_addr[i]);
+ }
+
+ while((mcount = recvmmsg(qctx->sockfd, mmsg, n, 0, NULL)) == -1 &&
+ SOCKERRNO == EINTR)
+ ;
+ if(mcount == -1) {
+ if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
+ DEBUGF(LOG_CF(data, cf, "ingress, recvmmsg -> EAGAIN"));
+ goto out;
+ }
+ if(!cf->connected && SOCKERRNO == ECONNREFUSED) {
+ const char *r_ip;
+ int r_port;
+ Curl_cf_socket_peek(cf->next, data, NULL, NULL,
+ &r_ip, &r_port, NULL, NULL);
+ failf(data, "QUIC: connection to %s port %u refused",
+ r_ip, r_port);
+ result = CURLE_COULDNT_CONNECT;
+ goto out;
+ }
+ failf(data, "QUIC: recvmsg() unexpectedly returned %d (errno=%d)",
+ mcount, SOCKERRNO);
+ result = CURLE_RECV_ERROR;
+ goto out;
+ }
+
+ DEBUGF(LOG_CF(data, cf, "recvmmsg() -> %d packets", mcount));
+ pkts += mcount;
+ for(i = 0; i < mcount; ++i) {
+ total_nread += mmsg[i].msg_len;
+ result = recv_cb(bufs[i], mmsg[i].msg_len,
+ mmsg[i].msg_hdr.msg_name, mmsg[i].msg_hdr.msg_namelen,
+ 0, userp);
+ if(result)
+ goto out;
+ }
+ }
+
+out:
+ DEBUGF(LOG_CF(data, cf, "recvd %zu packets with %zu bytes -> %d",
+ pkts, total_nread, result));
+ return result;
+}
+
+#elif defined(HAVE_SENDMSG)
+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)
+{
+ struct iovec msg_iov;
+ struct msghdr msg;
+ uint8_t buf[64*1024];
+ struct sockaddr_storage remote_addr;
+ size_t total_nread, pkts;
+ ssize_t nread;
+ CURLcode result = CURLE_OK;
+
+ msg_iov.iov_base = buf;
+ msg_iov.iov_len = (int)sizeof(buf);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = &msg_iov;
+ msg.msg_iovlen = 1;
+
+ DEBUGASSERT(max_pkts > 0);
+ for(pkts = 0, total_nread = 0; pkts < max_pkts;) {
+ msg.msg_name = &remote_addr;
+ msg.msg_namelen = sizeof(remote_addr);
+ while((nread = recvmsg(qctx->sockfd, &msg, 0)) == -1 &&
+ SOCKERRNO == EINTR)
+ ;
+ if(nread == -1) {
+ if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
+ goto out;
+ }
+ if(!cf->connected && SOCKERRNO == ECONNREFUSED) {
+ const char *r_ip;
+ int r_port;
+ Curl_cf_socket_peek(cf->next, data, NULL, NULL,
+ &r_ip, &r_port, NULL, NULL);
+ failf(data, "QUIC: connection to %s port %u refused",
+ r_ip, r_port);
+ result = CURLE_COULDNT_CONNECT;
+ goto out;
+ }
+ failf(data, "QUIC: recvmsg() unexpectedly returned %zd (errno=%d)",
+ nread, SOCKERRNO);
+ result = CURLE_RECV_ERROR;
+ goto out;
+ }
+
+ ++pkts;
+ total_nread += (size_t)nread;
+ result = recv_cb(buf, (size_t)nread, msg.msg_name, msg.msg_namelen,
+ 0, userp);
+ if(result)
+ goto out;
+ }
+
+out:
+ DEBUGF(LOG_CF(data, cf, "recvd %zu packets with %zu bytes -> %d",
+ pkts, total_nread, result));
+ return result;
+}
+
+#else /* HAVE_SENDMMSG || HAVE_SENDMSG */
+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)
+{
+ 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;
+ ssize_t nread;
+ 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 &&
+ SOCKERRNO == EINTR)
+ ;
+ if(nread == -1) {
+ if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
+ DEBUGF(LOG_CF(data, cf, "ingress, recvfrom -> EAGAIN"));
+ goto out;
+ }
+ if(!cf->connected && SOCKERRNO == ECONNREFUSED) {
+ const char *r_ip;
+ int r_port;
+ Curl_cf_socket_peek(cf->next, data, NULL, NULL,
+ &r_ip, &r_port, NULL, NULL);
+ failf(data, "QUIC: connection to %s port %u refused",
+ r_ip, r_port);
+ result = CURLE_COULDNT_CONNECT;
+ goto out;
+ }
+ failf(data, "QUIC: recvfrom() unexpectedly returned %zd (errno=%d)",
+ nread, SOCKERRNO);
+ result = CURLE_RECV_ERROR;
+ goto out;
+ }
+
+ ++pkts;
+ total_nread += (size_t)nread;
+ result = recv_cb(buf, (size_t)nread, &remote_addr, remote_addrlen,
+ 0, userp);
+ if(result)
+ goto out;
+ }
+
+out:
+ DEBUGF(LOG_CF(data, cf, "recvd %zu packets with %zu bytes -> %d",
+ pkts, total_nread, result));
+ return result;
+}
+#endif /* !HAVE_SENDMMSG && !HAVE_SENDMSG */
+
+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)
+{
+#if defined(HAVE_SENDMMSG)
+ return recvmmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+#elif defined(HAVE_SENDMSG)
+ return recvmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+#else
+ return recvfrom_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+#endif
+}
+
/*
* If the QLOGDIR environment variable is set, open and return a file
* descriptor to write the log to.
@@ -84,4 +547,80 @@
return CURLE_OK;
}
+
+CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai,
+ int transport)
+{
+ (void)transport;
+ DEBUGASSERT(transport == TRNSPRT_QUIC);
+#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
+ return Curl_cf_ngtcp2_create(pcf, data, conn, ai);
+#elif defined(USE_QUICHE)
+ return Curl_cf_quiche_create(pcf, data, conn, ai);
+#elif defined(USE_MSH3)
+ return Curl_cf_msh3_create(pcf, data, conn, ai);
+#else
+ *pcf = NULL;
+ (void)data;
+ (void)conn;
+ (void)ai;
+ return CURLE_NOT_BUILT_IN;
#endif
+}
+
+bool Curl_conn_is_http3(const struct Curl_easy *data,
+ const struct connectdata *conn,
+ int sockindex)
+{
+#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
+ return Curl_conn_is_ngtcp2(data, conn, sockindex);
+#elif defined(USE_QUICHE)
+ return Curl_conn_is_quiche(data, conn, sockindex);
+#elif defined(USE_MSH3)
+ return Curl_conn_is_msh3(data, conn, sockindex);
+#else
+ return ((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+ (conn->httpversion == 30));
+#endif
+}
+
+CURLcode Curl_conn_may_http3(struct Curl_easy *data,
+ const struct connectdata *conn)
+{
+ if(conn->transport == TRNSPRT_UNIX) {
+ /* cannot do QUIC over a unix domain socket */
+ return CURLE_QUIC_CONNECT_ERROR;
+ }
+ if(!(conn->handler->flags & PROTOPT_SSL)) {
+ failf(data, "HTTP/3 requested for non-HTTPS URL");
+ return CURLE_URL_MALFORMAT;
+ }
+#ifndef CURL_DISABLE_PROXY
+ if(conn->bits.socksproxy) {
+ failf(data, "HTTP/3 is not supported over a SOCKS proxy");
+ return CURLE_URL_MALFORMAT;
+ }
+ if(conn->bits.httpproxy && conn->bits.tunnel_proxy) {
+ failf(data, "HTTP/3 is not supported over a HTTP proxy");
+ return CURLE_URL_MALFORMAT;
+ }
+#endif
+
+ return CURLE_OK;
+}
+
+#else /* ENABLE_QUIC */
+
+CURLcode Curl_conn_may_http3(struct Curl_easy *data,
+ const struct connectdata *conn)
+{
+ (void)conn;
+ (void)data;
+ DEBUGF(infof(data, "QUIC is not supported in this build"));
+ return CURLE_NOT_BUILT_IN;
+}
+
+#endif /* !ENABLE_QUIC */
diff --git a/lib/vquic/vquic.h b/lib/vquic/vquic.h
index 8f599a8..dc73957 100644
--- a/lib/vquic/vquic.h
+++ b/lib/vquic/vquic.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,10 +27,38 @@
#include "curl_setup.h"
#ifdef ENABLE_QUIC
+struct Curl_cfilter;
+struct Curl_easy;
+struct connectdata;
+struct Curl_addrinfo;
+
+void Curl_quic_ver(char *p, size_t len);
+
CURLcode Curl_qlogdir(struct Curl_easy *data,
unsigned char *scid,
size_t scidlen,
int *qlogfdp);
-#endif
+
+
+CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai,
+ int transport);
+
+bool Curl_conn_is_http3(const struct Curl_easy *data,
+ const struct connectdata *conn,
+ int sockindex);
+
+extern struct Curl_cftype Curl_cft_http3;
+
+#else /* ENABLE_QUIC */
+
+#define Curl_conn_is_http3(a,b,c) FALSE
+
+#endif /* !ENABLE_QUIC */
+
+CURLcode Curl_conn_may_http3(struct Curl_easy *data,
+ const struct connectdata *conn);
#endif /* HEADER_CURL_VQUIC_QUIC_H */
diff --git a/lib/vquic/vquic_int.h b/lib/vquic/vquic_int.h
new file mode 100644
index 0000000..8e08784
--- /dev/null
+++ b/lib/vquic/vquic_int.h
@@ -0,0 +1,82 @@
+#ifndef HEADER_CURL_VQUIC_QUIC_INT_H
+#define HEADER_CURL_VQUIC_QUIC_INT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "bufq.h"
+
+#ifdef ENABLE_QUIC
+
+#define MAX_PKT_BURST 10
+#define MAX_UDP_PAYLOAD_SIZE 1452
+
+struct cf_quic_ctx {
+ 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 */
+ 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 */
+ bool no_gso; /* do not use gso on sending */
+};
+
+CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx);
+void vquic_ctx_free(struct cf_quic_ctx *qctx);
+
+void vquic_push_blocked_pkt(struct Curl_cfilter *cf,
+ struct cf_quic_ctx *qctx,
+ const uint8_t *pkt, size_t pktlen, size_t gsolen);
+
+CURLcode vquic_send_blocked_pkts(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct cf_quic_ctx *qctx);
+
+CURLcode vquic_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct cf_quic_ctx *qctx, size_t gsolen);
+
+CURLcode vquic_send_tail_split(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct cf_quic_ctx *qctx, size_t gsolen,
+ size_t tail_len, size_t tail_gsolen);
+
+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);
+
+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);
+
+#endif /* !ENABLE_QUIC */
+
+#endif /* HEADER_CURL_VQUIC_QUIC_INT_H */
diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c
index 5aa99e6..1cecb64 100644
--- a/lib/vssh/libssh.c
+++ b/lib/vssh/libssh.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017 - 2022 Red Hat, Inc.
+ * Copyright (C) Red Hat, Inc.
*
* Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
* Robert Kolcun, Andreas Schneider
@@ -51,11 +51,6 @@
#include <inet.h>
#endif
-#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
-#undef in_addr_t
-#define in_addr_t unsigned long
-#endif
-
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
@@ -71,6 +66,7 @@
#include "strdup.h"
#include "strcase.h"
#include "vtls/vtls.h"
+#include "cfilters.h"
#include "connect.h"
#include "inet_ntop.h"
#include "parsedate.h" /* for the week day and month names */
@@ -96,6 +92,13 @@
#include "curl_memory.h"
#include "memdebug.h"
+/* in 0.10.0 or later, ignore deprecated warnings */
+#if defined(__GNUC__) && \
+ (LIBSSH_VERSION_MINOR >= 10) || \
+ (LIBSSH_VERSION_MAJOR > 0)
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
/* A recent macro provided by libssh. Or make our own. */
#ifndef SSH_STRING_FREE_CHAR
#define SSH_STRING_FREE_CHAR(x) \
@@ -573,7 +576,7 @@
rc = SSH_ERROR; \
} while(0)
-#define MOVE_TO_LAST_AUTH do { \
+#define MOVE_TO_PASSWD_AUTH do { \
if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
rc = SSH_OK; \
state(data, SSH_AUTH_PASS_INIT); \
@@ -583,23 +586,23 @@
} \
} while(0)
-#define MOVE_TO_TERTIARY_AUTH do { \
+#define MOVE_TO_KEY_AUTH do { \
if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
rc = SSH_OK; \
state(data, SSH_AUTH_KEY_INIT); \
} \
else { \
- MOVE_TO_LAST_AUTH; \
+ MOVE_TO_PASSWD_AUTH; \
} \
} while(0)
-#define MOVE_TO_SECONDARY_AUTH do { \
+#define MOVE_TO_GSSAPI_AUTH do { \
if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
rc = SSH_OK; \
state(data, SSH_AUTH_GSSAPI); \
} \
else { \
- MOVE_TO_TERTIARY_AUTH; \
+ MOVE_TO_KEY_AUTH; \
} \
} while(0)
@@ -682,7 +685,6 @@
struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc = SSH_NO_ERROR, err;
- char *new_readdir_line;
int seekerr = CURL_SEEKFUNC_OK;
const char *err_msg;
*block = 0; /* we're not blocking by default */
@@ -751,6 +753,16 @@
}
sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
+ if(sshc->auth_methods)
+ infof(data, "SSH authentication methods available: %s%s%s%s",
+ sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY ?
+ "public key, ": "",
+ sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC ?
+ "GSSAPI, " : "",
+ sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE ?
+ "keyboard-interactive, " : "",
+ sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD ?
+ "password": "");
if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
state(data, SSH_AUTH_PKEY_INIT);
infof(data, "Authentication using SSH public key file");
@@ -773,7 +785,7 @@
}
case SSH_AUTH_PKEY_INIT:
if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) {
- MOVE_TO_SECONDARY_AUTH;
+ MOVE_TO_GSSAPI_AUTH;
break;
}
@@ -789,7 +801,7 @@
}
if(rc != SSH_OK) {
- MOVE_TO_SECONDARY_AUTH;
+ MOVE_TO_GSSAPI_AUTH;
break;
}
}
@@ -824,7 +836,7 @@
break;
}
- MOVE_TO_SECONDARY_AUTH;
+ MOVE_TO_GSSAPI_AUTH;
}
break;
case SSH_AUTH_PKEY:
@@ -842,13 +854,13 @@
}
else {
infof(data, "Failed public key authentication (rc: %d)", rc);
- MOVE_TO_SECONDARY_AUTH;
+ MOVE_TO_GSSAPI_AUTH;
}
break;
case SSH_AUTH_GSSAPI:
if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) {
- MOVE_TO_TERTIARY_AUTH;
+ MOVE_TO_KEY_AUTH;
break;
}
@@ -866,7 +878,7 @@
break;
}
- MOVE_TO_TERTIARY_AUTH;
+ MOVE_TO_KEY_AUTH;
break;
case SSH_AUTH_KEY_INIT:
@@ -874,13 +886,12 @@
state(data, SSH_AUTH_KEY);
}
else {
- MOVE_TO_LAST_AUTH;
+ MOVE_TO_PASSWD_AUTH;
}
break;
case SSH_AUTH_KEY:
-
- /* Authentication failed. Continue with keyboard-interactive now. */
+ /* keyboard-interactive authentication */
rc = myssh_auth_interactive(conn);
if(rc == SSH_AGAIN) {
break;
@@ -888,13 +899,15 @@
if(rc == SSH_OK) {
sshc->authed = TRUE;
infof(data, "completed keyboard interactive authentication");
+ state(data, SSH_AUTH_DONE);
}
- state(data, SSH_AUTH_DONE);
+ else {
+ MOVE_TO_PASSWD_AUTH;
+ }
break;
case SSH_AUTH_PASS_INIT:
if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) {
- /* Host key authentication is intentionally not implemented */
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
break;
}
@@ -956,10 +969,9 @@
rc = sftp_init(sshc->sftp_session);
if(rc != SSH_OK) {
- rc = sftp_get_error(sshc->sftp_session);
failf(data, "Failure initializing sftp session: %s",
ssh_get_error(sshc->ssh_session));
- MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc));
+ MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(SSH_FX_FAILURE));
break;
}
state(data, SSH_SFTP_REALPATH);
@@ -1208,7 +1220,7 @@
}
case SSH_SFTP_TRANS_INIT:
- if(data->set.upload)
+ if(data->state.upload)
state(data, SSH_SFTP_UPLOAD_INIT);
else {
if(protop->path[strlen(protop->path)-1] == '/')
@@ -1409,7 +1421,7 @@
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
- if(data->set.opt_no_body) {
+ if(data->req.no_body) {
state(data, SSH_STOP);
break;
}
@@ -1430,7 +1442,7 @@
break;
case SSH_SFTP_READDIR:
-
+ Curl_dyn_reset(&sshc->readdir_buf);
if(sshc->readdir_attrs)
sftp_attributes_free(sshc->readdir_attrs);
@@ -1466,17 +1478,12 @@
sshc->readdir_len);
}
else {
- sshc->readdir_currLen = strlen(sshc->readdir_longentry);
- sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
- sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
- if(!sshc->readdir_line) {
- state(data, SSH_SFTP_CLOSE);
+ if(Curl_dyn_add(&sshc->readdir_buf, sshc->readdir_longentry)) {
sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ state(data, SSH_STOP);
break;
}
- memcpy(sshc->readdir_line, sshc->readdir_longentry,
- sshc->readdir_currLen);
if((sshc->readdir_attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
((sshc->readdir_attrs->permissions & SSH_S_IFMT) ==
SSH_S_IFLNK)) {
@@ -1539,24 +1546,11 @@
Curl_safefree(sshc->readdir_linkPath);
- /* get room for the filename and extra output */
- sshc->readdir_totalLen += 4 + sshc->readdir_len;
- new_readdir_line = Curl_saferealloc(sshc->readdir_line,
- sshc->readdir_totalLen);
- if(!new_readdir_line) {
- sshc->readdir_line = NULL;
- state(data, SSH_SFTP_CLOSE);
+ if(Curl_dyn_addf(&sshc->readdir_buf, " -> %s",
+ sshc->readdir_filename)) {
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- sshc->readdir_line = new_readdir_line;
-
- sshc->readdir_currLen += msnprintf(sshc->readdir_line +
- sshc->readdir_currLen,
- sshc->readdir_totalLen -
- sshc->readdir_currLen,
- " -> %s",
- sshc->readdir_filename);
sftp_attributes_free(sshc->readdir_link_attrs);
sshc->readdir_link_attrs = NULL;
@@ -1566,21 +1560,19 @@
state(data, SSH_SFTP_READDIR_BOTTOM);
/* FALLTHROUGH */
case SSH_SFTP_READDIR_BOTTOM:
- sshc->readdir_currLen += msnprintf(sshc->readdir_line +
- sshc->readdir_currLen,
- sshc->readdir_totalLen -
- sshc->readdir_currLen, "\n");
- result = Curl_client_write(data, CLIENTWRITE_BODY,
- sshc->readdir_line,
- sshc->readdir_currLen);
+ if(Curl_dyn_addn(&sshc->readdir_buf, "\n", 1))
+ result = CURLE_OUT_OF_MEMORY;
+ else
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
+ Curl_dyn_ptr(&sshc->readdir_buf),
+ Curl_dyn_len(&sshc->readdir_buf));
if(!result) {
/* output debug output if that is requested */
- Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
- sshc->readdir_currLen);
- data->req.bytecount += sshc->readdir_currLen;
+ Curl_debug(data, CURLINFO_DATA_OUT, Curl_dyn_ptr(&sshc->readdir_buf),
+ Curl_dyn_len(&sshc->readdir_buf));
+ data->req.bytecount += Curl_dyn_len(&sshc->readdir_buf);
}
- Curl_safefree(sshc->readdir_line);
ssh_string_free_char(sshc->readdir_tmp);
sshc->readdir_tmp = NULL;
@@ -1616,7 +1608,7 @@
MOVE_TO_SFTP_CLOSE_STATE();
break;
}
-
+ sftp_file_set_nonblocking(sshc->sftp_file);
state(data, SSH_SFTP_DOWNLOAD_STAT);
break;
@@ -1656,13 +1648,13 @@
CURLofft to_t;
CURLofft from_t;
- from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
+ from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from);
if(from_t == CURL_OFFT_FLOW) {
return CURLE_RANGE_ERROR;
}
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+ while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
ptr++;
- to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
+ to_t = curlx_strtoofft(ptr, &ptr2, 10, &to);
if(to_t == CURL_OFFT_FLOW) {
return CURLE_RANGE_ERROR;
}
@@ -1821,7 +1813,7 @@
/* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */
ssh_set_blocking(sshc->ssh_session, 1);
- if(data->set.upload) {
+ if(data->state.upload) {
if(data->state.infilesize < 0) {
failf(data, "SCP requires a known file size for upload");
sshc->actualcode = CURLE_UPLOAD_FAILED;
@@ -1926,7 +1918,7 @@
break;
}
case SSH_SCP_DONE:
- if(data->set.upload)
+ if(data->state.upload)
state(data, SSH_SCP_SEND_EOF);
else
state(data, SSH_SCP_CHANNEL_FREE);
@@ -2019,7 +2011,7 @@
Curl_safefree(sshc->rsa);
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- Curl_safefree(sshc->readdir_line);
+ Curl_dyn_free(&sshc->readdir_buf);
Curl_safefree(sshc->readdir_linkPath);
SSH_STRING_FREE_CHAR(sshc->homedir);
@@ -2164,11 +2156,12 @@
struct connectdata *conn)
{
struct SSHPROTO *ssh;
- (void)conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh)
return CURLE_OUT_OF_MEMORY;
+ Curl_dyn_init(&sshc->readdir_buf, PATH_MAX * 2);
return CURLE_OK;
}
@@ -2317,7 +2310,6 @@
bool *connected, bool *dophase_done)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
DEBUGF(infof(data, "DO phase starts"));
@@ -2328,7 +2320,7 @@
result = myssh_multi_statemach(data, dophase_done);
- *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+ *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
if(*dophase_done) {
DEBUGF(infof(data, "DO phase is complete"));
@@ -2498,7 +2490,6 @@
bool *dophase_done)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
DEBUGF(infof(data, "DO phase starts"));
@@ -2510,7 +2501,7 @@
/* run the state-machine */
result = myssh_multi_statemach(data, dophase_done);
- *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+ *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
if(*dophase_done) {
DEBUGF(infof(data, "DO phase is complete"));
@@ -2911,32 +2902,33 @@
}
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
}
- else if(strncasecompare(cmd, "atime", 5)) {
+ else if(strncasecompare(cmd, "atime", 5) ||
+ strncasecompare(cmd, "mtime", 5)) {
time_t date = Curl_getdate_capped(sshc->quote_path1);
+ bool fail = FALSE;
if(date == -1) {
+ failf(data, "incorrect date format for %.*s", 5, cmd);
+ fail = TRUE;
+ }
+#if SIZEOF_TIME_T > 4
+ else if(date > 0xffffffff) {
+ failf(data, "date overflow");
+ fail = TRUE; /* avoid setting a capped time */
+ }
+#endif
+ if(fail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- failf(data, "Syntax error: incorrect access date format");
state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
}
- sshc->quote_attrs->atime = (uint32_t)date;
- sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
- }
- else if(strncasecompare(cmd, "mtime", 5)) {
- time_t date = Curl_getdate_capped(sshc->quote_path1);
- if(date == -1) {
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
- failf(data, "Syntax error: incorrect modification date format");
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
- return;
- }
- sshc->quote_attrs->mtime = (uint32_t)date;
+ if(strncasecompare(cmd, "atime", 5))
+ sshc->quote_attrs->atime = (uint32_t)date;
+ else /* mtime */
+ sshc->quote_attrs->mtime = (uint32_t)date;
+
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
}
diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c
index 2026a88..98fce51 100644
--- a/lib/vssh/libssh2.c
+++ b/lib/vssh/libssh2.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -54,11 +54,6 @@
#include <inet.h>
#endif
-#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
-#undef in_addr_t
-#define in_addr_t unsigned long
-#endif
-
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
@@ -74,6 +69,7 @@
#include "strdup.h"
#include "strcase.h"
#include "vtls/vtls.h"
+#include "cfilters.h"
#include "connect.h"
#include "inet_ntop.h"
#include "parsedate.h" /* for the week day and month names */
@@ -83,7 +79,6 @@
#include "select.h"
#include "warnless.h"
#include "curl_path.h"
-#include "strcase.h"
#include <curl_base64.h> /* for base64 encoding/decoding */
#include <curl_sha256.h>
@@ -108,7 +103,6 @@
static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
static LIBSSH2_FREE_FUNC(my_libssh2_free);
-
static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data);
static CURLcode ssh_connect(struct Curl_easy *data, bool *done);
static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done);
@@ -149,7 +143,7 @@
scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
- ssh_attach,
+ ssh_attach, /* attach */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
CURLPROTO_SCP, /* family */
@@ -178,7 +172,7 @@
sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
- ssh_attach,
+ ssh_attach, /* attach */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
CURLPROTO_SFTP, /* family */
@@ -610,9 +604,9 @@
/* remove old host+key that doesn't match */
if(host)
libssh2_knownhost_del(sshc->kh, host);
- /*FALLTHROUGH*/
+ /* FALLTHROUGH */
case CURLKHSTAT_FINE:
- /*FALLTHROUGH*/
+ /* FALLTHROUGH */
case CURLKHSTAT_FINE_ADD_TO_FILE:
/* proceed */
if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
@@ -728,11 +722,10 @@
*/
if((pub_pos != b64_pos) ||
strncmp(fingerprint_b64, pubkey_sha256, pub_pos)) {
- free(fingerprint_b64);
-
failf(data,
"Denied establishing ssh session: mismatch sha256 fingerprint. "
"Remote %s is not equal to %s", fingerprint_b64, pubkey_sha256);
+ free(fingerprint_b64);
state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
return sshc->actualcode;
@@ -785,7 +778,7 @@
size_t keylen = 0;
int sshkeytype = 0;
int rc = 0;
- /* we handle the process to the callback*/
+ /* we handle the process to the callback */
const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
&keylen, &sshkeytype);
if(remotekey) {
@@ -796,10 +789,14 @@
Curl_set_in_callback(data, false);
if(rc!= CURLKHMATCH_OK) {
state(data, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
+ return sshc->actualcode;
}
}
else {
state(data, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
+ return sshc->actualcode;
}
return CURLE_OK;
}
@@ -841,6 +838,8 @@
#endif
static const char * const hostkey_method_ssh_rsa
= "ssh-rsa";
+ 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";
@@ -890,6 +889,7 @@
}
if(found) {
+ int rc;
infof(data, "Found host %s in %s",
conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]);
@@ -915,7 +915,16 @@
break;
#endif
case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
- hostkey_method = hostkey_method_ssh_rsa;
+#ifdef HAVE_LIBSSH2_VERSION
+ if(libssh2_version(0x010900))
+ /* since 1.9.0 libssh2_session_method_pref() works as expected */
+ hostkey_method = hostkey_method_ssh_rsa_all;
+ else
+#endif
+ /* old libssh2 which cannot correctly remove unsupported methods due
+ * to bug in src/kex.c or does not support the new methods anyways.
+ */
+ hostkey_method = hostkey_method_ssh_rsa;
break;
case LIBSSH2_KNOWNHOST_KEY_SSHDSS:
hostkey_method = hostkey_method_ssh_dss;
@@ -930,9 +939,15 @@
}
infof(data, "Set \"%s\" as SSH hostkey type", hostkey_method);
- result = libssh2_session_error_to_CURLE(
- libssh2_session_method_pref(
- sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
+ rc = libssh2_session_method_pref(sshc->ssh_session,
+ LIBSSH2_METHOD_HOSTKEY, hostkey_method);
+ if(rc) {
+ char *errmsg = NULL;
+ int errlen;
+ libssh2_session_last_error(sshc->ssh_session, &errmsg, &errlen, 0);
+ failf(data, "libssh2: %s", errmsg);
+ result = libssh2_session_error_to_CURLE(rc);
+ }
}
else {
infof(data, "Did not find host %s in %s",
@@ -1755,32 +1770,35 @@
break;
}
}
- else if(strncasecompare(cmd, "atime", 5)) {
+ else if(strncasecompare(cmd, "atime", 5) ||
+ strncasecompare(cmd, "mtime", 5)) {
time_t date = Curl_getdate_capped(sshc->quote_path1);
+ bool fail = FALSE;
+
if(date == -1) {
+ failf(data, "incorrect date format for %.*s", 5, cmd);
+ fail = TRUE;
+ }
+#if SIZEOF_TIME_T > SIZEOF_LONG
+ if(date > 0xffffffff) {
+ /* if 'long' can't old >32bit, this date cannot be sent */
+ failf(data, "date overflow");
+ fail = TRUE;
+ }
+#endif
+ if(fail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- failf(data, "Syntax error: incorrect access date format");
state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- sshp->quote_attrs.atime = (unsigned long)date;
- sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
- }
- else if(strncasecompare(cmd, "mtime", 5)) {
- time_t date = Curl_getdate_capped(sshc->quote_path1);
- if(date == -1) {
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
- failf(data, "Syntax error: incorrect modification date format");
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
- break;
- }
- sshp->quote_attrs.mtime = (unsigned long)date;
+ if(strncasecompare(cmd, "atime", 5))
+ sshp->quote_attrs.atime = (unsigned long)date;
+ else /* mtime */
+ sshp->quote_attrs.mtime = (unsigned long)date;
+
sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
}
@@ -2001,7 +2019,7 @@
}
case SSH_SFTP_TRANS_INIT:
- if(data->set.upload)
+ if(data->state.upload)
state(data, SSH_SFTP_UPLOAD_INIT);
else {
if(sshp->path[strlen(sshp->path)-1] == '/')
@@ -2248,7 +2266,7 @@
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
- if(data->set.opt_no_body) {
+ if(data->req.no_body) {
state(data, SSH_STOP);
break;
}
@@ -2335,7 +2353,8 @@
((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
LIBSSH2_SFTP_S_IFLNK)) {
Curl_dyn_init(&sshp->readdir_link, PATH_MAX);
- result = Curl_dyn_add(&sshp->readdir_link, sshp->path);
+ result = Curl_dyn_addf(&sshp->readdir_link, "%s%s", sshp->path,
+ sshp->readdir_filename);
state(data, SSH_SFTP_READDIR_LINK);
if(!result)
break;
@@ -2386,7 +2405,6 @@
result = Curl_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);
if(result) {
- sshc->readdir_line = NULL;
Curl_safefree(sshp->readdir_filename);
Curl_safefree(sshp->readdir_longentry);
state(data, SSH_SFTP_CLOSE);
@@ -2499,12 +2517,12 @@
CURLofft to_t;
CURLofft from_t;
- from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
+ from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from);
if(from_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+ while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
ptr++;
- to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
+ to_t = curlx_strtoofft(ptr, &ptr2, 10, &to);
if(to_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
@@ -2673,7 +2691,7 @@
break;
}
- if(data->set.upload) {
+ if(data->state.upload) {
if(data->state.infilesize < 0) {
failf(data, "SCP requires a known file size for upload");
sshc->actualcode = CURLE_UPLOAD_FAILED;
@@ -2813,7 +2831,7 @@
break;
case SSH_SCP_DONE:
- if(data->set.upload)
+ if(data->state.upload)
state(data, SSH_SCP_SEND_EOF);
else
state(data, SSH_SCP_CHANNEL_FREE);
@@ -2990,12 +3008,9 @@
Curl_safefree(sshc->rsa_pub);
Curl_safefree(sshc->rsa);
-
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
-
Curl_safefree(sshc->homedir);
- Curl_safefree(sshc->readdir_line);
/* the code we are about to return */
result = sshc->actualcode;
@@ -3254,14 +3269,27 @@
sock = conn->sock[FIRSTSOCKET];
#endif /* CURL_LIBSSH2_DEBUG */
+ /* libcurl MUST to set custom memory functions so that the kbd_callback
+ funciton's memory allocations can be properled freed */
sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
my_libssh2_free,
my_libssh2_realloc, data);
+
if(!sshc->ssh_session) {
failf(data, "Failure initialising ssh session");
return CURLE_FAILED_INIT;
}
+#ifdef HAVE_LIBSSH2_VERSION
+ /* Set the packet read timeout if the libssh2 version supports it */
+#if LIBSSH2_VERSION_NUM >= 0x010B00
+ if(data->set.server_response_timeout > 0) {
+ libssh2_session_set_read_timeout(sshc->ssh_session,
+ data->set.server_response_timeout / 1000);
+ }
+#endif
+#endif
+
#ifndef CURL_DISABLE_PROXY
if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
/*
@@ -3371,7 +3399,6 @@
bool *dophase_done)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
DEBUGF(infof(data, "DO phase starts"));
@@ -3383,7 +3410,7 @@
/* run the state-machine */
result = ssh_multi_statemach(data, dophase_done);
- *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+ *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
if(*dophase_done) {
DEBUGF(infof(data, "DO phase is complete"));
@@ -3572,7 +3599,7 @@
/* run the state-machine */
result = ssh_multi_statemach(data, dophase_done);
- *connected = data->conn->bits.tcpconnect[FIRSTSOCKET];
+ *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
if(*dophase_done) {
DEBUGF(infof(data, "DO phase is complete"));
diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h
index 7e1d815..1e1b137 100644
--- a/lib/vssh/ssh.h
+++ b/lib/vssh/ssh.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,10 +26,10 @@
#include "curl_setup.h"
-#if defined(HAVE_LIBSSH2_H)
+#if defined(USE_LIBSSH2)
#include <libssh2.h>
#include <libssh2_sftp.h>
-#elif defined(HAVE_LIBSSH_LIBSSH_H)
+#elif defined(USE_LIBSSH)
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#elif defined(USE_WOLFSSH)
@@ -147,7 +147,6 @@
char *homedir; /* when doing SFTP we figure out home dir in the
connect phase */
- char *readdir_line;
/* end of READDIR stuff */
int secondCreateDirs; /* counter use by the code to see if the
@@ -158,7 +157,8 @@
#if defined(USE_LIBSSH)
char *readdir_linkPath;
- size_t readdir_len, readdir_totalLen, readdir_currLen;
+ size_t readdir_len;
+ struct dynbuf readdir_buf;
/* our variables */
unsigned kbd_state; /* 0 or 1 */
ssh_key privkey;
diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c
index c2f85f3..b47c231 100644
--- a/lib/vssh/wolfssh.c
+++ b/lib/vssh/wolfssh.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,6 +31,7 @@
#include <wolfssh/ssh.h>
#include <wolfssh/wolfsftp.h>
#include "urldata.h"
+#include "cfilters.h"
#include "connect.h"
#include "sendf.h"
#include "progress.h"
@@ -276,7 +277,7 @@
return -1;
}
DEBUGASSERT(rc == (int)len);
- infof(data, "sent %zd bytes SFTP from offset %zd",
+ infof(data, "sent %zu bytes SFTP from offset %" CURL_FORMAT_CURL_OFF_T,
len, sshc->offset);
sshc->offset += len;
return (ssize_t)rc;
@@ -424,7 +425,7 @@
state(data, SSH_SFTP_INIT);
return wssh_multi_statemach(data, done);
- error:
+error:
wolfSSH_free(sshc->ssh_session);
wolfSSH_CTX_free(sshc->ctx);
return CURLE_FAILED_INIT;
@@ -556,7 +557,7 @@
}
break;
case SSH_SFTP_TRANS_INIT:
- if(data->set.upload)
+ if(data->state.upload)
state(data, SSH_SFTP_UPLOAD_INIT);
else {
if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
@@ -836,7 +837,7 @@
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
- if(data->set.opt_no_body) {
+ if(data->req.no_body) {
state(data, SSH_STOP);
break;
}
@@ -939,7 +940,6 @@
bool *dophase_done)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
DEBUGF(infof(data, "DO phase starts"));
@@ -951,7 +951,7 @@
/* run the state-machine */
result = wssh_multi_statemach(data, dophase_done);
- *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+ *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
if(*dophase_done) {
DEBUGF(infof(data, "DO phase is complete"));
diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c
index f14eb66..6ed453b 100644
--- a/lib/vtls/bearssl.c
+++ b/lib/vtls/bearssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Michael Forney, <mforney@mforney.org>
+ * Copyright (C) Michael Forney, <mforney@mforney.org>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -32,13 +32,17 @@
#include "sendf.h"
#include "inet_pton.h"
#include "vtls.h"
+#include "vtls_int.h"
#include "connect.h"
#include "select.h"
#include "multiif.h"
#include "curl_printf.h"
-#include "curl_memory.h"
#include "strcase.h"
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
struct x509_context {
const br_x509_class *vtable;
br_x509_minimal_context minimal;
@@ -48,13 +52,13 @@
int cert_num;
};
-struct ssl_backend_data {
+struct bearssl_ssl_backend_data {
br_ssl_client_context ctx;
struct x509_context x509;
unsigned char buf[BR_SSL_BUFSIZE_BIDI];
br_x509_trust_anchor *anchors;
size_t anchors_len;
- const char *protocols[2];
+ const char *protocols[ALPN_ENTRIES_MAX];
/* SSL client context is active */
bool active;
/* size of pending write, yet to be flushed */
@@ -76,9 +80,9 @@
#define CAFILE_SOURCE_PATH 1
#define CAFILE_SOURCE_BLOB 2
struct cafile_source {
- const int type;
- const char * const data;
- const size_t len;
+ int type;
+ const char *data;
+ size_t len;
};
static void append_dn(void *ctx, const void *buf, size_t len)
@@ -566,18 +570,21 @@
return CURLE_OK;
}
-static CURLcode bearssl_connect_step1(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
const char * const ssl_cafile =
/* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
- (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
- const char *hostname = SSL_HOST_NAME();
- const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- const bool verifyhost = SSL_CONN_CONFIG(verifyhost);
+ (ca_info_blob ? NULL : conn_config->CAfile);
+ const char *hostname = connssl->hostname;
+ const bool verifypeer = conn_config->verifypeer;
+ const bool verifyhost = conn_config->verifyhost;
CURLcode ret;
unsigned version_min, version_max;
#ifdef ENABLE_IPV6
@@ -588,7 +595,7 @@
DEBUGASSERT(backend);
- switch(SSL_CONN_CONFIG(version)) {
+ switch(conn_config->version) {
case CURL_SSLVERSION_SSLv2:
failf(data, "BearSSL does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
@@ -618,11 +625,11 @@
}
if(ca_info_blob) {
- struct cafile_source source = {
- CAFILE_SOURCE_BLOB,
- ca_info_blob->data,
- ca_info_blob->len,
- };
+ struct cafile_source source;
+ source.type = CAFILE_SOURCE_BLOB;
+ source.data = ca_info_blob->data;
+ source.len = ca_info_blob->len;
+
ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
if(ret != CURLE_OK) {
if(verifypeer) {
@@ -635,11 +642,11 @@
}
if(ssl_cafile) {
- struct cafile_source source = {
- CAFILE_SOURCE_PATH,
- ssl_cafile,
- 0,
- };
+ struct cafile_source source;
+ source.type = CAFILE_SOURCE_PATH;
+ source.data = ssl_cafile;
+ source.len = 0;
+
ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
if(ret != CURLE_OK) {
if(verifypeer) {
@@ -659,11 +666,11 @@
br_ssl_engine_set_buffer(&backend->ctx.eng, backend->buf,
sizeof(backend->buf), 1);
- if(SSL_CONN_CONFIG(cipher_list)) {
+ if(conn_config->cipher_list) {
/* Override the ciphers as specified. For the default cipher list see the
BearSSL source code of br_ssl_client_init_full() */
ret = bearssl_set_selected_ciphers(data, &backend->ctx.eng,
- SSL_CONN_CONFIG(cipher_list));
+ conn_config->cipher_list);
if(ret)
return ret;
}
@@ -674,41 +681,28 @@
backend->x509.verifyhost = verifyhost;
br_ssl_engine_set_x509(&backend->ctx.eng, &backend->x509.vtable);
- if(SSL_SET_OPTION(primary.sessionid)) {
+ if(ssl_config->primary.sessionid) {
void *session;
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE,
- &session, NULL, sockindex)) {
+ if(!Curl_ssl_getsessionid(cf, data, &session, NULL)) {
br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
infof(data, "BearSSL: re-using session ID");
}
Curl_ssl_sessionid_unlock(data);
}
- if(conn->bits.tls_enable_alpn) {
- int cur = 0;
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
+ size_t i;
- /* NOTE: when adding more protocols here, increase the size of the
- * protocols array in `struct ssl_backend_data`.
- */
-
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2
-#ifndef CURL_DISABLE_PROXY
- && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
-#endif
- ) {
- backend->protocols[cur++] = ALPN_H2;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+ for(i = 0; i < connssl->alpn->count; ++i) {
+ backend->protocols[i] = connssl->alpn->entries[i];
}
-#endif
-
- backend->protocols[cur++] = ALPN_HTTP_1_1;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
-
- br_ssl_engine_set_protocol_names(&backend->ctx.eng,
- backend->protocols, cur);
+ br_ssl_engine_set_protocol_names(&backend->ctx.eng, backend->protocols,
+ connssl->alpn->count);
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
if((1 == Curl_inet_pton(AF_INET, hostname, &addr))
@@ -753,17 +747,18 @@
return CURLE_OK;
}
-static CURLcode bearssl_run_until(struct Curl_easy *data,
- struct connectdata *conn, int sockindex,
+static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
unsigned target)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
unsigned state;
unsigned char *buf;
size_t len;
ssize_t ret;
+ CURLcode result;
int err;
DEBUGASSERT(backend);
@@ -802,48 +797,38 @@
return CURLE_OK;
if(state & BR_SSL_SENDREC) {
buf = br_ssl_engine_sendrec_buf(&backend->ctx.eng, &len);
- ret = swrite(sockfd, buf, len);
- if(ret == -1) {
- if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
- if(connssl->state != ssl_connection_complete)
- connssl->connecting_state = ssl_connect_2_writing;
- return CURLE_AGAIN;
- }
- return CURLE_WRITE_ERROR;
+ ret = Curl_conn_cf_send(cf->next, data, (char *)buf, len, &result);
+ if(ret <= 0) {
+ return result;
}
br_ssl_engine_sendrec_ack(&backend->ctx.eng, ret);
}
else if(state & BR_SSL_RECVREC) {
buf = br_ssl_engine_recvrec_buf(&backend->ctx.eng, &len);
- ret = sread(sockfd, buf, len);
+ ret = Curl_conn_cf_recv(cf->next, data, (char *)buf, len, &result);
if(ret == 0) {
failf(data, "SSL: EOF without close notify");
return CURLE_READ_ERROR;
}
- if(ret == -1) {
- if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
- if(connssl->state != ssl_connection_complete)
- connssl->connecting_state = ssl_connect_2_reading;
- return CURLE_AGAIN;
- }
- return CURLE_READ_ERROR;
+ if(ret <= 0) {
+ return result;
}
br_ssl_engine_recvrec_ack(&backend->ctx.eng, ret);
}
}
}
-static CURLcode bearssl_connect_step2(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode bearssl_connect_step2(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
CURLcode ret;
DEBUGASSERT(backend);
- ret = bearssl_run_until(data, conn, sockindex,
- BR_SSL_SENDAPP | BR_SSL_RECVAPP);
+ ret = bearssl_run_until(cf, data, BR_SSL_SENDAPP | BR_SSL_RECVAPP);
if(ret == CURLE_AGAIN)
return CURLE_OK;
if(ret == CURLE_OK) {
@@ -856,40 +841,27 @@
return ret;
}
-static CURLcode bearssl_connect_step3(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
CURLcode ret;
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
DEBUGASSERT(backend);
- if(conn->bits.tls_enable_alpn) {
- const char *protocol;
+ if(connssl->alpn) {
+ const char *proto;
- protocol = br_ssl_engine_get_selected_protocol(&backend->ctx.eng);
- if(protocol) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, protocol);
-
-#ifdef USE_HTTP2
- if(!strcmp(protocol, ALPN_H2))
- conn->negnpn = CURL_HTTP_VERSION_2;
- else
-#endif
- if(!strcmp(protocol, ALPN_HTTP_1_1))
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- else
- infof(data, "ALPN, unrecognized protocol %s", protocol);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
- }
- else
- infof(data, VTLS_INFOF_NO_ALPN);
+ proto = br_ssl_engine_get_selected_protocol(&backend->ctx.eng);
+ Curl_alpn_set_negotiated(cf, data, (const unsigned char *)proto,
+ proto? strlen(proto) : 0);
}
- if(SSL_SET_OPTION(primary.sessionid)) {
+ if(ssl_config->primary.sessionid) {
bool incache;
bool added = FALSE;
void *oldsession;
@@ -900,14 +872,10 @@
return CURLE_OUT_OF_MEMORY;
br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(data, conn,
- SSL_IS_PROXY() ? TRUE : FALSE,
- &oldsession, NULL, sockindex));
+ incache = !(Curl_ssl_getsessionid(cf, data, &oldsession, NULL));
if(incache)
Curl_ssl_delsessionid(data, oldsession);
- ret = Curl_ssl_addsessionid(data, conn,
- SSL_IS_PROXY() ? TRUE : FALSE,
- session, 0, sockindex, &added);
+ ret = Curl_ssl_addsessionid(cf, data, session, 0, &added);
Curl_ssl_sessionid_unlock(data);
if(!added)
free(session);
@@ -921,20 +889,20 @@
return CURLE_OK;
}
-static ssize_t bearssl_send(struct Curl_easy *data, int sockindex,
+static ssize_t bearssl_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
unsigned char *app;
size_t applen;
DEBUGASSERT(backend);
for(;;) {
- *err = bearssl_run_until(data, conn, sockindex, BR_SSL_SENDAPP);
- if (*err != CURLE_OK)
+ *err = bearssl_run_until(cf, data, BR_SSL_SENDAPP);
+ if(*err)
return -1;
app = br_ssl_engine_sendapp_buf(&backend->ctx.eng, &applen);
if(!app) {
@@ -956,18 +924,18 @@
}
}
-static ssize_t bearssl_recv(struct Curl_easy *data, int sockindex,
+static ssize_t bearssl_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
unsigned char *app;
size_t applen;
DEBUGASSERT(backend);
- *err = bearssl_run_until(data, conn, sockindex, BR_SSL_RECVAPP);
+ *err = bearssl_run_until(cf, data, BR_SSL_RECVAPP);
if(*err != CURLE_OK)
return -1;
app = br_ssl_engine_recvapp_buf(&backend->ctx.eng, &applen);
@@ -981,15 +949,14 @@
return applen;
}
-static CURLcode bearssl_connect_common(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
+static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
bool nonblocking,
bool *done)
{
CURLcode ret;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
timediff_t timeout_ms;
int what;
@@ -1000,7 +967,7 @@
}
if(ssl_connect_1 == connssl->connecting_state) {
- ret = bearssl_connect_step1(data, conn, sockindex);
+ ret = bearssl_connect_step1(cf, data);
if(ret)
return ret;
}
@@ -1053,7 +1020,7 @@
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
- ret = bearssl_connect_step2(data, conn, sockindex);
+ ret = bearssl_connect_step2(cf, data);
if(ret || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -1062,15 +1029,13 @@
}
if(ssl_connect_3 == connssl->connecting_state) {
- ret = bearssl_connect_step3(data, conn, sockindex);
+ ret = bearssl_connect_step3(cf, data);
if(ret)
return ret;
}
if(ssl_connect_done == connssl->connecting_state) {
connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = bearssl_recv;
- conn->send[sockindex] = bearssl_send;
*done = TRUE;
}
else
@@ -1087,12 +1052,15 @@
return msnprintf(buffer, size, "BearSSL");
}
-static bool bearssl_data_pending(const struct connectdata *conn,
- int connindex)
+static bool bearssl_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
- const struct ssl_connect_data *connssl = &conn->ssl[connindex];
- struct ssl_backend_data *backend = connssl->backend;
- DEBUGASSERT(backend);
+ struct ssl_connect_data *ctx = cf->ctx;
+ struct bearssl_ssl_backend_data *backend;
+
+ (void)data;
+ DEBUGASSERT(ctx && ctx->backend);
+ backend = (struct bearssl_ssl_backend_data *)ctx->backend;
return br_ssl_engine_current_state(&backend->ctx.eng) & BR_SSL_RECVAPP;
}
@@ -1116,13 +1084,13 @@
return CURLE_OK;
}
-static CURLcode bearssl_connect(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode bearssl_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
CURLcode ret;
bool done = FALSE;
- ret = bearssl_connect_common(data, conn, sockindex, FALSE, &done);
+ ret = bearssl_connect_common(cf, data, FALSE, &done);
if(ret)
return ret;
@@ -1131,37 +1099,41 @@
return CURLE_OK;
}
-static CURLcode bearssl_connect_nonblocking(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode bearssl_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done)
{
- return bearssl_connect_common(data, conn, sockindex, TRUE, done);
+ return bearssl_connect_common(cf, data, TRUE, done);
}
static void *bearssl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
return &backend->ctx;
}
-static void bearssl_close(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static void bearssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
size_t i;
DEBUGASSERT(backend);
if(backend->active) {
+ backend->active = FALSE;
br_ssl_engine_close(&backend->ctx.eng);
- (void)bearssl_run_until(data, conn, sockindex, BR_SSL_CLOSED);
+ (void)bearssl_run_until(cf, data, BR_SSL_CLOSED);
}
- for(i = 0; i < backend->anchors_len; ++i)
- free(backend->anchors[i].dn.data);
- free(backend->anchors);
+ if(backend->anchors) {
+ for(i = 0; i < backend->anchors_len; ++i)
+ free(backend->anchors[i].dn.data);
+ Curl_safefree(backend->anchors);
+ }
}
static void bearssl_session_free(void *ptr)
@@ -1184,8 +1156,8 @@
const struct Curl_ssl Curl_ssl_bearssl = {
{ CURLSSLBACKEND_BEARSSL, "bearssl" }, /* info */
- SSLSUPP_CAINFO_BLOB | SSLSUPP_SSL_CTX,
- sizeof(struct ssl_backend_data),
+ SSLSUPP_CAINFO_BLOB | SSLSUPP_SSL_CTX | SSLSUPP_HTTPS_PROXY,
+ sizeof(struct bearssl_ssl_backend_data),
Curl_none_init, /* init */
Curl_none_cleanup, /* cleanup */
@@ -1197,7 +1169,7 @@
Curl_none_cert_status_request, /* cert_status_request */
bearssl_connect, /* connect */
bearssl_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_getsock, /* getsock */
+ Curl_ssl_get_select_socks, /* getsock */
bearssl_get_internals, /* get_internals */
bearssl_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -1208,7 +1180,10 @@
Curl_none_false_start, /* false_start */
bearssl_sha256sum, /* sha256sum */
NULL, /* associate_connection */
- NULL /* disassociate_connection */
+ NULL, /* disassociate_connection */
+ NULL, /* free_multi_ssl_backend_data */
+ bearssl_recv, /* recv decrypted data */
+ bearssl_send, /* send data to encrypt */
};
#endif /* USE_BEARSSL */
diff --git a/lib/vtls/bearssl.h b/lib/vtls/bearssl.h
index 5125359..b3651b0 100644
--- a/lib/vtls/bearssl.h
+++ b/lib/vtls/bearssl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Michael Forney, <mforney@mforney.org>
+ * Copyright (C) Michael Forney, <mforney@mforney.org>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index 4ee4ede..c128293 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -73,6 +73,7 @@
#include "sendf.h"
#include "gskit.h"
#include "vtls.h"
+#include "vtls_int.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
#include "strcase.h"
@@ -102,16 +103,14 @@
#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
#define CURL_GSKPROTO_LAST 5
-struct ssl_backend_data {
+struct gskit_ssl_backend_data {
gsk_handle handle;
int iocport;
-#ifndef CURL_DISABLE_PROXY
int localfd;
int remotefd;
-#endif
};
-#define BACKEND connssl->backend
+#define BACKEND ((struct gskit_ssl_backend_data *)connssl->backend)
/* Supported ciphers. */
struct gskit_cipher {
@@ -295,11 +294,12 @@
}
-static CURLcode set_ciphers(struct Curl_easy *data,
+static CURLcode set_ciphers(struct Curl_cfilter *cf, struct Curl_easy *data,
gsk_handle h, unsigned int *protoflags)
{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct connectdata *conn = data->conn;
- const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
+ const char *cipherlist = conn_config->cipher_list;
const char *clp;
const struct gskit_cipher *ctp;
int i;
@@ -324,7 +324,7 @@
GSKit tokens are always shorter than their cipher names, allocated buffers
will always be large enough to accommodate the result. */
l = strlen(cipherlist) + 1;
- memset((char *) ciphers, 0, sizeof(ciphers));
+ memset(ciphers, 0, sizeof(ciphers));
for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
ciphers[i].buf = malloc(l);
if(!ciphers[i].buf) {
@@ -490,14 +490,16 @@
}
-static void cancel_async_handshake(struct connectdata *conn, int sockindex)
+static void cancel_async_handshake(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
Qso_OverlappedIO_t cstat;
+ (void)data;
DEBUGASSERT(BACKEND);
- if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
+ if(QsoCancelOperation(Curl_conn_cf_get_socket(cf, data), 0) > 0)
QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL);
}
@@ -509,12 +511,14 @@
BACKEND->iocport = -1;
}
-static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
+static int pipe_ssloverssl(struct Curl_cfilter *cf, struct Curl_easy *data,
int directions)
{
-#ifndef CURL_DISABLE_PROXY
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
+ struct ssl_connect_data *connssl_next = cf_ssl_next?
+ cf_ssl_next->ctx : NULL;
+ struct gskit_ssl_backend_data *backend_next;
struct pollfd fds[2];
int n;
int m;
@@ -523,14 +527,16 @@
char buf[CURL_MAX_WRITE_SIZE];
DEBUGASSERT(BACKEND);
- DEBUGASSERT(connproxyssl->backend);
- if(!connssl->use || !connproxyssl->use)
+ if(!connssl_next)
return 0; /* No SSL over SSL: OK. */
+ DEBUGASSERT(connssl_next->backend);
+ backend_next = (struct gskit_ssl_backend_data *)connssl_next->backend;
+
n = 1;
fds[0].fd = BACKEND->remotefd;
- fds[1].fd = conn->sock[sockindex];
+ fds[1].fd = Curl_conn_cf_get_socket(cf, data);
if(directions & SOS_READ) {
fds[0].events |= POLLOUT;
@@ -547,8 +553,7 @@
if(fds[0].revents & POLLOUT) {
/* Try getting data from HTTPS proxy and pipe it upstream. */
n = 0;
- i = gsk_secure_soc_read(connproxyssl->backend->handle,
- buf, sizeof(buf), &n);
+ i = gsk_secure_soc_read(backend_next->handle, buf, sizeof(buf), &n);
switch(i) {
case GSK_OK:
if(n) {
@@ -572,7 +577,7 @@
if(n < 0)
return -1;
if(n) {
- i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m);
+ i = gsk_secure_soc_write(backend_next->handle, buf, n, &m);
if(i != GSK_OK || n != m)
return -1;
ret = 1;
@@ -580,24 +585,21 @@
}
return ret; /* OK */
-#else
- return 0;
-#endif
}
-static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static void close_one(struct Curl_cfilter *cf, struct Curl_easy *data)
{
+ struct ssl_connect_data *connssl = cf->ctx;
+
DEBUGASSERT(BACKEND);
if(BACKEND->handle) {
gskit_status(data, gsk_secure_soc_close(&BACKEND->handle),
"gsk_secure_soc_close()", 0);
/* Last chance to drain output. */
- while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
+ while(pipe_ssloverssl(cf, data, SOS_WRITE) > 0)
;
BACKEND->handle = (gsk_handle) NULL;
-#ifndef CURL_DISABLE_PROXY
if(BACKEND->localfd >= 0) {
close(BACKEND->localfd);
BACKEND->localfd = -1;
@@ -606,30 +608,29 @@
close(BACKEND->remotefd);
BACKEND->remotefd = -1;
}
-#endif
}
if(BACKEND->iocport >= 0)
close_async_handshake(connssl);
}
-static ssize_t gskit_send(struct Curl_easy *data, int sockindex,
+static ssize_t gskit_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *mem, size_t len, CURLcode *curlcode)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct connectdata *conn = cf->conn;
+ struct ssl_connect_data *connssl = cf->ctx;
CURLcode cc = CURLE_SEND_ERROR;
int written;
DEBUGASSERT(BACKEND);
- if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
+ if(pipe_ssloverssl(cf, data, SOS_WRITE) >= 0) {
cc = gskit_status(data,
gsk_secure_soc_write(BACKEND->handle,
(char *) mem, (int) len, &written),
"gsk_secure_soc_write()", CURLE_SEND_ERROR);
if(cc == CURLE_OK)
- if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
+ if(pipe_ssloverssl(cf, data, SOS_WRITE) < 0)
cc = CURLE_SEND_ERROR;
}
if(cc != CURLE_OK) {
@@ -640,17 +641,18 @@
}
-static ssize_t gskit_recv(struct Curl_easy *data, int num, char *buf,
- size_t buffersize, CURLcode *curlcode)
+static ssize_t gskit_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t buffersize, CURLcode *curlcode)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[num];
+ struct connectdata *conn = cf->conn;
+ struct ssl_connect_data *connssl = cf->ctx;
int nread;
CURLcode cc = CURLE_RECV_ERROR;
+ (void)data;
DEBUGASSERT(BACKEND);
- if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
+ if(pipe_ssloverssl(cf, data, SOS_READ) >= 0) {
int buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
buf, buffsize, &nread),
@@ -670,11 +672,14 @@
}
static CURLcode
-set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data)
+set_ssl_version_min_max(unsigned int *protoflags,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct connectdata *conn = data->conn;
- long ssl_version = SSL_CONN_CONFIG(version);
- long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ long ssl_version = conn_config->version;
+ long ssl_version_max = conn_config->version_max;
long i = ssl_version;
switch(ssl_version_max) {
case CURL_SSLVERSION_MAX_NONE:
@@ -702,35 +707,36 @@
return CURLE_OK;
}
-static CURLcode gskit_connect_step1(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode gskit_connect_step1(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
+ struct ssl_connect_data *connssl_next = cf_ssl_next?
+ cf_ssl_next->ctx : NULL;
gsk_handle envir;
CURLcode result;
- const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
- const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
- const char * const keyringlabel = SSL_SET_OPTION(primary.clientcert);
- const long int ssl_version = SSL_CONN_CONFIG(version);
- const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- const char * const hostname = SSL_HOST_NAME();
+ const char * const keyringfile = conn_config->CAfile;
+ const char * const keyringpwd = ssl_config->key_passwd;
+ const char * const keyringlabel = ssl_config->primary.clientcert;
+ const long int ssl_version = conn_config->version;
+ const bool verifypeer = conn_config->verifypeer;
+ const char *hostname = connssl->hostname;
const char *sni;
unsigned int protoflags = 0;
Qso_OverlappedIO_t commarea;
-#ifndef CURL_DISABLE_PROXY
int sockpair[2];
static const int sobufsize = CURL_MAX_WRITE_SIZE;
-#endif
/* Create SSL environment, start (preferably asynchronous) handshake. */
DEBUGASSERT(BACKEND);
BACKEND->handle = (gsk_handle) NULL;
BACKEND->iocport = -1;
-#ifndef CURL_DISABLE_PROXY
BACKEND->localfd = -1;
BACKEND->remotefd = -1;
-#endif
/* GSKit supports two ways of specifying an SSL context: either by
* application identifier (that should have been defined at the system
@@ -769,9 +775,8 @@
if(result)
return result;
-#ifndef CURL_DISABLE_PROXY
/* Establish a pipelining socket pair for SSL over SSL. */
- if(conn->proxy_ssl[sockindex].use) {
+ if(connssl_next) {
if(Curl_socketpair(0, 0, 0, sockpair))
return CURLE_SSL_CONNECT_ERROR;
BACKEND->localfd = sockpair[0];
@@ -787,7 +792,6 @@
curlx_nonblock(BACKEND->localfd, TRUE);
curlx_nonblock(BACKEND->remotefd, TRUE);
}
-#endif
/* Determine which SSL/TLS version should be enabled. */
sni = hostname;
@@ -809,7 +813,7 @@
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
- result = set_ssl_version_min_max(&protoflags, data);
+ result = set_ssl_version_min_max(&protoflags, cf, data);
if(result != CURLE_OK)
return result;
break;
@@ -845,15 +849,10 @@
if(!result)
result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
if(!result)
-#ifndef CURL_DISABLE_PROXY
result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
- BACKEND->localfd: conn->sock[sockindex]);
-#else
- result = set_numeric(data, BACKEND->handle, GSK_FD,
- conn->sock[sockindex]);
-#endif
+ BACKEND->localfd: Curl_conn_cf_get_socket(cf, data));
if(!result)
- result = set_ciphers(data, BACKEND->handle, &protoflags);
+ result = set_ciphers(cf, data, BACKEND->handle, &protoflags);
if(!protoflags) {
failf(data, "No SSL protocol/cipher combination enabled");
result = CURLE_SSL_CIPHER;
@@ -920,12 +919,10 @@
else if(errno != ENOBUFS)
result = gskit_status(data, GSK_ERROR_IO,
"QsoCreateIOCompletionPort()", 0);
-#ifndef CURL_DISABLE_PROXY
- else if(conn->proxy_ssl[sockindex].use) {
+ else if(connssl_next) {
/* Cannot pipeline while handshaking synchronously. */
result = CURLE_SSL_CONNECT_ERROR;
}
-#endif
else {
/* No more completion port available. Use synchronous IO. */
result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle),
@@ -938,16 +935,16 @@
}
/* Error: rollback. */
- close_one(connssl, data, conn, sockindex);
+ close_one(cf, data);
return result;
}
-static CURLcode gskit_connect_step2(struct Curl_easy *data,
- struct connectdata *conn, int sockindex,
+static CURLcode gskit_connect_step2(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
bool nonblocking)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
Qso_OverlappedIO_t cstat;
struct timeval stmv;
CURLcode result;
@@ -975,7 +972,7 @@
char buffer[STRERROR_LEN];
failf(data, "QsoWaitForIOCompletion() I/O error: %s",
Curl_strerror(errno, buffer, sizeof(buffer)));
- cancel_async_handshake(conn, sockindex);
+ cancel_async_handshake(cf, data);
close_async_handshake(connssl);
return CURLE_SSL_CONNECT_ERROR;
}
@@ -983,7 +980,7 @@
case 0: /* Handshake in progress, timeout occurred. */
if(nonblocking)
return CURLE_OK;
- cancel_async_handshake(conn, sockindex);
+ cancel_async_handshake(cf, data);
close_async_handshake(connssl);
return CURLE_OPERATION_TIMEDOUT;
}
@@ -998,15 +995,15 @@
}
-static CURLcode gskit_connect_step3(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode gskit_connect_step3(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
const gsk_cert_data_elem *cdev;
int cdec;
const gsk_cert_data_elem *p;
const char *cert = (const char *) NULL;
- const char *certend;
+ const char *certend = (const char *) NULL;
const char *ptr;
CURLcode result;
@@ -1044,7 +1041,7 @@
}
/* Verify host. */
- result = Curl_verifyhost(data, conn, cert, certend);
+ result = Curl_verifyhost(cf, data, cert, certend);
if(result)
return result;
@@ -1066,7 +1063,9 @@
}
/* Check pinned public key. */
- ptr = SSL_PINNED_PUB_KEY();
+ ptr = Curl_ssl_cf_is_proxy(cf)?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
if(!result && ptr) {
struct Curl_X509certificate x509;
struct Curl_asn1Element *p;
@@ -1087,11 +1086,11 @@
}
-static CURLcode gskit_connect_common(struct Curl_easy *data,
- struct connectdata *conn, int sockindex,
+static CURLcode gskit_connect_common(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
bool nonblocking, bool *done)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
timediff_t timeout_ms;
CURLcode result = CURLE_OK;
@@ -1110,12 +1109,12 @@
result = CURLE_OPERATION_TIMEDOUT;
}
else
- result = gskit_connect_step1(data, conn, sockindex);
+ result = gskit_connect_step1(cf, data);
}
/* Handle handshake pipelining. */
if(!result)
- if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
+ if(pipe_ssloverssl(cf, data, SOS_READ | SOS_WRITE) < 0)
result = CURLE_SSL_CONNECT_ERROR;
/* Step 2: check if handshake is over. */
@@ -1129,25 +1128,23 @@
result = CURLE_OPERATION_TIMEDOUT;
}
else
- result = gskit_connect_step2(data, conn, sockindex, nonblocking);
+ result = gskit_connect_step2(cf, data, nonblocking);
}
/* Handle handshake pipelining. */
if(!result)
- if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
+ if(pipe_ssloverssl(cf, data, SOS_READ | SOS_WRITE) < 0)
result = CURLE_SSL_CONNECT_ERROR;
/* Step 3: gather certificate info, verify host. */
if(!result && connssl->connecting_state == ssl_connect_3)
- result = gskit_connect_step3(data, conn, sockindex);
+ result = gskit_connect_step3(cf, data);
if(result)
- close_one(connssl, data, conn, sockindex);
+ close_one(cf, data);
else if(connssl->connecting_state == ssl_connect_done) {
connssl->state = ssl_connection_complete;
connssl->connecting_state = ssl_connect_1;
- conn->recv[sockindex] = gskit_recv;
- conn->send[sockindex] = gskit_send;
*done = TRUE;
}
@@ -1155,27 +1152,29 @@
}
-static CURLcode gskit_connect_nonblocking(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode gskit_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done)
{
+ struct ssl_connect_data *connssl = cf->ctx;
CURLcode result;
- result = gskit_connect_common(data, conn, sockindex, TRUE, done);
+ result = gskit_connect_common(cf, data, TRUE, done);
if(*done || result)
- conn->ssl[sockindex].connecting_state = ssl_connect_1;
+ connssl->connecting_state = ssl_connect_1;
return result;
}
-static CURLcode gskit_connect(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode gskit_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
+ struct ssl_connect_data *connssl = cf->ctx;
CURLcode result;
bool done;
- conn->ssl[sockindex].connecting_state = ssl_connect_1;
- result = gskit_connect_common(data, conn, sockindex, FALSE, &done);
+ connssl->connecting_state = ssl_connect_1;
+ result = gskit_connect_common(cf, data, FALSE, &done);
if(result)
return result;
@@ -1185,20 +1184,16 @@
}
-static void gskit_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static void gskit_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- close_one(&conn->ssl[sockindex], data, conn, sockindex);
-#ifndef CURL_DISABLE_PROXY
- close_one(&conn->proxy_ssl[sockindex], data, conn, sockindex);
-#endif
+ close_one(cf, data);
}
-static int gskit_shutdown(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static int gskit_shutdown(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
int what;
int rc;
char buf[120];
@@ -1214,9 +1209,9 @@
return 0;
#endif
- close_one(connssl, data, conn, sockindex);
+ close_one(cf, data);
rc = 0;
- what = SOCKET_READABLE(conn->sock[sockindex],
+ what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
SSL_SHUTDOWN_TIMEOUT);
while(loop--) {
@@ -1238,7 +1233,7 @@
notify alert from the server. No way to gsk_secure_soc_read() now, so
use read(). */
- nread = read(conn->sock[sockindex], buf, sizeof(buf));
+ nread = read(Curl_conn_cf_get_socket(cf, data), buf, sizeof(buf));
if(nread < 0) {
char buffer[STRERROR_LEN];
@@ -1249,7 +1244,7 @@
if(nread <= 0)
break;
- what = SOCKET_READABLE(conn->sock[sockindex], 0);
+ what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data), 0);
}
return rc;
@@ -1262,12 +1257,14 @@
}
-static int gskit_check_cxn(struct connectdata *cxn)
+static int gskit_check_cxn(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
+ struct ssl_connect_data *connssl = cf->ctx;
int err;
int errlen;
+ (void)data;
/* The only thing that can be tested here is at the socket level. */
DEBUGASSERT(BACKEND);
@@ -1277,7 +1274,7 @@
err = 0;
errlen = sizeof(err);
- if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
+ if(getsockopt(Curl_conn_cf_get_socket(cf, data), SOL_SOCKET, SO_ERROR,
(unsigned char *) &err, &errlen) ||
errlen != sizeof(err) || err)
return 0; /* connection has been closed */
@@ -1299,7 +1296,7 @@
SSLSUPP_CERTINFO |
SSLSUPP_PINNEDPUBKEY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct gskit_ssl_backend_data),
gskit_init, /* init */
gskit_cleanup, /* cleanup */
@@ -1311,7 +1308,7 @@
Curl_none_cert_status_request, /* cert_status_request */
gskit_connect, /* connect */
gskit_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_getsock, /* getsock */
+ Curl_ssl_get_select_socks, /* getsock */
gskit_get_internals, /* get_internals */
gskit_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -1323,7 +1320,10 @@
Curl_none_false_start, /* false_start */
NULL, /* sha256sum */
NULL, /* associate_connection */
- NULL /* disassociate_connection */
+ NULL, /* disassociate_connection */
+ NULL, /* free_multi_ssl_backend_data */
+ gskit_recv, /* recv decrypted data */
+ gskit_send, /* send data to encrypt */
};
#endif /* USE_GSKIT */
diff --git a/lib/vtls/gskit.h b/lib/vtls/gskit.h
index cf923f6..c71e6a0 100644
--- a/lib/vtls/gskit.h
+++ b/lib/vtls/gskit.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index e2d41f4..f6f1e10 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -45,6 +45,8 @@
#include "inet_pton.h"
#include "gtls.h"
#include "vtls.h"
+#include "vtls_int.h"
+#include "vauth/vauth.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
@@ -57,14 +59,6 @@
/* The last #include file should be: */
#include "memdebug.h"
-#ifdef HAVE_GNUTLS_SRP
-/* the function exists */
-#ifdef USE_TLS_SRP
-/* the functionality is not disabled */
-#define USE_GNUTLS_SRP
-#endif
-#endif
-
/* Enable GnuTLS debugging by defining GTLSDEBUG */
/*#define GTLSDEBUG */
@@ -82,36 +76,48 @@
# include <gnutls/ocsp.h>
-struct ssl_backend_data {
- gnutls_session_t session;
- gnutls_certificate_credentials_t cred;
-#ifdef USE_GNUTLS_SRP
- gnutls_srp_client_credentials_t srp_client_cred;
-#endif
+struct gtls_ssl_backend_data {
+ struct gtls_instance gtls;
};
-static ssize_t gtls_push(void *s, const void *buf, size_t len)
+static ssize_t gtls_push(void *s, const void *buf, size_t blen)
{
- curl_socket_t sock = *(curl_socket_t *)s;
- ssize_t ret = swrite(sock, buf, len);
- return ret;
+ struct Curl_cfilter *cf = s;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nwritten;
+ CURLcode result;
+
+ DEBUGASSERT(data);
+ nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
+ if(nwritten < 0) {
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
+ gnutls_transport_set_errno(backend->gtls.session,
+ (CURLE_AGAIN == result)? EAGAIN : EINVAL);
+ nwritten = -1;
+ }
+ return nwritten;
}
-static ssize_t gtls_pull(void *s, void *buf, size_t len)
+static ssize_t gtls_pull(void *s, void *buf, size_t blen)
{
- curl_socket_t sock = *(curl_socket_t *)s;
- ssize_t ret = sread(sock, buf, len);
- return ret;
-}
+ struct Curl_cfilter *cf = s;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nread;
+ CURLcode result;
-static ssize_t gtls_push_ssl(void *s, const void *buf, size_t len)
-{
- return gnutls_record_send((gnutls_session_t) s, buf, len);
-}
-
-static ssize_t gtls_pull_ssl(void *s, void *buf, size_t len)
-{
- return gnutls_record_recv((gnutls_session_t) s, buf, len);
+ DEBUGASSERT(data);
+ nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
+ if(nread < 0) {
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
+ gnutls_transport_set_errno(backend->gtls.session,
+ (CURLE_AGAIN == result)? EAGAIN : EINVAL);
+ nread = -1;
+ }
+ return nread;
}
/* gtls_init()
@@ -204,19 +210,19 @@
/* this function does a SSL/TLS (re-)handshake */
-static CURLcode handshake(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
+static CURLcode handshake(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
bool duringconnect,
bool nonblocking)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
gnutls_session_t session;
- curl_socket_t sockfd = conn->sock[sockindex];
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
DEBUGASSERT(backend);
- session = backend->session;
+ session = backend->gtls.session;
for(;;) {
timediff_t timeout_ms;
@@ -322,12 +328,12 @@
static CURLcode
set_ssl_version_min_max(struct Curl_easy *data,
+ struct ssl_primary_config *conn_config,
const char **prioritylist,
const char *tls13support)
{
- struct connectdata *conn = data->conn;
- long ssl_version = SSL_CONN_CONFIG(version);
- long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ long ssl_version = conn_config->version;
+ long ssl_version_max = conn_config->version_max;
if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
(ssl_version == CURL_SSLVERSION_TLSv1))
@@ -393,20 +399,16 @@
return CURLE_SSL_CONNECT_ERROR;
}
-static CURLcode
-gtls_connect_step1(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex)
+CURLcode gtls_client_init(struct Curl_easy *data,
+ struct ssl_primary_config *config,
+ struct ssl_config_data *ssl_config,
+ const char *hostname,
+ struct gtls_instance *gtls,
+ long *pverifyresult)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
unsigned int init_flags;
- gnutls_session_t session;
int rc;
bool sni = TRUE; /* default is SNI enabled */
- void *transport_ptr = NULL;
- gnutls_push_func gnutls_transport_push = NULL;
- gnutls_pull_func gnutls_transport_pull = NULL;
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
@@ -414,54 +416,42 @@
#endif
const char *prioritylist;
const char *err = NULL;
- const char * const hostname = SSL_HOST_NAME();
- long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
const char *tls13support;
CURLcode result;
- DEBUGASSERT(backend);
-
- if(connssl->state == ssl_connection_complete)
- /* to make us tolerant against being called more than once for the
- same connection */
- return CURLE_OK;
-
if(!gtls_inited)
gtls_init();
- /* Initialize certverifyresult to OK */
- *certverifyresult = 0;
+ *pverifyresult = 0;
- if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
+ if(config->version == CURL_SSLVERSION_SSLv2) {
failf(data, "GnuTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
}
- else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
+ else if(config->version == CURL_SSLVERSION_SSLv3)
sni = FALSE; /* SSLv3 has no SNI */
/* allocate a cred struct */
- rc = gnutls_certificate_allocate_credentials(&backend->cred);
+ rc = gnutls_certificate_allocate_credentials(>ls->cred);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
}
#ifdef USE_GNUTLS_SRP
- if((SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) &&
- Curl_allow_auth_to_host(data)) {
- infof(data, "Using TLS-SRP username: %s",
- SSL_SET_OPTION(primary.username));
+ if(config->username && Curl_auth_allowed_to_host(data)) {
+ infof(data, "Using TLS-SRP username: %s", config->username);
- rc = gnutls_srp_allocate_client_credentials(&backend->srp_client_cred);
+ rc = gnutls_srp_allocate_client_credentials(>ls->srp_client_cred);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
gnutls_strerror(rc));
return CURLE_OUT_OF_MEMORY;
}
- rc = gnutls_srp_set_client_credentials(backend->srp_client_cred,
- SSL_SET_OPTION(primary.username),
- SSL_SET_OPTION(primary.password));
+ rc = gnutls_srp_set_client_credentials(gtls->srp_client_cred,
+ config->username,
+ config->password);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_srp_set_client_cred() failed: %s",
gnutls_strerror(rc));
@@ -470,67 +460,63 @@
}
#endif
- if(SSL_CONN_CONFIG(CAfile)) {
+ if(config->CAfile) {
/* set the trusted CA cert bundle file */
- gnutls_certificate_set_verify_flags(backend->cred,
+ gnutls_certificate_set_verify_flags(gtls->cred,
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
- rc = gnutls_certificate_set_x509_trust_file(backend->cred,
- SSL_CONN_CONFIG(CAfile),
+ rc = gnutls_certificate_set_x509_trust_file(gtls->cred,
+ config->CAfile,
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
infof(data, "error reading ca cert file %s (%s)",
- SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
- if(SSL_CONN_CONFIG(verifypeer)) {
- *certverifyresult = rc;
+ config->CAfile, gnutls_strerror(rc));
+ if(config->verifypeer) {
+ *pverifyresult = rc;
return CURLE_SSL_CACERT_BADFILE;
}
}
else
- infof(data, "found %d certificates in %s", rc,
- SSL_CONN_CONFIG(CAfile));
+ infof(data, "found %d certificates in %s", rc, config->CAfile);
}
- if(SSL_CONN_CONFIG(CApath)) {
+ if(config->CApath) {
/* set the trusted CA cert directory */
- rc = gnutls_certificate_set_x509_trust_dir(backend->cred,
- SSL_CONN_CONFIG(CApath),
+ rc = gnutls_certificate_set_x509_trust_dir(gtls->cred,
+ config->CApath,
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
infof(data, "error reading ca cert file %s (%s)",
- SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
- if(SSL_CONN_CONFIG(verifypeer)) {
- *certverifyresult = rc;
+ config->CApath, gnutls_strerror(rc));
+ if(config->verifypeer) {
+ *pverifyresult = rc;
return CURLE_SSL_CACERT_BADFILE;
}
}
else
- infof(data, "found %d certificates in %s",
- rc, SSL_CONN_CONFIG(CApath));
+ infof(data, "found %d certificates in %s", rc, config->CApath);
}
#ifdef CURL_CA_FALLBACK
/* use system ca certificate store as fallback */
- if(SSL_CONN_CONFIG(verifypeer) &&
- !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
+ if(config->verifypeer && !(config->CAfile || config->CApath)) {
/* this ignores errors on purpose */
- gnutls_certificate_set_x509_system_trust(backend->cred);
+ gnutls_certificate_set_x509_system_trust(gtls->cred);
}
#endif
- if(SSL_SET_OPTION(primary.CRLfile)) {
+ if(config->CRLfile) {
/* set the CRL list file */
- rc = gnutls_certificate_set_x509_crl_file(backend->cred,
- SSL_SET_OPTION(primary.CRLfile),
+ rc = gnutls_certificate_set_x509_crl_file(gtls->cred,
+ config->CRLfile,
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
failf(data, "error reading crl file %s (%s)",
- SSL_SET_OPTION(primary.CRLfile), gnutls_strerror(rc));
+ config->CRLfile, gnutls_strerror(rc));
return CURLE_SSL_CRL_BADFILE;
}
else
- infof(data, "found %d CRL in %s",
- rc, SSL_SET_OPTION(primary.CRLfile));
+ infof(data, "found %d CRL in %s", rc, config->CRLfile);
}
/* Initialize TLS session as a client */
@@ -545,15 +531,12 @@
init_flags |= GNUTLS_NO_TICKETS;
#endif
- rc = gnutls_init(&backend->session, init_flags);
+ rc = gnutls_init(>ls->session, init_flags);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_init() failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR;
}
- /* convenient assign */
- session = backend->session;
-
if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
#ifdef ENABLE_IPV6
(0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
@@ -561,15 +544,15 @@
sni) {
size_t snilen;
char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
- if(!snihost || gnutls_server_name_set(session, GNUTLS_NAME_DNS, snihost,
- snilen) < 0) {
+ if(!snihost || gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
+ snihost, snilen) < 0) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
}
/* Use default priorities */
- rc = gnutls_set_default_priority(session);
+ rc = gnutls_set_default_priority(gtls->session);
if(rc != GNUTLS_E_SUCCESS)
return CURLE_SSL_CONNECT_ERROR;
@@ -580,13 +563,13 @@
* removed if a run-time error indicates that SRP is not supported by this
* GnuTLS version */
- if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2 ||
- SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3) {
+ 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(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_TLSv1_3) {
+ if(config->version == CURL_SSLVERSION_TLSv1_3) {
if(!tls13support) {
failf(data, "This GnuTLS installation does not support TLS 1.3");
return CURLE_SSL_CONNECT_ERROR;
@@ -594,14 +577,14 @@
}
/* At this point we know we have a supported TLS version, so set it */
- result = set_ssl_version_min_max(data, &prioritylist, tls13support);
+ result = set_ssl_version_min_max(data, config, &prioritylist, tls13support);
if(result)
return result;
#ifdef USE_GNUTLS_SRP
/* Only add SRP to the cipher list if SRP is requested. Otherwise
* GnuTLS will disable TLS 1.3 support. */
- if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) {
+ if(config->username) {
size_t len = strlen(prioritylist);
char *prioritysrp = malloc(len + sizeof(GNUTLS_SRP) + 1);
@@ -609,7 +592,7 @@
return CURLE_OUT_OF_MEMORY;
strcpy(prioritysrp, prioritylist);
strcpy(prioritysrp + len, ":" GNUTLS_SRP);
- rc = gnutls_priority_set_direct(session, prioritysrp, &err);
+ rc = gnutls_priority_set_direct(gtls->session, prioritysrp, &err);
free(prioritysrp);
if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
@@ -619,7 +602,7 @@
else {
#endif
infof(data, "GnuTLS ciphers: %s", prioritylist);
- rc = gnutls_priority_set_direct(session, prioritylist, &err);
+ rc = gnutls_priority_set_direct(gtls->session, prioritylist, &err);
#ifdef USE_GNUTLS_SRP
}
#endif
@@ -630,48 +613,19 @@
return CURLE_SSL_CONNECT_ERROR;
}
- if(conn->bits.tls_enable_alpn) {
- int cur = 0;
- gnutls_datum_t protocols[2];
-
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2
-#ifndef CURL_DISABLE_PROXY
- && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
-#endif
- ) {
- protocols[cur].data = (unsigned char *)ALPN_H2;
- protocols[cur].size = ALPN_H2_LENGTH;
- cur++;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
- }
-#endif
-
- protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
- protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
- cur++;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
-
- if(gnutls_alpn_set_protocols(session, protocols, cur, 0)) {
- failf(data, "failed setting ALPN");
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
-
- if(SSL_SET_OPTION(primary.clientcert)) {
- if(SSL_SET_OPTION(key_passwd)) {
+ if(config->clientcert) {
+ if(ssl_config->key_passwd) {
const unsigned int supported_key_encryption_algorithms =
GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
GNUTLS_PKCS_USE_PBES2_AES_256;
rc = gnutls_certificate_set_x509_key_file2(
- backend->cred,
- SSL_SET_OPTION(primary.clientcert),
- SSL_SET_OPTION(key) ?
- SSL_SET_OPTION(key) : SSL_SET_OPTION(primary.clientcert),
- do_file_type(SSL_SET_OPTION(cert_type)),
- SSL_SET_OPTION(key_passwd),
+ gtls->cred,
+ config->clientcert,
+ ssl_config->key ? ssl_config->key : config->clientcert,
+ do_file_type(ssl_config->cert_type),
+ ssl_config->key_passwd,
supported_key_encryption_algorithms);
if(rc != GNUTLS_E_SUCCESS) {
failf(data,
@@ -682,11 +636,10 @@
}
else {
if(gnutls_certificate_set_x509_key_file(
- backend->cred,
- SSL_SET_OPTION(primary.clientcert),
- SSL_SET_OPTION(key) ?
- SSL_SET_OPTION(key) : SSL_SET_OPTION(primary.clientcert),
- do_file_type(SSL_SET_OPTION(cert_type)) ) !=
+ gtls->cred,
+ config->clientcert,
+ ssl_config->key ? ssl_config->key : config->clientcert,
+ do_file_type(ssl_config->cert_type) ) !=
GNUTLS_E_SUCCESS) {
failf(data, "error reading X.509 key or certificate file");
return CURLE_SSL_CONNECT_ERROR;
@@ -696,9 +649,9 @@
#ifdef USE_GNUTLS_SRP
/* put the credentials to the current session */
- if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) {
- rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
- backend->srp_client_cred);
+ if(config->username) {
+ rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_SRP,
+ gtls->srp_client_cred);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
@@ -707,59 +660,79 @@
else
#endif
{
- rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
- backend->cred);
+ rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
+ gtls->cred);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
}
}
-#ifndef CURL_DISABLE_PROXY
- if(conn->proxy_ssl[sockindex].use) {
- struct ssl_backend_data *proxy_backend;
- proxy_backend = conn->proxy_ssl[sockindex].backend;
- DEBUGASSERT(proxy_backend);
- transport_ptr = proxy_backend->session;
- gnutls_transport_push = gtls_push_ssl;
- gnutls_transport_pull = gtls_pull_ssl;
- }
- else
-#endif
- {
- /* file descriptor for the socket */
- transport_ptr = &conn->sock[sockindex];
- gnutls_transport_push = gtls_push;
- gnutls_transport_pull = gtls_pull;
- }
-
- /* set the connection handle */
- gnutls_transport_set_ptr(session, transport_ptr);
-
- /* register callback functions to send and receive data. */
- gnutls_transport_set_push_function(session, gnutls_transport_push);
- gnutls_transport_set_pull_function(session, gnutls_transport_pull);
-
- if(SSL_CONN_CONFIG(verifystatus)) {
- rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
+ if(config->verifystatus) {
+ rc = gnutls_ocsp_status_request_enable_client(gtls->session,
+ NULL, 0, NULL);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR;
}
}
+ return CURLE_OK;
+}
+
+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 =
+ (struct gtls_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ long * const pverifyresult = &ssl_config->certverifyresult;
+ CURLcode result;
+
+ DEBUGASSERT(backend);
+
+ if(connssl->state == ssl_connection_complete)
+ /* to make us tolerant against being called more than once for the
+ same connection */
+ return CURLE_OK;
+
+ result = gtls_client_init(data, conn_config, ssl_config,
+ connssl->hostname,
+ &backend->gtls, pverifyresult);
+ if(result)
+ return result;
+
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
+ gnutls_datum_t alpn[ALPN_ENTRIES_MAX];
+ size_t i;
+
+ for(i = 0; i < connssl->alpn->count; ++i) {
+ alpn[i].data = (unsigned char *)connssl->alpn->entries[i];
+ alpn[i].size = (unsigned)strlen(connssl->alpn->entries[i]);
+ }
+ if(gnutls_alpn_set_protocols(backend->gtls.session, alpn,
+ (unsigned)connssl->alpn->count, 0)) {
+ failf(data, "failed setting ALPN");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
+ }
+
/* This might be a reconnect, so we check for a session ID in the cache
to speed up things */
- if(SSL_SET_OPTION(primary.sessionid)) {
+ if(conn_config->sessionid) {
void *ssl_sessionid;
size_t ssl_idsize;
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn,
- SSL_IS_PROXY() ? TRUE : FALSE,
- &ssl_sessionid, &ssl_idsize, sockindex)) {
+ if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, &ssl_idsize)) {
/* we got a session id, use it! */
- gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
+ gnutls_session_set_data(backend->gtls.session,
+ ssl_sessionid, ssl_idsize);
/* Informational message */
infof(data, "SSL re-using session ID");
@@ -767,6 +740,11 @@
Curl_ssl_sessionid_unlock(data);
}
+ /* register callback functions and handle to send and receive data. */
+ gnutls_transport_set_ptr(backend->gtls.session, cf);
+ gnutls_transport_set_push_function(backend->gtls.session, gtls_push);
+ gnutls_transport_set_pull_function(backend->gtls.session, gtls_pull);
+
return CURLE_OK;
}
@@ -828,14 +806,14 @@
return result;
}
-static Curl_recv gtls_recv;
-static Curl_send gtls_send;
-
CURLcode
Curl_gtls_verifyserver(struct Curl_easy *data,
- struct connectdata *conn,
gnutls_session_t session,
- int sockindex)
+ struct ssl_primary_config *config,
+ struct ssl_config_data *ssl_config,
+ const char *hostname,
+ const char *dispname,
+ const char *pinned_key)
{
unsigned int cert_list_size;
const gnutls_datum_t *chainp;
@@ -848,15 +826,13 @@
time_t certclock;
const char *ptr;
int rc;
- gnutls_datum_t proto;
CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
unsigned int algo;
unsigned int bits;
gnutls_protocol_t version = gnutls_protocol_get_version(session);
#endif
- const char * const hostname = SSL_HOST_NAME();
- long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
+ long * const certverifyresult = &ssl_config->certverifyresult;
/* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
@@ -874,14 +850,12 @@
chainp = gnutls_certificate_get_peers(session, &cert_list_size);
if(!chainp) {
- if(SSL_CONN_CONFIG(verifypeer) ||
- SSL_CONN_CONFIG(verifyhost) ||
- SSL_CONN_CONFIG(issuercert)) {
+ if(config->verifypeer ||
+ config->verifyhost ||
+ config->issuercert) {
#ifdef USE_GNUTLS_SRP
- if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP
- && SSL_SET_OPTION(primary.username)
- && !SSL_CONN_CONFIG(verifypeer)
- && gnutls_cipher_get(session)) {
+ if(ssl_config->primary.username && !config->verifypeer &&
+ gnutls_cipher_get(session)) {
/* no peer cert, but auth is ok if we have SRP user and cipher and no
peer verify */
}
@@ -914,7 +888,7 @@
}
}
- if(SSL_CONN_CONFIG(verifypeer)) {
+ if(config->verifypeer) {
/* This function will try to verify the peer's certificate and return its
status (trusted, invalid etc.). The value of status should be one or
more of the gnutls_certificate_status_t enumerated elements bitwise
@@ -933,12 +907,12 @@
/* verify_status is a bitmask of gnutls_certificate_status bits */
if(verify_status & GNUTLS_CERT_INVALID) {
- if(SSL_CONN_CONFIG(verifypeer)) {
+ if(config->verifypeer) {
failf(data, "server certificate verification failed. CAfile: %s "
- "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
+ "CRLfile: %s", config->CAfile ? config->CAfile:
"none",
- SSL_SET_OPTION(primary.CRLfile) ?
- SSL_SET_OPTION(primary.CRLfile) : "none");
+ ssl_config->primary.CRLfile ?
+ ssl_config->primary.CRLfile : "none");
return CURLE_PEER_FAILED_VERIFICATION;
}
else
@@ -950,7 +924,7 @@
else
infof(data, " server certificate verification SKIPPED");
- if(SSL_CONN_CONFIG(verifystatus)) {
+ if(config->verifystatus) {
if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
gnutls_datum_t status_request;
gnutls_ocsp_resp_t ocsp_resp;
@@ -1061,21 +1035,21 @@
gnutls_x509_crt_t format */
gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
- if(SSL_CONN_CONFIG(issuercert)) {
+ if(config->issuercert) {
gnutls_x509_crt_init(&x509_issuer);
- issuerp = load_file(SSL_CONN_CONFIG(issuercert));
+ issuerp = load_file(config->issuercert);
gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
gnutls_x509_crt_deinit(x509_issuer);
unload_file(issuerp);
if(rc <= 0) {
failf(data, "server certificate issuer check failed (IssuerCert: %s)",
- SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
+ config->issuercert?config->issuercert:"none");
gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_ISSUER_ERROR;
}
infof(data, " server certificate issuer check OK (Issuer Cert: %s)",
- SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
+ config->issuercert?config->issuercert:"none");
}
size = sizeof(certname);
@@ -1138,15 +1112,15 @@
}
#endif
if(!rc) {
- if(SSL_CONN_CONFIG(verifyhost)) {
+ if(config->verifyhost) {
failf(data, "SSL: certificate subject name (%s) does not match "
- "target host name '%s'", certname, SSL_HOST_DISPNAME());
+ "target host name '%s'", certname, dispname);
gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
}
else
infof(data, " common name: %s (does not match '%s')",
- certname, SSL_HOST_DISPNAME());
+ certname, dispname);
}
else
infof(data, " common name: %s (matched)", certname);
@@ -1155,7 +1129,7 @@
certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
if(certclock == (time_t)-1) {
- if(SSL_CONN_CONFIG(verifypeer)) {
+ if(config->verifypeer) {
failf(data, "server cert expiration date verify failed");
*certverifyresult = GNUTLS_CERT_EXPIRED;
gnutls_x509_crt_deinit(x509_cert);
@@ -1166,7 +1140,7 @@
}
else {
if(certclock < time(NULL)) {
- if(SSL_CONN_CONFIG(verifypeer)) {
+ if(config->verifypeer) {
failf(data, "server certificate expiration date has passed.");
*certverifyresult = GNUTLS_CERT_EXPIRED;
gnutls_x509_crt_deinit(x509_cert);
@@ -1182,7 +1156,7 @@
certclock = gnutls_x509_crt_get_activation_time(x509_cert);
if(certclock == (time_t)-1) {
- if(SSL_CONN_CONFIG(verifypeer)) {
+ if(config->verifypeer) {
failf(data, "server cert activation date verify failed");
*certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
gnutls_x509_crt_deinit(x509_cert);
@@ -1193,7 +1167,7 @@
}
else {
if(certclock > time(NULL)) {
- if(SSL_CONN_CONFIG(verifypeer)) {
+ if(config->verifypeer) {
failf(data, "server certificate not activated yet.");
*certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
gnutls_x509_crt_deinit(x509_cert);
@@ -1206,9 +1180,8 @@
infof(data, " server certificate activation date OK");
}
- ptr = SSL_PINNED_PUB_KEY();
- if(ptr) {
- result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
+ if(pinned_key) {
+ result = pkp_pin_peer_pubkey(data, x509_cert, pinned_key);
if(result != CURLE_OK) {
failf(data, "SSL: public key does not match pinned public key");
gnutls_x509_crt_deinit(x509_cert);
@@ -1264,35 +1237,39 @@
gnutls_x509_crt_deinit(x509_cert);
- if(conn->bits.tls_enable_alpn) {
+ return result;
+}
+
+static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ gnutls_session_t session)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ const char *pinned_key = Curl_ssl_cf_is_proxy(cf)?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+ CURLcode result;
+
+ result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
+ connssl->hostname, connssl->dispname,
+ pinned_key);
+ if(result)
+ goto out;
+
+ if(connssl->alpn) {
+ gnutls_datum_t proto;
+ int rc;
+
rc = gnutls_alpn_get_selected_protocol(session, &proto);
- if(rc == 0) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, proto.size,
- proto.data);
-
-#ifdef USE_HTTP2
- if(proto.size == ALPN_H2_LENGTH &&
- !memcmp(ALPN_H2, proto.data,
- ALPN_H2_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(proto.size == ALPN_HTTP_1_1_LENGTH &&
- !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- }
- }
+ if(rc == 0)
+ Curl_alpn_set_negotiated(cf, data, proto.data, proto.size);
else
- infof(data, VTLS_INFOF_NO_ALPN);
-
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ Curl_alpn_set_negotiated(cf, data, NULL, 0);
}
- conn->ssl[sockindex].state = ssl_connection_complete;
-
- if(SSL_SET_OPTION(primary.sessionid)) {
+ if(ssl_config->primary.sessionid) {
/* 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
@@ -1313,9 +1290,7 @@
gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(data, conn,
- SSL_IS_PROXY() ? TRUE : FALSE,
- &ssl_sessionid, NULL, sockindex));
+ incache = !(Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL));
if(incache) {
/* there was one before in the cache, so instead of risking that the
previous one was rejected, we just kill that and store the new */
@@ -1323,10 +1298,8 @@
}
/* store this session id */
- result = Curl_ssl_addsessionid(data, conn,
- SSL_IS_PROXY() ? TRUE : FALSE,
- connect_sessionid, connect_idsize,
- sockindex, &added);
+ result = Curl_ssl_addsessionid(cf, data, connect_sessionid,
+ connect_idsize, &added);
Curl_ssl_sessionid_unlock(data);
if(!added)
free(connect_sessionid);
@@ -1338,10 +1311,10 @@
result = CURLE_OUT_OF_MEMORY;
}
+out:
return result;
}
-
/*
* This function is called after the TCP connect has completed. Setup the TLS
* layer and do all necessary magic.
@@ -1352,59 +1325,66 @@
'ssl_connect_2_writing' (waiting to be able to write).
*/
static CURLcode
-gtls_connect_common(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
+gtls_connect_common(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
bool nonblocking,
bool *done)
{
+ struct ssl_connect_data *connssl = cf->ctx;
int rc;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ CURLcode result = CURLE_OK;
/* Initiate the connection, if not already done */
if(ssl_connect_1 == connssl->connecting_state) {
- rc = gtls_connect_step1(data, conn, sockindex);
- if(rc)
- return rc;
+ rc = gtls_connect_step1(cf, data);
+ if(rc) {
+ result = rc;
+ goto out;
+ }
}
- rc = handshake(data, conn, sockindex, TRUE, nonblocking);
- if(rc)
+ rc = handshake(cf, data, TRUE, nonblocking);
+ if(rc) {
/* handshake() sets its own error message with failf() */
- return rc;
+ result = rc;
+ goto out;
+ }
/* Finish connecting once the handshake is done */
if(ssl_connect_1 == connssl->connecting_state) {
- struct ssl_backend_data *backend = connssl->backend;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
gnutls_session_t session;
DEBUGASSERT(backend);
- session = backend->session;
- rc = Curl_gtls_verifyserver(data, conn, session, sockindex);
- if(rc)
- return rc;
- conn->recv[sockindex] = gtls_recv;
- conn->send[sockindex] = gtls_send;
+ session = backend->gtls.session;
+ rc = gtls_verifyserver(cf, data, session);
+ if(rc) {
+ result = rc;
+ goto out;
+ }
+ connssl->state = ssl_connection_complete;
}
+out:
*done = ssl_connect_1 == connssl->connecting_state;
- return CURLE_OK;
+ return result;
}
-static CURLcode gtls_connect_nonblocking(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done)
{
- return gtls_connect_common(data, conn, sockindex, TRUE, done);
+ return gtls_connect_common(cf, data, TRUE, done);
}
-static CURLcode gtls_connect(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static CURLcode gtls_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
CURLcode result;
bool done = FALSE;
- result = gtls_connect_common(data, conn, sockindex, FALSE, &done);
+ result = gtls_connect_common(cf, data, FALSE, &done);
if(result)
return result;
@@ -1413,44 +1393,35 @@
return CURLE_OK;
}
-static bool gtls_data_pending(const struct connectdata *conn,
- int connindex)
+static bool gtls_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
- const struct ssl_connect_data *connssl = &conn->ssl[connindex];
- bool res = FALSE;
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *ctx = cf->ctx;
+ struct gtls_ssl_backend_data *backend;
- DEBUGASSERT(backend);
-
- if(backend->session &&
- 0 != gnutls_record_check_pending(backend->session))
- res = TRUE;
-
-#ifndef CURL_DISABLE_PROXY
- connssl = &conn->proxy_ssl[connindex];
- backend = connssl->backend;
- DEBUGASSERT(backend);
- if(backend->session &&
- 0 != gnutls_record_check_pending(backend->session))
- res = TRUE;
-#endif
-
- return res;
+ (void)data;
+ DEBUGASSERT(ctx && ctx->backend);
+ backend = (struct gtls_ssl_backend_data *)ctx->backend;
+ if(backend->gtls.session &&
+ 0 != gnutls_record_check_pending(backend->gtls.session))
+ return TRUE;
+ return FALSE;
}
-static ssize_t gtls_send(struct Curl_easy *data,
- int sockindex,
+static ssize_t gtls_send(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
const void *mem,
size_t len,
CURLcode *curlcode)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
ssize_t rc;
+ (void)data;
DEBUGASSERT(backend);
- rc = gnutls_record_send(backend->session, mem, len);
+ rc = gnutls_record_send(backend->gtls.session, mem, len);
if(rc < 0) {
*curlcode = (rc == GNUTLS_E_AGAIN)
@@ -1463,51 +1434,48 @@
return rc;
}
-static void close_one(struct ssl_connect_data *connssl)
+static void gtls_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
+
+ (void) data;
DEBUGASSERT(backend);
- if(backend->session) {
+ if(backend->gtls.session) {
char buf[32];
/* Maybe the server has already sent a close notify alert.
Read it to avoid an RST on the TCP connection. */
- (void)gnutls_record_recv(backend->session, buf, sizeof(buf));
- gnutls_bye(backend->session, GNUTLS_SHUT_WR);
- gnutls_deinit(backend->session);
- backend->session = NULL;
+ (void)gnutls_record_recv(backend->gtls.session, buf, sizeof(buf));
+ gnutls_bye(backend->gtls.session, GNUTLS_SHUT_WR);
+ gnutls_deinit(backend->gtls.session);
+ backend->gtls.session = NULL;
}
- if(backend->cred) {
- gnutls_certificate_free_credentials(backend->cred);
- backend->cred = NULL;
+ if(backend->gtls.cred) {
+ gnutls_certificate_free_credentials(backend->gtls.cred);
+ backend->gtls.cred = NULL;
}
#ifdef USE_GNUTLS_SRP
- if(backend->srp_client_cred) {
- gnutls_srp_free_client_credentials(backend->srp_client_cred);
- backend->srp_client_cred = NULL;
+ if(backend->gtls.srp_client_cred) {
+ gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
+ backend->gtls.srp_client_cred = NULL;
}
#endif
}
-static void gtls_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
-{
- (void) data;
- close_one(&conn->ssl[sockindex]);
-#ifndef CURL_DISABLE_PROXY
- close_one(&conn->proxy_ssl[sockindex]);
-#endif
-}
-
/*
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
-static int gtls_shutdown(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static int gtls_shutdown(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
int retval = 0;
DEBUGASSERT(backend);
@@ -1519,21 +1487,21 @@
we do not send one. Let's hope other servers do the same... */
if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
- gnutls_bye(backend->session, GNUTLS_SHUT_WR);
+ gnutls_bye(backend->gtls.session, GNUTLS_SHUT_WR);
#endif
- if(backend->session) {
+ if(backend->gtls.session) {
ssize_t result;
bool done = FALSE;
char buf[120];
while(!done) {
- int what = SOCKET_READABLE(conn->sock[sockindex],
+ int what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
SSL_SHUTDOWN_TIMEOUT);
if(what > 0) {
/* Something to read, let's do it and hope that it is the close
notify alert from the server */
- result = gnutls_record_recv(backend->session,
+ result = gnutls_record_recv(backend->gtls.session,
buf, sizeof(buf));
switch(result) {
case 0:
@@ -1563,51 +1531,53 @@
done = TRUE;
}
}
- gnutls_deinit(backend->session);
+ gnutls_deinit(backend->gtls.session);
}
- gnutls_certificate_free_credentials(backend->cred);
+ gnutls_certificate_free_credentials(backend->gtls.cred);
#ifdef USE_GNUTLS_SRP
- if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP
- && SSL_SET_OPTION(primary.username) != NULL)
- gnutls_srp_free_client_credentials(backend->srp_client_cred);
+ if(ssl_config->primary.username)
+ gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
#endif
- backend->cred = NULL;
- backend->session = NULL;
+ backend->gtls.cred = NULL;
+ backend->gtls.session = NULL;
return retval;
}
-static ssize_t gtls_recv(struct Curl_easy *data, /* connection data */
- int num, /* socketindex */
- char *buf, /* store read data here */
- size_t buffersize, /* max amount to read */
+static ssize_t gtls_recv(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ char *buf,
+ size_t buffersize,
CURLcode *curlcode)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[num];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
ssize_t ret;
+ (void)data;
DEBUGASSERT(backend);
- ret = gnutls_record_recv(backend->session, buf, buffersize);
+ ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
*curlcode = CURLE_AGAIN;
- return -1;
+ ret = -1;
+ goto out;
}
if(ret == 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. */
- CURLcode result = handshake(data, conn, num, FALSE, FALSE);
+ CURLcode result = handshake(cf, data, FALSE, FALSE);
if(result)
/* handshake() writes error message on its own */
*curlcode = result;
else
*curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
- return -1;
+ ret = -1;
+ goto out;
}
if(ret < 0) {
@@ -1615,9 +1585,11 @@
(int)ret, gnutls_strerror((int)ret));
*curlcode = CURLE_RECV_ERROR;
- return -1;
+ ret = -1;
+ goto out;
}
+out:
return ret;
}
@@ -1661,10 +1633,11 @@
static void *gtls_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
(void)info;
DEBUGASSERT(backend);
- return backend->session;
+ return backend->gtls.session;
}
const struct Curl_ssl Curl_ssl_gnutls = {
@@ -1675,7 +1648,7 @@
SSLSUPP_PINNEDPUBKEY |
SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct gtls_ssl_backend_data),
gtls_init, /* init */
gtls_cleanup, /* cleanup */
@@ -1687,7 +1660,7 @@
gtls_cert_status_request, /* cert_status_request */
gtls_connect, /* connect */
gtls_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_getsock, /* getsock */
+ Curl_ssl_get_select_socks, /* getsock */
gtls_get_internals, /* get_internals */
gtls_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -1698,7 +1671,10 @@
Curl_none_false_start, /* false_start */
gtls_sha256sum, /* sha256sum */
NULL, /* associate_connection */
- NULL /* disassociate_connection */
+ NULL, /* disassociate_connection */
+ NULL, /* free_multi_ssl_backend_data */
+ gtls_recv, /* recv decrypted data */
+ gtls_send, /* send data to encrypt */
};
#endif /* USE_GNUTLS */
diff --git a/lib/vtls/gtls.h b/lib/vtls/gtls.h
index abade73..ac141e1 100644
--- a/lib/vtls/gtls.h
+++ b/lib/vtls/gtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,15 +25,50 @@
***************************************************************************/
#include "curl_setup.h"
+#include <curl/curl.h>
#ifdef USE_GNUTLS
-#include "urldata.h"
#include <gnutls/gnutls.h>
+
+#ifdef HAVE_GNUTLS_SRP
+/* the function exists */
+#ifdef USE_TLS_SRP
+/* the functionality is not disabled */
+#define USE_GNUTLS_SRP
+#endif
+#endif
+
+struct Curl_easy;
+struct Curl_cfilter;
+struct ssl_primary_config;
+struct ssl_config_data;
+
+struct gtls_instance {
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t cred;
+#ifdef USE_GNUTLS_SRP
+ gnutls_srp_client_credentials_t srp_client_cred;
+#endif
+};
+
CURLcode
-Curl_gtls_verifyserver(struct Curl_easy *data, struct connectdata *conn,
+gtls_client_init(struct Curl_easy *data,
+ struct ssl_primary_config *config,
+ struct ssl_config_data *ssl_config,
+ const char *hostname,
+ struct gtls_instance *gtls,
+ long *pverifyresult);
+
+CURLcode
+Curl_gtls_verifyserver(struct Curl_easy *data,
gnutls_session_t session,
- int sockindex);
+ struct ssl_primary_config *config,
+ struct ssl_config_data *ssl_config,
+ const char *hostname,
+ const char *dispname,
+ const char *pinned_key);
+
extern const struct Curl_ssl Curl_ssl_gnutls;
#endif /* USE_GNUTLS */
diff --git a/lib/vtls/hostcheck.c b/lib/vtls/hostcheck.c
index 2a648f2..d061c63 100644
--- a/lib/vtls/hostcheck.c
+++ b/lib/vtls/hostcheck.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -71,7 +71,12 @@
* apparent distinction between a name and an IP. We need to detect the use of
* an IP address and not wildcard match on such names.
*
+ * Only match on "*" being used for the leftmost label, not "a*", "a*b" nor
+ * "*b".
+ *
* Return TRUE on a match. FALSE if not.
+ *
+ * @unittest: 1397
*/
static bool hostmatch(const char *hostname,
@@ -79,53 +84,42 @@
const char *pattern,
size_t patternlen)
{
- const char *pattern_label_end, *wildcard, *hostname_label_end;
- size_t prefixlen, suffixlen;
+ const char *pattern_label_end;
+
+ DEBUGASSERT(pattern);
+ DEBUGASSERT(patternlen);
+ DEBUGASSERT(hostname);
+ DEBUGASSERT(hostlen);
/* normalize pattern and hostname by stripping off trailing dots */
- DEBUGASSERT(patternlen);
if(hostname[hostlen-1]=='.')
hostlen--;
if(pattern[patternlen-1]=='.')
patternlen--;
- wildcard = memchr(pattern, '*', patternlen);
- if(!wildcard)
+ if(strncmp(pattern, "*.", 2))
return pmatch(hostname, hostlen, pattern, patternlen);
/* detect IP address as hostname and fail the match if so */
- if(Curl_host_is_ipnum(hostname))
+ else if(Curl_host_is_ipnum(hostname))
return FALSE;
/* We require at least 2 dots in the pattern to avoid too wide wildcard
match. */
pattern_label_end = memchr(pattern, '.', patternlen);
if(!pattern_label_end ||
- (memrchr(pattern, '.', patternlen) == pattern_label_end) ||
- strncasecompare(pattern, "xn--", 4))
+ (memrchr(pattern, '.', patternlen) == pattern_label_end))
return pmatch(hostname, hostlen, pattern, patternlen);
-
- hostname_label_end = memchr(hostname, '.', hostlen);
- if(!hostname_label_end)
- return FALSE;
else {
- size_t skiphost = hostname_label_end - hostname;
- size_t skiplen = pattern_label_end - pattern;
- if(!pmatch(hostname_label_end, hostlen - skiphost,
- pattern_label_end, patternlen - skiplen))
- return FALSE;
+ const char *hostname_label_end = memchr(hostname, '.', hostlen);
+ if(hostname_label_end) {
+ size_t skiphost = hostname_label_end - hostname;
+ size_t skiplen = pattern_label_end - pattern;
+ return pmatch(hostname_label_end, hostlen - skiphost,
+ pattern_label_end, patternlen - skiplen);
+ }
}
- /* The wildcard must match at least one character, so the left-most
- label of the hostname is at least as large as the left-most label
- of the pattern. */
- if(hostname_label_end - hostname < pattern_label_end - pattern)
- return FALSE;
-
- prefixlen = wildcard - pattern;
- suffixlen = pattern_label_end - (wildcard + 1);
- return strncasecompare(pattern, hostname, prefixlen) &&
- strncasecompare(wildcard + 1, hostname_label_end - suffixlen,
- suffixlen) ? TRUE : FALSE;
+ return FALSE;
}
/*
diff --git a/lib/vtls/hostcheck.h b/lib/vtls/hostcheck.h
index d3c4eab..22a1ac2 100644
--- a/lib/vtls/hostcheck.h
+++ b/lib/vtls/hostcheck.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vtls/keylog.c b/lib/vtls/keylog.c
index 7471217..d37bb18 100644
--- a/lib/vtls/keylog.c
+++ b/lib/vtls/keylog.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,6 +24,7 @@
#include "curl_setup.h"
#include "keylog.h"
+#include <curl/curl.h>
/* The last #include files should be: */
#include "curl_memory.h"
diff --git a/lib/vtls/keylog.h b/lib/vtls/keylog.h
index 5d3c675..eff5bf3 100644
--- a/lib/vtls/keylog.h
+++ b/lib/vtls/keylog.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index ad9bd10..8d0fa39 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -61,6 +61,7 @@
#include "inet_pton.h"
#include "mbedtls.h"
#include "vtls.h"
+#include "vtls_int.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
@@ -80,7 +81,7 @@
# endif
#endif
-struct ssl_backend_data {
+struct mbed_ssl_backend_data {
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy;
mbedtls_ssl_context ssl;
@@ -155,6 +156,44 @@
#else
#endif
+static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
+{
+ struct Curl_cfilter *cf = bio;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nwritten;
+ CURLcode result;
+
+ DEBUGASSERT(data);
+ nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &result);
+ DEBUGF(LOG_CF(data, cf, "bio_cf_out_write(len=%zu) -> %zd, err=%d",
+ blen, nwritten, result));
+ if(nwritten < 0 && CURLE_AGAIN == result) {
+ nwritten = MBEDTLS_ERR_SSL_WANT_WRITE;
+ }
+ return (int)nwritten;
+}
+
+static int bio_cf_read(void *bio, unsigned char *buf, size_t blen)
+{
+ struct Curl_cfilter *cf = bio;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nread;
+ CURLcode result;
+
+ DEBUGASSERT(data);
+ /* OpenSSL catches this case, so should we. */
+ if(!buf)
+ return 0;
+
+ nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &result);
+ DEBUGF(LOG_CF(data, cf, "bio_cf_in_read(len=%zu) -> %zd, err=%d",
+ blen, nread, result));
+ if(nread < 0 && CURLE_AGAIN == result) {
+ nread = MBEDTLS_ERR_SSL_WANT_READ;
+ }
+ return (int)nread;
+}
+
/*
* profile
*/
@@ -181,9 +220,6 @@
#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
-static Curl_recv mbed_recv;
-static Curl_send mbed_send;
-
static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
{
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
@@ -216,11 +252,12 @@
}
static CURLcode
-set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+set_ssl_version_min_max(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_3;
int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_3;
@@ -228,8 +265,8 @@
int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
#endif
- long ssl_version = SSL_CONN_CONFIG(version);
- long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ long ssl_version = conn_config->version;
+ long ssl_version_max = conn_config->version_max;
CURLcode result = CURLE_OK;
DEBUGASSERT(backend);
@@ -268,31 +305,30 @@
}
static CURLcode
-mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
const char * const ssl_cafile =
/* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
- (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
- const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
- char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
- const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
- const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile);
- const char * const hostname = SSL_HOST_NAME();
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- const long int port = SSL_HOST_PORT();
-#endif
+ (ca_info_blob ? NULL : conn_config->CAfile);
+ const bool verifypeer = conn_config->verifypeer;
+ 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;
+ const char * const ssl_crlfile = ssl_config->primary.CRLfile;
+ const char *hostname = connssl->hostname;
int ret = -1;
char errorbuf[128];
DEBUGASSERT(backend);
- if((SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) ||
- (SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)) {
+ if((conn_config->version == CURL_SSLVERSION_SSLv2) ||
+ (conn_config->version == CURL_SSLVERSION_SSLv3)) {
failf(data, "Not supported SSL version");
return CURLE_NOT_BUILT_IN;
}
@@ -416,7 +452,7 @@
if(ret) {
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
- SSL_SET_OPTION(key), -ret, errorbuf);
+ ssl_config->key, -ret, errorbuf);
return CURLE_SSL_CERTPROBLEM;
}
}
@@ -424,23 +460,23 @@
/* Load the client private key */
mbedtls_pk_init(&backend->pk);
- if(SSL_SET_OPTION(key) || SSL_SET_OPTION(key_blob)) {
- if(SSL_SET_OPTION(key)) {
+ if(ssl_config->key || ssl_config->key_blob) {
+ if(ssl_config->key) {
#ifdef MBEDTLS_FS_IO
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
- ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key),
- SSL_SET_OPTION(key_passwd),
+ ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
+ ssl_config->key_passwd,
mbedtls_ctr_drbg_random,
&backend->ctr_drbg);
#else
- ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key),
- SSL_SET_OPTION(key_passwd));
+ ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
+ ssl_config->key_passwd);
#endif
if(ret) {
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
- SSL_SET_OPTION(key), -ret, errorbuf);
+ ssl_config->key, -ret, errorbuf);
return CURLE_SSL_CERTPROBLEM;
}
#else
@@ -449,10 +485,10 @@
#endif
}
else {
- const struct curl_blob *ssl_key_blob = SSL_SET_OPTION(key_blob);
+ const struct curl_blob *ssl_key_blob = ssl_config->key_blob;
const unsigned char *key_data =
(const unsigned char *)ssl_key_blob->data;
- const char *passwd = SSL_SET_OPTION(key_passwd);
+ const char *passwd = ssl_config->key_passwd;
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
(const unsigned char *)passwd,
@@ -505,7 +541,7 @@
}
#endif
- infof(data, "mbedTLS: Connecting to %s:%ld", hostname, port);
+ infof(data, "mbedTLS: Connecting to %s:%d", hostname, connssl->port);
mbedtls_ssl_config_init(&backend->config);
ret = mbedtls_ssl_config_defaults(&backend->config,
@@ -527,7 +563,7 @@
mbedtls_ssl_conf_cert_profile(&backend->config,
&mbedtls_x509_crt_profile_fr);
- switch(SSL_CONN_CONFIG(version)) {
+ switch(conn_config->version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
#if MBEDTLS_VERSION_NUMBER < 0x03000000
@@ -541,7 +577,7 @@
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
+ CURLcode result = set_ssl_version_min_max(cf, data);
if(result != CURLE_OK)
return result;
break;
@@ -555,9 +591,7 @@
mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random,
&backend->ctr_drbg);
- mbedtls_ssl_set_bio(&backend->ssl, &conn->sock[sockindex],
- mbedtls_net_send,
- mbedtls_net_recv,
+ mbedtls_ssl_set_bio(&backend->ssl, cf, bio_cf_write, bio_cf_read,
NULL /* rev_timeout() */);
mbedtls_ssl_conf_ciphersuites(&backend->config,
@@ -574,13 +608,11 @@
#endif
/* Check if there's a cached ID we can/should use here! */
- if(SSL_SET_OPTION(primary.sessionid)) {
+ if(ssl_config->primary.sessionid) {
void *old_session = NULL;
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn,
- SSL_IS_PROXY() ? TRUE : FALSE,
- &old_session, NULL, sockindex)) {
+ if(!Curl_ssl_getsessionid(cf, data, &old_session, NULL)) {
ret = mbedtls_ssl_set_session(&backend->ssl, old_session);
if(ret) {
Curl_ssl_sessionid_unlock(data);
@@ -600,7 +632,7 @@
NULL);
#endif
- if(SSL_SET_OPTION(key) || SSL_SET_OPTION(key_blob)) {
+ if(ssl_config->key || ssl_config->key_blob) {
mbedtls_ssl_conf_own_cert(&backend->config,
&backend->clicert, &backend->pk);
}
@@ -616,14 +648,13 @@
}
#ifdef HAS_ALPN
- if(conn->bits.tls_enable_alpn) {
- const char **p = &backend->protocols[0];
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2)
- *p++ = ALPN_H2;
-#endif
- *p++ = ALPN_HTTP_1_1;
- *p = NULL;
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
+ size_t i;
+
+ for(i = 0; i < connssl->alpn->count; ++i) {
+ backend->protocols[i] = connssl->alpn->entries[i];
+ }
/* this function doesn't clone the protocols array, which is why we need
to keep it around */
if(mbedtls_ssl_conf_alpn_protocols(&backend->config,
@@ -631,8 +662,8 @@
failf(data, "Failed setting ALPN protocols");
return CURLE_SSL_CONNECT_ERROR;
}
- for(p = &backend->protocols[0]; *p; ++p)
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, *p);
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
#endif
@@ -664,20 +695,20 @@
}
static CURLcode
-mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
{
int ret;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
const mbedtls_x509_crt *peercert;
- const char * const pinnedpubkey = SSL_PINNED_PUB_KEY();
+ const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
DEBUGASSERT(backend);
- conn->recv[sockindex] = mbed_recv;
- conn->send[sockindex] = mbed_send;
-
ret = mbedtls_ssl_handshake(&backend->ssl);
if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
@@ -701,11 +732,11 @@
ret = mbedtls_ssl_get_verify_result(&backend->ssl);
- if(!SSL_CONN_CONFIG(verifyhost))
+ if(!conn_config->verifyhost)
/* Ignore hostname errors if verifyhost is disabled */
ret &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
- if(ret && SSL_CONN_CONFIG(verifypeer)) {
+ if(ret && conn_config->verifypeer) {
if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
failf(data, "Cert verify failed: BADCERT_EXPIRED");
@@ -803,7 +834,7 @@
result = Curl_pin_peer_pubkey(data,
pinnedpubkey,
&pubkey[PUB_DER_MAX_BYTES - size], size);
- pinnedpubkey_error:
+pinnedpubkey_error:
mbedtls_x509_crt_free(p);
free(p);
free(pubkey);
@@ -813,28 +844,11 @@
}
#ifdef HAS_ALPN
- if(conn->bits.tls_enable_alpn) {
- const char *next_protocol = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
+ if(connssl->alpn) {
+ const char *proto = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
- if(next_protocol) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, next_protocol);
-#ifdef USE_HTTP2
- if(!strncmp(next_protocol, ALPN_H2, ALPN_H2_LENGTH) &&
- !next_protocol[ALPN_H2_LENGTH]) {
- conn->negnpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) &&
- !next_protocol[ALPN_HTTP_1_1_LENGTH]) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- }
- }
- else {
- infof(data, VTLS_INFOF_NO_ALPN);
- }
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ Curl_alpn_set_negotiated(cf, data, (const unsigned char *)proto,
+ proto? strlen(proto) : 0);
}
#endif
@@ -845,21 +859,21 @@
}
static CURLcode
-mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+mbed_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
{
CURLcode retcode = CURLE_OK;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ 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);
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
DEBUGASSERT(backend);
- if(SSL_SET_OPTION(primary.sessionid)) {
+ if(ssl_config->primary.sessionid) {
int ret;
mbedtls_ssl_session *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
- bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE;
bool added = FALSE;
our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session));
@@ -879,12 +893,11 @@
/* If there's already a matching session in the cache, delete it */
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn, isproxy, &old_ssl_sessionid, NULL,
- sockindex))
+ if(!Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL))
Curl_ssl_delsessionid(data, old_ssl_sessionid);
- retcode = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid,
- 0, sockindex, &added);
+ retcode = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid,
+ 0, &added);
Curl_ssl_sessionid_unlock(data);
if(!added) {
mbedtls_ssl_session_free(our_ssl_sessionid);
@@ -901,17 +914,17 @@
return CURLE_OK;
}
-static ssize_t mbed_send(struct Curl_easy *data, int sockindex,
+static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *mem, size_t len,
CURLcode *curlcode)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
int ret = -1;
+ (void)data;
DEBUGASSERT(backend);
-
ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len);
if(ret < 0) {
@@ -928,14 +941,14 @@
(void)data;
}
-static void mbedtls_close(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
char buf[32];
- (void) data;
+ (void)data;
DEBUGASSERT(backend);
/* Maybe the server has already sent a close notify alert.
@@ -956,16 +969,17 @@
#endif /* THREADING_SUPPORT */
}
-static ssize_t mbed_recv(struct Curl_easy *data, int num,
+static ssize_t mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t buffersize,
CURLcode *curlcode)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[num];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
int ret = -1;
ssize_t len = -1;
+ (void)data;
DEBUGASSERT(backend);
ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf,
@@ -1048,15 +1062,13 @@
}
static CURLcode
-mbed_connect_common(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
+mbed_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
bool nonblocking,
bool *done)
{
CURLcode retcode;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
timediff_t timeout_ms;
int what;
@@ -1075,7 +1087,7 @@
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
- retcode = mbed_connect_step1(data, conn, sockindex);
+ retcode = mbed_connect_step1(cf, data);
if(retcode)
return retcode;
}
@@ -1130,7 +1142,7 @@
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
- retcode = mbed_connect_step2(data, conn, sockindex);
+ retcode = mbed_connect_step2(cf, data);
if(retcode || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -1140,15 +1152,13 @@
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- retcode = mbed_connect_step3(data, conn, sockindex);
+ retcode = mbed_connect_step3(cf, data);
if(retcode)
return retcode;
}
if(ssl_connect_done == connssl->connecting_state) {
connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = mbed_recv;
- conn->send[sockindex] = mbed_send;
*done = TRUE;
}
else
@@ -1160,21 +1170,21 @@
return CURLE_OK;
}
-static CURLcode mbedtls_connect_nonblocking(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode mbedtls_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done)
{
- return mbed_connect_common(data, conn, sockindex, TRUE, done);
+ return mbed_connect_common(cf, data, TRUE, done);
}
-static CURLcode mbedtls_connect(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode mbedtls_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
CURLcode retcode;
bool done = FALSE;
- retcode = mbed_connect_common(data, conn, sockindex, FALSE, &done);
+ retcode = mbed_connect_common(cf, data, FALSE, &done);
if(retcode)
return retcode;
@@ -1197,12 +1207,15 @@
(void)Curl_mbedtlsthreadlock_thread_cleanup();
}
-static bool mbedtls_data_pending(const struct connectdata *conn,
- int sockindex)
+static bool mbedtls_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
- const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- DEBUGASSERT(backend);
+ struct ssl_connect_data *ctx = cf->ctx;
+ struct mbed_ssl_backend_data *backend;
+
+ (void)data;
+ DEBUGASSERT(ctx && ctx->backend);
+ backend = (struct mbed_ssl_backend_data *)ctx->backend;
return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0;
}
@@ -1230,7 +1243,8 @@
static void *mbedtls_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
(void)info;
DEBUGASSERT(backend);
return &backend->ssl;
@@ -1242,9 +1256,10 @@
SSLSUPP_CA_PATH |
SSLSUPP_CAINFO_BLOB |
SSLSUPP_PINNEDPUBKEY |
- SSLSUPP_SSL_CTX,
+ SSLSUPP_SSL_CTX |
+ SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct mbed_ssl_backend_data),
mbedtls_init, /* init */
mbedtls_cleanup, /* cleanup */
@@ -1256,7 +1271,7 @@
Curl_none_cert_status_request, /* cert_status_request */
mbedtls_connect, /* connect */
mbedtls_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_getsock, /* getsock */
+ Curl_ssl_get_select_socks, /* getsock */
mbedtls_get_internals, /* get_internals */
mbedtls_close, /* close_one */
mbedtls_close_all, /* close_all */
@@ -1267,7 +1282,10 @@
Curl_none_false_start, /* false_start */
mbedtls_sha256sum, /* sha256sum */
NULL, /* associate_connection */
- NULL /* disassociate_connection */
+ NULL, /* disassociate_connection */
+ NULL, /* free_multi_ssl_backend_data */
+ mbed_recv, /* recv decrypted data */
+ mbed_send, /* send data to encrypt */
};
#endif /* USE_MBEDTLS */
diff --git a/lib/vtls/mbedtls.h b/lib/vtls/mbedtls.h
index ec3b43b..d8a0a06 100644
--- a/lib/vtls/mbedtls.h
+++ b/lib/vtls/mbedtls.h
@@ -7,8 +7,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vtls/mbedtls_threadlock.c b/lib/vtls/mbedtls_threadlock.c
index 3971e69..bcb7106 100644
--- a/lib/vtls/mbedtls_threadlock.c
+++ b/lib/vtls/mbedtls_threadlock.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,13 +26,12 @@
#if defined(USE_MBEDTLS) && \
((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
- (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)))
+ defined(USE_THREADS_WIN32))
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
# include <pthread.h>
# define MBEDTLS_MUTEX_T pthread_mutex_t
-#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
-# include <process.h>
+#elif defined(USE_THREADS_WIN32)
# define MBEDTLS_MUTEX_T HANDLE
#endif
@@ -60,7 +59,7 @@
#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(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
+#elif defined(USE_THREADS_WIN32)
mutex_buf[i] = CreateMutex(0, FALSE, 0);
if(mutex_buf[i] == 0)
return 0; /* CreateMutex failed */
@@ -81,7 +80,7 @@
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
if(pthread_mutex_destroy(&mutex_buf[i]))
return 0; /* pthread_mutex_destroy failed */
-#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
+#elif defined(USE_THREADS_WIN32)
if(!CloseHandle(mutex_buf[i]))
return 0; /* CloseHandle failed */
#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */
@@ -101,7 +100,7 @@
"Error: mbedtlsthreadlock_lock_function failed\n"));
return 0; /* pthread_mutex_lock failed */
}
-#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
+#elif defined(USE_THREADS_WIN32)
if(WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED) {
DEBUGF(fprintf(stderr,
"Error: mbedtlsthreadlock_lock_function failed\n"));
@@ -121,7 +120,7 @@
"Error: mbedtlsthreadlock_unlock_function failed\n"));
return 0; /* pthread_mutex_unlock failed */
}
-#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
+#elif defined(USE_THREADS_WIN32)
if(!ReleaseMutex(mutex_buf[n])) {
DEBUGF(fprintf(stderr,
"Error: mbedtlsthreadlock_unlock_function failed\n"));
diff --git a/lib/vtls/mbedtls_threadlock.h b/lib/vtls/mbedtls_threadlock.h
index 3a50d03..2b0bd41 100644
--- a/lib/vtls/mbedtls_threadlock.h
+++ b/lib/vtls/mbedtls_threadlock.h
@@ -7,8 +7,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,7 +29,7 @@
#ifdef USE_MBEDTLS
#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
- (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H))
+ defined(USE_THREADS_WIN32)
int Curl_mbedtlsthreadlock_thread_setup(void);
int Curl_mbedtlsthreadlock_thread_cleanup(void);
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index 9d3a858..322f507 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -39,6 +39,7 @@
#include "strcase.h"
#include "select.h"
#include "vtls.h"
+#include "vtls_int.h"
#include "llist.h"
#include "multiif.h"
#include "curl_printf.h"
@@ -68,7 +69,6 @@
#include <ocsp.h>
#endif
-#include "strcase.h"
#include "warnless.h"
#include "x509asn1.h"
@@ -81,7 +81,7 @@
/* enough to fit the string "PEM Token #[0|1]" */
#define SLOTSIZE 13
-struct ssl_backend_data {
+struct nss_ssl_backend_data {
PRFileDesc *handle;
char *client_nickname;
struct Curl_easy *data;
@@ -336,7 +336,7 @@
char name[MAX_CIPHER_LENGTH + 1];
size_t len;
bool found = FALSE;
- while((*cipher) && (ISSPACE(*cipher)))
+ while((*cipher) && (ISBLANK(*cipher)))
++cipher;
end = strpbrk(cipher, ":, ");
@@ -489,7 +489,8 @@
const int slot_id = (cacert) ? 0 : 1;
char *slot_name = aprintf("PEM Token #%d", slot_id);
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
@@ -696,17 +697,18 @@
return CURLE_SSL_CRL_BADFILE;
}
-static CURLcode nss_load_key(struct Curl_easy *data, struct connectdata *conn,
- int sockindex, char *key_file)
+static CURLcode nss_load_key(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ char *key_file)
{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
PK11SlotInfo *slot, *tmp;
SECStatus status;
CURLcode result;
- struct ssl_connect_data *ssl = conn->ssl;
- (void)sockindex; /* unused */
-
- result = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE);
+ (void)data;
+ result = nss_create_object(connssl, CKO_PRIVATE_KEY, key_file, FALSE);
if(result) {
PR_SetError(SEC_ERROR_BAD_KEY, 0);
return result;
@@ -725,7 +727,7 @@
return CURLE_SSL_CERTPROBLEM;
}
- status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd));
+ status = PK11_Authenticate(slot, PR_TRUE, ssl_config->key_passwd);
PK11_FreeSlot(slot);
return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
@@ -747,13 +749,15 @@
return 0; /* The caller will print a generic error */
}
-static CURLcode cert_stuff(struct Curl_easy *data, struct connectdata *conn,
- int sockindex, char *cert_file, char *key_file)
+static CURLcode cert_stuff(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ char *cert_file, char *key_file)
{
+ struct ssl_connect_data *connssl = cf->ctx;
CURLcode result;
if(cert_file) {
- result = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE);
+ result = nss_load_cert(connssl, cert_file, PR_FALSE);
if(result) {
const PRErrorCode err = PR_GetError();
if(!display_error(data, err, cert_file)) {
@@ -767,10 +771,10 @@
if(key_file || (is_file(cert_file))) {
if(key_file)
- result = nss_load_key(data, conn, sockindex, key_file);
+ result = nss_load_key(cf, data, key_file);
else
/* In case the cert file also has the key */
- result = nss_load_key(data, conn, sockindex, cert_file);
+ result = nss_load_key(cf, data, cert_file);
if(result) {
const PRErrorCode err = PR_GetError();
if(!display_error(data, err, key_file)) {
@@ -800,11 +804,16 @@
static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
PRBool isServer)
{
- struct Curl_easy *data = (struct Curl_easy *)arg;
- struct connectdata *conn = data->conn;
+ struct Curl_cfilter *cf = (struct Curl_cfilter *)arg;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
+ struct Curl_easy *data = backend->data;
+ DEBUGASSERT(data);
#ifdef SSL_ENABLE_OCSP_STAPLING
- if(SSL_CONN_CONFIG(verifystatus)) {
+ if(conn_config->verifystatus) {
SECStatus cacheResult;
const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
@@ -830,7 +839,7 @@
}
#endif
- if(!SSL_CONN_CONFIG(verifypeer)) {
+ if(!conn_config->verifypeer) {
infof(data, "skipping SSL peer certificate verification");
return SECSuccess;
}
@@ -843,14 +852,18 @@
*/
static void HandshakeCallback(PRFileDesc *sock, void *arg)
{
- struct Curl_easy *data = (struct Curl_easy *)arg;
- struct connectdata *conn = data->conn;
+ struct Curl_cfilter *cf = (struct Curl_cfilter *)arg;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
+ struct Curl_easy *data = backend->data;
unsigned int buflenmax = 50;
unsigned char buf[50];
unsigned int buflen;
SSLNextProtoState state;
- if(!conn->bits.tls_enable_npn && !conn->bits.tls_enable_alpn) {
+ DEBUGASSERT(data);
+ if(!connssl->alpn) {
return;
}
@@ -864,37 +877,18 @@
#endif
case SSL_NEXT_PROTO_NO_SUPPORT:
case SSL_NEXT_PROTO_NO_OVERLAP:
- infof(data, VTLS_INFOF_NO_ALPN);
+ Curl_alpn_set_negotiated(cf, data, NULL, 0);
return;
#ifdef SSL_ENABLE_ALPN
case SSL_NEXT_PROTO_SELECTED:
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, buflen, buf);
+ Curl_alpn_set_negotiated(cf, data, buf, buflen);
break;
#endif
- case SSL_NEXT_PROTO_NEGOTIATED:
- infof(data, "NPN, server accepted to use %.*s", buflen, buf);
+ default:
+ /* ignore SSL_NEXT_PROTO_NEGOTIATED */
break;
}
-#ifdef USE_HTTP2
- if(buflen == ALPN_H2_LENGTH &&
- !memcmp(ALPN_H2, buf, ALPN_H2_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(buflen == ALPN_HTTP_1_1_LENGTH &&
- !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- }
-
- /* This callback might get called when PR_Recv() is used within
- * close_one() during a connection shutdown. At that point there might not
- * be any "bundle" associated with the connection anymore.
- */
- if(conn->bundle)
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
}
@@ -936,8 +930,8 @@
if(cipherInfo.symCipher != ssl_calg_aes_gcm)
goto end;
- /* Enforce ALPN or NPN to do False Start, as an indicator of server
- * compatibility. */
+ /* Enforce ALPN to do False Start, as an indicator of server
+ compatibility. */
rv = SSL_HandshakeNegotiatedExtension(sock, ssl_app_layer_protocol_xtn,
&negotiatedExtension);
if(rv != SECSuccess || !negotiatedExtension) {
@@ -1064,15 +1058,22 @@
static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
{
- struct Curl_easy *data = (struct Curl_easy *)arg;
- struct connectdata *conn = data->conn;
+ struct Curl_cfilter *cf = (struct Curl_cfilter *)arg;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
+ struct Curl_easy *data = backend->data;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config;
PRErrorCode err = PR_GetError();
CERTCertificate *cert;
+ DEBUGASSERT(data);
+ ssl_config = Curl_ssl_cf_get_config(cf, data);
/* remember the cert verification result */
- SSL_SET_OPTION_LVALUE(certverifyresult) = err;
+ ssl_config->certverifyresult = err;
- if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost))
+ if(err == SSL_ERROR_BAD_CERT_DOMAIN && !conn_config->verifyhost)
/* we are asked not to verify the host name */
return SECSuccess;
@@ -1123,7 +1124,8 @@
const char *pinnedpubkey)
{
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
struct Curl_easy *data = NULL;
CERTCertificate *cert;
@@ -1179,7 +1181,8 @@
struct SECKEYPrivateKeyStr **pRetKey)
{
struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
struct Curl_easy *data = NULL;
const char *nickname = NULL;
static const char pem_slotname[] = "PEM Token #1";
@@ -1541,39 +1544,11 @@
initialized = 0;
}
-/*
- * This function uses SSL_peek to determine connection status.
- *
- * Return codes:
- * 1 means the connection is still in place
- * 0 means the connection has been closed
- * -1 means the connection status is unknown
- */
-static int nss_check_cxn(struct connectdata *conn)
-{
- struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
- struct ssl_backend_data *backend = connssl->backend;
- int rc;
- char buf;
-
- DEBUGASSERT(backend);
-
- rc =
- PR_Recv(backend->handle, (void *)&buf, 1, PR_MSG_PEEK,
- PR_SecondsToInterval(1));
- if(rc > 0)
- return 1; /* connection still in place */
-
- if(rc == 0)
- return 0; /* connection has been closed */
-
- return -1; /* connection status unknown */
-}
-
static void close_one(struct ssl_connect_data *connssl)
{
/* before the cleanup, check whether we are using a client certificate */
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
bool client_cert = true;
DEBUGASSERT(backend);
@@ -1612,41 +1587,21 @@
/*
* This function is called when an SSL connection is closed.
*/
-static void nss_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static void nss_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-#ifndef CURL_DISABLE_PROXY
- struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
-#endif
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
(void)data;
-
DEBUGASSERT(backend);
-#ifndef CURL_DISABLE_PROXY
- DEBUGASSERT(connssl_proxy->backend != NULL);
-#endif
- if(backend->handle
-#ifndef CURL_DISABLE_PROXY
- || connssl_proxy->backend->handle
-#endif
- ) {
+ if(backend->handle) {
/* NSS closes the socket we previously handed to it, so we must mark it
as closed to avoid double close */
- fake_sclose(conn->sock[sockindex]);
- conn->sock[sockindex] = CURL_SOCKET_BAD;
+ fake_sclose(cf->conn->sock[cf->sockindex]);
+ cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
}
-#ifndef CURL_DISABLE_PROXY
- if(backend->handle)
- /* nss_close(connssl) will transitively close also
- connssl_proxy->backend->handle if both are used. Clear it to avoid
- a double close leading to crash. */
- connssl_proxy->backend->handle = NULL;
-
- close_one(connssl_proxy);
-#endif
close_one(connssl);
}
@@ -1680,15 +1635,13 @@
}
}
-static Curl_recv nss_recv;
-static Curl_send nss_send;
-
-static CURLcode nss_load_ca_certificates(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex)
+static CURLcode nss_load_ca_certificates(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- const char *cafile = SSL_CONN_CONFIG(CAfile);
- const char *capath = SSL_CONN_CONFIG(CApath);
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ const char *cafile = conn_config->CAfile;
+ const char *capath = conn_config->CApath;
bool use_trust_module;
CURLcode result = CURLE_OK;
@@ -1723,7 +1676,7 @@
PR_Unlock(nss_trustload_lock);
if(cafile)
- result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
+ result = nss_load_cert(connssl, cafile, PR_TRUE);
if(result)
return result;
@@ -1747,7 +1700,7 @@
return CURLE_OUT_OF_MEMORY;
}
- if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE))
+ if(CURLE_OK != nss_load_cert(connssl, fullpath, PR_TRUE))
/* This is purposefully tolerant of errors so non-PEM files can
* be in the same directory */
infof(data, "failed to load '%s' from CURLOPT_CAPATH", fullpath);
@@ -1808,12 +1761,13 @@
}
static CURLcode nss_init_sslver(SSLVersionRange *sslver,
- struct Curl_easy *data,
- struct connectdata *conn)
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
CURLcode result;
- const long min = SSL_CONN_CONFIG(version);
- const long max = SSL_CONN_CONFIG(version_max);
+ const long min = conn_config->version;
+ const long max = conn_config->version_max;
SSLVersionRange vrange;
switch(min) {
@@ -1848,11 +1802,13 @@
return CURLE_OK;
}
-static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
+static CURLcode nss_fail_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
CURLcode curlerr)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
@@ -1876,12 +1832,14 @@
}
/* Switch the SSL socket into blocking or non-blocking mode. */
-static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
+static CURLcode nss_set_blocking(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking)
{
+ struct ssl_connect_data *connssl = cf->ctx;
PRSocketOptionData sock_opt;
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
@@ -1889,22 +1847,28 @@
sock_opt.value.non_blocking = !blocking;
if(PR_SetSocketOption(backend->handle, &sock_opt) != PR_SUCCESS)
- return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
+ return nss_fail_connect(cf, data, CURLE_SSL_CONNECT_ERROR);
return CURLE_OK;
}
-static CURLcode nss_setup_connect(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode nss_setup_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
PRFileDesc *model = NULL;
PRFileDesc *nspr_io = NULL;
PRFileDesc *nspr_io_stub = NULL;
PRBool ssl_no_cache;
PRBool ssl_cbc_random_iv;
- curl_socket_t sockfd = conn->sock[sockindex];
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
+ struct ssl_connect_data *connssl_next = cf_ssl_next?
+ cf_ssl_next->ctx : NULL;
CURLcode result;
bool second_layer = FALSE;
SSLVersionRange sslver_supported;
@@ -1920,7 +1884,10 @@
SSL_LIBRARY_VERSION_TLS_1_0
#endif
};
- char *snihost = Curl_ssl_snihost(data, SSL_HOST_NAME(), NULL);
+ const char *hostname = connssl->hostname;
+ char *snihost;
+
+ snihost = Curl_ssl_snihost(data, hostname, NULL);
if(!snihost) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
@@ -1965,13 +1932,13 @@
goto error;
/* do not use SSL cache if disabled or we are not going to verify peer */
- ssl_no_cache = (SSL_SET_OPTION(primary.sessionid)
- && SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE;
+ ssl_no_cache = (ssl_config->primary.sessionid
+ && conn_config->verifypeer) ? PR_FALSE : PR_TRUE;
if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
goto error;
/* enable/disable the requested SSL version(s) */
- if(nss_init_sslver(&sslver, data, conn) != CURLE_OK)
+ if(nss_init_sslver(&sslver, cf, data) != CURLE_OK)
goto error;
if(SSL_VersionRangeGetSupported(ssl_variant_stream,
&sslver_supported) != SECSuccess)
@@ -1990,7 +1957,7 @@
if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
goto error;
- ssl_cbc_random_iv = !SSL_SET_OPTION(enable_beast);
+ ssl_cbc_random_iv = !ssl_config->enable_beast;
#ifdef SSL_CBC_RANDOM_IV
/* unless the user explicitly asks to allow the protocol vulnerability, we
use the work-around */
@@ -2002,33 +1969,33 @@
infof(data, "WARNING: support for SSL_CBC_RANDOM_IV not compiled in");
#endif
- if(SSL_CONN_CONFIG(cipher_list)) {
- if(set_ciphers(data, model, SSL_CONN_CONFIG(cipher_list)) != SECSuccess) {
+ if(conn_config->cipher_list) {
+ if(set_ciphers(data, model, conn_config->cipher_list) != SECSuccess) {
result = CURLE_SSL_CIPHER;
goto error;
}
}
- if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost))
+ if(!conn_config->verifypeer && conn_config->verifyhost)
infof(data, "WARNING: ignoring value of ssl.verifyhost");
/* bypass the default SSL_AuthCertificate() hook in case we do not want to
* verify peer */
- if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, data) != SECSuccess)
+ if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, cf) != SECSuccess)
goto error;
/* not checked yet */
- SSL_SET_OPTION_LVALUE(certverifyresult) = 0;
+ ssl_config->certverifyresult = 0;
- if(SSL_BadCertHook(model, BadCertHandler, data) != SECSuccess)
+ if(SSL_BadCertHook(model, BadCertHandler, cf) != SECSuccess)
goto error;
- if(SSL_HandshakeCallback(model, HandshakeCallback, data) != SECSuccess)
+ if(SSL_HandshakeCallback(model, HandshakeCallback, cf) != SECSuccess)
goto error;
{
- const CURLcode rv = nss_load_ca_certificates(data, conn, sockindex);
- if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer))
+ const CURLcode rv = nss_load_ca_certificates(cf, data);
+ if((rv == CURLE_SSL_CACERT_BADFILE) && !conn_config->verifypeer)
/* not a fatal error because we are not going to verify the peer */
infof(data, "WARNING: CA certificates failed to load");
else if(rv) {
@@ -2037,25 +2004,25 @@
}
}
- if(SSL_SET_OPTION(primary.CRLfile)) {
- const CURLcode rv = nss_load_crl(SSL_SET_OPTION(primary.CRLfile));
+ if(ssl_config->primary.CRLfile) {
+ const CURLcode rv = nss_load_crl(ssl_config->primary.CRLfile);
if(rv) {
result = rv;
goto error;
}
- infof(data, " CRLfile: %s", SSL_SET_OPTION(primary.CRLfile));
+ infof(data, " CRLfile: %s", ssl_config->primary.CRLfile);
}
- if(SSL_SET_OPTION(primary.clientcert)) {
- char *nickname = dup_nickname(data, SSL_SET_OPTION(primary.clientcert));
+ if(ssl_config->primary.clientcert) {
+ char *nickname = dup_nickname(data, ssl_config->primary.clientcert);
if(nickname) {
/* we are not going to use libnsspem.so to read the client cert */
backend->obj_clicert = NULL;
}
else {
- CURLcode rv = cert_stuff(data, conn, sockindex,
- SSL_SET_OPTION(primary.clientcert),
- SSL_SET_OPTION(key));
+ CURLcode rv = cert_stuff(cf, data,
+ ssl_config->primary.clientcert,
+ ssl_config->key);
if(rv) {
/* failf() is already done in cert_stuff() */
result = rv;
@@ -2075,17 +2042,21 @@
goto error;
}
-#ifndef CURL_DISABLE_PROXY
- if(conn->proxy_ssl[sockindex].use) {
- struct ssl_backend_data *proxy_backend;
- proxy_backend = conn->proxy_ssl[sockindex].backend;
- DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
- DEBUGASSERT(proxy_backend);
- DEBUGASSERT(proxy_backend->handle);
- nspr_io = proxy_backend->handle;
+ /* Is there an SSL filter "in front" of us or are we writing directly
+ * to the socket? */
+ if(connssl_next) {
+ struct nss_ssl_backend_data *backend_next =
+ (struct nss_ssl_backend_data *)connssl_next->backend;
+ /* The filter should be connected by now, with full handshake */
+ DEBUGASSERT(backend_next->handle);
+ DEBUGASSERT(ssl_connection_complete == connssl_next->state);
+ /* We tell our NSS instance to use do IO with the 'next' NSS
+ * instance. This NSS instance will take ownership of the next
+ * one, including its destruction. We therefore need to `disown`
+ * the next filter's handle, once import succeeds. */
+ nspr_io = backend->handle;
second_layer = TRUE;
}
-#endif
else {
/* wrap OS file descriptor by NSPR's file descriptor abstraction */
nspr_io = PR_ImportTCPSocket(sockfd);
@@ -2122,29 +2093,29 @@
PR_Close(model); /* We don't need this any more */
model = NULL;
+ if(connssl_next) { /* steal the NSS handle we just imported successfully */
+ struct nss_ssl_backend_data *backend_next =
+ (struct nss_ssl_backend_data *)connssl_next->backend;
+ backend_next->handle = NULL;
+ }
/* This is the password associated with the cert that we're using */
- if(SSL_SET_OPTION(key_passwd)) {
- SSL_SetPKCS11PinArg(backend->handle, SSL_SET_OPTION(key_passwd));
+ if(ssl_config->key_passwd) {
+ SSL_SetPKCS11PinArg(backend->handle, ssl_config->key_passwd);
}
#ifdef SSL_ENABLE_OCSP_STAPLING
- if(SSL_CONN_CONFIG(verifystatus)) {
+ if(conn_config->verifystatus) {
if(SSL_OptionSet(backend->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
!= SECSuccess)
goto error;
}
#endif
-#ifdef SSL_ENABLE_NPN
- if(SSL_OptionSet(backend->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn
- ? PR_TRUE : PR_FALSE) != SECSuccess)
- goto error;
-#endif
-
#ifdef SSL_ENABLE_ALPN
- if(SSL_OptionSet(backend->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn
- ? PR_TRUE : PR_FALSE) != SECSuccess)
+ if(SSL_OptionSet(backend->handle, SSL_ENABLE_ALPN,
+ connssl->alpn ? PR_TRUE : PR_FALSE)
+ != SECSuccess)
goto error;
#endif
@@ -2160,28 +2131,18 @@
}
#endif
-#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
- if(conn->bits.tls_enable_npn || conn->bits.tls_enable_alpn) {
- int cur = 0;
- unsigned char protocols[128];
+#if defined(SSL_ENABLE_ALPN)
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2
-#ifndef CURL_DISABLE_PROXY
- && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
-#endif
- ) {
- protocols[cur++] = ALPN_H2_LENGTH;
- memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH);
- cur += ALPN_H2_LENGTH;
- }
-#endif
- protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
- memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
- cur += ALPN_HTTP_1_1_LENGTH;
-
- if(SSL_SetNextProtoNego(backend->handle, protocols, cur) != SECSuccess)
+ result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
+ if(result || SSL_SetNextProtoNego(backend->handle, proto.data, proto.len)
+ != SECSuccess) {
+ failf(data, "Error setting ALPN");
goto error;
+ }
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
#endif
@@ -2205,14 +2166,17 @@
if(model)
PR_Close(model);
- return nss_fail_connect(connssl, data, result);
+ return nss_fail_connect(cf, data, result);
}
-static CURLcode nss_do_connect(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode nss_do_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
CURLcode result = CURLE_SSL_CONNECT_ERROR;
PRUint32 timeout;
@@ -2232,9 +2196,9 @@
if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
/* blocking direction is updated by nss_update_connecting_state() */
return CURLE_AGAIN;
- else if(SSL_SET_OPTION(certverifyresult) == SSL_ERROR_BAD_CERT_DOMAIN)
+ else if(ssl_config->certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
result = CURLE_PEER_FAILED_VERIFICATION;
- else if(SSL_SET_OPTION(certverifyresult) != 0)
+ else if(ssl_config->certverifyresult)
result = CURLE_PEER_FAILED_VERIFICATION;
goto error;
}
@@ -2243,9 +2207,9 @@
if(result)
goto error;
- if(SSL_CONN_CONFIG(issuercert)) {
+ if(conn_config->issuercert) {
SECStatus ret = SECFailure;
- char *nickname = dup_nickname(data, SSL_CONN_CONFIG(issuercert));
+ char *nickname = dup_nickname(data, conn_config->issuercert);
if(nickname) {
/* we support only nicknames in case of issuercert for now */
ret = check_issuer_cert(backend->handle, nickname);
@@ -2262,7 +2226,9 @@
}
}
- result = cmp_peer_pubkey(connssl, SSL_PINNED_PUB_KEY());
+ result = cmp_peer_pubkey(connssl, Curl_ssl_cf_is_proxy(cf)?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
if(result)
/* status already printed */
goto error;
@@ -2270,14 +2236,14 @@
return CURLE_OK;
error:
- return nss_fail_connect(connssl, data, result);
+ return nss_fail_connect(cf, data, result);
}
-static CURLcode nss_connect_common(struct Curl_easy *data,
- struct connectdata *conn, int sockindex,
+static CURLcode nss_connect_common(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
bool *done)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
const bool blocking = (done == NULL);
CURLcode result;
@@ -2288,7 +2254,7 @@
}
if(connssl->connecting_state == ssl_connect_1) {
- result = nss_setup_connect(data, conn, sockindex);
+ result = nss_setup_connect(cf, data);
if(result)
/* we do not expect CURLE_AGAIN from nss_setup_connect() */
return result;
@@ -2297,11 +2263,11 @@
}
/* enable/disable blocking mode before handshake */
- result = nss_set_blocking(connssl, data, blocking);
+ result = nss_set_blocking(cf, data, blocking);
if(result)
return result;
- result = nss_do_connect(data, conn, sockindex);
+ result = nss_do_connect(cf, data);
switch(result) {
case CURLE_OK:
break;
@@ -2317,7 +2283,7 @@
if(blocking) {
/* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */
- result = nss_set_blocking(connssl, data, /* blocking */ FALSE);
+ result = nss_set_blocking(cf, data, /* blocking */ FALSE);
if(result)
return result;
}
@@ -2326,8 +2292,6 @@
*done = TRUE;
connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = nss_recv;
- conn->send[sockindex] = nss_send;
/* ssl_connect_done is never used outside, go back to the initial state */
connssl->connecting_state = ssl_connect_1;
@@ -2335,30 +2299,31 @@
return CURLE_OK;
}
-static CURLcode nss_connect(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static CURLcode nss_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- return nss_connect_common(data, conn, sockindex, /* blocking */ NULL);
+ return nss_connect_common(cf, data, /* blocking */ NULL);
}
-static CURLcode nss_connect_nonblocking(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode nss_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done)
{
- return nss_connect_common(data, conn, sockindex, done);
+ return nss_connect_common(cf, data, done);
}
-static ssize_t nss_send(struct Curl_easy *data, /* transfer */
- int sockindex, /* socketindex */
+static ssize_t nss_send(struct Curl_cfilter *cf,
+ struct Curl_easy *data, /* transfer */
const void *mem, /* send this data */
size_t len, /* amount to write */
CURLcode *curlcode)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
ssize_t rc;
+ (void)data;
DEBUGASSERT(backend);
/* The SelectClientCert() hook uses this for infof() and failf() but the
@@ -2389,17 +2354,33 @@
return rc; /* number of bytes */
}
-static ssize_t nss_recv(struct Curl_easy *data, /* transfer */
- int sockindex, /* socketindex */
+static bool
+nss_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
+ PRFileDesc *fd = backend->handle->lower;
+ char buf;
+
+ (void) data;
+
+ /* Returns true in case of error to force reading. */
+ return PR_Recv(fd, (void *) &buf, 1, PR_MSG_PEEK, PR_INTERVAL_NO_WAIT) != 0;
+}
+
+static ssize_t nss_recv(struct Curl_cfilter *cf,
+ struct Curl_easy *data, /* transfer */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
ssize_t nread;
+ (void)data;
DEBUGASSERT(backend);
/* The SelectClientCert() hook uses this for infof() and failf() but the
@@ -2498,12 +2479,36 @@
static void *nss_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
(void)info;
DEBUGASSERT(backend);
return backend->handle;
}
+static bool nss_attach_data(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
+
+ if(!backend->data)
+ backend->data = data;
+ return TRUE;
+}
+
+static void nss_detach_data(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
+
+ if(backend->data == data)
+ backend->data = NULL;
+}
+
const struct Curl_ssl Curl_ssl_nss = {
{ CURLSSLBACKEND_NSS, "nss" }, /* info */
@@ -2512,20 +2517,20 @@
SSLSUPP_PINNEDPUBKEY |
SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct nss_ssl_backend_data),
nss_init, /* init */
nss_cleanup, /* cleanup */
nss_version, /* version */
- nss_check_cxn, /* check_cxn */
+ Curl_none_check_cxn, /* check_cxn */
/* NSS has no shutdown function provided and thus always fail */
Curl_none_shutdown, /* shutdown */
- Curl_none_data_pending, /* data_pending */
+ nss_data_pending, /* data_pending */
nss_random, /* random */
nss_cert_status_request, /* cert_status_request */
nss_connect, /* connect */
nss_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_getsock, /* getsock */
+ Curl_ssl_get_select_socks, /* getsock */
nss_get_internals, /* get_internals */
nss_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -2536,8 +2541,11 @@
Curl_none_engines_list, /* engines_list */
nss_false_start, /* false_start */
nss_sha256sum, /* sha256sum */
- NULL, /* associate_connection */
- NULL /* disassociate_connection */
+ nss_attach_data, /* associate_connection */
+ nss_detach_data, /* disassociate_connection */
+ NULL, /* free_multi_ssl_backend_data */
+ nss_recv, /* recv decrypted data */
+ nss_send, /* send data to encrypt */
};
#endif /* USE_NSS */
diff --git a/lib/vtls/nssg.h b/lib/vtls/nssg.h
index 454a38f..ad7eef5 100644
--- a/lib/vtls/nssg.h
+++ b/lib/vtls/nssg.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 78aacd0..ae33147 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,7 +29,7 @@
#include "curl_setup.h"
-#ifdef USE_OPENSSL
+#if defined(USE_QUICHE) || defined(USE_OPENSSL)
#include <limits.h>
@@ -55,6 +55,8 @@
#include "slist.h"
#include "select.h"
#include "vtls.h"
+#include "vtls_int.h"
+#include "vauth/vauth.h"
#include "keylog.h"
#include "strcase.h"
#include "hostcheck.h"
@@ -78,10 +80,6 @@
#include <openssl/buffer.h>
#include <openssl/pkcs12.h>
-#ifdef USE_AMISSL
-#include "amigaos.h"
-#endif
-
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP)
#include <openssl/ocsp.h>
#endif
@@ -98,6 +96,7 @@
#include "curl_memory.h"
#include "memdebug.h"
+
/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
renegotiations when built with BoringSSL. Renegotiating is non-compliant
with HTTP/2 and "an extremely dangerous protocol feature". Beware.
@@ -208,8 +207,10 @@
#if ((OPENSSL_VERSION_NUMBER >= 0x10101000L) && \
!defined(LIBRESSL_VERSION_NUMBER) && \
!defined(OPENSSL_IS_BORINGSSL))
-#define HAVE_SSL_CTX_SET_CIPHERSUITES
-#define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
+ #define HAVE_SSL_CTX_SET_CIPHERSUITES
+ #if !defined(OPENSSL_IS_AWSLC)
+ #define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
+ #endif
#endif
/*
@@ -228,6 +229,8 @@
#define OSSL_PACKAGE "LibreSSL"
#elif defined(OPENSSL_IS_BORINGSSL)
#define OSSL_PACKAGE "BoringSSL"
+#elif defined(OPENSSL_IS_AWSLC)
+#define OSSL_PACKAGE "AWS-LC"
#else
#define OSSL_PACKAGE "OpenSSL"
#endif
@@ -258,26 +261,562 @@
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
!(defined(LIBRESSL_VERSION_NUMBER) && \
LIBRESSL_VERSION_NUMBER < 0x2070100fL) && \
- !defined(OPENSSL_IS_BORINGSSL)
+ !defined(OPENSSL_IS_BORINGSSL) && \
+ !defined(OPENSSL_IS_AWSLC)
#define HAVE_OPENSSL_VERSION
#endif
-struct ssl_backend_data {
- struct Curl_easy *logger; /* transfer handle to pass trace logs to, only
- using sockindex 0 */
+#ifdef OPENSSL_IS_BORINGSSL
+typedef uint32_t sslerr_t;
+#else
+typedef unsigned long sslerr_t;
+#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
+
+/* What API version do we use? */
+#if defined(LIBRESSL_VERSION_NUMBER)
+#define USE_PRE_1_1_API (LIBRESSL_VERSION_NUMBER < 0x2070000f)
+#else /* !LIBRESSL_VERSION_NUMBER */
+#define USE_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L)
+#endif /* !LIBRESSL_VERSION_NUMBER */
+
+struct ossl_ssl_backend_data {
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
SSL* handle;
X509* server_cert;
+ BIO_METHOD *bio_method;
+ CURLcode io_result; /* result of last BIO cfilter operation */
#ifndef HAVE_KEYLOG_CALLBACK
/* Set to true once a valid keylog entry has been created to avoid dupes. */
bool keylog_done;
#endif
+ bool x509_store_setup; /* x509 store has been set up */
};
-static bool ossl_associate_connection(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex);
+#if defined(HAVE_SSL_X509_STORE_SHARE)
+struct multi_ssl_backend_data {
+ 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 */
+};
+#endif /* HAVE_SSL_X509_STORE_SHARE */
+
+#define push_certinfo(_label, _num) \
+do { \
+ long info_len = BIO_get_mem_data(mem, &ptr); \
+ Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \
+ if(1 != BIO_reset(mem)) \
+ break; \
+} while(0)
+
+static void pubkey_show(struct Curl_easy *data,
+ BIO *mem,
+ int num,
+ const char *type,
+ const char *name,
+ const BIGNUM *bn)
+{
+ char *ptr;
+ char namebuf[32];
+
+ msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
+
+ if(bn)
+ BN_print(mem, bn);
+ push_certinfo(namebuf, num);
+}
+
+#ifdef HAVE_OPAQUE_RSA_DSA_DH
+#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(ASN1_OBJECT *a, char *buf, size_t len)
+{
+ int i, ilen;
+
+ ilen = (int)len;
+ if(ilen < 0)
+ return 1; /* buffer too big */
+
+ i = i2t_ASN1_OBJECT(buf, ilen, a);
+
+ if(i >= ilen)
+ return 1; /* buffer too small */
+
+ return 0;
+}
+
+static void X509V3_ext(struct Curl_easy *data,
+ int certnum,
+ CONST_EXTS STACK_OF(X509_EXTENSION) *exts)
+{
+ int i;
+
+ if((int)sk_X509_EXTENSION_num(exts) <= 0)
+ /* no extensions, bail out */
+ return;
+
+ for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
+ ASN1_OBJECT *obj;
+ X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+ BUF_MEM *biomem;
+ char namebuf[128];
+ BIO *bio_out = BIO_new(BIO_s_mem());
+
+ if(!bio_out)
+ return;
+
+ obj = X509_EXTENSION_get_object(ext);
+
+ asn1_object_dump(obj, namebuf, sizeof(namebuf));
+
+ if(!X509V3_EXT_print(bio_out, ext, 0, 0))
+ ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
+
+ BIO_get_mem_ptr(bio_out, &biomem);
+ Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data,
+ biomem->length);
+ BIO_free(bio_out);
+ }
+}
+
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+typedef size_t numcert_t;
+#else
+typedef int numcert_t;
+#endif
+
+CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
+{
+ CURLcode result;
+ STACK_OF(X509) *sk;
+ int i;
+ numcert_t numcerts;
+ BIO *mem;
+
+ DEBUGASSERT(ssl);
+
+ sk = SSL_get_peer_cert_chain(ssl);
+ if(!sk) {
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ numcerts = sk_X509_num(sk);
+
+ result = Curl_ssl_init_certinfo(data, (int)numcerts);
+ if(result) {
+ return result;
+ }
+
+ mem = BIO_new(BIO_s_mem());
+ if(!mem) {
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ for(i = 0; i < (int)numcerts; i++) {
+ ASN1_INTEGER *num;
+ X509 *x = sk_X509_value(sk, i);
+ EVP_PKEY *pubkey = NULL;
+ int j;
+ char *ptr;
+ const ASN1_BIT_STRING *psig = NULL;
+
+ X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
+ push_certinfo("Subject", i);
+
+ X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
+ push_certinfo("Issuer", i);
+
+ BIO_printf(mem, "%lx", X509_get_version(x));
+ push_certinfo("Version", i);
+
+ num = X509_get_serialNumber(x);
+ if(num->type == V_ASN1_NEG_INTEGER)
+ BIO_puts(mem, "-");
+ for(j = 0; j < num->length; j++)
+ BIO_printf(mem, "%02x", num->data[j]);
+ push_certinfo("Serial Number", i);
+
+#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS)
+ {
+ const X509_ALGOR *sigalg = NULL;
+ X509_PUBKEY *xpubkey = NULL;
+ ASN1_OBJECT *pubkeyoid = NULL;
+
+ X509_get0_signature(&psig, &sigalg, x);
+ if(sigalg) {
+ i2a_ASN1_OBJECT(mem, sigalg->algorithm);
+ push_certinfo("Signature Algorithm", i);
+ }
+
+ xpubkey = X509_get_X509_PUBKEY(x);
+ if(xpubkey) {
+ X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey);
+ if(pubkeyoid) {
+ i2a_ASN1_OBJECT(mem, pubkeyoid);
+ push_certinfo("Public Key Algorithm", i);
+ }
+ }
+
+ X509V3_ext(data, i, X509_get0_extensions(x));
+ }
+#else
+ {
+ /* before OpenSSL 1.0.2 */
+ X509_CINF *cinf = x->cert_info;
+
+ i2a_ASN1_OBJECT(mem, cinf->signature->algorithm);
+ push_certinfo("Signature Algorithm", i);
+
+ i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm);
+ push_certinfo("Public Key Algorithm", i);
+
+ X509V3_ext(data, i, cinf->extensions);
+
+ psig = x->signature;
+ }
+#endif
+
+ ASN1_TIME_print(mem, X509_get0_notBefore(x));
+ push_certinfo("Start date", i);
+
+ ASN1_TIME_print(mem, X509_get0_notAfter(x));
+ push_certinfo("Expire date", i);
+
+ pubkey = X509_get_pubkey(x);
+ 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", BN_num_bits(n));
+#else
+ BIO_printf(mem, "%d", BN_num_bits(rsa->n));
+#endif /* HAVE_OPAQUE_RSA_DSA_DH */
+ push_certinfo("RSA Public Key", i);
+ print_pubkey_BN(rsa, n, i);
+ print_pubkey_BN(rsa, e, i);
+ FREE_PKEY_PARAM_BIGNUM(n);
+ FREE_PKEY_PARAM_BIGNUM(e);
+ }
+
+ 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 */
+ 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);
+ }
+ break;
+ }
+ }
+ EVP_PKEY_free(pubkey);
+ }
+
+ if(psig) {
+ for(j = 0; j < psig->length; j++)
+ BIO_printf(mem, "%02x:", psig->data[j]);
+ push_certinfo("Signature", i);
+ }
+
+ PEM_write_bio_X509(mem, x);
+ push_certinfo("Cert", i);
+ }
+
+ BIO_free(mem);
+
+ return CURLE_OK;
+}
+
+#endif /* quiche or OpenSSL */
+
+#ifdef USE_OPENSSL
+
+#if USE_PRE_1_1_API
+#if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER < 0x2070000fL
+#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))
+#endif
+#define BIO_get_shutdown(x) ((x)->shutdown)
+#define BIO_set_shutdown(x,v) ((x)->shutdown=(v))
+#endif /* USE_PRE_1_1_API */
+
+static int bio_cf_create(BIO *bio)
+{
+ BIO_set_shutdown(bio, 1);
+ BIO_set_init(bio, 1);
+#if USE_PRE_1_1_API
+ bio->num = -1;
+#endif
+ BIO_set_data(bio, NULL);
+ return 1;
+}
+
+static int bio_cf_destroy(BIO *bio)
+{
+ if(!bio)
+ return 0;
+ return 1;
+}
+
+static long bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr)
+{
+ struct Curl_cfilter *cf = BIO_get_data(bio);
+ long ret = 1;
+
+ (void)cf;
+ (void)ptr;
+ switch(cmd) {
+ case BIO_CTRL_GET_CLOSE:
+ ret = (long)BIO_get_shutdown(bio);
+ break;
+ case BIO_CTRL_SET_CLOSE:
+ BIO_set_shutdown(bio, (int)num);
+ break;
+ case BIO_CTRL_FLUSH:
+ /* we do no delayed writes, but if we ever would, this
+ * needs to trigger it. */
+ ret = 1;
+ break;
+ case BIO_CTRL_DUP:
+ ret = 1;
+ break;
+#ifdef BIO_CTRL_EOF
+ case BIO_CTRL_EOF:
+ /* EOF has been reached on input? */
+ return (!cf->next || !cf->next->connected);
+#endif
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
+{
+ struct Curl_cfilter *cf = BIO_get_data(bio);
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nwritten;
+ CURLcode result = CURLE_SEND_ERROR;
+
+ DEBUGASSERT(data);
+ nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
+ DEBUGF(LOG_CF(data, cf, "bio_cf_out_write(len=%d) -> %d, err=%d",
+ blen, (int)nwritten, result));
+ BIO_clear_retry_flags(bio);
+ backend->io_result = result;
+ if(nwritten < 0) {
+ if(CURLE_AGAIN == result)
+ BIO_set_retry_write(bio);
+ }
+ return (int)nwritten;
+}
+
+static int bio_cf_in_read(BIO *bio, char *buf, int blen)
+{
+ struct Curl_cfilter *cf = BIO_get_data(bio);
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nread;
+ CURLcode result = CURLE_RECV_ERROR;
+
+ DEBUGASSERT(data);
+ /* OpenSSL catches this case, so should we. */
+ if(!buf)
+ return 0;
+
+ nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
+ DEBUGF(LOG_CF(data, cf, "bio_cf_in_read(len=%d) -> %d, err=%d",
+ blen, (int)nread, result));
+ BIO_clear_retry_flags(bio);
+ backend->io_result = result;
+ if(nread < 0) {
+ if(CURLE_AGAIN == result)
+ BIO_set_retry_read(bio);
+ }
+
+ /* Before returning server replies to the SSL instance, we need
+ * to have setup the x509 store or verification will fail. */
+ if(!backend->x509_store_setup) {
+ result = Curl_ssl_setup_x509_store(cf, data, backend->ctx);
+ if(result) {
+ backend->io_result = result;
+ return -1;
+ }
+ backend->x509_store_setup = TRUE;
+ }
+
+ return (int)nread;
+}
+
+#if USE_PRE_1_1_API
+
+static BIO_METHOD bio_cf_meth_1_0 = {
+ BIO_TYPE_MEM,
+ "OpenSSL CF BIO",
+ bio_cf_out_write,
+ bio_cf_in_read,
+ NULL, /* puts is never called */
+ NULL, /* gets is never called */
+ bio_cf_ctrl,
+ bio_cf_create,
+ bio_cf_destroy,
+ NULL
+};
+
+static BIO_METHOD *bio_cf_method_create(void)
+{
+ return &bio_cf_meth_1_0;
+}
+
+#define bio_cf_method_free(m) Curl_nop_stmt
+
+#else
+
+static BIO_METHOD *bio_cf_method_create(void)
+{
+ BIO_METHOD *m = BIO_meth_new(BIO_TYPE_MEM, "OpenSSL CF BIO");
+ if(m) {
+ BIO_meth_set_write(m, &bio_cf_out_write);
+ BIO_meth_set_read(m, &bio_cf_in_read);
+ BIO_meth_set_ctrl(m, &bio_cf_ctrl);
+ BIO_meth_set_create(m, &bio_cf_create);
+ BIO_meth_set_destroy(m, &bio_cf_destroy);
+ }
+ return m;
+}
+
+static void bio_cf_method_free(BIO_METHOD *m)
+{
+ if(m)
+ BIO_meth_free(m);
+}
+
+#endif
+
/*
* Number of bytes to read from the random number seed file. This must be
@@ -310,9 +849,9 @@
if(!session || *keylog_done)
return;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
- !(defined(LIBRESSL_VERSION_NUMBER) && \
- LIBRESSL_VERSION_NUMBER < 0x20700000L)
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
/* 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);
@@ -376,20 +915,33 @@
}
}
+static size_t ossl_version(char *buffer, size_t size);
+
/* Return error string for last OpenSSL error
*/
static char *ossl_strerror(unsigned long error, char *buf, size_t size)
{
- if(size)
- *buf = '\0';
+ size_t len;
+ DEBUGASSERT(size);
+ *buf = '\0';
-#ifdef OPENSSL_IS_BORINGSSL
+ len = ossl_version(buf, size);
+ DEBUGASSERT(len < (size - 2));
+ if(len < (size - 2)) {
+ buf += len;
+ size -= (len + 2);
+ *buf++ = ':';
+ *buf++ = ' ';
+ *buf = '\0';
+ }
+
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
ERR_error_string_n((uint32_t)error, buf, size);
#else
ERR_error_string_n(error, buf, size);
#endif
- if(size > 1 && !*buf) {
+ if(!*buf) {
strncpy(buf, (error ? "Unknown error" : "No error"), size);
buf[size - 1] = '\0';
}
@@ -397,54 +949,6 @@
return buf;
}
-/* Return an extra data index for the transfer data.
- * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
- */
-static int ossl_get_ssl_data_index(void)
-{
- static int ssl_ex_data_data_index = -1;
- if(ssl_ex_data_data_index < 0) {
- ssl_ex_data_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- }
- return ssl_ex_data_data_index;
-}
-
-/* Return an extra data index for the connection data.
- * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
- */
-static int ossl_get_ssl_conn_index(void)
-{
- static int ssl_ex_data_conn_index = -1;
- if(ssl_ex_data_conn_index < 0) {
- ssl_ex_data_conn_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- }
- return ssl_ex_data_conn_index;
-}
-
-/* Return an extra data index for the sockindex.
- * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
- */
-static int ossl_get_ssl_sockindex_index(void)
-{
- static int sockindex_index = -1;
- if(sockindex_index < 0) {
- sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- }
- return sockindex_index;
-}
-
-/* Return an extra data index for proxy boolean.
- * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
- */
-static int ossl_get_proxy_index(void)
-{
- static int proxy_index = -1;
- if(proxy_index < 0) {
- proxy_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- }
- return proxy_index;
-}
-
static int passwd_callback(char *buf, int num, int encrypting,
void *global_passwd)
{
@@ -653,7 +1157,7 @@
}
ret = SSL_CTX_use_certificate(ctx, x);
- end:
+end:
X509_free(x);
BIO_free(in);
return ret;
@@ -661,7 +1165,7 @@
static int
SSL_CTX_use_PrivateKey_blob(SSL_CTX *ctx, const struct curl_blob *blob,
- int type, const char *key_passwd)
+ int type, const char *key_passwd)
{
int ret = 0;
EVP_PKEY *pkey = NULL;
@@ -684,7 +1188,7 @@
}
ret = SSL_CTX_use_PrivateKey(ctx, pkey);
EVP_PKEY_free(pkey);
- end:
+end:
BIO_free(in);
return ret;
}
@@ -695,8 +1199,8 @@
{
/* SSL_CTX_add1_chain_cert introduced in OpenSSL 1.0.2 */
#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* OpenSSL 1.0.2 or later */ \
- !(defined(LIBRESSL_VERSION_NUMBER) && \
- (LIBRESSL_VERSION_NUMBER < 0x2090100fL)) /* LibreSSL 2.9.1 or later */
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ (LIBRESSL_VERSION_NUMBER < 0x2090100fL)) /* LibreSSL 2.9.1 or later */
int ret = 0;
X509 *x = NULL;
void *passwd_callback_userdata = (void *)key_passwd;
@@ -721,7 +1225,7 @@
if(ret) {
X509 *ca;
- unsigned long err;
+ sslerr_t err;
if(!SSL_CTX_clear_chain_certs(ctx)) {
ret = 0;
@@ -747,7 +1251,7 @@
ret = 0;
}
- end:
+end:
X509_free(x);
BIO_free(in);
return ret;
@@ -797,9 +1301,10 @@
SSL_CTX_use_certificate_chain_file(ctx, cert_file);
if(cert_use_result != 1) {
failf(data,
- "could not load PEM client certificate, " OSSL_PACKAGE
+ "could not load PEM client certificate from %s, " OSSL_PACKAGE
" error %s, "
"(no key found, wrong pass phrase, or wrong file format?)",
+ (cert_blob ? "CURLOPT_SSLCERT_BLOB" : cert_file),
ossl_strerror(ERR_get_error(), error_buffer,
sizeof(error_buffer)) );
return 0;
@@ -814,12 +1319,13 @@
cert_use_result = cert_blob ?
SSL_CTX_use_certificate_blob(ctx, cert_blob,
file_type, key_passwd) :
- SSL_CTX_use_certificate_file(ctx, cert_file, file_type);
+ SSL_CTX_use_certificate_file(ctx, cert_file, file_type);
if(cert_use_result != 1) {
failf(data,
- "could not load ASN1 client certificate, " OSSL_PACKAGE
+ "could not load ASN1 client certificate from %s, " OSSL_PACKAGE
" error %s, "
"(no key found, wrong pass phrase, or wrong file format?)",
+ (cert_blob ? "CURLOPT_SSLCERT_BLOB" : cert_file),
ossl_strerror(ERR_get_error(), error_buffer,
sizeof(error_buffer)) );
return 0;
@@ -827,66 +1333,67 @@
break;
case SSL_FILETYPE_ENGINE:
#if defined(USE_OPENSSL_ENGINE) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
- {
- /* Implicitly use pkcs11 engine if none was provided and the
- * cert_file is a PKCS#11 URI */
- if(!data->state.engine) {
- if(is_pkcs11_uri(cert_file)) {
- if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
- return 0;
- }
- }
- }
-
- if(data->state.engine) {
- const char *cmd_name = "LOAD_CERT_CTRL";
- struct {
- const char *cert_id;
- X509 *cert;
- } params;
-
- params.cert_id = cert_file;
- params.cert = NULL;
-
- /* Does the engine supports LOAD_CERT_CTRL ? */
- if(!ENGINE_ctrl(data->state.engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
- 0, (void *)cmd_name, NULL)) {
- failf(data, "ssl engine does not support loading certificates");
+ {
+ /* Implicitly use pkcs11 engine if none was provided and the
+ * cert_file is a PKCS#11 URI */
+ if(!data->state.engine) {
+ if(is_pkcs11_uri(cert_file)) {
+ if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
return 0;
}
-
- /* 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,
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)));
- return 0;
- }
-
- if(!params.cert) {
- failf(data, "ssl engine didn't initialized the certificate "
- "properly.");
- return 0;
- }
-
- if(SSL_CTX_use_certificate(ctx, params.cert) != 1) {
- failf(data, "unable to set client certificate");
- X509_free(params.cert);
- return 0;
- }
- X509_free(params.cert); /* we don't need the handle any more... */
- }
- else {
- failf(data, "crypto engine not set, can't load certificate");
- return 0;
}
}
- break;
+
+ if(data->state.engine) {
+ const char *cmd_name = "LOAD_CERT_CTRL";
+ struct {
+ const char *cert_id;
+ X509 *cert;
+ } params;
+
+ params.cert_id = cert_file;
+ params.cert = NULL;
+
+ /* Does the engine supports LOAD_CERT_CTRL ? */
+ if(!ENGINE_ctrl(data->state.engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
+ 0, (void *)cmd_name, NULL)) {
+ failf(data, "ssl engine does not support loading certificates");
+ return 0;
+ }
+
+ /* 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,
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ return 0;
+ }
+
+ if(!params.cert) {
+ failf(data, "ssl engine didn't initialized the certificate "
+ "properly.");
+ return 0;
+ }
+
+ if(SSL_CTX_use_certificate(ctx, params.cert) != 1) {
+ failf(data, "unable to set client certificate [%s]",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ return 0;
+ }
+ X509_free(params.cert); /* we don't need the handle any more... */
+ }
+ else {
+ failf(data, "crypto engine not set, can't load certificate");
+ return 0;
+ }
+ }
+ break;
#else
- failf(data, "file type ENG for certificate not implemented");
- return 0;
+ failf(data, "file type ENG for certificate not implemented");
+ return 0;
#endif
case SSL_FILETYPE_PKCS12:
@@ -993,14 +1500,10 @@
}
cert_done = 1;
- fail:
+fail:
EVP_PKEY_free(pri);
X509_free(x509);
-#ifdef USE_AMISSL
- sk_X509_pop_free(ca, Curl_amiga_X509_free);
-#else
sk_X509_pop_free(ca, X509_free);
-#endif
if(!cert_done)
return 0; /* failure! */
break;
@@ -1025,7 +1528,7 @@
case SSL_FILETYPE_ASN1:
cert_use_result = key_blob ?
SSL_CTX_use_PrivateKey_blob(ctx, key_blob, file_type, key_passwd) :
- SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type);
+ SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type);
if(cert_use_result != 1) {
failf(data, "unable to set private key file: '%s' type %s",
key_file?key_file:"(memory blob)", key_type?key_type:"PEM");
@@ -1034,57 +1537,57 @@
break;
case SSL_FILETYPE_ENGINE:
#ifdef USE_OPENSSL_ENGINE
- { /* XXXX still needs some work */
- EVP_PKEY *priv_key = NULL;
+ {
+ EVP_PKEY *priv_key = NULL;
- /* Implicitly use pkcs11 engine if none was provided and the
- * key_file is a PKCS#11 URI */
- if(!data->state.engine) {
- if(is_pkcs11_uri(key_file)) {
- if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
- return 0;
- }
- }
- }
-
- if(data->state.engine) {
- UI_METHOD *ui_method =
- UI_create_method((char *)"curl user interface");
- if(!ui_method) {
- failf(data, "unable do create " OSSL_PACKAGE
- " user-interface method");
+ /* Implicitly use pkcs11 engine if none was provided and the
+ * key_file is a PKCS#11 URI */
+ if(!data->state.engine) {
+ if(is_pkcs11_uri(key_file)) {
+ if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
return 0;
}
- UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
- UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
- UI_method_set_reader(ui_method, ssl_ui_reader);
- UI_method_set_writer(ui_method, ssl_ui_writer);
- /* the typecast below was added to please mingw32 */
- priv_key = (EVP_PKEY *)
- ENGINE_load_private_key(data->state.engine, key_file,
- ui_method,
- key_passwd);
- UI_destroy_method(ui_method);
- if(!priv_key) {
- failf(data, "failed to load private key from crypto engine");
- return 0;
- }
- if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) {
- failf(data, "unable to set private key");
- EVP_PKEY_free(priv_key);
- return 0;
- }
- EVP_PKEY_free(priv_key); /* we don't need the handle any more... */
- }
- else {
- failf(data, "crypto engine not set, can't load private key");
- return 0;
}
}
- break;
+
+ if(data->state.engine) {
+ UI_METHOD *ui_method =
+ UI_create_method((char *)"curl user interface");
+ if(!ui_method) {
+ failf(data, "unable do create " OSSL_PACKAGE
+ " user-interface method");
+ return 0;
+ }
+ UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
+ UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
+ UI_method_set_reader(ui_method, ssl_ui_reader);
+ UI_method_set_writer(ui_method, ssl_ui_writer);
+ /* the typecast below was added to please mingw32 */
+ priv_key = (EVP_PKEY *)
+ ENGINE_load_private_key(data->state.engine, key_file,
+ ui_method,
+ key_passwd);
+ UI_destroy_method(ui_method);
+ if(!priv_key) {
+ failf(data, "failed to load private key from crypto engine");
+ return 0;
+ }
+ if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) {
+ failf(data, "unable to set private key");
+ EVP_PKEY_free(priv_key);
+ return 0;
+ }
+ EVP_PKEY_free(priv_key); /* we don't need the handle any more... */
+ }
+ else {
+ failf(data, "crypto engine not set, can't load private key");
+ return 0;
+ }
+ }
+ break;
#else
- failf(data, "file type ENG for private key not supported");
- return 0;
+ failf(data, "file type ENG for private key not supported");
+ return 0;
#endif
case SSL_FILETYPE_PKCS12:
if(!cert_done) {
@@ -1113,8 +1616,8 @@
EVP_PKEY_free(pktmp);
}
-#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_IS_BORINGSSL) && \
- !defined(OPENSSL_NO_DEPRECATED_3_0)
+#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_IS_BORINGSSL) && \
+ !defined(OPENSSL_NO_DEPRECATED_3_0)
{
/* If RSA is used, don't check the private key if its flags indicate
* it doesn't support it. */
@@ -1246,19 +1749,14 @@
Curl_tls_keylog_open();
- /* Initialize the extra data indexes */
- if(ossl_get_ssl_data_index() < 0 || ossl_get_ssl_conn_index() < 0 ||
- ossl_get_ssl_sockindex_index() < 0 || ossl_get_proxy_index() < 0)
- return 0;
-
return 1;
}
/* Global cleanup */
static void ossl_cleanup(void)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
- !defined(LIBRESSL_VERSION_NUMBER)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
+ !defined(LIBRESSL_VERSION_NUMBER)
/* OpenSSL 1.1 deprecates all these cleanup functions and
turns them into no-ops in OpenSSL 1.0 compatibility mode */
#else
@@ -1291,58 +1789,6 @@
Curl_tls_keylog_close();
}
-/*
- * This function is used to determine connection status.
- *
- * Return codes:
- * 1 means the connection is still in place
- * 0 means the connection has been closed
- * -1 means the connection status is unknown
- */
-static int ossl_check_cxn(struct connectdata *conn)
-{
- /* SSL_peek takes data out of the raw recv buffer without peeking so we use
- recv MSG_PEEK instead. Bug #795 */
-#ifdef MSG_PEEK
- char buf;
- ssize_t nread;
- nread = recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
- (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK);
- if(nread == 0)
- return 0; /* connection has been closed */
- if(nread == 1)
- return 1; /* connection still in place */
- else if(nread == -1) {
- int err = SOCKERRNO;
- if(err == EINPROGRESS ||
-#if defined(EAGAIN) && (EAGAIN != EWOULDBLOCK)
- err == EAGAIN ||
-#endif
- err == EWOULDBLOCK)
- return 1; /* connection still in place */
- if(err == ECONNRESET ||
-#ifdef ECONNABORTED
- err == ECONNABORTED ||
-#endif
-#ifdef ENETDOWN
- err == ENETDOWN ||
-#endif
-#ifdef ENETRESET
- err == ENETRESET ||
-#endif
-#ifdef ESHUTDOWN
- err == ESHUTDOWN ||
-#endif
-#ifdef ETIMEDOUT
- err == ETIMEDOUT ||
-#endif
- err == ENOTCONN)
- return 0; /* connection has been closed */
- }
-#endif
- return -1; /* connection status unknown */
-}
-
/* Selects an OpenSSL crypto engine
*/
static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine)
@@ -1432,33 +1878,25 @@
return list;
}
-#define set_logger(conn, data) \
- conn->ssl[0].backend->logger = data
-
-static void ossl_closeone(struct Curl_easy *data,
- struct connectdata *conn,
- struct ssl_connect_data *connssl)
+static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
+ (void)data;
DEBUGASSERT(backend);
if(backend->handle) {
- char buf[32];
- set_logger(conn, data);
- /*
- * The conn->sock[0] socket is passed to openssl with SSL_set_fd(). Make
- * sure the socket is not closed before calling OpenSSL functions that
- * will use it.
- */
- DEBUGASSERT(conn->sock[FIRSTSOCKET] != CURL_SOCKET_BAD);
+ if(cf->next && cf->next->connected) {
+ char buf[32];
+ /* Maybe the server has already sent a close notify alert.
+ Read it to avoid an RST on the TCP connection. */
+ (void)SSL_read(backend->handle, buf, (int)sizeof(buf));
- /* Maybe the server has already sent a close notify alert.
- Read it to avoid an RST on the TCP connection. */
- (void)SSL_read(backend->handle, buf, (int)sizeof(buf));
-
- (void)SSL_shutdown(backend->handle);
- SSL_set_connect_state(backend->handle);
+ (void)SSL_shutdown(backend->handle);
+ SSL_set_connect_state(backend->handle);
+ }
SSL_free(backend->handle);
backend->handle = NULL;
@@ -1466,38 +1904,32 @@
if(backend->ctx) {
SSL_CTX_free(backend->ctx);
backend->ctx = NULL;
+ backend->x509_store_setup = FALSE;
}
-}
-
-/*
- * This function is called when an SSL connection is closed.
- */
-static void ossl_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
-{
- ossl_closeone(data, conn, &conn->ssl[sockindex]);
-#ifndef CURL_DISABLE_PROXY
- ossl_closeone(data, conn, &conn->proxy_ssl[sockindex]);
-#endif
+ if(backend->bio_method) {
+ bio_cf_method_free(backend->bio_method);
+ backend->bio_method = NULL;
+ }
}
/*
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
-static int ossl_shutdown(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static int ossl_shutdown(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
int retval = 0;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
char buf[256]; /* We will use this for the OpenSSL error buffer, so it has
to be at least 256 bytes long. */
unsigned long sslerror;
- ssize_t nread;
+ int nread;
int buffsize;
int err;
bool done = FALSE;
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
int loop = 10;
DEBUGASSERT(backend);
@@ -1509,21 +1941,21 @@
we do not send one. Let's hope other servers do the same... */
if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
- (void)SSL_shutdown(backend->handle);
+ (void)SSL_shutdown(backend->handle);
#endif
if(backend->handle) {
buffsize = (int)sizeof(buf);
while(!done && loop--) {
- int what = SOCKET_READABLE(conn->sock[sockindex],
+ int what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
SSL_SHUTDOWN_TIMEOUT);
if(what > 0) {
ERR_clear_error();
/* Something to read, let's do it and hope that it is the close
notify alert from the server */
- nread = (ssize_t)SSL_read(backend->handle, buf, buffsize);
- err = SSL_get_error(backend->handle, (int)nread);
+ nread = SSL_read(backend->handle, buf, buffsize);
+ err = SSL_get_error(backend->handle, nread);
switch(err) {
case SSL_ERROR_NONE: /* this is not an error */
@@ -1610,7 +2042,7 @@
#else
(void)data;
#endif
-#if !defined(HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED) && \
+#if !defined(HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED) && \
defined(HAVE_ERR_REMOVE_THREAD_STATE)
/* 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
@@ -1638,12 +2070,28 @@
#endif
if(Curl_cert_hostcheck(match_pattern, matchlen, hostname, hostlen)) {
infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"",
- dispname, match_pattern);
+ dispname, match_pattern);
return TRUE;
}
return FALSE;
}
+static CURLcode
+ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ X509 *server_cert, const char *hostname,
+ const char *dispname);
+
+CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ X509 *server_cert)
+{
+ const char *hostname, *dispname;
+ int port;
+
+ (void)conn;
+ Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &dispname, &port);
+ return ossl_verifyhost(data, conn, server_cert, hostname, dispname);
+}
+
/* Quote from RFC2818 section 3.1 "Server Identity"
If a subjectAltName extension of type dNSName is present, that MUST
@@ -1666,8 +2114,10 @@
This function is now used from ngtcp2 (QUIC) as well.
*/
-CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- X509 *server_cert)
+static CURLcode
+ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ X509 *server_cert, const char *hostname,
+ const char *dispname)
{
bool matched = FALSE;
int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
@@ -1681,9 +2131,15 @@
CURLcode result = CURLE_OK;
bool dNSName = FALSE; /* if a dNSName field exists in the cert */
bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */
- const char * const hostname = SSL_HOST_NAME();
- const char * const dispname = SSL_HOST_DISPNAME();
- size_t hostlen = strlen(hostname);
+ size_t hostlen;
+
+ (void)conn;
+ hostlen = strlen(hostname);
+
+#ifndef ENABLE_IPV6
+ /* Silence compiler warnings for unused params */
+ (void) conn;
+#endif
#ifdef ENABLE_IPV6
if(conn->bits.ipv6_ip &&
@@ -1702,7 +2158,7 @@
altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
if(altnames) {
-#ifdef OPENSSL_IS_BORINGSSL
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
size_t numalts;
size_t i;
#else
@@ -1858,10 +2314,11 @@
}
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
- !defined(OPENSSL_NO_OCSP)
-static CURLcode verifystatus(struct Curl_easy *data,
- struct ssl_connect_data *connssl)
+ !defined(OPENSSL_NO_OCSP)
+static CURLcode verifystatus(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
+ struct ssl_connect_data *connssl = cf->ctx;
int i, ocsp_status;
unsigned char *status;
const unsigned char *p;
@@ -1870,7 +2327,8 @@
OCSP_BASICRESP *br = NULL;
X509_STORE *st = NULL;
STACK_OF(X509) *ch = NULL;
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
X509 *cert;
OCSP_CERTID *id = NULL;
int cert_status, crl_reason;
@@ -2031,81 +2489,81 @@
#ifdef SSL2_VERSION_MAJOR
if(ssl_ver == SSL2_VERSION_MAJOR) {
switch(msg) {
- case SSL2_MT_ERROR:
- return "Error";
- case SSL2_MT_CLIENT_HELLO:
- return "Client hello";
- case SSL2_MT_CLIENT_MASTER_KEY:
- return "Client key";
- case SSL2_MT_CLIENT_FINISHED:
- return "Client finished";
- case SSL2_MT_SERVER_HELLO:
- return "Server hello";
- case SSL2_MT_SERVER_VERIFY:
- return "Server verify";
- case SSL2_MT_SERVER_FINISHED:
- return "Server finished";
- case SSL2_MT_REQUEST_CERTIFICATE:
- return "Request CERT";
- case SSL2_MT_CLIENT_CERTIFICATE:
- return "Client CERT";
+ case SSL2_MT_ERROR:
+ return "Error";
+ case SSL2_MT_CLIENT_HELLO:
+ return "Client hello";
+ case SSL2_MT_CLIENT_MASTER_KEY:
+ return "Client key";
+ case SSL2_MT_CLIENT_FINISHED:
+ return "Client finished";
+ case SSL2_MT_SERVER_HELLO:
+ return "Server hello";
+ case SSL2_MT_SERVER_VERIFY:
+ return "Server verify";
+ case SSL2_MT_SERVER_FINISHED:
+ return "Server finished";
+ case SSL2_MT_REQUEST_CERTIFICATE:
+ return "Request CERT";
+ case SSL2_MT_CLIENT_CERTIFICATE:
+ return "Client CERT";
}
}
else
#endif
if(ssl_ver == SSL3_VERSION_MAJOR) {
switch(msg) {
- case SSL3_MT_HELLO_REQUEST:
- return "Hello request";
- case SSL3_MT_CLIENT_HELLO:
- return "Client hello";
- case SSL3_MT_SERVER_HELLO:
- return "Server hello";
+ case SSL3_MT_HELLO_REQUEST:
+ return "Hello request";
+ case SSL3_MT_CLIENT_HELLO:
+ return "Client hello";
+ case SSL3_MT_SERVER_HELLO:
+ return "Server hello";
#ifdef SSL3_MT_NEWSESSION_TICKET
- case SSL3_MT_NEWSESSION_TICKET:
- return "Newsession Ticket";
+ case SSL3_MT_NEWSESSION_TICKET:
+ return "Newsession Ticket";
#endif
- case SSL3_MT_CERTIFICATE:
- return "Certificate";
- case SSL3_MT_SERVER_KEY_EXCHANGE:
- return "Server key exchange";
- case SSL3_MT_CLIENT_KEY_EXCHANGE:
- return "Client key exchange";
- case SSL3_MT_CERTIFICATE_REQUEST:
- return "Request CERT";
- case SSL3_MT_SERVER_DONE:
- return "Server finished";
- case SSL3_MT_CERTIFICATE_VERIFY:
- return "CERT verify";
- case SSL3_MT_FINISHED:
- return "Finished";
+ case SSL3_MT_CERTIFICATE:
+ return "Certificate";
+ case SSL3_MT_SERVER_KEY_EXCHANGE:
+ return "Server key exchange";
+ case SSL3_MT_CLIENT_KEY_EXCHANGE:
+ return "Client key exchange";
+ case SSL3_MT_CERTIFICATE_REQUEST:
+ return "Request CERT";
+ case SSL3_MT_SERVER_DONE:
+ return "Server finished";
+ case SSL3_MT_CERTIFICATE_VERIFY:
+ return "CERT verify";
+ case SSL3_MT_FINISHED:
+ return "Finished";
#ifdef SSL3_MT_CERTIFICATE_STATUS
- case SSL3_MT_CERTIFICATE_STATUS:
- return "Certificate Status";
+ case SSL3_MT_CERTIFICATE_STATUS:
+ return "Certificate Status";
#endif
#ifdef SSL3_MT_ENCRYPTED_EXTENSIONS
- case SSL3_MT_ENCRYPTED_EXTENSIONS:
- return "Encrypted Extensions";
+ case SSL3_MT_ENCRYPTED_EXTENSIONS:
+ return "Encrypted Extensions";
#endif
#ifdef SSL3_MT_SUPPLEMENTAL_DATA
- case SSL3_MT_SUPPLEMENTAL_DATA:
- return "Supplemental data";
+ case SSL3_MT_SUPPLEMENTAL_DATA:
+ return "Supplemental data";
#endif
#ifdef SSL3_MT_END_OF_EARLY_DATA
- case SSL3_MT_END_OF_EARLY_DATA:
- return "End of early data";
+ case SSL3_MT_END_OF_EARLY_DATA:
+ return "End of early data";
#endif
#ifdef SSL3_MT_KEY_UPDATE
- case SSL3_MT_KEY_UPDATE:
- return "Key update";
+ case SSL3_MT_KEY_UPDATE:
+ return "Key update";
#endif
#ifdef SSL3_MT_NEXT_PROTO
- case SSL3_MT_NEXT_PROTO:
- return "Next protocol";
+ case SSL3_MT_NEXT_PROTO:
+ return "Next protocol";
#endif
#ifdef SSL3_MT_MESSAGE_HASH
- case SSL3_MT_MESSAGE_HASH:
- return "Message hash";
+ case SSL3_MT_MESSAGE_HASH:
+ return "Message hash";
#endif
}
}
@@ -2139,18 +2597,15 @@
const void *buf, size_t len, SSL *ssl,
void *userp)
{
- char unknown[32];
- const char *verstr = NULL;
- struct connectdata *conn = userp;
- struct ssl_connect_data *connssl = &conn->ssl[0];
- struct ssl_backend_data *backend = connssl->backend;
+ const char *verstr = "???";
+ struct Curl_cfilter *cf = userp;
struct Curl_easy *data = NULL;
+ char unknown[32];
- DEBUGASSERT(backend);
- data = backend->logger;
-
- if(!conn || !data || !data->set.fdebug ||
- (direction != 0 && direction != 1))
+ if(!cf)
+ return;
+ data = CF_DATA_CURRENT(cf);
+ if(!data || !data->set.fdebug || (direction && direction != 1))
return;
switch(ssl_ver) {
@@ -2195,6 +2650,9 @@
* For TLS 1.3, skip notification of the decrypted inner Content-Type.
*/
if(ssl_ver
+#ifdef SSL3_RT_HEADER
+ && content_type != SSL3_RT_HEADER
+#endif
#ifdef SSL3_RT_INNER_CONTENT_TYPE
&& content_type != SSL3_RT_INNER_CONTENT_TYPE
#endif
@@ -2229,7 +2687,8 @@
msg_name = ssl_msg_type(ssl_ver, msg_type);
}
- txt_len = msnprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n",
+ txt_len = msnprintf(ssl_buf, sizeof(ssl_buf),
+ "%s (%s), %s, %s (%d):\n",
verstr, direction?"OUT":"IN",
tls_rt_name, msg_name, msg_type);
if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) {
@@ -2254,87 +2713,24 @@
/* Check for OpenSSL 1.0.2 which has ALPN support. */
#undef HAS_ALPN
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L \
- && !defined(OPENSSL_NO_TLSEXT)
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L \
+ && !defined(OPENSSL_NO_TLSEXT)
# define HAS_ALPN 1
#endif
-/* Check for OpenSSL 1.0.1 which has NPN support. */
-#undef HAS_NPN
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L \
- && !defined(OPENSSL_NO_TLSEXT) \
- && !defined(OPENSSL_NO_NEXTPROTONEG)
-# define HAS_NPN 1
-#endif
-
-#ifdef HAS_NPN
-
-/*
- * in is a list of length prefixed strings. this function has to select
- * the protocol we want to use from the list and write its string into out.
- */
-
-static int
-select_next_protocol(unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen,
- const char *key, unsigned int keylen)
-{
- unsigned int i;
- for(i = 0; i + keylen <= inlen; i += in[i] + 1) {
- if(memcmp(&in[i + 1], key, keylen) == 0) {
- *out = (unsigned char *) &in[i + 1];
- *outlen = in[i];
- return 0;
- }
- }
- return -1;
-}
-
-static int
-select_next_proto_cb(SSL *ssl,
- unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen,
- void *arg)
-{
- struct Curl_easy *data = (struct Curl_easy *)arg;
- struct connectdata *conn = data->conn;
- (void)ssl;
-
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2 &&
- !select_next_protocol(out, outlen, in, inlen, ALPN_H2, ALPN_H2_LENGTH)) {
- infof(data, "NPN, negotiated HTTP2 (%s)", ALPN_H2);
- conn->negnpn = CURL_HTTP_VERSION_2;
- return SSL_TLSEXT_ERR_OK;
- }
-#endif
-
- if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1,
- ALPN_HTTP_1_1_LENGTH)) {
- infof(data, "NPN, negotiated HTTP1.1");
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- return SSL_TLSEXT_ERR_OK;
- }
-
- infof(data, "NPN, no overlap, use HTTP1.1");
- *out = (unsigned char *)ALPN_HTTP_1_1;
- *outlen = ALPN_HTTP_1_1_LENGTH;
- conn->negnpn = CURL_HTTP_VERSION_1_1;
-
- return SSL_TLSEXT_ERR_OK;
-}
-#endif /* HAS_NPN */
-
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
static CURLcode
-set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
+ossl_set_ssl_version_min_max(struct Curl_cfilter *cf, SSL_CTX *ctx)
{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
/* first, TLS min version... */
- long curl_ssl_version_min = SSL_CONN_CONFIG(version);
+ long curl_ssl_version_min = conn_config->version;
long curl_ssl_version_max;
/* convert curl min SSL version option to OpenSSL constant */
-#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
+#if (defined(OPENSSL_IS_BORINGSSL) || \
+ defined(OPENSSL_IS_AWSLC) || \
+ defined(LIBRESSL_VERSION_NUMBER))
uint16_t ossl_ssl_version_min = 0;
uint16_t ossl_ssl_version_max = 0;
#else
@@ -2342,22 +2738,22 @@
long ossl_ssl_version_max = 0;
#endif
switch(curl_ssl_version_min) {
- case CURL_SSLVERSION_TLSv1: /* TLS 1.x */
- case CURL_SSLVERSION_TLSv1_0:
- ossl_ssl_version_min = TLS1_VERSION;
- break;
- case CURL_SSLVERSION_TLSv1_1:
- ossl_ssl_version_min = TLS1_1_VERSION;
- break;
- case CURL_SSLVERSION_TLSv1_2:
- ossl_ssl_version_min = TLS1_2_VERSION;
- break;
- case CURL_SSLVERSION_TLSv1_3:
+ case CURL_SSLVERSION_TLSv1: /* TLS 1.x */
+ case CURL_SSLVERSION_TLSv1_0:
+ ossl_ssl_version_min = TLS1_VERSION;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ ossl_ssl_version_min = TLS1_1_VERSION;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ 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;
+ ossl_ssl_version_min = TLS1_3_VERSION;
+ break;
#else
- return CURLE_NOT_BUILT_IN;
+ return CURLE_NOT_BUILT_IN;
#endif
}
@@ -2374,33 +2770,33 @@
}
/* ... then, TLS max version */
- curl_ssl_version_max = SSL_CONN_CONFIG(version_max);
+ curl_ssl_version_max = conn_config->version_max;
/* convert curl max SSL version option to OpenSSL constant */
switch(curl_ssl_version_max) {
- case CURL_SSLVERSION_MAX_TLSv1_0:
- ossl_ssl_version_max = TLS1_VERSION;
- break;
- case CURL_SSLVERSION_MAX_TLSv1_1:
- ossl_ssl_version_max = TLS1_1_VERSION;
- break;
- case CURL_SSLVERSION_MAX_TLSv1_2:
- ossl_ssl_version_max = TLS1_2_VERSION;
- break;
+ case CURL_SSLVERSION_MAX_TLSv1_0:
+ ossl_ssl_version_max = TLS1_VERSION;
+ break;
+ case CURL_SSLVERSION_MAX_TLSv1_1:
+ ossl_ssl_version_max = TLS1_1_VERSION;
+ break;
+ 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;
+ 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:
- /* SSL_CTX_set_max_proto_version states that:
- setting the maximum to 0 will enable
- protocol versions up to the highest version
- supported by the library */
- ossl_ssl_version_max = 0;
- break;
+ case CURL_SSLVERSION_MAX_NONE: /* none selected */
+ case CURL_SSLVERSION_MAX_DEFAULT: /* max selected */
+ default:
+ /* SSL_CTX_set_max_proto_version states that:
+ setting the maximum to 0 will enable
+ protocol versions up to the highest version
+ supported by the library */
+ ossl_ssl_version_max = 0;
+ break;
}
if(!SSL_CTX_set_max_proto_version(ctx, ossl_ssl_version_max)) {
@@ -2411,7 +2807,7 @@
}
#endif
-#ifdef OPENSSL_IS_BORINGSSL
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
typedef uint32_t ctx_option_t;
#elif OPENSSL_VERSION_NUMBER >= 0x30000000L
typedef uint64_t ctx_option_t;
@@ -2421,75 +2817,76 @@
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) /* 1.1.0 */
static CURLcode
-set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
- struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- long ssl_version = SSL_CONN_CONFIG(version);
- long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ 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's unused. */
switch(ssl_version) {
- case CURL_SSLVERSION_TLSv1_3:
+ case CURL_SSLVERSION_TLSv1_3:
#ifdef TLS1_3_VERSION
- {
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- DEBUGASSERT(backend);
- SSL_CTX_set_max_proto_version(backend->ctx, TLS1_3_VERSION);
- *ctx_options |= SSL_OP_NO_TLSv1_2;
- }
+ {
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
+ DEBUGASSERT(backend);
+ SSL_CTX_set_max_proto_version(backend->ctx, TLS1_3_VERSION);
+ *ctx_options |= SSL_OP_NO_TLSv1_2;
+ }
#else
- (void)sockindex;
- (void)ctx_options;
- failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
- return CURLE_NOT_BUILT_IN;
+ (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:
+ /* FALLTHROUGH */
+ case CURL_SSLVERSION_TLSv1_2:
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- *ctx_options |= SSL_OP_NO_TLSv1_1;
+ *ctx_options |= SSL_OP_NO_TLSv1_1;
#else
- failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
- return CURLE_NOT_BUILT_IN;
+ failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
+ return CURLE_NOT_BUILT_IN;
#endif
- /* FALLTHROUGH */
- case CURL_SSLVERSION_TLSv1_1:
+ /* FALLTHROUGH */
+ case CURL_SSLVERSION_TLSv1_1:
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- *ctx_options |= SSL_OP_NO_TLSv1;
+ *ctx_options |= SSL_OP_NO_TLSv1;
#else
- failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
- return CURLE_NOT_BUILT_IN;
+ failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
+ return CURLE_NOT_BUILT_IN;
#endif
- /* FALLTHROUGH */
- case CURL_SSLVERSION_TLSv1_0:
- case CURL_SSLVERSION_TLSv1:
- break;
+ /* FALLTHROUGH */
+ case CURL_SSLVERSION_TLSv1_0:
+ case CURL_SSLVERSION_TLSv1:
+ break;
}
switch(ssl_version_max) {
- case CURL_SSLVERSION_MAX_TLSv1_0:
+ case CURL_SSLVERSION_MAX_TLSv1_0:
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- *ctx_options |= SSL_OP_NO_TLSv1_1;
+ *ctx_options |= SSL_OP_NO_TLSv1_1;
#endif
- /* FALLTHROUGH */
- case CURL_SSLVERSION_MAX_TLSv1_1:
+ /* FALLTHROUGH */
+ case CURL_SSLVERSION_MAX_TLSv1_1:
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- *ctx_options |= SSL_OP_NO_TLSv1_2;
+ *ctx_options |= SSL_OP_NO_TLSv1_2;
#endif
- /* FALLTHROUGH */
- case CURL_SSLVERSION_MAX_TLSv1_2:
+ /* FALLTHROUGH */
+ case CURL_SSLVERSION_MAX_TLSv1_2:
#ifdef TLS1_3_VERSION
- *ctx_options |= SSL_OP_NO_TLSv1_3;
+ *ctx_options |= SSL_OP_NO_TLSv1_3;
#endif
- break;
- case CURL_SSLVERSION_MAX_TLSv1_3:
+ break;
+ case CURL_SSLVERSION_MAX_TLSv1_3:
#ifdef TLS1_3_VERSION
- break;
+ break;
#else
- failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
- return CURLE_NOT_BUILT_IN;
+ failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
+ return CURLE_NOT_BUILT_IN;
#endif
}
return CURLE_OK;
@@ -2502,31 +2899,23 @@
static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
{
int res = 0;
- struct connectdata *conn;
struct Curl_easy *data;
- int sockindex;
- curl_socket_t *sockindex_ptr;
- int data_idx = ossl_get_ssl_data_index();
- int connectdata_idx = ossl_get_ssl_conn_index();
- int sockindex_idx = ossl_get_ssl_sockindex_index();
- int proxy_idx = ossl_get_proxy_index();
+ struct Curl_cfilter *cf;
+ const struct ssl_config_data *config;
+ struct ssl_connect_data *connssl;
bool isproxy;
- if(data_idx < 0 || connectdata_idx < 0 || sockindex_idx < 0 || proxy_idx < 0)
- return 0;
-
- conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx);
- data = (struct Curl_easy *) SSL_get_ex_data(ssl, data_idx);
+ cf = (struct Curl_cfilter*) SSL_get_app_data(ssl);
+ connssl = cf? cf->ctx : NULL;
+ data = connssl? CF_DATA_CURRENT(cf) : NULL;
/* The sockindex has been stored as a pointer to an array element */
- sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx);
- if(!conn || !data || !sockindex_ptr)
+ if(!cf || !data)
return 0;
- sockindex = (int)(sockindex_ptr - conn->sock);
+ isproxy = Curl_ssl_cf_is_proxy(cf);
- isproxy = SSL_get_ex_data(ssl, proxy_idx) ? TRUE : FALSE;
-
- if(SSL_SET_OPTION(primary.sessionid)) {
+ config = Curl_ssl_cf_get_config(cf, data);
+ if(config->primary.sessionid) {
bool incache;
bool added = FALSE;
void *old_ssl_sessionid = NULL;
@@ -2535,8 +2924,7 @@
if(isproxy)
incache = FALSE;
else
- incache = !(Curl_ssl_getsessionid(data, conn, isproxy,
- &old_ssl_sessionid, NULL, sockindex));
+ incache = !(Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL));
if(incache) {
if(old_ssl_sessionid != ssl_sessionid) {
infof(data, "old SSL session ID is stale, removing");
@@ -2546,8 +2934,8 @@
}
if(!incache) {
- if(!Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid,
- 0 /* unknown size */, sockindex, &added)) {
+ if(!Curl_ssl_addsessionid(cf, data, ssl_sessionid,
+ 0 /* unknown size */, &added)) {
if(added) {
/* the session has been put into the session cache */
res = 1;
@@ -2562,7 +2950,7 @@
return res;
}
-static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
+static CURLcode load_cacert_from_memory(X509_STORE *store,
const struct curl_blob *ca_info_blob)
{
/* these need to be freed at the end */
@@ -2571,16 +2959,11 @@
/* everything else is just a reference */
int i, count = 0;
- X509_STORE *cts = NULL;
X509_INFO *itmp = NULL;
if(ca_info_blob->len > (size_t)INT_MAX)
return CURLE_SSL_CACERT_BADFILE;
- cts = SSL_CTX_get_cert_store(ctx);
- if(!cts)
- return CURLE_OUT_OF_MEMORY;
-
cbio = BIO_new_mem_buf(ca_info_blob->data, (int)ca_info_blob->len);
if(!cbio)
return CURLE_OUT_OF_MEMORY;
@@ -2595,7 +2978,7 @@
for(i = 0; i < (int)sk_X509_INFO_num(inf); ++i) {
itmp = sk_X509_INFO_value(inf, i);
if(itmp->x509) {
- if(X509_STORE_add_cert(cts, itmp->x509)) {
+ if(X509_STORE_add_cert(store, itmp->x509)) {
++count;
}
else {
@@ -2605,7 +2988,7 @@
}
}
if(itmp->crl) {
- if(X509_STORE_add_crl(cts, itmp->crl)) {
+ if(X509_STORE_add_crl(store, itmp->crl)) {
++count;
}
else {
@@ -2620,24 +3003,430 @@
BIO_free(cbio);
/* if we didn't end up importing anything, treat that as an error */
- return (count > 0 ? CURLE_OK : CURLE_SSL_CACERT_BADFILE);
+ return (count > 0) ? CURLE_OK : CURLE_SSL_CACERT_BADFILE;
}
-static CURLcode ossl_connect_step1(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode populate_x509_store(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ X509_STORE *store)
+{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ CURLcode result = CURLE_OK;
+ X509_LOOKUP *lookup = NULL;
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+ const char * const ssl_cafile =
+ /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
+ (ca_info_blob ? NULL : conn_config->CAfile);
+ const char * const ssl_capath = conn_config->CApath;
+ const char * const ssl_crlfile = ssl_config->primary.CRLfile;
+ const bool verifypeer = conn_config->verifypeer;
+ bool imported_native_ca = false;
+ bool imported_ca_info_blob = false;
+
+ if(!store)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(verifypeer) {
+#if defined(USE_WIN32_CRYPTO)
+ /* Import certificates from the Windows root certificate store if
+ requested.
+ https://stackoverflow.com/questions/9507184/
+ https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
+ https://datatracker.ietf.org/doc/html/rfc5280 */
+ if(ssl_config->native_ca_store) {
+ HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
+
+ if(hStore) {
+ PCCERT_CONTEXT pContext = NULL;
+ /* The array of enhanced key usage OIDs will vary per certificate and
+ is declared outside of the loop so that rather than malloc/free each
+ iteration we can grow it with realloc, when necessary. */
+ CERT_ENHKEY_USAGE *enhkey_usage = NULL;
+ DWORD enhkey_usage_size = 0;
+
+ /* This loop makes a best effort to import all valid certificates from
+ the MS root store. If a certificate cannot be imported it is
+ skipped. 'result' is used to store only hard-fail conditions (such
+ as out of memory) that cause an early break. */
+ result = CURLE_OK;
+ for(;;) {
+ X509 *x509;
+ FILETIME now;
+ BYTE key_usage[2];
+ DWORD req_size;
+ const unsigned char *encoded_cert;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ char cert_name[256];
+#endif
+
+ pContext = CertEnumCertificatesInStore(hStore, pContext);
+ if(!pContext)
+ break;
+
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
+ NULL, cert_name, sizeof(cert_name))) {
+ strcpy(cert_name, "Unknown");
+ }
+ infof(data, "SSL: Checking cert \"%s\"", cert_name);
+#endif
+ encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
+ if(!encoded_cert)
+ continue;
+
+ GetSystemTimeAsFileTime(&now);
+ if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
+ CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
+ continue;
+
+ /* If key usage exists check for signing attribute */
+ if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
+ pContext->pCertInfo,
+ key_usage, sizeof(key_usage))) {
+ if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
+ continue;
+ }
+ else if(GetLastError())
+ continue;
+
+ /* If enhanced key usage exists check for server auth attribute.
+ *
+ * Note "In a Microsoft environment, a certificate might also have
+ * EKU extended properties that specify valid uses for the
+ * certificate." The call below checks both, and behavior varies
+ * depending on what is found. For more details see
+ * CertGetEnhancedKeyUsage doc.
+ */
+ if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
+ if(req_size && req_size > enhkey_usage_size) {
+ void *tmp = realloc(enhkey_usage, req_size);
+
+ if(!tmp) {
+ failf(data, "SSL: Out of memory allocating for OID list");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
+ enhkey_usage_size = req_size;
+ }
+
+ if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
+ if(!enhkey_usage->cUsageIdentifier) {
+ /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate
+ is good for all uses. If it returns zero, the certificate
+ has no valid uses." */
+ if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
+ continue;
+ }
+ else {
+ DWORD i;
+ bool found = false;
+
+ for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
+ if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
+ enhkey_usage->rgpszUsageIdentifier[i])) {
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ continue;
+ }
+ }
+ else
+ continue;
+ }
+ else
+ continue;
+
+ x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
+ if(!x509)
+ continue;
+
+ /* Try to import the certificate. This may fail for legitimate
+ reasons such as duplicate certificate, which is allowed by MS but
+ not OpenSSL. */
+ if(X509_STORE_add_cert(store, x509) == 1) {
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ infof(data, "SSL: Imported cert \"%s\"", cert_name);
+#endif
+ imported_native_ca = true;
+ }
+ X509_free(x509);
+ }
+
+ free(enhkey_usage);
+ CertFreeCertificateContext(pContext);
+ CertCloseStore(hStore, 0);
+
+ if(result)
+ return result;
+ }
+ if(imported_native_ca)
+ infof(data, "successfully imported Windows CA store");
+ else
+ infof(data, "error importing Windows CA store, continuing anyway");
+ }
+#endif
+ if(ca_info_blob) {
+ result = load_cacert_from_memory(store, ca_info_blob);
+ if(result) {
+ failf(data, "error importing CA certificate blob");
+ return result;
+ }
+ else {
+ imported_ca_info_blob = true;
+ infof(data, "successfully imported CA certificate blob");
+ }
+ }
+
+ if(ssl_cafile || ssl_capath) {
+#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+ /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
+ if(ssl_cafile && !X509_STORE_load_file(store, ssl_cafile)) {
+ if(!imported_native_ca && !imported_ca_info_blob) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate file: %s", ssl_cafile);
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else
+ infof(data, "error setting certificate file, continuing anyway");
+ }
+ if(ssl_capath && !X509_STORE_load_path(store, ssl_capath)) {
+ if(!imported_native_ca && !imported_ca_info_blob) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate path: %s", ssl_capath);
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else
+ infof(data, "error setting certificate path, continuing anyway");
+ }
+#else
+ /* tell OpenSSL where to find CA certificates that are used to verify the
+ server's certificate. */
+ if(!X509_STORE_load_locations(store, ssl_cafile, ssl_capath)) {
+ if(!imported_native_ca && !imported_ca_info_blob) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ infof(data, "error setting certificate verify locations,"
+ " continuing anyway");
+ }
+ }
+#endif
+ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+ }
+
+#ifdef CURL_CA_FALLBACK
+ if(!ssl_cafile && !ssl_capath &&
+ !imported_native_ca && !imported_ca_info_blob) {
+ /* verifying the peer without any CA certificates won't
+ work so use openssl's built-in default as fallback */
+ X509_STORE_set_default_paths(store);
+ }
+#endif
+ }
+
+ if(ssl_crlfile) {
+ /* tell OpenSSL where to find CRL file that is used to check certificate
+ * revocation */
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
+ if(!lookup ||
+ (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
+ failf(data, "error loading CRL file: %s", ssl_crlfile);
+ return CURLE_SSL_CRL_BADFILE;
+ }
+ /* Everything is fine. */
+ infof(data, "successfully loaded CRL file:");
+ X509_STORE_set_flags(store,
+ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+
+ infof(data, " CRLfile: %s", ssl_crlfile);
+ }
+
+ if(verifypeer) {
+ /* Try building a chain using issuers in the trusted store first to avoid
+ problems with server-sent legacy intermediates. Newer versions of
+ OpenSSL do alternate chain checking by default but we do not know how to
+ determine that in a reliable manner.
+ https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
+ */
+#if defined(X509_V_FLAG_TRUSTED_FIRST)
+ X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST);
+#endif
+#ifdef X509_V_FLAG_PARTIAL_CHAIN
+ 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.
+
+ 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);
+ }
+#endif
+ }
+
+ return result;
+}
+
+#if defined(HAVE_SSL_X509_STORE_SHARE)
+static bool cached_x509_store_expired(const struct Curl_easy *data,
+ const struct multi_ssl_backend_data *mb)
+{
+ const struct ssl_general_config *cfg = &data->set.general_ssl;
+ struct curltime now = Curl_now();
+ timediff_t elapsed_ms = Curl_timediff(now, mb->time);
+ timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
+
+ if(timeout_ms < 0)
+ return false;
+
+ return elapsed_ms >= timeout_ms;
+}
+
+static bool cached_x509_store_different(
+ struct Curl_cfilter *cf,
+ const struct multi_ssl_backend_data *mb)
+{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!mb->CAfile || !conn_config->CAfile)
+ return mb->CAfile != conn_config->CAfile;
+
+ return strcmp(mb->CAfile, conn_config->CAfile);
+}
+
+static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
+ X509_STORE *store = NULL;
+
+ if(multi &&
+ multi->ssl_backend_data &&
+ multi->ssl_backend_data->store &&
+ !cached_x509_store_expired(data, multi->ssl_backend_data) &&
+ !cached_x509_store_different(cf, multi->ssl_backend_data)) {
+ store = multi->ssl_backend_data->store;
+ }
+
+ return store;
+}
+
+static void set_cached_x509_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data,
+ X509_STORE *store)
+{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
+ struct multi_ssl_backend_data *mbackend;
+
+ if(!multi)
+ return;
+
+ if(!multi->ssl_backend_data) {
+ multi->ssl_backend_data = calloc(1, sizeof(struct multi_ssl_backend_data));
+ if(!multi->ssl_backend_data)
+ return;
+ }
+
+ mbackend = multi->ssl_backend_data;
+
+ if(X509_STORE_up_ref(store)) {
+ char *CAfile = NULL;
+
+ if(conn_config->CAfile) {
+ CAfile = strdup(conn_config->CAfile);
+ if(!CAfile) {
+ X509_STORE_free(store);
+ return;
+ }
+ }
+
+ if(mbackend->store) {
+ X509_STORE_free(mbackend->store);
+ free(mbackend->CAfile);
+ }
+
+ mbackend->time = Curl_now();
+ mbackend->store = store;
+ mbackend->CAfile = CAfile;
+ }
+}
+
+CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ SSL_CTX *ssl_ctx)
+{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ CURLcode result = CURLE_OK;
+ X509_STORE *cached_store;
+ bool cache_criteria_met;
+
+ /* 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. */
+ cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) &&
+ conn_config->verifypeer &&
+ !conn_config->CApath &&
+ !conn_config->ca_info_blob &&
+ !ssl_config->primary.CRLfile &&
+ !ssl_config->native_ca_store;
+
+ cached_store = get_cached_x509_store(cf, data);
+ if(cached_store && cache_criteria_met && X509_STORE_up_ref(cached_store)) {
+ SSL_CTX_set_cert_store(ssl_ctx, cached_store);
+ }
+ else {
+ X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
+
+ result = populate_x509_store(cf, data, store);
+ if(result == CURLE_OK && cache_criteria_met) {
+ set_cached_x509_store(cf, data, store);
+ }
+ }
+
+ return result;
+}
+#else /* HAVE_SSL_X509_STORE_SHARE */
+CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ SSL_CTX *ssl_ctx)
+{
+ X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
+
+ return populate_x509_store(cf, data, store);
+}
+#endif /* HAVE_SSL_X509_STORE_SHARE */
+
+static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
char *ciphers;
SSL_METHOD_QUAL SSL_METHOD *req_method = NULL;
- X509_LOOKUP *lookup = NULL;
- curl_socket_t sockfd = conn->sock[sockindex];
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
ctx_option_t ctx_options = 0;
void *ssl_sessionid = NULL;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ BIO *bio;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
bool sni;
- const char * const hostname = SSL_HOST_NAME();
+ const char *hostname = connssl->hostname;
#ifdef ENABLE_IPV6
struct in6_addr addr;
@@ -2645,23 +3434,14 @@
struct in_addr addr;
#endif
#endif
- const long int ssl_version = SSL_CONN_CONFIG(version);
-#ifdef USE_OPENSSL_SRP
- const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(primary.authtype);
-#endif
- char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
- const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
- const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
- const char * const ssl_cert_type = SSL_SET_OPTION(cert_type);
- const char * const ssl_cafile =
- /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
- (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
- const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
- const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile);
+ const long int ssl_version = conn_config->version;
+ char * const ssl_cert = ssl_config->primary.clientcert;
+ const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
+ const char * const ssl_cert_type = ssl_config->cert_type;
+ const bool verifypeer = conn_config->verifypeer;
char error_buffer[256];
- struct ssl_backend_data *backend = connssl->backend;
- bool imported_native_ca = false;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
DEBUGASSERT(backend);
@@ -2671,7 +3451,7 @@
if(result)
return result;
- SSL_SET_OPTION_LVALUE(certverifyresult) = !X509_V_OK;
+ ssl_config->certverifyresult = !X509_V_OK;
/* check to see if we've been told to use an explicit SSL/TLS version */
@@ -2701,7 +3481,12 @@
return CURLE_SSL_CONNECT_ERROR;
}
- DEBUGASSERT(!backend->ctx);
+ if(backend->ctx) {
+ /* This happens when an error was encountered before in this
+ * step and we are called to do it again. Get rid of any leftover
+ * from the previous call. */
+ ossl_close(cf, data);
+ }
backend->ctx = SSL_CTX_new(req_method);
if(!backend->ctx) {
@@ -2718,8 +3503,7 @@
if(data->set.fdebug && data->set.verbose) {
/* the SSL trace callback is only used for verbose logging */
SSL_CTX_set_msg_callback(backend->ctx, ossl_trace);
- SSL_CTX_set_msg_callback_arg(backend->ctx, conn);
- set_logger(conn, data);
+ SSL_CTX_set_msg_callback_arg(backend->ctx, cf);
}
#endif
@@ -2777,80 +3561,55 @@
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
/* unless the user explicitly asks to allow the protocol vulnerability we
use the work-around */
- if(!SSL_SET_OPTION(enable_beast))
+ if(!ssl_config->enable_beast)
ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#endif
switch(ssl_version) {
- case CURL_SSLVERSION_SSLv2:
- case CURL_SSLVERSION_SSLv3:
- return CURLE_NOT_BUILT_IN;
+ case CURL_SSLVERSION_SSLv2:
+ case CURL_SSLVERSION_SSLv3:
+ return CURLE_NOT_BUILT_IN;
/* "--tlsv<x.y>" options mean TLS >= version <x.y> */
- case CURL_SSLVERSION_DEFAULT:
- 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 */
- case CURL_SSLVERSION_TLSv1_3: /* TLS >= version 1.3 */
- /* asking for any TLS version as the minimum, means no SSL versions
- allowed */
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
+ case CURL_SSLVERSION_DEFAULT:
+ 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 */
+ case CURL_SSLVERSION_TLSv1_3: /* TLS >= version 1.3 */
+ /* asking for any TLS version as the minimum, means no SSL versions
+ allowed */
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
- result = set_ssl_version_min_max(backend->ctx, conn);
+ result = ossl_set_ssl_version_min_max(cf, backend->ctx);
#else
- result = set_ssl_version_min_max_legacy(&ctx_options, data, conn,
- sockindex);
+ result = ossl_set_ssl_version_min_max_legacy(&ctx_options, cf, data);
#endif
- if(result != CURLE_OK)
- return result;
- break;
+ if(result != CURLE_OK)
+ return result;
+ break;
- default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
- return CURLE_SSL_CONNECT_ERROR;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
}
SSL_CTX_set_options(backend->ctx, ctx_options);
-#ifdef HAS_NPN
- if(conn->bits.tls_enable_npn)
- SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, data);
-#endif
-
#ifdef HAS_ALPN
- if(conn->bits.tls_enable_alpn) {
- int cur = 0;
- unsigned char protocols[128];
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2
-#ifndef CURL_DISABLE_PROXY
- && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
-#endif
- ) {
- protocols[cur++] = ALPN_H2_LENGTH;
-
- memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH);
- cur += ALPN_H2_LENGTH;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
- }
-#endif
-
- protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
- memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
- cur += ALPN_HTTP_1_1_LENGTH;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
-
- /* expects length prefixed preference ordered list of protocols in wire
- * format
- */
- if(SSL_CTX_set_alpn_protos(backend->ctx, protocols, cur)) {
+ result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
+ if(result ||
+ SSL_CTX_set_alpn_protos(backend->ctx, proto.data, proto.len)) {
failf(data, "Error setting ALPN");
return CURLE_SSL_CONNECT_ERROR;
}
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
#endif
@@ -2858,15 +3617,15 @@
if(!result &&
!cert_stuff(data, backend->ctx,
ssl_cert, ssl_cert_blob, ssl_cert_type,
- SSL_SET_OPTION(key), SSL_SET_OPTION(key_blob),
- SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd)))
+ ssl_config->key, ssl_config->key_blob,
+ ssl_config->key_type, ssl_config->key_passwd))
result = CURLE_SSL_CERTPROBLEM;
if(result)
/* failf() is already done in cert_stuff() */
return result;
}
- ciphers = SSL_CONN_CONFIG(cipher_list);
+ ciphers = conn_config->cipher_list;
if(!ciphers)
ciphers = (char *)DEFAULT_CIPHER_SELECTION;
if(ciphers) {
@@ -2879,7 +3638,7 @@
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
{
- char *ciphers13 = SSL_CONN_CONFIG(cipher_list13);
+ char *ciphers13 = conn_config->cipher_list13;
if(ciphers13) {
if(!SSL_CTX_set_ciphersuites(backend->ctx, ciphers13)) {
failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13);
@@ -2897,7 +3656,7 @@
#ifdef HAVE_SSL_CTX_SET_EC_CURVES
{
- char *curves = SSL_CONN_CONFIG(curves);
+ char *curves = conn_config->curves;
if(curves) {
if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) {
failf(data, "failed setting curves list: '%s'", curves);
@@ -2908,10 +3667,9 @@
#endif
#ifdef USE_OPENSSL_SRP
- if((ssl_authtype == CURL_TLSAUTH_SRP) &&
- Curl_allow_auth_to_host(data)) {
- char * const ssl_username = SSL_SET_OPTION(primary.username);
- char * const ssl_password = SSL_SET_OPTION(primary.password);
+ if(ssl_config->primary.username && Curl_auth_allowed_to_host(data)) {
+ char * const ssl_username = ssl_config->primary.username;
+ char * const ssl_password = ssl_config->primary.password;
infof(data, "Using TLS-SRP username: %s", ssl_username);
if(!SSL_CTX_set_srp_username(backend->ctx, ssl_username)) {
@@ -2922,7 +3680,7 @@
failf(data, "failed setting SRP password");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- if(!SSL_CONN_CONFIG(cipher_list)) {
+ if(!conn_config->cipher_list) {
infof(data, "Setting cipher list SRP");
if(!SSL_CTX_set_cipher_list(backend->ctx, "SRP")) {
@@ -2933,250 +3691,6 @@
}
#endif
-
-#if defined(USE_WIN32_CRYPTO)
- /* Import certificates from the Windows root certificate store if requested.
- https://stackoverflow.com/questions/9507184/
- https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
- https://datatracker.ietf.org/doc/html/rfc5280 */
- if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) &&
- (SSL_SET_OPTION(native_ca_store))) {
- X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
- HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
-
- if(hStore) {
- PCCERT_CONTEXT pContext = NULL;
- /* The array of enhanced key usage OIDs will vary per certificate and is
- declared outside of the loop so that rather than malloc/free each
- iteration we can grow it with realloc, when necessary. */
- CERT_ENHKEY_USAGE *enhkey_usage = NULL;
- DWORD enhkey_usage_size = 0;
-
- /* This loop makes a best effort to import all valid certificates from
- the MS root store. If a certificate cannot be imported it is skipped.
- 'result' is used to store only hard-fail conditions (such as out of
- memory) that cause an early break. */
- result = CURLE_OK;
- for(;;) {
- X509 *x509;
- FILETIME now;
- BYTE key_usage[2];
- DWORD req_size;
- const unsigned char *encoded_cert;
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- char cert_name[256];
-#endif
-
- pContext = CertEnumCertificatesInStore(hStore, pContext);
- if(!pContext)
- break;
-
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
- NULL, cert_name, sizeof(cert_name))) {
- strcpy(cert_name, "Unknown");
- }
- infof(data, "SSL: Checking cert \"%s\"", cert_name);
-#endif
-
- encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
- if(!encoded_cert)
- continue;
-
- GetSystemTimeAsFileTime(&now);
- if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
- CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
- continue;
-
- /* If key usage exists check for signing attribute */
- if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
- pContext->pCertInfo,
- key_usage, sizeof(key_usage))) {
- if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
- continue;
- }
- else if(GetLastError())
- continue;
-
- /* If enhanced key usage exists check for server auth attribute.
- *
- * Note "In a Microsoft environment, a certificate might also have EKU
- * extended properties that specify valid uses for the certificate."
- * The call below checks both, and behavior varies depending on what is
- * found. For more details see CertGetEnhancedKeyUsage doc.
- */
- if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
- if(req_size && req_size > enhkey_usage_size) {
- void *tmp = realloc(enhkey_usage, req_size);
-
- if(!tmp) {
- failf(data, "SSL: Out of memory allocating for OID list");
- result = CURLE_OUT_OF_MEMORY;
- break;
- }
-
- enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
- enhkey_usage_size = req_size;
- }
-
- if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
- if(!enhkey_usage->cUsageIdentifier) {
- /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate is
- good for all uses. If it returns zero, the certificate has no
- valid uses." */
- if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
- continue;
- }
- else {
- DWORD i;
- bool found = false;
-
- for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
- if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
- enhkey_usage->rgpszUsageIdentifier[i])) {
- found = true;
- break;
- }
- }
-
- if(!found)
- continue;
- }
- }
- else
- continue;
- }
- else
- continue;
-
- x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
- if(!x509)
- continue;
-
- /* Try to import the certificate. This may fail for legitimate reasons
- such as duplicate certificate, which is allowed by MS but not
- OpenSSL. */
- if(X509_STORE_add_cert(store, x509) == 1) {
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- infof(data, "SSL: Imported cert \"%s\"", cert_name);
-#endif
- imported_native_ca = true;
- }
- X509_free(x509);
- }
-
- free(enhkey_usage);
- CertFreeCertificateContext(pContext);
- CertCloseStore(hStore, 0);
-
- if(result)
- return result;
- }
- if(imported_native_ca)
- infof(data, "successfully imported Windows CA store");
- else
- infof(data, "error importing Windows CA store, continuing anyway");
- }
-#endif
-
- if(ca_info_blob) {
- result = load_cacert_from_memory(backend->ctx, ca_info_blob);
- if(result) {
- if(result == CURLE_OUT_OF_MEMORY ||
- (verifypeer && !imported_native_ca)) {
- failf(data, "error importing CA certificate blob");
- return result;
- }
- /* Only warn if no certificate verification is required. */
- infof(data, "error importing CA certificate blob, continuing anyway");
- }
- }
-
- if(verifypeer && !imported_native_ca && (ssl_cafile || ssl_capath)) {
-#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
- /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
- if(ssl_cafile &&
- !SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate file: %s", ssl_cafile);
- return CURLE_SSL_CACERT_BADFILE;
- }
- if(ssl_capath &&
- !SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate path: %s", ssl_capath);
- return CURLE_SSL_CACERT_BADFILE;
- }
-#else
- /* tell OpenSSL where to find CA certificates that are used to verify the
- server's certificate. */
- if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:"
- " CAfile: %s CApath: %s",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
- return CURLE_SSL_CACERT_BADFILE;
- }
-#endif
- infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
- infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
- }
-
-#ifdef CURL_CA_FALLBACK
- if(verifypeer &&
- !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) {
- /* verifying the peer without any CA certificates won't
- work so use openssl's built-in default as fallback */
- SSL_CTX_set_default_verify_paths(backend->ctx);
- }
-#endif
-
- if(ssl_crlfile) {
- /* tell OpenSSL where to find CRL file that is used to check certificate
- * revocation */
- lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(backend->ctx),
- X509_LOOKUP_file());
- if(!lookup ||
- (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
- failf(data, "error loading CRL file: %s", ssl_crlfile);
- return CURLE_SSL_CRL_BADFILE;
- }
- /* Everything is fine. */
- infof(data, "successfully loaded CRL file:");
- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
- X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
-
- infof(data, " CRLfile: %s", ssl_crlfile);
- }
-
- if(verifypeer) {
- /* Try building a chain using issuers in the trusted store first to avoid
- problems with server-sent legacy intermediates. Newer versions of
- OpenSSL do alternate chain checking by default but we do not know how to
- determine that in a reliable manner.
- https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
- */
-#if defined(X509_V_FLAG_TRUSTED_FIRST)
- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
- X509_V_FLAG_TRUSTED_FIRST);
-#endif
-#ifdef X509_V_FLAG_PARTIAL_CHAIN
- if(!SSL_SET_OPTION(no_partialchain) && !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.
-
- Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we
- cannot do partial chains with a CRL check.
- */
- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
- X509_V_FLAG_PARTIAL_CHAIN);
- }
-#endif
- }
-
/* OpenSSL always tries to verify the peer, this only says whether it should
* fail to connect if the verification fails, or if it should continue
* anyway. In the latter case the result of the verification is checked with
@@ -3196,7 +3710,8 @@
* an internal session cache.
*/
SSL_CTX_set_session_cache_mode(backend->ctx,
- SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL);
+ SSL_SESS_CACHE_CLIENT |
+ SSL_SESS_CACHE_NO_INTERNAL);
SSL_CTX_sess_set_new_cb(backend->ctx, ossl_new_session_cb);
/* give application a chance to interfere with SSL set up. */
@@ -3220,13 +3735,16 @@
return CURLE_OUT_OF_MEMORY;
}
+ SSL_set_app_data(backend->handle, cf);
+
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
- !defined(OPENSSL_NO_OCSP)
- if(SSL_CONN_CONFIG(verifystatus))
+ !defined(OPENSSL_NO_OCSP)
+ if(conn_config->verifystatus)
SSL_set_tlsext_status_type(backend->handle, TLSEXT_STATUSTYPE_ocsp);
#endif
-#if defined(OPENSSL_IS_BORINGSSL) && defined(ALLOW_RENEG)
+#if (defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)) && \
+ defined(ALLOW_RENEG)
SSL_set_renegotiate_mode(backend->handle, ssl_renegotiate_freely);
#endif
@@ -3247,18 +3765,11 @@
}
#endif
- if(!ossl_associate_connection(data, conn, sockindex)) {
- /* Maybe the internal errors of SSL_get_ex_new_index or SSL_set_ex_data */
- failf(data, "SSL: ossl_associate_connection failed: %s",
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)));
- return CURLE_SSL_CONNECT_ERROR;
- }
+ SSL_set_app_data(backend->handle, cf);
- if(SSL_SET_OPTION(primary.sessionid)) {
+ if(ssl_config->primary.sessionid) {
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE,
- &ssl_sessionid, NULL, sockindex)) {
+ if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) {
/* we got a session id, use it! */
if(!SSL_set_session(backend->handle, ssl_sessionid)) {
Curl_ssl_sessionid_unlock(data);
@@ -3273,40 +3784,39 @@
Curl_ssl_sessionid_unlock(data);
}
-#ifndef CURL_DISABLE_PROXY
- if(conn->proxy_ssl[sockindex].use) {
- BIO *const bio = BIO_new(BIO_f_ssl());
- struct ssl_backend_data *proxy_backend;
- SSL* handle = NULL;
- proxy_backend = conn->proxy_ssl[sockindex].backend;
- DEBUGASSERT(proxy_backend);
- handle = proxy_backend->handle;
- DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
- DEBUGASSERT(handle != NULL);
- DEBUGASSERT(bio != NULL);
- BIO_set_ssl(bio, handle, FALSE);
- SSL_set_bio(backend->handle, bio, bio);
- }
- else
-#endif
- if(!SSL_set_fd(backend->handle, (int)sockfd)) {
- /* pass the raw socket into the SSL layers */
- failf(data, "SSL: SSL_set_fd failed: %s",
- ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
- return CURLE_SSL_CONNECT_ERROR;
- }
+ backend->bio_method = bio_cf_method_create();
+ if(!backend->bio_method)
+ return CURLE_OUT_OF_MEMORY;
+ bio = BIO_new(backend->bio_method);
+ if(!bio)
+ return CURLE_OUT_OF_MEMORY;
+ BIO_set_data(bio, cf);
+#ifdef HAVE_SSL_SET0_WBIO
+ /* with OpenSSL v1.1.1 we get an alternative to SSL_set_bio() that works
+ * without backward compat quirks. Every call takes one reference, so we
+ * up it and pass. SSL* then owns it and will free.
+ * We check on the function in configure, since libressl and friends
+ * each have their own versions to add support for this. */
+ BIO_up_ref(bio);
+ SSL_set0_rbio(backend->handle, bio);
+ SSL_set0_wbio(backend->handle, bio);
+#else
+ SSL_set_bio(backend->handle, bio, bio);
+#endif
connssl->connecting_state = ssl_connect_2;
return CURLE_OK;
}
-static CURLcode ossl_connect_step2(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
int err;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|| ssl_connect_2_reading == connssl->connecting_state
|| ssl_connect_2_writing == connssl->connecting_state);
@@ -3315,6 +3825,16 @@
ERR_clear_error();
err = SSL_connect(backend->handle);
+
+ if(!backend->x509_store_setup) {
+ /* After having send off the ClientHello, we prepare the x509
+ * store to verify the coming certificate from the server */
+ CURLcode result = Curl_ssl_setup_x509_store(cf, data, backend->ctx);
+ if(result)
+ return result;
+ backend->x509_store_setup = TRUE;
+ }
+
#ifndef HAVE_KEYLOG_CALLBACK
if(Curl_tls_keylog_enabled()) {
/* If key logging is enabled, wait for the handshake to complete and then
@@ -3344,9 +3864,12 @@
return CURLE_OK;
}
#endif
+ else if(backend->io_result == CURLE_AGAIN) {
+ return CURLE_OK;
+ }
else {
/* untreated error */
- unsigned long errdetail;
+ sslerr_t errdetail;
char error_buffer[256]="";
CURLcode result;
long lerr;
@@ -3371,7 +3894,7 @@
lerr = SSL_get_verify_result(backend->handle);
if(lerr != X509_V_OK) {
- SSL_SET_OPTION_LVALUE(certverifyresult) = lerr;
+ ssl_config->certverifyresult = lerr;
msnprintf(error_buffer, sizeof(error_buffer),
"SSL certificate problem: %s",
X509_verify_cert_error_string(lerr));
@@ -3381,17 +3904,19 @@
error_buffer */
strcpy(error_buffer, "SSL certificate verification failed");
}
-#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
- !defined(LIBRESSL_VERSION_NUMBER) && \
- !defined(OPENSSL_IS_BORINGSSL))
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
+ !defined(LIBRESSL_VERSION_NUMBER) && \
+ !defined(OPENSSL_IS_BORINGSSL) && \
+ !defined(OPENSSL_IS_AWSLC))
+
/* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on
- OpenSSL version above v1.1.1, not LibreSSL nor BoringSSL */
+ OpenSSL version above v1.1.1, not LibreSSL, BoringSSL, or AWS-LC */
else if((lib == ERR_LIB_SSL) &&
(reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) {
- /* If client certificate is required, communicate the
- error to client */
- result = CURLE_SSL_CLIENTCERT;
- ossl_strerror(errdetail, error_buffer, sizeof(error_buffer));
+ /* If client certificate is required, communicate the
+ error to client */
+ result = CURLE_SSL_CLIENTCERT;
+ ossl_strerror(errdetail, error_buffer, sizeof(error_buffer));
}
#endif
else {
@@ -3406,15 +3931,14 @@
* the SO_ERROR is also lost.
*/
if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
- const char * const hostname = SSL_HOST_NAME();
- const long int port = SSL_HOST_PORT();
char extramsg[80]="";
int sockerr = SOCKERRNO;
+
if(sockerr && detail == SSL_ERROR_SYSCALL)
Curl_strerror(sockerr, extramsg, sizeof(extramsg));
- failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%ld ",
+ failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%d ",
extramsg[0] ? extramsg : SSL_ERROR_to_str(detail),
- hostname, port);
+ connssl->hostname, connssl->port);
return result;
}
@@ -3437,30 +3961,12 @@
/* Sets data and len to negotiated protocol, len is 0 if no protocol was
* negotiated
*/
- if(conn->bits.tls_enable_alpn) {
+ if(connssl->alpn) {
const unsigned char *neg_protocol;
unsigned int len;
SSL_get0_alpn_selected(backend->handle, &neg_protocol, &len);
- if(len) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, len, neg_protocol);
-#ifdef USE_HTTP2
- if(len == ALPN_H2_LENGTH &&
- !memcmp(ALPN_H2, neg_protocol, len)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(len == ALPN_HTTP_1_1_LENGTH &&
- !memcmp(ALPN_HTTP_1_1, neg_protocol, ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- }
- }
- else
- infof(data, VTLS_INFOF_NO_ALPN);
-
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ return Curl_alpn_set_negotiated(cf, data, neg_protocol, len);
}
#endif
@@ -3468,348 +3974,12 @@
}
}
-static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
-{
- int i, ilen;
-
- ilen = (int)len;
- if(ilen < 0)
- return 1; /* buffer too big */
-
- i = i2t_ASN1_OBJECT(buf, ilen, a);
-
- if(i >= ilen)
- return 1; /* buffer too small */
-
- return 0;
-}
-
-#define push_certinfo(_label, _num) \
-do { \
- long info_len = BIO_get_mem_data(mem, &ptr); \
- Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \
- if(1 != BIO_reset(mem)) \
- break; \
-} while(0)
-
-static void pubkey_show(struct Curl_easy *data,
- BIO *mem,
- int num,
- const char *type,
- const char *name,
- const BIGNUM *bn)
-{
- char *ptr;
- char namebuf[32];
-
- msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
-
- if(bn)
- BN_print(mem, bn);
- push_certinfo(namebuf, num);
-}
-
-#ifdef HAVE_OPAQUE_RSA_DSA_DH
-#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 void X509V3_ext(struct Curl_easy *data,
- int certnum,
- CONST_EXTS STACK_OF(X509_EXTENSION) *exts)
-{
- int i;
-
- if((int)sk_X509_EXTENSION_num(exts) <= 0)
- /* no extensions, bail out */
- return;
-
- for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
- ASN1_OBJECT *obj;
- X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
- BUF_MEM *biomem;
- char namebuf[128];
- BIO *bio_out = BIO_new(BIO_s_mem());
-
- if(!bio_out)
- return;
-
- obj = X509_EXTENSION_get_object(ext);
-
- asn1_object_dump(obj, namebuf, sizeof(namebuf));
-
- if(!X509V3_EXT_print(bio_out, ext, 0, 0))
- ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
-
- BIO_get_mem_ptr(bio_out, &biomem);
- Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data,
- biomem->length);
- BIO_free(bio_out);
- }
-}
-
-#ifdef OPENSSL_IS_BORINGSSL
-typedef size_t numcert_t;
-#else
-typedef int numcert_t;
-#endif
-
-static CURLcode get_cert_chain(struct Curl_easy *data,
- struct ssl_connect_data *connssl)
-{
- CURLcode result;
- STACK_OF(X509) *sk;
- int i;
- numcert_t numcerts;
- BIO *mem;
- struct ssl_backend_data *backend = connssl->backend;
-
- DEBUGASSERT(backend);
-
- sk = SSL_get_peer_cert_chain(backend->handle);
- if(!sk) {
- return CURLE_OUT_OF_MEMORY;
- }
-
- numcerts = sk_X509_num(sk);
-
- result = Curl_ssl_init_certinfo(data, (int)numcerts);
- if(result) {
- return result;
- }
-
- mem = BIO_new(BIO_s_mem());
- if(!mem) {
- return CURLE_OUT_OF_MEMORY;
- }
-
- for(i = 0; i < (int)numcerts; i++) {
- ASN1_INTEGER *num;
- X509 *x = sk_X509_value(sk, i);
- EVP_PKEY *pubkey = NULL;
- int j;
- char *ptr;
- const ASN1_BIT_STRING *psig = NULL;
-
- X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
- push_certinfo("Subject", i);
-
- X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
- push_certinfo("Issuer", i);
-
- BIO_printf(mem, "%lx", X509_get_version(x));
- push_certinfo("Version", i);
-
- num = X509_get_serialNumber(x);
- if(num->type == V_ASN1_NEG_INTEGER)
- BIO_puts(mem, "-");
- for(j = 0; j < num->length; j++)
- BIO_printf(mem, "%02x", num->data[j]);
- push_certinfo("Serial Number", i);
-
-#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS)
- {
- const X509_ALGOR *sigalg = NULL;
- X509_PUBKEY *xpubkey = NULL;
- ASN1_OBJECT *pubkeyoid = NULL;
-
- X509_get0_signature(&psig, &sigalg, x);
- if(sigalg) {
- i2a_ASN1_OBJECT(mem, sigalg->algorithm);
- push_certinfo("Signature Algorithm", i);
- }
-
- xpubkey = X509_get_X509_PUBKEY(x);
- if(xpubkey) {
- X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey);
- if(pubkeyoid) {
- i2a_ASN1_OBJECT(mem, pubkeyoid);
- push_certinfo("Public Key Algorithm", i);
- }
- }
-
- X509V3_ext(data, i, X509_get0_extensions(x));
- }
-#else
- {
- /* before OpenSSL 1.0.2 */
- X509_CINF *cinf = x->cert_info;
-
- i2a_ASN1_OBJECT(mem, cinf->signature->algorithm);
- push_certinfo("Signature Algorithm", i);
-
- i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm);
- push_certinfo("Public Key Algorithm", i);
-
- X509V3_ext(data, i, cinf->extensions);
-
- psig = x->signature;
- }
-#endif
-
- ASN1_TIME_print(mem, X509_get0_notBefore(x));
- push_certinfo("Start date", i);
-
- ASN1_TIME_print(mem, X509_get0_notAfter(x));
- push_certinfo("Expire date", i);
-
- pubkey = X509_get_pubkey(x);
- 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", BN_num_bits(n));
-#else
- BIO_printf(mem, "%d", BN_num_bits(rsa->n));
-#endif /* HAVE_OPAQUE_RSA_DSA_DH */
- push_certinfo("RSA Public Key", i);
- print_pubkey_BN(rsa, n, i);
- print_pubkey_BN(rsa, e, i);
- FREE_PKEY_PARAM_BIGNUM(n);
- FREE_PKEY_PARAM_BIGNUM(e);
- }
-
- 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 */
- 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);
- }
- break;
- }
- }
- EVP_PKEY_free(pubkey);
- }
-
- if(psig) {
- for(j = 0; j < psig->length; j++)
- BIO_printf(mem, "%02x:", psig->data[j]);
- push_certinfo("Signature", i);
- }
-
- PEM_write_bio_X509(mem, x);
- push_certinfo("Cert", i);
- }
-
- BIO_free(mem);
-
- return CURLE_OK;
-}
-
/*
* Heavily modified from:
* https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL
*/
-static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
- const char *pinnedpubkey)
+static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
+ const char *pinnedpubkey)
{
/* Scratch */
int len1 = 0, len2 = 0;
@@ -3830,7 +4000,7 @@
/* Thanks to Viktor Dukhovni on the OpenSSL mailing list */
/* https://groups.google.com/group/mailing.openssl.users/browse_thread
- /thread/d61858dae102c6c7 */
+ /thread/d61858dae102c6c7 */
len1 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL);
if(len1 < 1)
break; /* failed */
@@ -3870,11 +4040,14 @@
* We check certificates to authenticate the server; otherwise we risk
* man-in-the-middle attack.
*/
-static CURLcode servercert(struct Curl_easy *data,
- struct connectdata *conn,
- struct ssl_connect_data *connssl,
+static CURLcode servercert(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
bool strict)
{
+ struct connectdata *conn = cf->conn;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
CURLcode result = CURLE_OK;
int rc;
long lerr;
@@ -3884,7 +4057,8 @@
char buffer[2048];
const char *ptr;
BIO *mem = BIO_new(BIO_s_mem());
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
@@ -3898,8 +4072,8 @@
}
if(data->set.ssl.certinfo)
- /* we've been asked to gather certificate info! */
- (void)get_cert_chain(data, connssl);
+ /* asked to gather certificate info */
+ (void)Curl_ossl_certchain(data, backend->handle);
backend->server_cert = SSL_get1_peer_certificate(backend->handle);
if(!backend->server_cert) {
@@ -3911,7 +4085,8 @@
return CURLE_PEER_FAILED_VERIFICATION;
}
- infof(data, "%s certificate:", SSL_IS_PROXY() ? "Proxy" : "Server");
+ infof(data, "%s certificate:",
+ Curl_ssl_cf_is_proxy(cf)? "Proxy" : "Server");
rc = x509_name_oneline(X509_get_subject_name(backend->server_cert),
buffer, sizeof(buffer));
@@ -3934,8 +4109,9 @@
BIO_free(mem);
- if(SSL_CONN_CONFIG(verifyhost)) {
- result = Curl_ossl_verifyhost(data, conn, backend->server_cert);
+ if(conn_config->verifyhost) {
+ result = ossl_verifyhost(data, conn, backend->server_cert,
+ connssl->hostname, connssl->dispname);
if(result) {
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -3957,10 +4133,10 @@
deallocating the certificate. */
/* e.g. match issuer name with provided issuer certificate */
- if(SSL_CONN_CONFIG(issuercert) || SSL_CONN_CONFIG(issuercert_blob)) {
- if(SSL_CONN_CONFIG(issuercert_blob)) {
- fp = BIO_new_mem_buf(SSL_CONN_CONFIG(issuercert_blob)->data,
- (int)SSL_CONN_CONFIG(issuercert_blob)->len);
+ if(conn_config->issuercert || conn_config->issuercert_blob) {
+ if(conn_config->issuercert_blob) {
+ fp = BIO_new_mem_buf(conn_config->issuercert_blob->data,
+ (int)conn_config->issuercert_blob->len);
if(!fp) {
failf(data,
"BIO_new_mem_buf NULL, " OSSL_PACKAGE
@@ -3985,10 +4161,10 @@
return CURLE_OUT_OF_MEMORY;
}
- if(BIO_read_filename(fp, SSL_CONN_CONFIG(issuercert)) <= 0) {
+ if(BIO_read_filename(fp, conn_config->issuercert) <= 0) {
if(strict)
failf(data, "SSL: Unable to open issuer cert (%s)",
- SSL_CONN_CONFIG(issuercert));
+ conn_config->issuercert);
BIO_free(fp);
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -4000,7 +4176,7 @@
if(!issuer) {
if(strict)
failf(data, "SSL: Unable to read issuer cert (%s)",
- SSL_CONN_CONFIG(issuercert));
+ conn_config->issuercert);
BIO_free(fp);
X509_free(issuer);
X509_free(backend->server_cert);
@@ -4011,7 +4187,7 @@
if(X509_check_issued(issuer, backend->server_cert) != X509_V_OK) {
if(strict)
failf(data, "SSL: Certificate issuer check failed (%s)",
- SSL_CONN_CONFIG(issuercert));
+ conn_config->issuercert);
BIO_free(fp);
X509_free(issuer);
X509_free(backend->server_cert);
@@ -4020,15 +4196,15 @@
}
infof(data, " SSL certificate issuer check ok (%s)",
- SSL_CONN_CONFIG(issuercert));
+ conn_config->issuercert);
BIO_free(fp);
X509_free(issuer);
}
lerr = SSL_get_verify_result(backend->handle);
- SSL_SET_OPTION_LVALUE(certverifyresult) = lerr;
+ ssl_config->certverifyresult = lerr;
if(lerr != X509_V_OK) {
- if(SSL_CONN_CONFIG(verifypeer)) {
+ if(conn_config->verifypeer) {
/* We probably never reach this, because SSL_connect() will fail
and we return earlier if verifypeer is set? */
if(strict)
@@ -4046,9 +4222,9 @@
}
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
- !defined(OPENSSL_NO_OCSP)
- if(SSL_CONN_CONFIG(verifystatus)) {
- result = verifystatus(data, connssl);
+ !defined(OPENSSL_NO_OCSP)
+ if(conn_config->verifystatus) {
+ result = verifystatus(cf, data);
if(result) {
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -4061,9 +4237,11 @@
/* when not strict, we don't bother about the verify cert problems */
result = CURLE_OK;
- ptr = SSL_PINNED_PUB_KEY();
+ ptr = Curl_ssl_cf_is_proxy(cf)?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
if(!result && ptr) {
- result = pkp_pin_peer_pubkey(data, backend->server_cert, ptr);
+ result = ossl_pkp_pin_peer_pubkey(data, backend->server_cert, ptr);
if(result)
failf(data, "SSL: public key does not match pinned public key");
}
@@ -4075,11 +4253,12 @@
return result;
}
-static CURLcode ossl_connect_step3(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode ossl_connect_step3(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
@@ -4090,8 +4269,8 @@
* operations.
*/
- result = servercert(data, conn, connssl, (SSL_CONN_CONFIG(verifypeer) ||
- SSL_CONN_CONFIG(verifyhost)));
+ result = servercert(cf, data, conn_config->verifypeer ||
+ conn_config->verifyhost);
if(!result)
connssl->connecting_state = ssl_connect_done;
@@ -4099,18 +4278,14 @@
return result;
}
-static Curl_recv ossl_recv;
-static Curl_send ossl_send;
-
-static CURLcode ossl_connect_common(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
+static CURLcode ossl_connect_common(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
bool nonblocking,
bool *done)
{
- CURLcode result;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- curl_socket_t sockfd = conn->sock[sockindex];
+ CURLcode result = CURLE_OK;
+ struct ssl_connect_data *connssl = cf->ctx;
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
int what;
/* check if the connection has already been established */
@@ -4129,9 +4304,9 @@
return CURLE_OPERATION_TIMEDOUT;
}
- result = ossl_connect_step1(data, conn, sockindex);
+ result = ossl_connect_step1(cf, data);
if(result)
- return result;
+ goto out;
}
while(ssl_connect_2 == connssl->connecting_state ||
@@ -4144,12 +4319,14 @@
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "SSL connection timeout");
- return CURLE_OPERATION_TIMEDOUT;
+ result = CURLE_OPERATION_TIMEDOUT;
+ goto out;
}
/* if ssl is expecting something, check if it's available. */
- if(connssl->connecting_state == ssl_connect_2_reading ||
- connssl->connecting_state == ssl_connect_2_writing) {
+ if(!nonblocking &&
+ (connssl->connecting_state == ssl_connect_2_reading ||
+ connssl->connecting_state == ssl_connect_2_writing)) {
curl_socket_t writefd = ssl_connect_2_writing ==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
@@ -4157,20 +4334,18 @@
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
- nonblocking?0:timeout_ms);
+ timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
- return CURLE_SSL_CONNECT_ERROR;
+ result = CURLE_SSL_CONNECT_ERROR;
+ goto out;
}
if(0 == what) {
- if(nonblocking) {
- *done = FALSE;
- return CURLE_OK;
- }
/* timeout */
failf(data, "SSL connection timeout");
- return CURLE_OPERATION_TIMEDOUT;
+ result = CURLE_OPERATION_TIMEDOUT;
+ goto out;
}
/* socket is readable or writable */
}
@@ -4181,25 +4356,23 @@
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
- result = ossl_connect_step2(data, conn, sockindex);
+ result = ossl_connect_step2(cf, data);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
ssl_connect_2_writing == connssl->connecting_state)))
- return result;
+ goto out;
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- result = ossl_connect_step3(data, conn, sockindex);
+ result = ossl_connect_step3(cf, data);
if(result)
- return result;
+ goto out;
}
if(ssl_connect_done == connssl->connecting_state) {
connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = ossl_recv;
- conn->send[sockindex] = ossl_send;
*done = TRUE;
}
else
@@ -4208,24 +4381,24 @@
/* Reset our connect state machine */
connssl->connecting_state = ssl_connect_1;
- return CURLE_OK;
+out:
+ return result;
}
-static CURLcode ossl_connect_nonblocking(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
+static CURLcode ossl_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
bool *done)
{
- return ossl_connect_common(data, conn, sockindex, TRUE, done);
+ return ossl_connect_common(cf, data, TRUE, done);
}
-static CURLcode ossl_connect(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static CURLcode ossl_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
CURLcode result;
bool done = FALSE;
- result = ossl_connect_common(data, conn, sockindex, FALSE, &done);
+ result = ossl_connect_common(cf, data, FALSE, &done);
if(result)
return result;
@@ -4234,28 +4407,22 @@
return CURLE_OK;
}
-static bool ossl_data_pending(const struct connectdata *conn,
- int connindex)
+static bool ossl_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
- const struct ssl_connect_data *connssl = &conn->ssl[connindex];
- DEBUGASSERT(connssl->backend);
- if(connssl->backend->handle && SSL_pending(connssl->backend->handle))
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
+
+ (void)data;
+ DEBUGASSERT(connssl && backend);
+ if(backend->handle && SSL_pending(backend->handle))
return TRUE;
-#ifndef CURL_DISABLE_PROXY
- {
- const struct ssl_connect_data *proxyssl = &conn->proxy_ssl[connindex];
- DEBUGASSERT(proxyssl->backend);
- if(proxyssl->backend->handle && SSL_pending(proxyssl->backend->handle))
- return TRUE;
- }
-#endif
return FALSE;
}
-static size_t ossl_version(char *buffer, size_t size);
-
-static ssize_t ossl_send(struct Curl_easy *data,
- int sockindex,
+static ssize_t ossl_send(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
const void *mem,
size_t len,
CURLcode *curlcode)
@@ -4264,19 +4431,19 @@
'size_t' */
int err;
char error_buffer[256];
- unsigned long sslerror;
+ sslerr_t sslerror;
int memlen;
int rc;
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
+ (void)data;
DEBUGASSERT(backend);
ERR_clear_error();
memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
- set_logger(conn, data);
rc = SSL_write(backend->handle, mem, memlen);
if(rc <= 0) {
@@ -4289,34 +4456,43 @@
should be called again later. This is basically an EWOULDBLOCK
equivalent. */
*curlcode = CURLE_AGAIN;
- return -1;
+ rc = -1;
+ goto out;
case SSL_ERROR_SYSCALL:
- {
- int sockerr = SOCKERRNO;
- sslerror = ERR_get_error();
- if(sslerror)
- ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
- else if(sockerr)
- Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
- else {
- strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
- error_buffer[sizeof(error_buffer) - 1] = '\0';
- }
- failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
- error_buffer, sockerr);
- *curlcode = CURLE_SEND_ERROR;
- return -1;
+ {
+ int sockerr = SOCKERRNO;
+
+ if(backend->io_result == CURLE_AGAIN) {
+ *curlcode = CURLE_AGAIN;
+ rc = -1;
+ goto out;
}
- case SSL_ERROR_SSL:
+ sslerror = ERR_get_error();
+ if(sslerror)
+ ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
+ else if(sockerr)
+ Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
+ else {
+ strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
+ error_buffer[sizeof(error_buffer) - 1] = '\0';
+ }
+ failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
+ error_buffer, sockerr);
+ *curlcode = CURLE_SEND_ERROR;
+ rc = -1;
+ goto out;
+ }
+ case SSL_ERROR_SSL: {
/* A failure in the SSL library occurred, usually a protocol error.
The OpenSSL error queue contains more information on the error. */
+ struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
+ struct ssl_connect_data *connssl_next = cf_ssl_next?
+ cf_ssl_next->ctx : NULL;
sslerror = ERR_get_error();
if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL &&
ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET &&
- conn->ssl[sockindex].state == ssl_connection_complete
-#ifndef CURL_DISABLE_PROXY
- && conn->proxy_ssl[sockindex].state == ssl_connection_complete
-#endif
+ connssl->state == ssl_connection_complete &&
+ (connssl_next && connssl_next->state == ssl_connection_complete)
) {
char ver[120];
(void)ossl_version(ver, sizeof(ver));
@@ -4326,20 +4502,26 @@
failf(data, "SSL_write() error: %s",
ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
*curlcode = CURLE_SEND_ERROR;
- return -1;
+ rc = -1;
+ goto out;
}
- /* a true error */
- failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
- SSL_ERROR_to_str(err), SOCKERRNO);
- *curlcode = CURLE_SEND_ERROR;
- return -1;
+ default:
+ /* a true error */
+ failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
+ SSL_ERROR_to_str(err), SOCKERRNO);
+ *curlcode = CURLE_SEND_ERROR;
+ rc = -1;
+ goto out;
+ }
}
*curlcode = CURLE_OK;
+
+out:
return (ssize_t)rc; /* number of bytes */
}
-static ssize_t ossl_recv(struct Curl_easy *data, /* transfer */
- int num, /* socketindex */
+static ssize_t ossl_recv(struct Curl_cfilter *cf,
+ struct Curl_easy *data, /* transfer */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
@@ -4348,17 +4530,19 @@
unsigned long sslerror;
ssize_t nread;
int buffsize;
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[num];
- struct ssl_backend_data *backend = connssl->backend;
+ struct connectdata *conn = cf->conn;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
+ (void)data;
DEBUGASSERT(backend);
ERR_clear_error();
buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
- set_logger(conn, data);
nread = (ssize_t)SSL_read(backend->handle, buf, buffsize);
+
if(nread <= 0) {
/* failed SSL_read */
int err = SSL_get_error(backend->handle, (int)nread);
@@ -4368,7 +4552,7 @@
break;
case SSL_ERROR_ZERO_RETURN: /* no more data */
/* close_notify alert */
- if(num == FIRSTSOCKET)
+ if(cf->sockindex == FIRSTSOCKET)
/* mark the connection for close if it is indeed the control
connection */
connclose(conn, "TLS close_notify");
@@ -4377,11 +4561,17 @@
case SSL_ERROR_WANT_WRITE:
/* there's data pending, re-invoke SSL_read() */
*curlcode = CURLE_AGAIN;
- return -1;
+ nread = -1;
+ goto out;
default:
/* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return
value/errno" */
/* https://www.openssl.org/docs/crypto/ERR_get_error.html */
+ if(backend->io_result == CURLE_AGAIN) {
+ *curlcode = CURLE_AGAIN;
+ nread = -1;
+ goto out;
+ }
sslerror = ERR_get_error();
if((nread < 0) || sslerror) {
/* If the return code was negative or there actually is an error in the
@@ -4398,7 +4588,8 @@
failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d",
error_buffer, sockerr);
*curlcode = CURLE_RECV_ERROR;
- return -1;
+ nread = -1;
+ goto out;
}
/* For debug builds be a little stricter and error on any
SSL_ERROR_SYSCALL. For example a server may have closed the connection
@@ -4421,11 +4612,14 @@
" (Fatal because this is a curl debug build)",
error_buffer, sockerr);
*curlcode = CURLE_RECV_ERROR;
- return -1;
+ nread = -1;
+ goto out;
}
#endif
}
}
+
+out:
return nread;
}
@@ -4437,12 +4631,12 @@
int count;
const char *ver = OpenSSL_version(OPENSSL_VERSION);
const char expected[] = OSSL_PACKAGE " "; /* ie "LibreSSL " */
- if(Curl_strncasecompare(ver, expected, sizeof(expected) - 1)) {
+ if(strncasecompare(ver, expected, sizeof(expected) - 1)) {
ver += sizeof(expected) - 1;
}
count = msnprintf(buffer, size, "%s/%s", OSSL_PACKAGE, ver);
for(p = buffer; *p; ++p) {
- if(ISSPACE(*p))
+ if(ISBLANK(*p))
*p = '_';
}
return count;
@@ -4454,7 +4648,17 @@
(LIBRESSL_VERSION_NUMBER>>12)&0xff);
#endif
#elif defined(OPENSSL_IS_BORINGSSL)
+#ifdef CURL_BORINGSSL_VERSION
+ return msnprintf(buffer, size, "%s/%s",
+ OSSL_PACKAGE,
+ CURL_BORINGSSL_VERSION);
+#else
return msnprintf(buffer, size, OSSL_PACKAGE);
+#endif
+#elif defined(OPENSSL_IS_AWSLC)
+ return msnprintf(buffer, size, "%s/%s",
+ OSSL_PACKAGE,
+ AWSLC_VERSION_NUMBER_STRING);
#elif defined(HAVE_OPENSSL_VERSION) && defined(OPENSSL_VERSION_STRING)
return msnprintf(buffer, size, "%s/%s",
OSSL_PACKAGE, OpenSSL_version(OPENSSL_VERSION_STRING));
@@ -4541,7 +4745,7 @@
static bool ossl_cert_status_request(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
- !defined(OPENSSL_NO_OCSP)
+ !defined(OPENSSL_NO_OCSP)
return TRUE;
#else
return FALSE;
@@ -4552,90 +4756,25 @@
CURLINFO info)
{
/* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
return info == CURLINFO_TLS_SESSION ?
- (void *)backend->ctx : (void *)backend->handle;
+ (void *)backend->ctx : (void *)backend->handle;
}
-static bool ossl_associate_connection(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex)
+static void ossl_free_multi_ssl_backend_data(
+ struct multi_ssl_backend_data *mbackend)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- DEBUGASSERT(backend);
-
- /* If we don't have SSL context, do nothing. */
- if(!backend->handle)
- return FALSE;
-
- if(SSL_SET_OPTION(primary.sessionid)) {
- int data_idx = ossl_get_ssl_data_index();
- int connectdata_idx = ossl_get_ssl_conn_index();
- int sockindex_idx = ossl_get_ssl_sockindex_index();
- int proxy_idx = ossl_get_proxy_index();
-
- if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 &&
- proxy_idx >= 0) {
- int data_status, conn_status, sockindex_status, proxy_status;
-
- /* Store the data needed for the "new session" callback.
- * The sockindex is stored as a pointer to an array element. */
- data_status = SSL_set_ex_data(backend->handle, data_idx, data);
- conn_status = SSL_set_ex_data(backend->handle, connectdata_idx, conn);
- sockindex_status = SSL_set_ex_data(backend->handle, sockindex_idx,
- conn->sock + sockindex);
-#ifndef CURL_DISABLE_PROXY
- proxy_status = SSL_set_ex_data(backend->handle, proxy_idx,
- SSL_IS_PROXY() ? (void *) 1 : NULL);
-#else
- proxy_status = SSL_set_ex_data(backend->handle, proxy_idx, NULL);
-#endif
- if(data_status && conn_status && sockindex_status && proxy_status)
- return TRUE;
- }
- return FALSE;
+#if defined(HAVE_SSL_X509_STORE_SHARE)
+ if(mbackend->store) {
+ X509_STORE_free(mbackend->store);
}
- return TRUE;
-}
-
-/*
- * Starting with TLS 1.3, the ossl_new_session_cb callback gets called after
- * the handshake. If the transfer that sets up the callback gets killed before
- * this callback arrives, we must make sure to properly clear the data to
- * avoid UAF problems. A future optimization could be to instead store another
- * transfer that might still be using the same connection.
- */
-
-static void ossl_disassociate_connection(struct Curl_easy *data,
- int sockindex)
-{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- DEBUGASSERT(backend);
-
- /* If we don't have SSL context, do nothing. */
- if(!backend->handle)
- return;
-
- if(SSL_SET_OPTION(primary.sessionid)) {
- int data_idx = ossl_get_ssl_data_index();
- int connectdata_idx = ossl_get_ssl_conn_index();
- int sockindex_idx = ossl_get_ssl_sockindex_index();
- int proxy_idx = ossl_get_proxy_index();
-
- if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 &&
- proxy_idx >= 0) {
- /* Disable references to data in "new session" callback to avoid
- * accessing a stale pointer. */
- SSL_set_ex_data(backend->handle, data_idx, NULL);
- SSL_set_ex_data(backend->handle, connectdata_idx, NULL);
- SSL_set_ex_data(backend->handle, sockindex_idx, NULL);
- SSL_set_ex_data(backend->handle, proxy_idx, NULL);
- }
- }
+ free(mbackend->CAfile);
+ free(mbackend);
+#else /* HAVE_SSL_X509_STORE_SHARE */
+ (void)mbackend;
+#endif /* HAVE_SSL_X509_STORE_SHARE */
}
const struct Curl_ssl Curl_ssl_openssl = {
@@ -4651,19 +4790,19 @@
#endif
SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct ossl_ssl_backend_data),
ossl_init, /* init */
ossl_cleanup, /* cleanup */
ossl_version, /* version */
- ossl_check_cxn, /* check_cxn */
+ Curl_none_check_cxn, /* check_cxn */
ossl_shutdown, /* shutdown */
ossl_data_pending, /* data_pending */
ossl_random, /* random */
ossl_cert_status_request, /* cert_status_request */
ossl_connect, /* connect */
ossl_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_getsock, /* getsock */
+ Curl_ssl_get_select_socks,/* getsock */
ossl_get_internals, /* get_internals */
ossl_close, /* close_one */
ossl_close_all, /* close_all */
@@ -4677,8 +4816,11 @@
#else
NULL, /* sha256sum */
#endif
- ossl_associate_connection, /* associate_connection */
- ossl_disassociate_connection /* disassociate_connection */
+ NULL, /* use of data in this connection */
+ NULL, /* remote of data from this connection */
+ ossl_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */
+ ossl_recv, /* recv decrypted data */
+ ossl_send, /* send data to encrypt */
};
#endif /* USE_OPENSSL */
diff --git a/lib/vtls/openssl.h b/lib/vtls/openssl.h
index cb47f4e..950faab 100644
--- a/lib/vtls/openssl.h
+++ b/lib/vtls/openssl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,6 +31,7 @@
* This header should only be needed to get included by vtls.c, openssl.c
* and ngtcp2.c
*/
+#include <openssl/ssl.h>
#include "urldata.h"
@@ -53,5 +54,16 @@
const struct curl_blob *key_blob,
const char *key_type, char *key_passwd);
+CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl);
+
+/**
+ * Setup the OpenSSL X509_STORE in `ssl_ctx` for the cfilter `cf` and
+ * easy handle `data`. Will allow reuse of a shared cache if suitable
+ * and configured.
+ */
+CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ SSL_CTX *ssl_ctx);
+
#endif /* USE_OPENSSL */
#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c
index be4af98..76d3e24 100644
--- a/lib/vtls/rustls.c
+++ b/lib/vtls/rustls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Jacob Hoffman-Andrews,
+ * Copyright (C) Jacob Hoffman-Andrews,
* <github@hoffman-andrews.com>
*
* This software is licensed as described in the file COPYING, which
@@ -35,11 +35,12 @@
#include "urldata.h"
#include "sendf.h"
#include "vtls.h"
+#include "vtls_int.h"
#include "select.h"
#include "strerror.h"
#include "multiif.h"
-struct ssl_backend_data
+struct rustls_ssl_backend_data
{
const struct rustls_client_config *config;
struct rustls_connection *conn;
@@ -63,43 +64,117 @@
}
static bool
-cr_data_pending(const struct connectdata *conn, int sockindex)
+cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
{
- const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- DEBUGASSERT(backend);
+ struct ssl_connect_data *ctx = cf->ctx;
+ struct rustls_ssl_backend_data *backend;
+
+ (void)data;
+ DEBUGASSERT(ctx && ctx->backend);
+ backend = (struct rustls_ssl_backend_data *)ctx->backend;
return backend->data_pending;
}
static CURLcode
-cr_connect(struct Curl_easy *data UNUSED_PARAM,
- struct connectdata *conn UNUSED_PARAM,
- int sockindex UNUSED_PARAM)
+cr_connect(struct Curl_cfilter *cf UNUSED_PARAM,
+ struct Curl_easy *data UNUSED_PARAM)
{
infof(data, "rustls_connect: unimplemented");
return CURLE_SSL_CONNECT_ERROR;
}
+struct io_ctx {
+ struct Curl_cfilter *cf;
+ struct Curl_easy *data;
+};
+
static int
read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n)
{
- ssize_t n = sread(*(int *)userdata, buf, len);
- if(n < 0) {
- return SOCKERRNO;
+ struct io_ctx *io_ctx = userdata;
+ CURLcode result;
+ int ret = 0;
+ ssize_t nread = Curl_conn_cf_recv(io_ctx->cf->next, io_ctx->data,
+ (char *)buf, len, &result);
+ if(nread < 0) {
+ nread = 0;
+ if(CURLE_AGAIN == result)
+ ret = EAGAIN;
+ else
+ ret = EINVAL;
}
- *out_n = n;
- return 0;
+ *out_n = (int)nread;
+ /*
+ DEBUGF(LOG_CF(io_ctx->data, io_ctx->cf, "cf->next recv(len=%zu) -> %zd, %d",
+ len, nread, result));
+ */
+ return ret;
}
static int
write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n)
{
- ssize_t n = swrite(*(int *)userdata, buf, len);
- if(n < 0) {
- return SOCKERRNO;
+ struct io_ctx *io_ctx = userdata;
+ CURLcode result;
+ int ret = 0;
+ ssize_t nwritten = Curl_conn_cf_send(io_ctx->cf->next, io_ctx->data,
+ (const char *)buf, len, &result);
+ if(nwritten < 0) {
+ nwritten = 0;
+ if(CURLE_AGAIN == result)
+ ret = EAGAIN;
+ else
+ ret = EINVAL;
}
- *out_n = n;
- return 0;
+ *out_n = (int)nwritten;
+ /*
+ DEBUGF(LOG_CF(io_ctx->data, io_ctx->cf, "cf->next send(len=%zu) -> %zd, %d",
+ len, nwritten, result));
+ */
+ return ret;
+}
+
+static ssize_t tls_recv_more(struct Curl_cfilter *cf,
+ struct Curl_easy *data, CURLcode *err)
+{
+ 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;
+ rustls_io_result io_error;
+ rustls_result rresult = 0;
+
+ io_ctx.cf = cf;
+ io_ctx.data = data;
+ io_error = rustls_connection_read_tls(backend->conn, read_cb, &io_ctx,
+ &tls_bytes_read);
+ if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+ else if(io_error) {
+ char buffer[STRERROR_LEN];
+ failf(data, "reading from socket: %s",
+ Curl_strerror(io_error, buffer, sizeof(buffer)));
+ *err = CURLE_READ_ERROR;
+ return -1;
+ }
+
+ rresult = rustls_connection_process_new_packets(backend->conn);
+ if(rresult != RUSTLS_RESULT_OK) {
+ char errorbuf[255];
+ size_t errorlen;
+ rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
+ failf(data, "rustls_connection_process_new_packets: %.*s",
+ errorlen, errorbuf);
+ *err = map_error(rresult);
+ return -1;
+ }
+
+ backend->data_pending = TRUE;
+ *err = CURLE_OK;
+ return (ssize_t)tls_bytes_read;
}
/*
@@ -115,94 +190,86 @@
* output buffer.
*/
static ssize_t
-cr_recv(struct Curl_easy *data, int sockindex,
+cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *plainbuf, size_t plainlen, CURLcode *err)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *const connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *const backend = connssl->backend;
+ 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 n = 0;
- size_t tls_bytes_read = 0;
size_t plain_bytes_copied = 0;
rustls_result rresult = 0;
- char errorbuf[255];
- rustls_io_result io_error;
+ ssize_t nread;
+ bool eof = FALSE;
DEBUGASSERT(backend);
rconn = backend->conn;
- io_error = rustls_connection_read_tls(rconn, read_cb,
- &conn->sock[sockindex], &tls_bytes_read);
- if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
- infof(data, "sread: EAGAIN or EWOULDBLOCK");
- }
- else if(io_error) {
- char buffer[STRERROR_LEN];
- failf(data, "reading from socket: %s",
- Curl_strerror(io_error, buffer, sizeof(buffer)));
- *err = CURLE_READ_ERROR;
- return -1;
- }
-
- infof(data, "cr_recv read %ld bytes from the network", tls_bytes_read);
-
- rresult = rustls_connection_process_new_packets(rconn);
- if(rresult != RUSTLS_RESULT_OK) {
- rustls_error(rresult, errorbuf, sizeof(errorbuf), &n);
- failf(data, "%.*s", n, errorbuf);
- *err = map_error(rresult);
- return -1;
- }
-
- backend->data_pending = TRUE;
-
while(plain_bytes_copied < plainlen) {
+ if(!backend->data_pending) {
+ if(tls_recv_more(cf, data, err) < 0) {
+ if(*err != CURLE_AGAIN) {
+ nread = -1;
+ goto out;
+ }
+ break;
+ }
+ }
+
rresult = rustls_connection_read(rconn,
(uint8_t *)plainbuf + plain_bytes_copied,
plainlen - plain_bytes_copied,
&n);
if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) {
- infof(data, "cr_recv got PLAINTEXT_EMPTY. will try again later.");
backend->data_pending = FALSE;
- break;
+ }
+ else if(rresult == RUSTLS_RESULT_UNEXPECTED_EOF) {
+ failf(data, "rustls: peer closed TCP connection "
+ "without first closing TLS connection");
+ *err = CURLE_READ_ERROR;
+ nread = -1;
+ goto out;
}
else if(rresult != RUSTLS_RESULT_OK) {
/* n always equals 0 in this case, don't need to check it */
- failf(data, "error in rustls_connection_read: %d", rresult);
+ char errorbuf[255];
+ size_t errorlen;
+ rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
+ failf(data, "rustls_connection_read: %.*s", errorlen, errorbuf);
*err = CURLE_READ_ERROR;
- return -1;
+ nread = -1;
+ goto out;
}
else if(n == 0) {
/* n == 0 indicates clean EOF, but we may have read some other
plaintext bytes before we reached this. Break out of the loop
so we can figure out whether to return success or EOF. */
+ eof = TRUE;
break;
}
else {
- infof(data, "cr_recv copied out %ld bytes of plaintext", n);
plain_bytes_copied += n;
}
}
if(plain_bytes_copied) {
*err = CURLE_OK;
- return plain_bytes_copied;
+ nread = (ssize_t)plain_bytes_copied;
}
-
- /* If we wrote out 0 plaintext bytes, that means either we hit a clean EOF,
- OR we got a RUSTLS_RESULT_PLAINTEXT_EMPTY.
- If the latter, return CURLE_AGAIN so curl doesn't treat this as EOF. */
- if(!backend->data_pending) {
+ else if(eof) {
+ *err = CURLE_OK;
+ nread = 0;
+ }
+ else {
*err = CURLE_AGAIN;
- return -1;
+ nread = -1;
}
- /* Zero bytes read, and no RUSTLS_RESULT_PLAINTEXT_EMPTY, means the TCP
- connection was cleanly closed (with a close_notify alert). */
- *err = CURLE_OK;
- return 0;
+out:
+ DEBUGF(LOG_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d",
+ plainlen, nread, *err));
+ return nread;
}
/*
@@ -216,44 +283,52 @@
* It will only drain rustls' plaintext output buffer into the socket.
*/
static ssize_t
-cr_send(struct Curl_easy *data, int sockindex,
+cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *plainbuf, size_t plainlen, CURLcode *err)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *const connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *const backend = connssl->backend;
+ 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;
+ struct io_ctx io_ctx;
size_t plainwritten = 0;
size_t tlswritten = 0;
size_t tlswritten_total = 0;
rustls_result rresult;
rustls_io_result io_error;
+ char errorbuf[256];
+ size_t errorlen;
DEBUGASSERT(backend);
rconn = backend->conn;
- infof(data, "cr_send %ld bytes of plaintext", plainlen);
+ DEBUGF(LOG_CF(data, cf, "cf_send: %ld plain bytes", plainlen));
+
+ io_ctx.cf = cf;
+ io_ctx.data = data;
if(plainlen > 0) {
rresult = rustls_connection_write(rconn, plainbuf, plainlen,
&plainwritten);
if(rresult != RUSTLS_RESULT_OK) {
- failf(data, "error in rustls_connection_write");
+ rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
+ failf(data, "rustls_connection_write: %.*s", errorlen, errorbuf);
*err = CURLE_WRITE_ERROR;
return -1;
}
else if(plainwritten == 0) {
- failf(data, "EOF in rustls_connection_write");
+ failf(data, "rustls_connection_write: EOF");
*err = CURLE_WRITE_ERROR;
return -1;
}
}
while(rustls_connection_wants_write(rconn)) {
- io_error = rustls_connection_write_tls(rconn, write_cb,
- &conn->sock[sockindex], &tlswritten);
+ io_error = rustls_connection_write_tls(rconn, write_cb, &io_ctx,
+ &tlswritten);
if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
- infof(data, "swrite: EAGAIN after %ld bytes", tlswritten_total);
+ DEBUGF(LOG_CF(data, cf, "cf_send: EAGAIN after %zu bytes",
+ tlswritten_total));
*err = CURLE_AGAIN;
return -1;
}
@@ -269,7 +344,7 @@
*err = CURLE_WRITE_ERROR;
return -1;
}
- infof(data, "cr_send wrote %ld bytes to network", tlswritten);
+ DEBUGF(LOG_CF(data, cf, "cf_send: wrote %zu TLS bytes", tlswritten));
tlswritten_total += tlswritten;
}
@@ -302,37 +377,42 @@
}
static CURLcode
-cr_init_backend(struct Curl_easy *data, struct connectdata *conn,
- struct ssl_backend_data *const backend)
+cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct rustls_ssl_backend_data *const backend)
{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct rustls_connection *rconn = NULL;
struct rustls_client_config_builder *config_builder = NULL;
struct rustls_root_cert_store *roots = NULL;
- const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
const char * const ssl_cafile =
/* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
- (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
- const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- const char *hostname = conn->host.name;
+ (ca_info_blob ? NULL : conn_config->CAfile);
+ const bool verifypeer = conn_config->verifypeer;
+ const char *hostname = connssl->hostname;
char errorbuf[256];
size_t errorlen;
int result;
- rustls_slice_bytes alpn[2] = {
- { (const uint8_t *)ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH },
- { (const uint8_t *)ALPN_H2, ALPN_H2_LENGTH },
- };
DEBUGASSERT(backend);
rconn = backend->conn;
config_builder = rustls_client_config_builder_new();
-#ifdef USE_HTTP2
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
- rustls_client_config_builder_set_alpn_protocols(config_builder, alpn, 2);
-#else
- rustls_client_config_builder_set_alpn_protocols(config_builder, alpn, 1);
-#endif
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
+ rustls_slice_bytes alpn[ALPN_ENTRIES_MAX];
+ size_t i;
+
+ for(i = 0; i < connssl->alpn->count; ++i) {
+ alpn[i].data = (const uint8_t *)connssl->alpn->entries[i];
+ alpn[i].len = strlen(connssl->alpn->entries[i]);
+ }
+ rustls_client_config_builder_set_alpn_protocols(config_builder, alpn,
+ connssl->alpn->count);
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
+ }
if(!verifypeer) {
rustls_client_config_builder_dangerous_set_certificate_verifier(
config_builder, cr_verify_none);
@@ -352,7 +432,7 @@
result = rustls_root_cert_store_add_pem(roots, ca_info_blob->data,
ca_info_blob->len, verifypeer);
if(result != RUSTLS_RESULT_OK) {
- failf(data, "failed to parse trusted certificates from blob");
+ failf(data, "rustls: failed to parse trusted certificates from blob");
rustls_root_cert_store_free(roots);
rustls_client_config_free(
rustls_client_config_builder_build(config_builder));
@@ -362,7 +442,7 @@
result = rustls_client_config_builder_use_roots(config_builder, roots);
rustls_root_cert_store_free(roots);
if(result != RUSTLS_RESULT_OK) {
- failf(data, "failed to load trusted certificates");
+ failf(data, "rustls: failed to load trusted certificates");
rustls_client_config_free(
rustls_client_config_builder_build(config_builder));
return CURLE_SSL_CACERT_BADFILE;
@@ -372,7 +452,7 @@
result = rustls_client_config_builder_load_roots_from_file(
config_builder, ssl_cafile);
if(result != RUSTLS_RESULT_OK) {
- failf(data, "failed to load trusted certificates");
+ failf(data, "rustls: failed to load trusted certificates");
rustls_client_config_free(
rustls_client_config_builder_build(config_builder));
return CURLE_SSL_CACERT_BADFILE;
@@ -384,7 +464,7 @@
{
char *snihost = Curl_ssl_snihost(data, hostname, NULL);
if(!snihost) {
- failf(data, "Failed to set SNI");
+ failf(data, "rustls: failed to get SNI");
return CURLE_SSL_CONNECT_ERROR;
}
result = rustls_client_connection_new(backend->config, snihost, &rconn);
@@ -400,45 +480,24 @@
}
static void
-cr_set_negotiated_alpn(struct Curl_easy *data, struct connectdata *conn,
+cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data,
const struct rustls_connection *rconn)
{
const uint8_t *protocol = NULL;
size_t len = 0;
rustls_connection_get_alpn_protocol(rconn, &protocol, &len);
- if(!protocol) {
- infof(data, VTLS_INFOF_NO_ALPN);
- return;
- }
-
-#ifdef USE_HTTP2
- if(len == ALPN_H2_LENGTH && 0 == memcmp(ALPN_H2, protocol, len)) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, ALPN_H2);
- conn->negnpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(len == ALPN_HTTP_1_1_LENGTH &&
- 0 == memcmp(ALPN_HTTP_1_1, protocol, len)) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, ALPN_HTTP_1_1);
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- }
- else {
- infof(data, "ALPN, negotiated an unrecognized protocol");
- }
-
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ Curl_alpn_set_negotiated(cf, data, protocol, len);
}
static CURLcode
-cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
- int sockindex, bool *done)
+cr_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data, bool *done)
{
- struct ssl_connect_data *const connssl = &conn->ssl[sockindex];
- curl_socket_t sockfd = conn->sock[sockindex];
- struct ssl_backend_data *const backend = connssl->backend;
+ struct ssl_connect_data *const connssl = cf->ctx;
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
+ struct rustls_ssl_backend_data *const backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
struct rustls_connection *rconn = NULL;
CURLcode tmperr = CURLE_OK;
int result;
@@ -451,7 +510,8 @@
DEBUGASSERT(backend);
if(ssl_connection_none == connssl->state) {
- result = cr_init_backend(data, conn, connssl->backend);
+ result = cr_init_backend(cf, data,
+ (struct rustls_ssl_backend_data *)connssl->backend);
if(result != CURLE_OK) {
return result;
}
@@ -471,10 +531,8 @@
/* Done with the handshake. Set up callbacks to send/receive data. */
connssl->state = ssl_connection_complete;
- cr_set_negotiated_alpn(data, conn, rconn);
+ cr_set_negotiated_alpn(cf, data, rconn);
- conn->recv[sockindex] = cr_recv;
- conn->send[sockindex] = cr_send;
*done = TRUE;
return CURLE_OK;
}
@@ -502,7 +560,7 @@
if(wants_write) {
infof(data, "rustls_connection wants us to write_tls.");
- cr_send(data, sockindex, NULL, 0, &tmperr);
+ cr_send(cf, data, NULL, 0, &tmperr);
if(tmperr == CURLE_AGAIN) {
infof(data, "writing would block");
/* fall through */
@@ -515,13 +573,12 @@
if(wants_read) {
infof(data, "rustls_connection wants us to read_tls.");
- cr_recv(data, sockindex, NULL, 0, &tmperr);
- if(tmperr == CURLE_AGAIN) {
- infof(data, "reading would block");
- /* fall through */
- }
- else if(tmperr != CURLE_OK) {
- if(tmperr == CURLE_READ_ERROR) {
+ if(tls_recv_more(cf, data, &tmperr) < 0) {
+ if(tmperr == CURLE_AGAIN) {
+ infof(data, "reading would block");
+ /* fall through */
+ }
+ else if(tmperr == CURLE_READ_ERROR) {
return CURLE_SSL_CONNECT_ERROR;
}
else {
@@ -539,13 +596,16 @@
/* returns a bitmap of flags for this connection's first socket indicating
whether we want to read or write */
static int
-cr_getsock(struct connectdata *conn, curl_socket_t *socks)
+cr_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
+ curl_socket_t *socks)
{
- struct ssl_connect_data *const connssl = &conn->ssl[FIRSTSOCKET];
- curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- struct ssl_backend_data *const backend = connssl->backend;
+ struct ssl_connect_data *const connssl = cf->ctx;
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
+ struct rustls_ssl_backend_data *const backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
struct rustls_connection *rconn = NULL;
+ (void)data;
DEBUGASSERT(backend);
rconn = backend->conn;
@@ -565,17 +625,18 @@
cr_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct rustls_ssl_backend_data *backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
return &backend->conn;
}
static void
-cr_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+cr_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct rustls_ssl_backend_data *backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
CURLcode tmperr = CURLE_OK;
ssize_t n = 0;
@@ -583,9 +644,9 @@
if(backend->conn) {
rustls_connection_send_close_notify(backend->conn);
- n = cr_send(data, sockindex, NULL, 0, &tmperr);
+ n = cr_send(cf, data, NULL, 0, &tmperr);
if(n < 0) {
- failf(data, "error sending close notify: %d", tmperr);
+ failf(data, "rustls: error sending close_notify: %d", tmperr);
}
rustls_connection_free(backend->conn);
@@ -606,8 +667,9 @@
const struct Curl_ssl Curl_ssl_rustls = {
{ CURLSSLBACKEND_RUSTLS, "rustls" },
SSLSUPP_CAINFO_BLOB | /* supports */
- SSLSUPP_TLS13_CIPHERSUITES,
- sizeof(struct ssl_backend_data),
+ SSLSUPP_TLS13_CIPHERSUITES |
+ SSLSUPP_HTTPS_PROXY,
+ sizeof(struct rustls_ssl_backend_data),
Curl_none_init, /* init */
Curl_none_cleanup, /* cleanup */
@@ -619,7 +681,7 @@
Curl_none_cert_status_request, /* cert_status_request */
cr_connect, /* connect */
cr_connect_nonblocking, /* connect_nonblocking */
- cr_getsock, /* cr_getsock */
+ cr_get_select_socks, /* get_select_socks */
cr_get_internals, /* get_internals */
cr_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -630,7 +692,10 @@
Curl_none_false_start, /* false_start */
NULL, /* sha256sum */
NULL, /* associate_connection */
- NULL /* disassociate_connection */
+ NULL, /* disassociate_connection */
+ NULL, /* free_multi_ssl_backend_data */
+ cr_recv, /* recv decrypted data */
+ cr_send, /* send data to encrypt */
};
#endif /* USE_RUSTLS */
diff --git a/lib/vtls/rustls.h b/lib/vtls/rustls.h
index 6b393dd..bfbe23d 100644
--- a/lib/vtls/rustls.h
+++ b/lib/vtls/rustls.h
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Jacob Hoffman-Andrews,
+ * Copyright (C) Jacob Hoffman-Andrews,
* <github@hoffman-andrews.com>
*
* This software is licensed as described in the file COPYING, which
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 7e42285..5dcf5ba 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -5,9 +5,9 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
- * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Marc Hoersken, <info@marc-hoersken.de>
+ * Copyright (C) Mark Salisbury, <mark.salisbury@hp.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,14 +33,14 @@
#ifdef USE_SCHANNEL
-#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
-
#ifndef USE_WINDOWS_SSPI
# error "Can't compile SCHANNEL support without SSPI."
#endif
#include "schannel.h"
+#include "schannel_int.h"
#include "vtls.h"
+#include "vtls_int.h"
#include "strcase.h"
#include "sendf.h"
#include "connect.h" /* for the connect timeout */
@@ -53,6 +53,7 @@
#include "curl_printf.h"
#include "multiif.h"
#include "version_win32.h"
+#include "rand.h"
/* The last #include file should be: */
#include "curl_memory.h"
@@ -83,8 +84,35 @@
#endif
#endif
-#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX)
-#define HAS_CLIENT_CERT_PATH
+#ifndef BCRYPT_CHACHA20_POLY1305_ALGORITHM
+#define BCRYPT_CHACHA20_POLY1305_ALGORITHM L"CHACHA20_POLY1305"
+#endif
+
+#ifndef BCRYPT_CHAIN_MODE_CCM
+#define BCRYPT_CHAIN_MODE_CCM L"ChainingModeCCM"
+#endif
+
+#ifndef BCRYPT_CHAIN_MODE_GCM
+#define BCRYPT_CHAIN_MODE_GCM L"ChainingModeGCM"
+#endif
+
+#ifndef BCRYPT_AES_ALGORITHM
+#define BCRYPT_AES_ALGORITHM L"AES"
+#endif
+
+#ifndef BCRYPT_SHA256_ALGORITHM
+#define BCRYPT_SHA256_ALGORITHM L"SHA256"
+#endif
+
+#ifndef BCRYPT_SHA384_ALGORITHM
+#define BCRYPT_SHA384_ALGORITHM L"SHA384"
+#endif
+
+/* Workaround broken compilers like MinGW.
+ Return the number of elements in a statically sized array.
+*/
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
#ifdef HAS_CLIENT_CERT_PATH
@@ -119,6 +147,10 @@
#define SP_PROT_TLS1_2_CLIENT 0x00000800
#endif
+#ifndef SP_PROT_TLS1_3_CLIENT
+#define SP_PROT_TLS1_3_CLIENT 0x00002000
+#endif
+
#ifndef SCH_USE_STRONG_CRYPTO
#define SCH_USE_STRONG_CRYPTO 0x00400000
#endif
@@ -149,12 +181,13 @@
#define ALG_CLASS_DHASH ALG_CLASS_HASH
#endif
-static Curl_recv schannel_recv;
-static Curl_send schannel_send;
+#ifndef PKCS12_NO_PERSIST_KEY
+#define PKCS12_NO_PERSIST_KEY 0x00008000
+#endif
-static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
- struct connectdata *conn, int sockindex,
- const char *pinnedpubkey);
+static CURLcode schannel_pkp_pin_peer_pubkey(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *pinnedpubkey);
static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType,
void *BufDataPtr, unsigned long BufByteSize)
@@ -173,158 +206,190 @@
}
static CURLcode
-set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct Curl_easy *data,
- struct connectdata *conn)
+schannel_set_ssl_version_min_max(DWORD *enabled_protocols,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- long ssl_version = SSL_CONN_CONFIG(version);
- long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ 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;
long i = ssl_version;
switch(ssl_version_max) {
case CURL_SSLVERSION_MAX_NONE:
case CURL_SSLVERSION_MAX_DEFAULT:
- ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+
+ /* Windows Server 2022 and newer (including Windows 11) support TLS 1.3
+ built-in. Previous builds of Windows 10 had broken TLS 1.3
+ implementations that could be enabled via registry.
+ */
+ if(curlx_verify_windows_version(10, 0, 20348, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL)) {
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
+ }
+ else /* Windows 10 and older */
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+
break;
}
+
for(; i <= (ssl_version_max >> 16); ++i) {
switch(i) {
case CURL_SSLVERSION_TLSv1_0:
- schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT;
+ (*enabled_protocols) |= SP_PROT_TLS1_0_CLIENT;
break;
case CURL_SSLVERSION_TLSv1_1:
- schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT;
+ (*enabled_protocols) |= SP_PROT_TLS1_1_CLIENT;
break;
case CURL_SSLVERSION_TLSv1_2:
- schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT;
+ (*enabled_protocols) |= SP_PROT_TLS1_2_CLIENT;
break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "schannel: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+
+ /* Windows Server 2022 and newer */
+ if(curlx_verify_windows_version(10, 0, 20348, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL)) {
+ (*enabled_protocols) |= SP_PROT_TLS1_3_CLIENT;
+ break;
+ }
+ else { /* Windows 10 and older */
+ failf(data, "schannel: TLS 1.3 not supported on Windows prior to 11");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
}
}
return CURLE_OK;
}
-/*longest is 26, buffer is slightly bigger*/
+/* longest is 26, buffer is slightly bigger */
#define LONGEST_ALG_ID 32
-#define CIPHEROPTION(X) \
- if(strcmp(#X, tmp) == 0) \
- return X
+#define CIPHEROPTION(x) {#x, x}
+
+struct algo {
+ const char *name;
+ int id;
+};
+
+static const struct algo algs[]= {
+ CIPHEROPTION(CALG_MD2),
+ CIPHEROPTION(CALG_MD4),
+ CIPHEROPTION(CALG_MD5),
+ CIPHEROPTION(CALG_SHA),
+ CIPHEROPTION(CALG_SHA1),
+ CIPHEROPTION(CALG_MAC),
+ CIPHEROPTION(CALG_RSA_SIGN),
+ CIPHEROPTION(CALG_DSS_SIGN),
+/* ifdefs for the options that are defined conditionally in wincrypt.h */
+#ifdef CALG_NO_SIGN
+ CIPHEROPTION(CALG_NO_SIGN),
+#endif
+ CIPHEROPTION(CALG_RSA_KEYX),
+ CIPHEROPTION(CALG_DES),
+#ifdef CALG_3DES_112
+ CIPHEROPTION(CALG_3DES_112),
+#endif
+ CIPHEROPTION(CALG_3DES),
+ CIPHEROPTION(CALG_DESX),
+ CIPHEROPTION(CALG_RC2),
+ CIPHEROPTION(CALG_RC4),
+ CIPHEROPTION(CALG_SEAL),
+#ifdef CALG_DH_SF
+ CIPHEROPTION(CALG_DH_SF),
+#endif
+ CIPHEROPTION(CALG_DH_EPHEM),
+#ifdef CALG_AGREEDKEY_ANY
+ CIPHEROPTION(CALG_AGREEDKEY_ANY),
+#endif
+#ifdef CALG_HUGHES_MD5
+ CIPHEROPTION(CALG_HUGHES_MD5),
+#endif
+ CIPHEROPTION(CALG_SKIPJACK),
+#ifdef CALG_TEK
+ CIPHEROPTION(CALG_TEK),
+#endif
+ CIPHEROPTION(CALG_CYLINK_MEK),
+ CIPHEROPTION(CALG_SSL3_SHAMD5),
+#ifdef CALG_SSL3_MASTER
+ CIPHEROPTION(CALG_SSL3_MASTER),
+#endif
+#ifdef CALG_SCHANNEL_MASTER_HASH
+ CIPHEROPTION(CALG_SCHANNEL_MASTER_HASH),
+#endif
+#ifdef CALG_SCHANNEL_MAC_KEY
+ CIPHEROPTION(CALG_SCHANNEL_MAC_KEY),
+#endif
+#ifdef CALG_SCHANNEL_ENC_KEY
+ CIPHEROPTION(CALG_SCHANNEL_ENC_KEY),
+#endif
+#ifdef CALG_PCT1_MASTER
+ CIPHEROPTION(CALG_PCT1_MASTER),
+#endif
+#ifdef CALG_SSL2_MASTER
+ CIPHEROPTION(CALG_SSL2_MASTER),
+#endif
+#ifdef CALG_TLS1_MASTER
+ CIPHEROPTION(CALG_TLS1_MASTER),
+#endif
+#ifdef CALG_RC5
+ CIPHEROPTION(CALG_RC5),
+#endif
+#ifdef CALG_HMAC
+ CIPHEROPTION(CALG_HMAC),
+#endif
+#ifdef CALG_TLS1PRF
+ CIPHEROPTION(CALG_TLS1PRF),
+#endif
+#ifdef CALG_HASH_REPLACE_OWF
+ CIPHEROPTION(CALG_HASH_REPLACE_OWF),
+#endif
+#ifdef CALG_AES_128
+ CIPHEROPTION(CALG_AES_128),
+#endif
+#ifdef CALG_AES_192
+ CIPHEROPTION(CALG_AES_192),
+#endif
+#ifdef CALG_AES_256
+ CIPHEROPTION(CALG_AES_256),
+#endif
+#ifdef CALG_AES
+ CIPHEROPTION(CALG_AES),
+#endif
+#ifdef CALG_SHA_256
+ CIPHEROPTION(CALG_SHA_256),
+#endif
+#ifdef CALG_SHA_384
+ CIPHEROPTION(CALG_SHA_384),
+#endif
+#ifdef CALG_SHA_512
+ CIPHEROPTION(CALG_SHA_512),
+#endif
+#ifdef CALG_ECDH
+ CIPHEROPTION(CALG_ECDH),
+#endif
+#ifdef CALG_ECMQV
+ CIPHEROPTION(CALG_ECMQV),
+#endif
+#ifdef CALG_ECDSA
+ CIPHEROPTION(CALG_ECDSA),
+#endif
+#ifdef CALG_ECDH_EPHEM
+ CIPHEROPTION(CALG_ECDH_EPHEM),
+#endif
+ {NULL, 0},
+};
static int
get_alg_id_by_name(char *name)
{
- char tmp[LONGEST_ALG_ID] = { 0 };
char *nameEnd = strchr(name, ':');
- size_t n = nameEnd ? min((size_t)(nameEnd - name), LONGEST_ALG_ID - 1) : \
- min(strlen(name), LONGEST_ALG_ID - 1);
- strncpy(tmp, name, n);
- tmp[n] = 0;
- CIPHEROPTION(CALG_MD2);
- CIPHEROPTION(CALG_MD4);
- CIPHEROPTION(CALG_MD5);
- CIPHEROPTION(CALG_SHA);
- CIPHEROPTION(CALG_SHA1);
- CIPHEROPTION(CALG_MAC);
- CIPHEROPTION(CALG_RSA_SIGN);
- CIPHEROPTION(CALG_DSS_SIGN);
-/*ifdefs for the options that are defined conditionally in wincrypt.h*/
-#ifdef CALG_NO_SIGN
- CIPHEROPTION(CALG_NO_SIGN);
-#endif
- CIPHEROPTION(CALG_RSA_KEYX);
- CIPHEROPTION(CALG_DES);
-#ifdef CALG_3DES_112
- CIPHEROPTION(CALG_3DES_112);
-#endif
- CIPHEROPTION(CALG_3DES);
- CIPHEROPTION(CALG_DESX);
- CIPHEROPTION(CALG_RC2);
- CIPHEROPTION(CALG_RC4);
- CIPHEROPTION(CALG_SEAL);
-#ifdef CALG_DH_SF
- CIPHEROPTION(CALG_DH_SF);
-#endif
- CIPHEROPTION(CALG_DH_EPHEM);
-#ifdef CALG_AGREEDKEY_ANY
- CIPHEROPTION(CALG_AGREEDKEY_ANY);
-#endif
-#ifdef CALG_HUGHES_MD5
- CIPHEROPTION(CALG_HUGHES_MD5);
-#endif
- CIPHEROPTION(CALG_SKIPJACK);
-#ifdef CALG_TEK
- CIPHEROPTION(CALG_TEK);
-#endif
- CIPHEROPTION(CALG_CYLINK_MEK);
- CIPHEROPTION(CALG_SSL3_SHAMD5);
-#ifdef CALG_SSL3_MASTER
- CIPHEROPTION(CALG_SSL3_MASTER);
-#endif
-#ifdef CALG_SCHANNEL_MASTER_HASH
- CIPHEROPTION(CALG_SCHANNEL_MASTER_HASH);
-#endif
-#ifdef CALG_SCHANNEL_MAC_KEY
- CIPHEROPTION(CALG_SCHANNEL_MAC_KEY);
-#endif
-#ifdef CALG_SCHANNEL_ENC_KEY
- CIPHEROPTION(CALG_SCHANNEL_ENC_KEY);
-#endif
-#ifdef CALG_PCT1_MASTER
- CIPHEROPTION(CALG_PCT1_MASTER);
-#endif
-#ifdef CALG_SSL2_MASTER
- CIPHEROPTION(CALG_SSL2_MASTER);
-#endif
-#ifdef CALG_TLS1_MASTER
- CIPHEROPTION(CALG_TLS1_MASTER);
-#endif
-#ifdef CALG_RC5
- CIPHEROPTION(CALG_RC5);
-#endif
-#ifdef CALG_HMAC
- CIPHEROPTION(CALG_HMAC);
-#endif
-#ifdef CALG_TLS1PRF
- CIPHEROPTION(CALG_TLS1PRF);
-#endif
-#ifdef CALG_HASH_REPLACE_OWF
- CIPHEROPTION(CALG_HASH_REPLACE_OWF);
-#endif
-#ifdef CALG_AES_128
- CIPHEROPTION(CALG_AES_128);
-#endif
-#ifdef CALG_AES_192
- CIPHEROPTION(CALG_AES_192);
-#endif
-#ifdef CALG_AES_256
- CIPHEROPTION(CALG_AES_256);
-#endif
-#ifdef CALG_AES
- CIPHEROPTION(CALG_AES);
-#endif
-#ifdef CALG_SHA_256
- CIPHEROPTION(CALG_SHA_256);
-#endif
-#ifdef CALG_SHA_384
- CIPHEROPTION(CALG_SHA_384);
-#endif
-#ifdef CALG_SHA_512
- CIPHEROPTION(CALG_SHA_512);
-#endif
-#ifdef CALG_ECDH
- CIPHEROPTION(CALG_ECDH);
-#endif
-#ifdef CALG_ECMQV
- CIPHEROPTION(CALG_ECMQV);
-#endif
-#ifdef CALG_ECDSA
- CIPHEROPTION(CALG_ECDSA);
-#endif
-#ifdef CALG_ECDH_EPHEM
- CIPHEROPTION(CALG_ECDH_EPHEM);
-#endif
- return 0;
+ size_t n = nameEnd ? (size_t)(nameEnd - name) : strlen(name);
+ int i;
+
+ for(i = 0; algs[i].name; i++) {
+ if((n == strlen(algs[i].name) && !strncmp(algs[i].name, name, n)))
+ return algs[i].id;
+ }
+ return 0; /* not found */
}
#define NUM_CIPHERS 47 /* There are 47 options listed above */
@@ -385,13 +450,13 @@
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)
+ store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY;
else if(_tcsncmp(path, TEXT("LocalMachineGroupPolicy"),
- store_name_len) == 0)
+ store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY;
else if(_tcsncmp(path, TEXT("LocalMachineEnterprise"),
- store_name_len) == 0)
+ store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE;
else
return CURLE_SSL_CERTPROBLEM;
@@ -416,76 +481,81 @@
}
#endif
static CURLcode
-schannel_acquire_credential_handle(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex)
+schannel_acquire_credential_handle(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- SCHANNEL_CRED schannel_cred;
- ALG_ID algIds[NUM_CIPHERS];
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+
+#ifdef HAS_CLIENT_CERT_PATH
PCCERT_CONTEXT client_certs[1] = { NULL };
+ HCERTSTORE client_cert_store = NULL;
+#endif
SECURITY_STATUS sspi_status = SEC_E_OK;
CURLcode result;
- struct ssl_backend_data *backend = connssl->backend;
+
+ /* setup Schannel API options */
+ DWORD flags = 0;
+ DWORD enabled_protocols = 0;
+
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)(connssl->backend);
DEBUGASSERT(backend);
- /* setup Schannel API options */
- memset(&schannel_cred, 0, sizeof(schannel_cred));
- schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
-
- if(conn->ssl_config.verifypeer) {
+ if(conn_config->verifypeer) {
#ifdef HAS_MANUAL_VERIFY_API
if(backend->use_manual_cred_validation)
- schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
+ flags = SCH_CRED_MANUAL_CRED_VALIDATION;
else
#endif
- schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
+ flags = SCH_CRED_AUTO_CRED_VALIDATION;
- if(SSL_SET_OPTION(no_revoke)) {
- schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
+ if(ssl_config->no_revoke) {
+ flags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE;
DEBUGF(infof(data, "schannel: disabled server certificate revocation "
"checks"));
}
- else if(SSL_SET_OPTION(revoke_best_effort)) {
- schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
+ else if(ssl_config->revoke_best_effort) {
+ flags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN;
DEBUGF(infof(data, "schannel: ignore revocation offline errors"));
}
else {
- schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
+ flags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
DEBUGF(infof(data,
"schannel: checking server certificate revocation"));
}
}
else {
- schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
+ 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"));
}
- if(!conn->ssl_config.verifyhost) {
- schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
+ 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."));
}
- if(!SSL_SET_OPTION(auto_client_cert)) {
- schannel_cred.dwFlags &= ~SCH_CRED_USE_DEFAULT_CREDS;
- schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
+ if(!ssl_config->auto_client_cert) {
+ flags &= ~SCH_CRED_USE_DEFAULT_CREDS;
+ flags |= SCH_CRED_NO_DEFAULT_CREDS;
infof(data, "schannel: disabled automatic use of client certificate");
}
else
infof(data, "schannel: enabled automatic use of client certificate");
- switch(conn->ssl_config.version) {
+ switch(conn_config->version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
case CURL_SSLVERSION_TLSv1_0:
@@ -493,7 +563,7 @@
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- result = set_ssl_version_min_max(&schannel_cred, data, conn);
+ result = schannel_set_ssl_version_min_max(&enabled_protocols, cf, data);
if(result != CURLE_OK)
return result;
break;
@@ -507,16 +577,6 @@
return CURLE_SSL_CONNECT_ERROR;
}
- if(SSL_CONN_CONFIG(cipher_list)) {
- result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list),
- algIds);
- if(CURLE_OK != result) {
- failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
- return result;
- }
- }
-
-
#ifdef HAS_CLIENT_CERT_PATH
/* client certificate */
if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) {
@@ -542,7 +602,7 @@
return CURLE_OUT_OF_MEMORY;
result = get_cert_location(cert_path, &cert_store_name,
- &cert_store_path, &cert_thumbprint_str);
+ &cert_store_path, &cert_thumbprint_str);
if(result && (data->set.ssl.primary.clientcert[0]!='\0'))
fInCert = fopen(data->set.ssl.primary.clientcert, "rb");
@@ -557,18 +617,18 @@
}
if((fInCert || blob) && (data->set.ssl.cert_type) &&
- (!strcasecompare(data->set.ssl.cert_type, "P12"))) {
+ (!strcasecompare(data->set.ssl.cert_type, "P12"))) {
failf(data, "schannel: certificate format compatibility error "
- " for %s",
- blob ? "(memory blob)" : data->set.ssl.primary.clientcert);
+ " for %s",
+ blob ? "(memory blob)" : data->set.ssl.primary.clientcert);
curlx_unicodefree(cert_path);
return CURLE_SSL_CERTPROBLEM;
}
if(fInCert || blob) {
/* Reading a .P12 or .pfx file, like the example at bottom of
- https://social.msdn.microsoft.com/Forums/windowsdesktop/
- en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5
+ https://social.msdn.microsoft.com/Forums/windowsdesktop/
+ en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5
*/
CRYPT_DATA_BLOB datablob;
WCHAR* pszPassword;
@@ -596,7 +656,7 @@
fclose(fInCert);
if(!continue_reading) {
failf(data, "schannel: Failed to read cert file %s",
- data->set.ssl.primary.clientcert);
+ data->set.ssl.primary.clientcert);
free(certdata);
return CURLE_SSL_CERTPROBLEM;
}
@@ -612,16 +672,23 @@
if(pszPassword) {
if(pwd_len > 0)
str_w_len = MultiByteToWideChar(CP_UTF8,
- MB_ERR_INVALID_CHARS,
- data->set.ssl.key_passwd, (int)pwd_len,
- pszPassword, (int)(pwd_len + 1));
+ MB_ERR_INVALID_CHARS,
+ data->set.ssl.key_passwd,
+ (int)pwd_len,
+ pszPassword, (int)(pwd_len + 1));
if((str_w_len >= 0) && (str_w_len <= (int)pwd_len))
pszPassword[str_w_len] = 0;
else
pszPassword[0] = 0;
- cert_store = PFXImportCertStore(&datablob, pszPassword, 0);
+ if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL))
+ cert_store = PFXImportCertStore(&datablob, pszPassword,
+ PKCS12_NO_PERSIST_KEY);
+ else
+ cert_store = PFXImportCertStore(&datablob, pszPassword, 0);
+
free(pszPassword);
}
if(!blob)
@@ -650,9 +717,6 @@
CertCloseStore(cert_store, 0);
return CURLE_SSL_CERTPROBLEM;
}
-
- schannel_cred.cCreds = 1;
- schannel_cred.paCred = client_certs;
}
else {
cert_store =
@@ -690,17 +754,13 @@
curlx_unicodefree(cert_path);
- if(client_certs[0]) {
- schannel_cred.cCreds = 1;
- schannel_cred.paCred = client_certs;
- }
- else {
+ if(!client_certs[0]) {
/* CRYPT_E_NOT_FOUND / E_INVALIDARG */
CertCloseStore(cert_store, 0);
return CURLE_SSL_CERTPROBLEM;
}
}
- CertCloseStore(cert_store, 0);
+ client_cert_store = cert_store;
}
#else
if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) {
@@ -715,22 +775,279 @@
if(!backend->cred) {
failf(data, "schannel: unable to allocate memory");
+#ifdef HAS_CLIENT_CERT_PATH
if(client_certs[0])
CertFreeCertificateContext(client_certs[0]);
+ if(client_cert_store)
+ CertCloseStore(client_cert_store, 0);
+#endif
return CURLE_OUT_OF_MEMORY;
}
backend->cred->refcount = 1;
- sspi_status =
- s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
- SECPKG_CRED_OUTBOUND, NULL,
- &schannel_cred, NULL, NULL,
- &backend->cred->cred_handle,
- &backend->cred->time_stamp);
+#ifdef HAS_CLIENT_CERT_PATH
+ /* Since we did not persist the key, we need to extend the store's
+ * lifetime until the end of the connection
+ */
+ backend->cred->client_cert_store = client_cert_store;
+#endif
+ /* Windows 10, 1809 (a.k.a. Windows 10 build 17763) */
+ if(curlx_verify_windows_version(10, 0, 17763, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL)) {
+
+ char *ciphers13 = 0;
+
+ bool disable_aes_gcm_sha384 = FALSE;
+ bool disable_aes_gcm_sha256 = FALSE;
+ bool disable_chacha_poly = FALSE;
+ bool disable_aes_ccm_8_sha256 = FALSE;
+ bool disable_aes_ccm_sha256 = FALSE;
+
+ SCH_CREDENTIALS credentials = { 0 };
+ TLS_PARAMETERS tls_parameters = { 0 };
+ CRYPTO_SETTINGS crypto_settings[4] = { 0 };
+ UNICODE_STRING blocked_ccm_modes[1] = { 0 };
+ UNICODE_STRING blocked_gcm_modes[1] = { 0 };
+
+ int crypto_settings_idx = 0;
+
+
+ /* If TLS 1.3 ciphers are explicitly listed, then
+ * disable all the ciphers and re-enable which
+ * ciphers the user has provided.
+ */
+ ciphers13 = conn_config->cipher_list13;
+ if(ciphers13) {
+ const int remaining_ciphers = 5;
+
+ /* detect which remaining ciphers to enable
+ and then disable everything else.
+ */
+
+ char *startCur = ciphers13;
+ int algCount = 0;
+ char tmp[LONGEST_ALG_ID] = { 0 };
+ char *nameEnd;
+ size_t n;
+
+ disable_aes_gcm_sha384 = TRUE;
+ disable_aes_gcm_sha256 = TRUE;
+ disable_chacha_poly = TRUE;
+ disable_aes_ccm_8_sha256 = TRUE;
+ disable_aes_ccm_sha256 = TRUE;
+
+ while(startCur && (0 != *startCur) && (algCount < remaining_ciphers)) {
+ nameEnd = strchr(startCur, ':');
+ n = nameEnd ? (size_t)(nameEnd - startCur) : strlen(startCur);
+
+ /* reject too-long cipher names */
+ if(n > (LONGEST_ALG_ID - 1)) {
+ failf(data, "Cipher name too long, not checked.");
+ return CURLE_SSL_CIPHER;
+ }
+
+ strncpy(tmp, startCur, n);
+ tmp[n] = 0;
+
+ if(disable_aes_gcm_sha384
+ && !strcmp("TLS_AES_256_GCM_SHA384", tmp)) {
+ disable_aes_gcm_sha384 = FALSE;
+ }
+ else if(disable_aes_gcm_sha256
+ && !strcmp("TLS_AES_128_GCM_SHA256", tmp)) {
+ disable_aes_gcm_sha256 = FALSE;
+ }
+ else if(disable_chacha_poly
+ && !strcmp("TLS_CHACHA20_POLY1305_SHA256", tmp)) {
+ disable_chacha_poly = FALSE;
+ }
+ else if(disable_aes_ccm_8_sha256
+ && !strcmp("TLS_AES_128_CCM_8_SHA256", tmp)) {
+ disable_aes_ccm_8_sha256 = FALSE;
+ }
+ else if(disable_aes_ccm_sha256
+ && !strcmp("TLS_AES_128_CCM_SHA256", tmp)) {
+ disable_aes_ccm_sha256 = FALSE;
+ }
+ else {
+ failf(data, "Passed in an unknown TLS 1.3 cipher.");
+ return CURLE_SSL_CIPHER;
+ }
+
+ startCur = nameEnd;
+ if(startCur)
+ startCur++;
+
+ algCount++;
+ }
+ }
+
+ if(disable_aes_gcm_sha384 && disable_aes_gcm_sha256
+ && disable_chacha_poly && disable_aes_ccm_8_sha256
+ && disable_aes_ccm_sha256) {
+ failf(data, "All available TLS 1.3 ciphers were disabled.");
+ return CURLE_SSL_CIPHER;
+ }
+
+ /* Disable TLS_AES_128_CCM_8_SHA256 and/or TLS_AES_128_CCM_SHA256 */
+ if(disable_aes_ccm_8_sha256 || disable_aes_ccm_sha256) {
+ /*
+ Disallow AES_CCM algorithm.
+ */
+ blocked_ccm_modes[0].Length = sizeof(BCRYPT_CHAIN_MODE_CCM);
+ blocked_ccm_modes[0].MaximumLength = sizeof(BCRYPT_CHAIN_MODE_CCM);
+ blocked_ccm_modes[0].Buffer = (PWSTR)BCRYPT_CHAIN_MODE_CCM;
+
+ crypto_settings[crypto_settings_idx].eAlgorithmUsage =
+ TlsParametersCngAlgUsageCipher;
+ crypto_settings[crypto_settings_idx].rgstrChainingModes =
+ blocked_ccm_modes;
+ crypto_settings[crypto_settings_idx].cChainingModes =
+ ARRAYSIZE(blocked_ccm_modes);
+ crypto_settings[crypto_settings_idx].strCngAlgId.Length =
+ sizeof(BCRYPT_AES_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.MaximumLength =
+ sizeof(BCRYPT_AES_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.Buffer =
+ (PWSTR)BCRYPT_AES_ALGORITHM;
+
+ /* only disabling one of the CCM modes */
+ if(disable_aes_ccm_8_sha256 != disable_aes_ccm_sha256) {
+ if(disable_aes_ccm_8_sha256)
+ crypto_settings[crypto_settings_idx].dwMinBitLength = 128;
+ else /* disable_aes_ccm_sha256 */
+ crypto_settings[crypto_settings_idx].dwMaxBitLength = 64;
+ }
+
+ crypto_settings_idx++;
+ }
+
+ /* Disable TLS_AES_256_GCM_SHA384 and/or TLS_AES_128_GCM_SHA256 */
+ if(disable_aes_gcm_sha384 || disable_aes_gcm_sha256) {
+
+ /*
+ Disallow AES_GCM algorithm
+ */
+ blocked_gcm_modes[0].Length = sizeof(BCRYPT_CHAIN_MODE_GCM);
+ blocked_gcm_modes[0].MaximumLength = sizeof(BCRYPT_CHAIN_MODE_GCM);
+ blocked_gcm_modes[0].Buffer = (PWSTR)BCRYPT_CHAIN_MODE_GCM;
+
+ /* if only one is disabled, then explicitly disable the
+ digest cipher suite (sha384 or sha256) */
+ if(disable_aes_gcm_sha384 != disable_aes_gcm_sha256) {
+ crypto_settings[crypto_settings_idx].eAlgorithmUsage =
+ TlsParametersCngAlgUsageDigest;
+ crypto_settings[crypto_settings_idx].strCngAlgId.Length =
+ sizeof(disable_aes_gcm_sha384 ?
+ BCRYPT_SHA384_ALGORITHM : BCRYPT_SHA256_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.MaximumLength =
+ sizeof(disable_aes_gcm_sha384 ?
+ BCRYPT_SHA384_ALGORITHM : BCRYPT_SHA256_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.Buffer =
+ (PWSTR)(disable_aes_gcm_sha384 ?
+ BCRYPT_SHA384_ALGORITHM : BCRYPT_SHA256_ALGORITHM);
+ }
+ else { /* Disable both AES_GCM ciphers */
+ crypto_settings[crypto_settings_idx].eAlgorithmUsage =
+ TlsParametersCngAlgUsageCipher;
+ crypto_settings[crypto_settings_idx].strCngAlgId.Length =
+ sizeof(BCRYPT_AES_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.MaximumLength =
+ sizeof(BCRYPT_AES_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.Buffer =
+ (PWSTR)BCRYPT_AES_ALGORITHM;
+ }
+
+ crypto_settings[crypto_settings_idx].rgstrChainingModes =
+ blocked_gcm_modes;
+ crypto_settings[crypto_settings_idx].cChainingModes = 1;
+
+ crypto_settings_idx++;
+ }
+
+ /*
+ Disable ChaCha20-Poly1305.
+ */
+ if(disable_chacha_poly) {
+ crypto_settings[crypto_settings_idx].eAlgorithmUsage =
+ TlsParametersCngAlgUsageCipher;
+ crypto_settings[crypto_settings_idx].strCngAlgId.Length =
+ sizeof(BCRYPT_CHACHA20_POLY1305_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.MaximumLength =
+ sizeof(BCRYPT_CHACHA20_POLY1305_ALGORITHM);
+ crypto_settings[crypto_settings_idx].strCngAlgId.Buffer =
+ (PWSTR)BCRYPT_CHACHA20_POLY1305_ALGORITHM;
+ crypto_settings_idx++;
+ }
+
+ tls_parameters.pDisabledCrypto = crypto_settings;
+
+ /* The number of blocked suites */
+ tls_parameters.cDisabledCrypto = crypto_settings_idx;
+ credentials.pTlsParameters = &tls_parameters;
+ credentials.cTlsParameters = 1;
+
+ credentials.dwVersion = SCH_CREDENTIALS_VERSION;
+ credentials.dwFlags = flags | SCH_USE_STRONG_CRYPTO;
+
+ credentials.pTlsParameters->grbitDisabledProtocols =
+ (DWORD)~enabled_protocols;
+
+#ifdef HAS_CLIENT_CERT_PATH
+ if(client_certs[0]) {
+ credentials.cCreds = 1;
+ credentials.paCred = client_certs;
+ }
+#endif
+
+ sspi_status =
+ s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR*)UNISP_NAME,
+ SECPKG_CRED_OUTBOUND, NULL,
+ &credentials, NULL, NULL,
+ &backend->cred->cred_handle,
+ &backend->cred->time_stamp);
+ }
+ else {
+ /* Pre-Windows 10 1809 */
+ ALG_ID algIds[NUM_CIPHERS];
+ char *ciphers = conn_config->cipher_list;
+ SCHANNEL_CRED schannel_cred = { 0 };
+ schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
+ schannel_cred.dwFlags = flags;
+ schannel_cred.grbitEnabledProtocols = enabled_protocols;
+
+ if(ciphers) {
+ result = set_ssl_ciphers(&schannel_cred, ciphers, algIds);
+ if(CURLE_OK != result) {
+ failf(data, "Unable to set ciphers to from connection ssl config");
+ return result;
+ }
+ }
+ else {
+ schannel_cred.dwFlags = flags | SCH_USE_STRONG_CRYPTO;
+ }
+
+#ifdef HAS_CLIENT_CERT_PATH
+ if(client_certs[0]) {
+ schannel_cred.cCreds = 1;
+ schannel_cred.paCred = client_certs;
+ }
+#endif
+
+ sspi_status =
+ s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR*)UNISP_NAME,
+ SECPKG_CRED_OUTBOUND, NULL,
+ &schannel_cred, NULL, NULL,
+ &backend->cred->cred_handle,
+ &backend->cred->time_stamp);
+ }
+
+#ifdef HAS_CLIENT_CERT_PATH
if(client_certs[0])
CertFreeCertificateContext(client_certs[0]);
+#endif
if(sspi_status != SEC_E_OK) {
char buffer[STRERROR_LEN];
@@ -754,11 +1071,14 @@
}
static CURLcode
-schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
{
ssize_t written = -1;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
SecBuffer outbuf;
SecBufferDesc outbuf_desc;
SecBuffer inbuf;
@@ -773,14 +1093,12 @@
struct in6_addr addr6;
#endif
CURLcode result;
- char * const hostname = SSL_HOST_NAME();
- struct ssl_backend_data *backend = connssl->backend;
+ const char *hostname = connssl->hostname;
DEBUGASSERT(backend);
-
DEBUGF(infof(data,
- "schannel: SSL/TLS connection with %s port %hu (step 1/3)",
- hostname, conn->remote_port));
+ "schannel: SSL/TLS connection with %s port %d (step 1/3)",
+ hostname, connssl->port));
if(curlx_verify_windows_version(5, 1, 0, PLATFORM_WINNT,
VERSION_LESS_THAN_EQUAL)) {
@@ -793,7 +1111,7 @@
#ifdef HAS_ALPN
/* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
Also it doesn't seem to be supported for Wine, see curl bug #983. */
- backend->use_alpn = conn->bits.tls_enable_alpn &&
+ backend->use_alpn = connssl->alpn &&
!GetProcAddress(GetModuleHandle(TEXT("ntdll")),
"wine_get_version") &&
curlx_verify_windows_version(6, 3, 0, PLATFORM_WINNT,
@@ -812,7 +1130,7 @@
#endif
#else
#ifdef HAS_MANUAL_VERIFY_API
- if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) {
+ if(conn_config->CAfile || conn_config->ca_info_blob) {
if(curlx_verify_windows_version(6, 1, 0, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL)) {
backend->use_manual_cred_validation = true;
@@ -826,7 +1144,7 @@
else
backend->use_manual_cred_validation = false;
#else
- if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) {
+ if(conn_config->CAfile || conn_config->ca_info_blob) {
failf(data, "schannel: CA cert support not built in");
return CURLE_NOT_BUILT_IN;
}
@@ -836,11 +1154,9 @@
backend->cred = NULL;
/* check for an existing re-usable credential handle */
- if(SSL_SET_OPTION(primary.sessionid)) {
+ if(ssl_config->primary.sessionid) {
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn,
- SSL_IS_PROXY() ? TRUE : FALSE,
- (void **)&old_cred, NULL, sockindex)) {
+ if(!Curl_ssl_getsessionid(cf, data, (void **)&old_cred, NULL)) {
backend->cred = old_cred;
DEBUGF(infof(data, "schannel: re-using existing credential handle"));
@@ -855,13 +1171,15 @@
if(!backend->cred) {
char *snihost;
- result = schannel_acquire_credential_handle(data, conn, sockindex);
- if(result != CURLE_OK) {
+ result = schannel_acquire_credential_handle(cf, data);
+ if(result)
return result;
- }
+ /* schannel_acquire_credential_handle() sets backend->cred accordingly or
+ it returns error otherwise. */
+
/* A hostname associated with the credential is needed by
InitializeSecurityContext for SNI and other reasons. */
- snihost = Curl_ssl_snihost(data, SSL_HOST_NAME(), NULL);
+ snihost = Curl_ssl_snihost(data, hostname, NULL);
if(!snihost) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
@@ -886,44 +1204,44 @@
int list_start_index = 0;
unsigned int *extension_len = NULL;
unsigned short* list_len = NULL;
+ struct alpn_proto_buf proto;
/* The first four bytes will be an unsigned int indicating number
of bytes of data in the rest of the buffer. */
- extension_len = (unsigned int *)(&alpn_buffer[cur]);
- cur += sizeof(unsigned int);
+ extension_len = (unsigned int *)(void *)(&alpn_buffer[cur]);
+ cur += (int)sizeof(unsigned int);
/* The next four bytes are an indicator that this buffer will contain
ALPN data, as opposed to NPN, for example. */
- *(unsigned int *)&alpn_buffer[cur] =
+ *(unsigned int *)(void *)&alpn_buffer[cur] =
SecApplicationProtocolNegotiationExt_ALPN;
- cur += sizeof(unsigned int);
+ cur += (int)sizeof(unsigned int);
/* The next two bytes will be an unsigned short indicating the number
of bytes used to list the preferred protocols. */
- list_len = (unsigned short*)(&alpn_buffer[cur]);
- cur += sizeof(unsigned short);
+ list_len = (unsigned short*)(void *)(&alpn_buffer[cur]);
+ cur += (int)sizeof(unsigned short);
list_start_index = cur;
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
- alpn_buffer[cur++] = ALPN_H2_LENGTH;
- memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH);
- cur += ALPN_H2_LENGTH;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+ result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
+ if(result) {
+ failf(data, "Error setting ALPN");
+ return CURLE_SSL_CONNECT_ERROR;
}
-#endif
-
- alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH;
- memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
- cur += ALPN_HTTP_1_1_LENGTH;
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+ memcpy(&alpn_buffer[cur], proto.data, proto.len);
+ cur += proto.len;
*list_len = curlx_uitous(cur - list_start_index);
- *extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short);
+ *extension_len = *list_len +
+ (unsigned short)sizeof(unsigned int) +
+ (unsigned short)sizeof(unsigned short);
InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur);
InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
+
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
else {
InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
@@ -943,7 +1261,7 @@
ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
ISC_REQ_STREAM;
- if(!SSL_SET_OPTION(auto_client_cert)) {
+ if(!ssl_config->auto_client_cert) {
backend->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
}
@@ -1003,8 +1321,9 @@
"sending %lu bytes.", outbuf.cbBuffer));
/* send initial handshake data which is now stored in output buffer */
- result = Curl_write_plain(data, conn->sock[sockindex], outbuf.pvBuffer,
- outbuf.cbBuffer, &written);
+ written = Curl_conn_cf_send(cf->next, data,
+ outbuf.pvBuffer, outbuf.cbBuffer,
+ &result);
s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
failf(data, "schannel: failed to send initial handshake data: "
@@ -1018,6 +1337,7 @@
backend->recv_unrecoverable_err = CURLE_OK;
backend->recv_sspi_close_notify = false;
backend->recv_connection_closed = false;
+ backend->recv_renegotiating = false;
backend->encdata_is_incomplete = false;
/* continue to second handshake step */
@@ -1027,12 +1347,14 @@
}
static CURLcode
-schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+schannel_connect_step2(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_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
int i;
ssize_t nread = -1, written = -1;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
unsigned char *reallocated_buffer;
SecBuffer outbuf[3];
SecBufferDesc outbuf_desc;
@@ -1042,15 +1364,14 @@
CURLcode result;
bool doread;
const char *pubkey_ptr;
- struct ssl_backend_data *backend = connssl->backend;
DEBUGASSERT(backend);
doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
DEBUGF(infof(data,
- "schannel: SSL/TLS connection with %s port %hu (step 2/3)",
- SSL_HOST_NAME(), conn->remote_port));
+ "schannel: SSL/TLS connection with %s port %d (step 2/3)",
+ connssl->hostname, connssl->port));
if(!backend->cred || !backend->ctxt)
return CURLE_SSL_CONNECT_ERROR;
@@ -1100,12 +1421,12 @@
for(;;) {
if(doread) {
/* read encrypted handshake data from socket */
- result = Curl_read_plain(conn->sock[sockindex],
+ nread = Curl_conn_cf_recv(cf->next, data,
(char *) (backend->encdata_buffer +
backend->encdata_offset),
backend->encdata_length -
backend->encdata_offset,
- &nread);
+ &result);
if(result == CURLE_AGAIN) {
if(connssl->connecting_state != ssl_connect_2_writing)
connssl->connecting_state = ssl_connect_2_reading;
@@ -1189,9 +1510,9 @@
"sending %lu bytes.", outbuf[i].cbBuffer));
/* send handshake token to server */
- result = Curl_write_plain(data, conn->sock[sockindex],
- outbuf[i].pvBuffer, outbuf[i].cbBuffer,
- &written);
+ written = Curl_conn_cf_send(cf->next, data,
+ outbuf[i].pvBuffer, outbuf[i].cbBuffer,
+ &result);
if((result != CURLE_OK) ||
(outbuf[i].cbBuffer != (size_t) written)) {
failf(data, "schannel: failed to send next handshake data: "
@@ -1284,9 +1605,11 @@
DEBUGF(infof(data, "schannel: SSL/TLS handshake complete"));
}
- pubkey_ptr = SSL_PINNED_PUB_KEY();
+ pubkey_ptr = Curl_ssl_cf_is_proxy(cf)?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
if(pubkey_ptr) {
- result = pkp_pin_peer_pubkey(data, conn, sockindex, pubkey_ptr);
+ result = schannel_pkp_pin_peer_pubkey(cf, data, pubkey_ptr);
if(result) {
failf(data, "SSL: public key does not match pinned public key");
return result;
@@ -1294,8 +1617,8 @@
}
#ifdef HAS_MANUAL_VERIFY_API
- if(conn->ssl_config.verifypeer && backend->use_manual_cred_validation) {
- return Curl_verify_certificate(data, conn, sockindex);
+ if(conn_config->verifypeer && backend->use_manual_cred_validation) {
+ return Curl_verify_certificate(cf, data);
}
#endif
@@ -1362,28 +1685,25 @@
}
static CURLcode
-schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+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;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SECURITY_STATUS sspi_status = SEC_E_OK;
CERT_CONTEXT *ccert_context = NULL;
- bool isproxy = SSL_IS_PROXY();
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- const char * const hostname = SSL_HOST_NAME();
-#endif
#ifdef HAS_ALPN
SecPkgContext_ApplicationProtocol alpn_result;
#endif
- struct ssl_backend_data *backend = connssl->backend;
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
DEBUGASSERT(backend);
DEBUGF(infof(data,
- "schannel: SSL/TLS connection with %s port %hu (step 3/3)",
- hostname, conn->remote_port));
+ "schannel: SSL/TLS connection with %s port %d (step 3/3)",
+ connssl->hostname, connssl->port));
if(!backend->cred)
return CURLE_SSL_CONNECT_ERROR;
@@ -1417,39 +1737,35 @@
if(alpn_result.ProtoNegoStatus ==
SecApplicationProtocolNegotiationStatus_Success) {
+ unsigned char prev_alpn = cf->conn->alpn;
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR,
- alpn_result.ProtocolIdSize, alpn_result.ProtocolId);
-
-#ifdef USE_HTTP2
- if(alpn_result.ProtocolIdSize == ALPN_H2_LENGTH &&
- !memcmp(ALPN_H2, alpn_result.ProtocolId, ALPN_H2_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(alpn_result.ProtocolIdSize == ALPN_HTTP_1_1_LENGTH &&
- !memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId,
- ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ Curl_alpn_set_negotiated(cf, data, alpn_result.ProtocolId,
+ alpn_result.ProtocolIdSize);
+ if(backend->recv_renegotiating) {
+ if(prev_alpn != cf->conn->alpn &&
+ prev_alpn != CURL_HTTP_VERSION_NONE) {
+ /* Renegotiation selected a different protocol now, we cannot
+ * deal with this */
+ failf(data, "schannel: server selected an ALPN protocol too late");
+ return CURLE_SSL_CONNECT_ERROR;
}
+ }
}
- else
- infof(data, VTLS_INFOF_NO_ALPN);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ else {
+ if(!backend->recv_renegotiating)
+ Curl_alpn_set_negotiated(cf, data, NULL, 0);
+ }
}
#endif
/* save the current session data for possible re-use */
- if(SSL_SET_OPTION(primary.sessionid)) {
+ if(ssl_config->primary.sessionid) {
bool incache;
bool added = FALSE;
struct Curl_schannel_cred *old_cred = NULL;
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(data, conn, isproxy, (void **)&old_cred,
- NULL, sockindex));
+ incache = !(Curl_ssl_getsessionid(cf, data, (void **)&old_cred, NULL));
if(incache) {
if(old_cred != backend->cred) {
DEBUGF(infof(data,
@@ -1460,9 +1776,9 @@
}
}
if(!incache) {
- result = Curl_ssl_addsessionid(data, conn, isproxy, backend->cred,
+ result = Curl_ssl_addsessionid(cf, data, backend->cred,
sizeof(struct Curl_schannel_cred),
- sockindex, &added);
+ &added);
if(result) {
Curl_ssl_sessionid_unlock(data);
failf(data, "schannel: failed to store credential handle");
@@ -1512,12 +1828,13 @@
}
static CURLcode
-schannel_connect_common(struct Curl_easy *data, struct connectdata *conn,
- int sockindex, bool nonblocking, bool *done)
+schannel_connect_common(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool nonblocking, bool *done)
{
CURLcode result;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
timediff_t timeout_ms;
int what;
@@ -1537,7 +1854,7 @@
return CURLE_OPERATION_TIMEDOUT;
}
- result = schannel_connect_step1(data, conn, sockindex);
+ result = schannel_connect_step1(cf, data);
if(result)
return result;
}
@@ -1592,7 +1909,7 @@
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
- result = schannel_connect_step2(data, conn, sockindex);
+ result = schannel_connect_step2(cf, data);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -1602,15 +1919,13 @@
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- result = schannel_connect_step3(data, conn, sockindex);
+ result = schannel_connect_step3(cf, data);
if(result)
return result;
}
if(ssl_connect_done == connssl->connecting_state) {
connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = schannel_recv;
- conn->send[sockindex] = schannel_send;
#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
/* When SSPI is used in combination with Schannel
@@ -1619,9 +1934,10 @@
* Available on Windows 7 or later.
*/
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
- conn->sslContext = &backend->ctxt->ctxt_handle;
+ cf->conn->sslContext = &backend->ctxt->ctxt_handle;
}
#endif
@@ -1637,19 +1953,19 @@
}
static ssize_t
-schannel_send(struct Curl_easy *data, int sockindex,
+schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
ssize_t written = -1;
size_t data_len = 0;
unsigned char *ptr = NULL;
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
SecBuffer outbuf[4];
SecBufferDesc outbuf_desc;
SECURITY_STATUS sspi_status = SEC_E_OK;
CURLcode result;
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
@@ -1735,7 +2051,7 @@
}
else if(!timeout_ms)
timeout_ms = TIMEDIFF_T_MAX;
- what = SOCKET_WRITABLE(conn->sock[sockindex], timeout_ms);
+ what = SOCKET_WRITABLE(Curl_conn_cf_get_socket(cf, data), timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -1752,8 +2068,9 @@
}
/* socket is writable */
- result = Curl_write_plain(data, conn->sock[sockindex], ptr + written,
- len - written, &this_write);
+ this_write = Curl_conn_cf_send(cf->next, data,
+ ptr + written, len - written,
+ &result);
if(result == CURLE_AGAIN)
continue;
else if(result != CURLE_OK) {
@@ -1783,13 +2100,12 @@
}
static ssize_t
-schannel_recv(struct Curl_easy *data, int sockindex,
+schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
size_t size = 0;
ssize_t nread = -1;
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
unsigned char *reallocated_buffer;
size_t reallocated_length;
bool done = FALSE;
@@ -1799,7 +2115,8 @@
/* we want the length of the encrypted buffer to be at least large enough
that it can hold all the bytes requested and some TLS record overhead. */
size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE;
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
@@ -1865,19 +2182,19 @@
backend->encdata_offset, backend->encdata_length));
/* read encrypted data from socket */
- *err = Curl_read_plain(conn->sock[sockindex],
- (char *)(backend->encdata_buffer +
+ nread = Curl_conn_cf_recv(cf->next, data,
+ (char *)(backend->encdata_buffer +
backend->encdata_offset),
- size, &nread);
+ size, err);
if(*err) {
nread = -1;
if(*err == CURLE_AGAIN)
DEBUGF(infof(data,
- "schannel: Curl_read_plain returned CURLE_AGAIN"));
+ "schannel: recv returned CURLE_AGAIN"));
else if(*err == CURLE_RECV_ERROR)
- infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR");
+ infof(data, "schannel: recv returned CURLE_RECV_ERROR");
else
- infof(data, "schannel: Curl_read_plain returned error %d", *err);
+ infof(data, "schannel: recv returned error %d", *err);
}
else if(nread == 0) {
backend->recv_connection_closed = true;
@@ -1992,17 +2309,14 @@
infof(data, "schannel: can't renegotiate, an error is pending");
goto cleanup;
}
- if(backend->encdata_offset) {
- *err = CURLE_RECV_ERROR;
- infof(data, "schannel: can't renegotiate, "
- "encrypted data available");
- goto cleanup;
- }
+
/* begin renegotiation */
infof(data, "schannel: renegotiating SSL/TLS connection");
connssl->state = ssl_connection_negotiating;
connssl->connecting_state = ssl_connect_2_writing;
- *err = schannel_connect_common(data, conn, sockindex, FALSE, &done);
+ backend->recv_renegotiating = true;
+ *err = schannel_connect_common(cf, data, FALSE, &done);
+ backend->recv_renegotiating = false;
if(*err) {
infof(data, "schannel: renegotiation failed");
goto cleanup;
@@ -2050,7 +2364,7 @@
"schannel: decrypted data buffer: offset %zu length %zu",
backend->decdata_offset, backend->decdata_length));
- cleanup:
+cleanup:
/* Warning- there is no guarantee the encdata state is valid at this point */
DEBUGF(infof(data, "schannel: schannel_recv cleanup"));
@@ -2109,20 +2423,20 @@
return *err ? -1 : 0;
}
-static CURLcode schannel_connect_nonblocking(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode schannel_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done)
{
- return schannel_connect_common(data, conn, sockindex, TRUE, done);
+ return schannel_connect_common(cf, data, TRUE, done);
}
-static CURLcode schannel_connect(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode schannel_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
CURLcode result;
bool done = FALSE;
- result = schannel_connect_common(data, conn, sockindex, FALSE, &done);
+ result = schannel_connect_common(cf, data, FALSE, &done);
if(result)
return result;
@@ -2131,15 +2445,17 @@
return CURLE_OK;
}
-static bool schannel_data_pending(const struct connectdata *conn,
- int sockindex)
+static bool schannel_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
- const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ const struct ssl_connect_data *connssl = cf->ctx;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
+ (void)data;
DEBUGASSERT(backend);
- if(connssl->use) /* SSL/TLS is in use */
+ if(backend->ctxt) /* SSL/TLS is in use */
return (backend->decdata_offset > 0 ||
(backend->encdata_offset > 0 && !backend->encdata_is_incomplete));
else
@@ -2156,6 +2472,12 @@
if(cred->refcount == 0) {
s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
curlx_unicodefree(cred->sni_hostname);
+#ifdef HAS_CLIENT_CERT_PATH
+ if(cred->client_cert_store) {
+ CertCloseStore(cred->client_cert_store, 0);
+ cred->client_cert_store = NULL;
+ }
+#endif
Curl_safefree(cred);
}
}
@@ -2164,25 +2486,25 @@
/* shut down the SSL connection and clean up related memory.
this function can be called multiple times on the same connection including
if the SSL connection failed (eg connection made but failed handshake). */
-static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static int schannel_shutdown(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
/* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx
* Shutting Down an Schannel Connection
*/
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- char * const hostname = SSL_HOST_NAME();
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
DEBUGASSERT(data);
DEBUGASSERT(backend);
- if(connssl->use) {
- infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu",
- hostname, conn->remote_port);
+ if(backend->ctxt) {
+ infof(data, "schannel: shutting down SSL/TLS connection with %s port %d",
+ connssl->hostname, connssl->port);
}
- if(connssl->use && backend->cred && backend->ctxt) {
+ if(backend->cred && backend->ctxt) {
SecBufferDesc BuffDesc;
SecBuffer Buffer;
SECURITY_STATUS sspi_status;
@@ -2223,10 +2545,9 @@
if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
/* send close message which is in output buffer */
- ssize_t written;
- result = Curl_write_plain(data, conn->sock[sockindex], outbuf.pvBuffer,
- outbuf.cbBuffer, &written);
-
+ ssize_t written = Curl_conn_cf_send(cf->next, data,
+ outbuf.pvBuffer, outbuf.cbBuffer,
+ &result);
s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
infof(data, "schannel: failed to send close msg: %s"
@@ -2268,14 +2589,9 @@
return CURLE_OK;
}
-static void schannel_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static void schannel_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- if(conn->ssl[sockindex].use)
- /* Curl_ssl_shutdown resets the socket state and calls schannel_shutdown */
- Curl_ssl_shutdown(data, conn, sockindex);
- else
- schannel_shutdown(data, conn, sockindex);
+ schannel_shutdown(cf, data);
}
static int schannel_init(void)
@@ -2298,29 +2614,18 @@
static CURLcode schannel_random(struct Curl_easy *data UNUSED_PARAM,
unsigned char *entropy, size_t length)
{
- HCRYPTPROV hCryptProv = 0;
-
(void)data;
- if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
- return CURLE_FAILED_INIT;
-
- if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
- CryptReleaseContext(hCryptProv, 0UL);
- return CURLE_FAILED_INIT;
- }
-
- CryptReleaseContext(hCryptProv, 0UL);
- return CURLE_OK;
+ return Curl_win32_random(entropy, length);
}
-static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
- struct connectdata *conn, int sockindex,
- const char *pinnedpubkey)
+static CURLcode schannel_pkp_pin_peer_pubkey(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *pinnedpubkey)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
CERT_CONTEXT *pCertContextServer = NULL;
/* Result is returned to caller */
@@ -2446,7 +2751,8 @@
static void *schannel_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
(void)info;
DEBUGASSERT(backend);
return &backend->ctxt->ctxt_handle;
@@ -2459,9 +2765,11 @@
#ifdef HAS_MANUAL_VERIFY_API
SSLSUPP_CAINFO_BLOB |
#endif
- SSLSUPP_PINNEDPUBKEY,
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_TLS13_CIPHERSUITES |
+ SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct schannel_ssl_backend_data),
schannel_init, /* init */
schannel_cleanup, /* cleanup */
@@ -2473,7 +2781,7 @@
Curl_none_cert_status_request, /* cert_status_request */
schannel_connect, /* connect */
schannel_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_getsock, /* getsock */
+ Curl_ssl_get_select_socks, /* getsock */
schannel_get_internals, /* get_internals */
schannel_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -2484,7 +2792,10 @@
Curl_none_false_start, /* false_start */
schannel_sha256sum, /* sha256sum */
NULL, /* associate_connection */
- NULL /* disassociate_connection */
+ NULL, /* disassociate_connection */
+ NULL, /* free_multi_ssl_backend_data */
+ schannel_recv, /* recv decrypted data */
+ schannel_send, /* send data to encrypt */
};
#endif /* USE_SCHANNEL */
diff --git a/lib/vtls/schannel.h b/lib/vtls/schannel.h
index 0b4c4d9..b8cb494 100644
--- a/lib/vtls/schannel.h
+++ b/lib/vtls/schannel.h
@@ -7,8 +7,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012, Marc Hoersken, <info@marc-hoersken.de>, et al.
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Marc Hoersken, <info@marc-hoersken.de>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,10 +28,31 @@
#ifdef USE_SCHANNEL
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4201)
+#endif
+#include <subauth.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+/* Wincrypt must be included before anything that could include OpenSSL. */
+#if defined(USE_WIN32_CRYPTO)
+#include <wincrypt.h>
+/* Undefine wincrypt conflicting symbols for BoringSSL. */
+#undef X509_NAME
+#undef X509_EXTENSIONS
+#undef PKCS7_ISSUER_AND_SERIAL
+#undef PKCS7_SIGNER_INFO
+#undef OCSP_REQUEST
+#undef OCSP_RESPONSE
+#endif
+
#include <schnlsp.h>
#include <schannel.h>
#include "curl_sspi.h"
+#include "cfilters.h"
#include "urldata.h"
/* <wincrypt.h> has been included via the above <schnlsp.h>.
@@ -55,57 +76,8 @@
extern const struct Curl_ssl Curl_ssl_schannel;
-CURLcode Curl_verify_certificate(struct Curl_easy *data,
- struct connectdata *conn, int sockindex);
-
-/* structs to expose only in schannel.c and schannel_verify.c */
-#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
-
-#ifdef __MINGW32__
-#ifdef __MINGW64_VERSION_MAJOR
-#define HAS_MANUAL_VERIFY_API
-#endif
-#else
-#include <wincrypt.h>
-#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN
-#define HAS_MANUAL_VERIFY_API
-#endif
-#endif
-
-struct Curl_schannel_cred {
- CredHandle cred_handle;
- TimeStamp time_stamp;
- TCHAR *sni_hostname;
- int refcount;
-};
-
-struct Curl_schannel_ctxt {
- CtxtHandle ctxt_handle;
- TimeStamp time_stamp;
-};
-
-struct ssl_backend_data {
- struct Curl_schannel_cred *cred;
- struct Curl_schannel_ctxt *ctxt;
- SecPkgContext_StreamSizes stream_sizes;
- size_t encdata_length, decdata_length;
- size_t encdata_offset, decdata_offset;
- unsigned char *encdata_buffer, *decdata_buffer;
- /* encdata_is_incomplete: if encdata contains only a partial record that
- can't be decrypted without another Curl_read_plain (that is, status is
- SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
- more bytes into encdata then set this back to false. */
- bool encdata_is_incomplete;
- unsigned long req_flags, ret_flags;
- CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
- bool recv_sspi_close_notify; /* true if connection closed by close_notify */
- bool recv_connection_closed; /* true if connection closed, regardless how */
- bool use_alpn; /* true if ALPN is used for this connection */
-#ifdef HAS_MANUAL_VERIFY_API
- bool use_manual_cred_validation; /* true if manual cred validation is used */
-#endif
-};
-#endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */
+CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
#endif /* USE_SCHANNEL */
#endif /* HEADER_CURL_SCHANNEL_H */
diff --git a/lib/vtls/schannel_int.h b/lib/vtls/schannel_int.h
new file mode 100644
index 0000000..d8b6cce
--- /dev/null
+++ b/lib/vtls/schannel_int.h
@@ -0,0 +1,142 @@
+#ifndef HEADER_CURL_SCHANNEL_INT_H
+#define HEADER_CURL_SCHANNEL_INT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Marc Hoersken, <info@marc-hoersken.de>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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"
+
+#ifdef USE_SCHANNEL
+
+#ifdef __MINGW32__
+#ifdef __MINGW64_VERSION_MAJOR
+#define HAS_MANUAL_VERIFY_API
+#endif
+#else
+#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN
+#define HAS_MANUAL_VERIFY_API
+#endif
+#endif
+
+#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX) \
+ && !defined(DISABLE_SCHANNEL_CLIENT_CERT)
+#define HAS_CLIENT_CERT_PATH
+#endif
+
+#ifndef SCH_CREDENTIALS_VERSION
+
+#define SCH_CREDENTIALS_VERSION 0x00000005
+
+typedef enum _eTlsAlgorithmUsage
+{
+ TlsParametersCngAlgUsageKeyExchange,
+ TlsParametersCngAlgUsageSignature,
+ TlsParametersCngAlgUsageCipher,
+ TlsParametersCngAlgUsageDigest,
+ TlsParametersCngAlgUsageCertSig
+} eTlsAlgorithmUsage;
+
+typedef struct _CRYPTO_SETTINGS
+{
+ eTlsAlgorithmUsage eAlgorithmUsage;
+ UNICODE_STRING strCngAlgId;
+ DWORD cChainingModes;
+ PUNICODE_STRING rgstrChainingModes;
+ DWORD dwMinBitLength;
+ DWORD dwMaxBitLength;
+} CRYPTO_SETTINGS, * PCRYPTO_SETTINGS;
+
+typedef struct _TLS_PARAMETERS
+{
+ DWORD cAlpnIds;
+ PUNICODE_STRING rgstrAlpnIds;
+ DWORD grbitDisabledProtocols;
+ DWORD cDisabledCrypto;
+ PCRYPTO_SETTINGS pDisabledCrypto;
+ DWORD dwFlags;
+} TLS_PARAMETERS, * PTLS_PARAMETERS;
+
+typedef struct _SCH_CREDENTIALS
+{
+ DWORD dwVersion;
+ DWORD dwCredFormat;
+ DWORD cCreds;
+ PCCERT_CONTEXT* paCred;
+ HCERTSTORE hRootStore;
+
+ DWORD cMappers;
+ struct _HMAPPER **aphMappers;
+
+ DWORD dwSessionLifespan;
+ DWORD dwFlags;
+ DWORD cTlsParameters;
+ PTLS_PARAMETERS pTlsParameters;
+} SCH_CREDENTIALS, * PSCH_CREDENTIALS;
+
+#define SCH_CRED_MAX_SUPPORTED_PARAMETERS 16
+#define SCH_CRED_MAX_SUPPORTED_ALPN_IDS 16
+#define SCH_CRED_MAX_SUPPORTED_CRYPTO_SETTINGS 16
+#define SCH_CRED_MAX_SUPPORTED_CHAINING_MODES 16
+
+#endif /* SCH_CREDENTIALS_VERSION */
+
+struct Curl_schannel_cred {
+ CredHandle cred_handle;
+ TimeStamp time_stamp;
+ TCHAR *sni_hostname;
+#ifdef HAS_CLIENT_CERT_PATH
+ HCERTSTORE client_cert_store;
+#endif
+ int refcount;
+};
+
+struct Curl_schannel_ctxt {
+ CtxtHandle ctxt_handle;
+ TimeStamp time_stamp;
+};
+
+struct schannel_ssl_backend_data {
+ struct Curl_schannel_cred *cred;
+ struct Curl_schannel_ctxt *ctxt;
+ SecPkgContext_StreamSizes stream_sizes;
+ size_t encdata_length, decdata_length;
+ size_t encdata_offset, decdata_offset;
+ unsigned char *encdata_buffer, *decdata_buffer;
+ /* encdata_is_incomplete: if encdata contains only a partial record that
+ can't be decrypted without another recv() (that is, status is
+ SEC_E_INCOMPLETE_MESSAGE) then set this true. after an recv() adds
+ more bytes into encdata then set this back to false. */
+ bool encdata_is_incomplete;
+ unsigned long req_flags, ret_flags;
+ CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
+ bool recv_sspi_close_notify; /* true if connection closed by close_notify */
+ bool recv_connection_closed; /* true if connection closed, regardless how */
+ bool recv_renegotiating; /* true if recv is doing renegotiation */
+ bool use_alpn; /* true if ALPN is used for this connection */
+#ifdef HAS_MANUAL_VERIFY_API
+ bool use_manual_cred_validation; /* true if manual cred validation is used */
+#endif
+};
+
+#endif /* USE_SCHANNEL */
+#endif /* HEADER_CURL_SCHANNEL_INT_H */
diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c
index 1ac1d3e..c582ee4 100644
--- a/lib/vtls/schannel_verify.c
+++ b/lib/vtls/schannel_verify.c
@@ -5,9 +5,9 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
- * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Marc Hoersken, <info@marc-hoersken.de>
+ * Copyright (C) Mark Salisbury, <mark.salisbury@hp.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,12 +36,13 @@
# error "Can't compile SCHANNEL support without SSPI."
#endif
-#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
#include "schannel.h"
+#include "schannel_int.h"
#ifdef HAS_MANUAL_VERIFY_API
#include "vtls.h"
+#include "vtls_int.h"
#include "sendf.h"
#include "strerror.h"
#include "curl_multibyte.h"
@@ -53,7 +54,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-#define BACKEND connssl->backend
+#define BACKEND ((struct schannel_ssl_backend_data *)connssl->backend)
#define MAX_CAFILE_SIZE 1048576 /* 1 MiB */
#define BEGIN_CERT "-----BEGIN CERTIFICATE-----"
@@ -458,7 +459,7 @@
static CURLcode verify_host(struct Curl_easy *data,
CERT_CONTEXT *pCertContextServer,
- const char * const conn_hostname)
+ const char *conn_hostname)
{
CURLcode result = CURLE_PEER_FAILED_VERIFICATION;
TCHAR *cert_hostname_buff = NULL;
@@ -562,17 +563,18 @@
return result;
}
-CURLcode Curl_verify_certificate(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+CURLcode Curl_verify_certificate(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);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
SECURITY_STATUS sspi_status;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
CURLcode result = CURLE_OK;
CERT_CONTEXT *pCertContextServer = NULL;
const CERT_CHAIN_CONTEXT *pChainContext = NULL;
HCERTCHAINENGINE cert_chain_engine = NULL;
HCERTSTORE trust_store = NULL;
- const char * const conn_hostname = SSL_HOST_NAME();
DEBUGASSERT(BACKEND);
@@ -589,7 +591,7 @@
}
if(result == CURLE_OK &&
- (SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) &&
+ (conn_config->CAfile || conn_config->ca_info_blob) &&
BACKEND->use_manual_cred_validation) {
/*
* Create a chain engine that uses the certificates in the CA file as
@@ -616,7 +618,7 @@
result = CURLE_SSL_CACERT_BADFILE;
}
else {
- const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
if(ca_info_blob) {
result = add_certs_data_to_store(trust_store,
(const char *)ca_info_blob->data,
@@ -626,7 +628,7 @@
}
else {
result = add_certs_file_to_store(trust_store,
- SSL_CONN_CONFIG(CAfile),
+ conn_config->CAfile,
data);
}
}
@@ -669,7 +671,7 @@
NULL,
pCertContextServer->hCertStore,
&ChainPara,
- (SSL_SET_OPTION(no_revoke) ? 0 :
+ (ssl_config->no_revoke ? 0 :
CERT_CHAIN_REVOCATION_CHECK_CHAIN),
NULL,
&pChainContext)) {
@@ -718,8 +720,8 @@
}
if(result == CURLE_OK) {
- if(SSL_CONN_CONFIG(verifyhost)) {
- result = verify_host(data, pCertContextServer, conn_hostname);
+ if(conn_config->verifyhost) {
+ result = verify_host(data, pCertContextServer, connssl->hostname);
}
}
diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c
index a18ca4e..32bb3a5 100644
--- a/lib/vtls/sectransp.c
+++ b/lib/vtls/sectransp.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Nick Zitzmann, <nickzman@gmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -45,6 +45,11 @@
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
#endif /* __clang__ */
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Waddress"
+#pragma GCC diagnostic ignored "-Wundef"
+#endif
+
#include <limits.h>
#include <Security/Security.h>
@@ -122,12 +127,12 @@
#include <sys/sysctl.h>
#endif /* CURL_BUILD_MAC */
-#include "urldata.h"
#include "sendf.h"
#include "inet_pton.h"
#include "connect.h"
#include "select.h"
#include "vtls.h"
+#include "vtls_int.h"
#include "sectransp.h"
#include "curl_printf.h"
#include "strdup.h"
@@ -136,13 +141,13 @@
/* The last #include file should be: */
#include "memdebug.h"
+
/* From MacTypes.h (which we can't include because it isn't present in iOS: */
#define ioErr -36
#define paramErr -50
-struct ssl_backend_data {
+struct st_ssl_backend_data {
SSLContextRef ssl_ctx;
- curl_socket_t ssl_sockfd;
bool ssl_direction; /* true if writing, false if reading */
size_t ssl_write_buffered_length;
};
@@ -234,7 +239,7 @@
insert in between existing items to appropriate place based on
cipher suite IANA number
*/
-const static struct st_cipher ciphertable[] = {
+static const struct st_cipher ciphertable[] = {
/* SSL version 3.0 and initial TLS 1.0 cipher suites.
Defined since SDK 10.2.8 */
CIPHER_DEF_SSLTLS(NULL_WITH_NULL_NULL, /* 0x0000 */
@@ -825,116 +830,78 @@
#endif /* SECTRANSP_PINNEDPUBKEY_V1 */
#endif /* SECTRANSP_PINNEDPUBKEY */
-/* The following two functions were ripped from Apple sample code,
- * with some modifications: */
-static OSStatus SocketRead(SSLConnectionRef connection,
- void *data, /* owned by
- * caller, data
- * RETURNED */
- size_t *dataLength) /* IN/OUT */
+static OSStatus bio_cf_in_read(SSLConnectionRef connection,
+ void *buf,
+ size_t *dataLength) /* IN/OUT */
{
- size_t bytesToGo = *dataLength;
- size_t initLen = bytesToGo;
- UInt8 *currData = (UInt8 *)data;
- /*int sock = *(int *)connection;*/
- struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
- struct ssl_backend_data *backend = connssl->backend;
- int sock;
+ struct Curl_cfilter *cf = (struct Curl_cfilter *)connection;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nread;
+ CURLcode result;
OSStatus rtn = noErr;
- size_t bytesRead;
- ssize_t rrtn;
- int theErr;
- DEBUGASSERT(backend);
- sock = backend->ssl_sockfd;
- *dataLength = 0;
-
- for(;;) {
- bytesRead = 0;
- rrtn = read(sock, currData, bytesToGo);
- if(rrtn <= 0) {
- /* this is guesswork... */
- theErr = errno;
- if(rrtn == 0) { /* EOF = server hung up */
- /* the framework will turn this into errSSLClosedNoNotify */
- rtn = errSSLClosedGraceful;
- }
- else /* do the switch */
- switch(theErr) {
- case ENOENT:
- /* connection closed */
- rtn = errSSLClosedGraceful;
- break;
- case ECONNRESET:
- rtn = errSSLClosedAbort;
- break;
- case EAGAIN:
- rtn = errSSLWouldBlock;
- backend->ssl_direction = false;
- break;
- default:
- rtn = ioErr;
- break;
- }
- break;
+ DEBUGASSERT(data);
+ nread = Curl_conn_cf_recv(cf->next, data, buf, *dataLength, &result);
+ DEBUGF(LOG_CF(data, cf, "bio_read(len=%zu) -> %zd, result=%d",
+ *dataLength, nread, result));
+ if(nread < 0) {
+ switch(result) {
+ case CURLE_OK:
+ case CURLE_AGAIN:
+ rtn = errSSLWouldBlock;
+ backend->ssl_direction = false;
+ break;
+ default:
+ rtn = ioErr;
+ break;
}
- else {
- bytesRead = rrtn;
- }
- bytesToGo -= bytesRead;
- currData += bytesRead;
-
- if(bytesToGo == 0) {
- /* filled buffer with incoming data, done */
- break;
- }
+ nread = 0;
}
- *dataLength = initLen - bytesToGo;
-
+ else if(nread == 0) {
+ rtn = errSSLClosedGraceful;
+ }
+ else if((size_t)nread < *dataLength) {
+ rtn = errSSLWouldBlock;
+ }
+ *dataLength = nread;
return rtn;
}
-static OSStatus SocketWrite(SSLConnectionRef connection,
- const void *data,
- size_t *dataLength) /* IN/OUT */
+static OSStatus bio_cf_out_write(SSLConnectionRef connection,
+ const void *buf,
+ size_t *dataLength) /* IN/OUT */
{
- size_t bytesSent = 0;
- /*int sock = *(int *)connection;*/
- struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
- struct ssl_backend_data *backend = connssl->backend;
- int sock;
- ssize_t length;
- size_t dataLen = *dataLength;
- const UInt8 *dataPtr = (UInt8 *)data;
- OSStatus ortn;
- int theErr;
+ struct Curl_cfilter *cf = (struct Curl_cfilter *)connection;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nwritten;
+ CURLcode result;
+ OSStatus rtn = noErr;
- DEBUGASSERT(backend);
- sock = backend->ssl_sockfd;
- *dataLength = 0;
-
- do {
- length = write(sock,
- (char *)dataPtr + bytesSent,
- dataLen - bytesSent);
- } while((length > 0) &&
- ( (bytesSent += length) < dataLen) );
-
- if(length <= 0) {
- theErr = errno;
- if(theErr == EAGAIN) {
- ortn = errSSLWouldBlock;
+ DEBUGASSERT(data);
+ nwritten = Curl_conn_cf_send(cf->next, data, buf, *dataLength, &result);
+ DEBUGF(LOG_CF(data, cf, "bio_send(len=%zu) -> %zd, result=%d",
+ *dataLength, nwritten, result));
+ if(nwritten <= 0) {
+ if(result == CURLE_AGAIN) {
+ rtn = errSSLWouldBlock;
backend->ssl_direction = true;
}
else {
- ortn = ioErr;
+ rtn = ioErr;
}
+ nwritten = 0;
}
- else {
- ortn = noErr;
+ else if((size_t)nwritten < *dataLength) {
+ rtn = errSSLWouldBlock;
}
- *dataLength = bytesSent;
- return ortn;
+ *dataLength = nwritten;
+ return rtn;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
@@ -943,12 +910,12 @@
/* The first ciphers in the ciphertable are continuous. Here we do small
optimization and instead of loop directly get SSL name by cipher number.
*/
+ size_t i;
if(cipher <= SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA) {
return ciphertable[cipher].name;
}
/* Iterate through the rest of the ciphers */
- for(size_t i = SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA + 1;
- i < NUM_OF_CIPHERS;
+ for(i = SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA + 1; i < NUM_OF_CIPHERS;
++i) {
if(ciphertable[i].num == cipher) {
return ciphertable[i].name;
@@ -1372,14 +1339,15 @@
}
#endif
-static CURLcode
-set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static CURLcode set_ssl_version_min_max(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- long ssl_version = SSL_CONN_CONFIG(version);
- long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
+ 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;
long max_supported_version_by_os;
DEBUGASSERT(backend);
@@ -1472,7 +1440,8 @@
static bool is_cipher_suite_strong(SSLCipherSuite suite_num)
{
- for(size_t i = 0; i < NUM_OF_CIPHERS; ++i) {
+ size_t i;
+ for(i = 0; i < NUM_OF_CIPHERS; ++i) {
if(ciphertable[i].num == suite_num) {
return !ciphertable[i].weak;
}
@@ -1588,16 +1557,17 @@
size_t cipher_len = 0;
const char *cipher_end = NULL;
bool tls_name = FALSE;
+ size_t i;
/* Skip separators */
while(is_separator(*cipher_start))
- cipher_start++;
+ cipher_start++;
if(*cipher_start == '\0') {
break;
}
/* Find last position of a cipher in the ciphers string */
cipher_end = cipher_start;
- while (*cipher_end != '\0' && !is_separator(*cipher_end)) {
+ while(*cipher_end != '\0' && !is_separator(*cipher_end)) {
++cipher_end;
}
@@ -1611,7 +1581,7 @@
/* Iterate through the cipher table and look for the cipher, starting
the cipher number 0x01 because the 0x00 is not the real cipher */
cipher_len = cipher_end - cipher_start;
- for(size_t i = 1; i < NUM_OF_CIPHERS; ++i) {
+ for(i = 1; i < NUM_OF_CIPHERS; ++i) {
const char *table_cipher_name = NULL;
if(tls_name) {
table_cipher_name = ciphertable[i].name;
@@ -1665,23 +1635,21 @@
return CURLE_OK;
}
-static CURLcode sectransp_connect_step1(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex)
+static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- curl_socket_t sockfd = conn->sock[sockindex];
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- const struct curl_blob *ssl_cablob = SSL_CONN_CONFIG(ca_info_blob);
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ const struct curl_blob *ssl_cablob = conn_config->ca_info_blob;
const char * const ssl_cafile =
/* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
- (ssl_cablob ? NULL : SSL_CONN_CONFIG(CAfile));
- const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
- const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
- bool isproxy = SSL_IS_PROXY();
- const char * const hostname = SSL_HOST_NAME();
- const long int port = SSL_HOST_PORT();
+ (ssl_cablob ? NULL : conn_config->CAfile);
+ const bool verifypeer = conn_config->verifypeer;
+ char * const ssl_cert = ssl_config->primary.clientcert;
+ const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
@@ -1694,6 +1662,7 @@
DEBUGASSERT(backend);
+ DEBUGF(LOG_CF(data, cf, "connect_step1"));
GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
#endif /* CURL_BUILD_MAC */
@@ -1733,7 +1702,7 @@
/* check to see if we've been told to use an explicit SSL/TLS version */
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
if(SSLSetProtocolVersionMax) {
- switch(conn->ssl_config.version) {
+ switch(conn_config->version) {
case CURL_SSLVERSION_TLSv1:
(void)SSLSetProtocolVersionMin(backend->ssl_ctx, kTLSProtocol1);
#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
@@ -1754,7 +1723,7 @@
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
+ CURLcode result = set_ssl_version_min_max(cf, data);
if(result != CURLE_OK)
return result;
break;
@@ -1773,7 +1742,7 @@
(void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
kSSLProtocolAll,
false);
- switch(conn->ssl_config.version) {
+ switch(conn_config->version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
(void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
@@ -1791,7 +1760,7 @@
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
+ CURLcode result = set_ssl_version_min_max(cf, data);
if(result != CURLE_OK)
return result;
break;
@@ -1807,13 +1776,13 @@
#endif /* CURL_SUPPORT_MAC_10_8 */
}
#else
- if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) {
+ if(conn_config->version_max != CURL_SSLVERSION_MAX_NONE) {
failf(data, "Your version of the OS does not support to set maximum"
" SSL/TLS version");
return CURLE_SSL_CONNECT_ERROR;
}
(void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocolAll, false);
- switch(conn->ssl_config.version) {
+ switch(conn_config->version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
case CURL_SSLVERSION_TLSv1_0:
@@ -1841,38 +1810,33 @@
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
- if(conn->bits.tls_enable_alpn) {
+ if(connssl->alpn) {
if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
+ struct alpn_proto_buf proto;
+ size_t i;
+ CFStringRef cstr;
CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
&kCFTypeArrayCallBacks);
-
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2
-#ifndef CURL_DISABLE_PROXY
- && (!isproxy || !conn->bits.tunnel_proxy)
-#endif
- ) {
- CFArrayAppendValue(alpnArr, CFSTR(ALPN_H2));
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+ for(i = 0; i < connssl->alpn->count; ++i) {
+ cstr = CFStringCreateWithCString(NULL, connssl->alpn->entries[i],
+ kCFStringEncodingUTF8);
+ if(!cstr)
+ return CURLE_OUT_OF_MEMORY;
+ CFArrayAppendValue(alpnArr, cstr);
+ CFRelease(cstr);
}
-#endif
-
- CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
-
- /* expects length prefixed preference ordered list of protocols in wire
- * format
- */
err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr);
if(err != noErr)
infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d",
err);
CFRelease(alpnArr);
+ Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
}
#endif
- if(SSL_SET_OPTION(key)) {
+ if(ssl_config->key) {
infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
"Transport. The private key must be in the Keychain.");
}
@@ -1891,17 +1855,17 @@
else
err = !noErr;
if((err != noErr) && (is_cert_file || is_cert_data)) {
- if(!SSL_SET_OPTION(cert_type))
+ if(!ssl_config->cert_type)
infof(data, "SSL: Certificate type not set, assuming "
"PKCS#12 format.");
- else if(!strcasecompare(SSL_SET_OPTION(cert_type), "P12")) {
+ else if(!strcasecompare(ssl_config->cert_type, "P12")) {
failf(data, "SSL: The Security framework only supports "
"loading identities that are in PKCS#12 format.");
return CURLE_SSL_CERTPROBLEM;
}
err = CopyIdentityFromPKCS12File(ssl_cert, ssl_cert_blob,
- SSL_SET_OPTION(key_passwd),
+ ssl_config->key_passwd,
&cert_and_key);
}
@@ -1994,7 +1958,7 @@
#else
if(SSLSetSessionOption) {
#endif /* CURL_BUILD_MAC */
- bool break_on_auth = !conn->ssl_config.verifypeer ||
+ bool break_on_auth = !conn_config->verifypeer ||
ssl_cafile || ssl_cablob;
err = SSLSetSessionOption(backend->ssl_ctx,
kSSLSessionOptionBreakOnServerAuth,
@@ -2007,7 +1971,7 @@
else {
#if CURL_SUPPORT_MAC_10_8
err = SSLSetEnableCertVerify(backend->ssl_ctx,
- conn->ssl_config.verifypeer?true:false);
+ conn_config->verifypeer?true:false);
if(err != noErr) {
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
@@ -2016,7 +1980,7 @@
}
#else
err = SSLSetEnableCertVerify(backend->ssl_ctx,
- conn->ssl_config.verifypeer?true:false);
+ conn_config->verifypeer?true:false);
if(err != noErr) {
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
@@ -2037,9 +2001,9 @@
/* Configure hostname check. SNI is used if available.
* Both hostname check and SNI require SSLSetPeerDomainName().
* Also: the verifyhost setting influences SNI usage */
- if(conn->ssl_config.verifyhost) {
+ if(conn_config->verifyhost) {
size_t snilen;
- char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
+ char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen);
if(!snihost) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
@@ -2052,9 +2016,9 @@
return CURLE_SSL_CONNECT_ERROR;
}
- if((Curl_inet_pton(AF_INET, hostname, &addr))
+ if((Curl_inet_pton(AF_INET, connssl->hostname, &addr))
#ifdef ENABLE_IPV6
- || (Curl_inet_pton(AF_INET6, hostname, &addr))
+ || (Curl_inet_pton(AF_INET6, connssl->hostname, &addr))
#endif
) {
infof(data, "WARNING: using IP address, SNI is being disabled by "
@@ -2065,7 +2029,7 @@
infof(data, "WARNING: disabling hostname validation also disables SNI.");
}
- ciphers = SSL_CONN_CONFIG(cipher_list);
+ ciphers = conn_config->cipher_list;
if(ciphers) {
err = sectransp_set_selected_ciphers(data, backend->ssl_ctx, ciphers);
}
@@ -2083,20 +2047,20 @@
specifically doesn't want us doing that: */
if(SSLSetSessionOption) {
SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
- !SSL_SET_OPTION(enable_beast));
+ !ssl_config->enable_beast);
SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionFalseStart,
- data->set.ssl.falsestart); /* false start support */
+ ssl_config->falsestart); /* false start support */
}
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
/* Check if there's a cached ID we can/should use here! */
- if(SSL_SET_OPTION(primary.sessionid)) {
+ if(ssl_config->primary.sessionid) {
char *ssl_sessionid;
size_t ssl_sessionid_len;
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn, isproxy, (void **)&ssl_sessionid,
- &ssl_sessionid_len, sockindex)) {
+ if(!Curl_ssl_getsessionid(cf, data, (void **)&ssl_sessionid,
+ &ssl_sessionid_len)) {
/* we got a session id, use it! */
err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
Curl_ssl_sessionid_unlock(data);
@@ -2112,9 +2076,10 @@
else {
CURLcode result;
ssl_sessionid =
- aprintf("%s:%d:%d:%s:%ld",
+ aprintf("%s:%d:%d:%s:%d",
ssl_cafile ? ssl_cafile : "(blob memory)",
- verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
+ verifypeer, conn_config->verifyhost, connssl->hostname,
+ connssl->port);
ssl_sessionid_len = strlen(ssl_sessionid);
err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
@@ -2124,8 +2089,8 @@
return CURLE_SSL_CONNECT_ERROR;
}
- result = Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid,
- ssl_sessionid_len, sockindex, NULL);
+ result = Curl_ssl_addsessionid(cf, data, ssl_sessionid,
+ ssl_sessionid_len, NULL);
Curl_ssl_sessionid_unlock(data);
if(result) {
failf(data, "failed to store ssl session");
@@ -2134,18 +2099,13 @@
}
}
- err = SSLSetIOFuncs(backend->ssl_ctx, SocketRead, SocketWrite);
+ err = SSLSetIOFuncs(backend->ssl_ctx, bio_cf_in_read, bio_cf_out_write);
if(err != noErr) {
failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
}
- /* pass the raw socket into the SSL layers */
- /* We need to store the FD in a constant memory address, because
- * SSLSetConnection() will not copy that address. I've found that
- * conn->sock[sockindex] may change on its own. */
- backend->ssl_sockfd = sockfd;
- err = SSLSetConnection(backend->ssl_ctx, connssl);
+ err = SSLSetConnection(backend->ssl_ctx, cf);
if(err != noErr) {
failf(data, "SSL: SSLSetConnection() failed: %d", err);
return CURLE_SSL_CONNECT_ERROR;
@@ -2204,50 +2164,39 @@
return sep_end - in;
}
+#define MAX_CERTS_SIZE (50*1024*1024) /* arbitrary - to catch mistakes */
+
static int read_cert(const char *file, unsigned char **out, size_t *outlen)
{
int fd;
- ssize_t n, len = 0, cap = 512;
- unsigned char buf[512], *data;
+ ssize_t n;
+ unsigned char buf[512];
+ struct dynbuf certs;
+
+ Curl_dyn_init(&certs, MAX_CERTS_SIZE);
fd = open(file, 0);
if(fd < 0)
return -1;
- data = malloc(cap);
- if(!data) {
- close(fd);
- return -1;
- }
-
for(;;) {
n = read(fd, buf, sizeof(buf));
+ if(!n)
+ break;
if(n < 0) {
close(fd);
- free(data);
+ Curl_dyn_free(&certs);
return -1;
}
- else if(n == 0) {
+ if(Curl_dyn_addn(&certs, buf, n)) {
close(fd);
- break;
+ return -1;
}
-
- if(len + n >= cap) {
- cap *= 2;
- data = Curl_saferealloc(data, cap);
- if(!data) {
- close(fd);
- return -1;
- }
- }
-
- memcpy(data + len, buf, n);
- len += n;
}
- data[len] = '\0';
+ close(fd);
- *out = data;
- *outlen = len;
+ *out = Curl_dyn_uptr(&certs);
+ *outlen = Curl_dyn_len(&certs);
return 0;
}
@@ -2256,16 +2205,18 @@
const unsigned char *buf, size_t buflen,
CFMutableArrayRef array)
{
- CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
char *certp;
CURLcode result;
+ SecCertificateRef cacert;
+ CFDataRef certdata;
+
+ certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
if(!certdata) {
failf(data, "SSL: failed to allocate array for CA certificate");
return CURLE_OUT_OF_MEMORY;
}
- SecCertificateRef cacert =
- SecCertificateCreateWithData(kCFAllocatorDefault, certdata);
+ cacert = SecCertificateCreateWithData(kCFAllocatorDefault, certdata);
CFRelease(certdata);
if(!cacert) {
failf(data, "SSL: failed to create SecCertificate from CA certificate");
@@ -2291,7 +2242,8 @@
return CURLE_OK;
}
-static CURLcode verify_cert_buf(struct Curl_easy *data,
+static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
const unsigned char *certbuf, size_t buflen,
SSLContextRef ctx)
{
@@ -2299,7 +2251,12 @@
long res;
unsigned char *der;
size_t derlen, offset = 0;
-
+ OSStatus ret;
+ SecTrustResultType trust_eval;
+ CFMutableArrayRef array = NULL;
+ SecTrustRef trust = NULL;
+ CURLcode result = CURLE_PEER_FAILED_VERIFICATION;
+ (void)cf;
/*
* Certbuf now contains the contents of the certificate file, which can be
* - a single DER certificate,
@@ -2309,11 +2266,11 @@
* Go through certbuf, and convert any PEM certificate in it into DER
* format.
*/
- CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeArrayCallBacks);
+ array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
if(!array) {
failf(data, "SSL: out of memory creating CA certificate array");
- return CURLE_OUT_OF_MEMORY;
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
}
while(offset < buflen) {
@@ -2325,10 +2282,10 @@
*/
res = pem_to_der((const char *)certbuf + offset, &der, &derlen);
if(res < 0) {
- CFRelease(array);
failf(data, "SSL: invalid CA certificate #%d (offset %zu) in bundle",
n, offset);
- return CURLE_SSL_CACERT_BADFILE;
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto out;
}
offset += res;
@@ -2336,8 +2293,9 @@
/* This is not a PEM file, probably a certificate in DER format. */
rc = append_cert_to_array(data, certbuf, buflen, array);
if(rc != CURLE_OK) {
- CFRelease(array);
- return rc;
+ DEBUGF(LOG_CF(data, cf, "append_cert for CA failed"));
+ result = rc;
+ goto out;
}
break;
}
@@ -2349,63 +2307,73 @@
rc = append_cert_to_array(data, der, derlen, array);
free(der);
if(rc != CURLE_OK) {
- CFRelease(array);
- return rc;
+ DEBUGF(LOG_CF(data, cf, "append_cert for CA failed"));
+ result = rc;
+ goto out;
}
}
- SecTrustRef trust;
- OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
+ ret = SSLCopyPeerTrust(ctx, &trust);
if(!trust) {
failf(data, "SSL: error getting certificate chain");
- CFRelease(array);
- return CURLE_PEER_FAILED_VERIFICATION;
+ goto out;
}
else if(ret != noErr) {
- CFRelease(array);
failf(data, "SSLCopyPeerTrust() returned error %d", ret);
- return CURLE_PEER_FAILED_VERIFICATION;
+ goto out;
}
+ DEBUGF(LOG_CF(data, cf, "setting %d trust anchors", n));
ret = SecTrustSetAnchorCertificates(trust, array);
if(ret != noErr) {
- CFRelease(array);
- CFRelease(trust);
failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
- return CURLE_PEER_FAILED_VERIFICATION;
+ goto out;
}
ret = SecTrustSetAnchorCertificatesOnly(trust, true);
if(ret != noErr) {
- CFRelease(array);
- CFRelease(trust);
failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret);
- return CURLE_PEER_FAILED_VERIFICATION;
+ goto out;
}
- SecTrustResultType trust_eval = 0;
+ trust_eval = 0;
ret = SecTrustEvaluate(trust, &trust_eval);
- CFRelease(array);
- CFRelease(trust);
if(ret != noErr) {
failf(data, "SecTrustEvaluate() returned error %d", ret);
- return CURLE_PEER_FAILED_VERIFICATION;
+ goto out;
}
switch(trust_eval) {
case kSecTrustResultUnspecified:
+ /* what does this really mean? */
+ DEBUGF(LOG_CF(data, cf, "trust result: Unspecified"));
+ result = CURLE_OK;
+ goto out;
case kSecTrustResultProceed:
- return CURLE_OK;
+ DEBUGF(LOG_CF(data, cf, "trust result: Proceed"));
+ result = CURLE_OK;
+ goto out;
case kSecTrustResultRecoverableTrustFailure:
+ failf(data, "SSL: peer not verified: RecoverableTrustFailure");
+ goto out;
case kSecTrustResultDeny:
+ failf(data, "SSL: peer not verified: Deny");
+ goto out;
default:
- failf(data, "SSL: certificate verification failed (result: %d)",
- trust_eval);
- return CURLE_PEER_FAILED_VERIFICATION;
+ failf(data, "SSL: perr not verified: result=%d", trust_eval);
+ goto out;
}
+
+out:
+ if(trust)
+ CFRelease(trust);
+ if(array)
+ CFRelease(array);
+ return result;
}
-static CURLcode verify_cert(struct Curl_easy *data, const char *cafile,
+static CURLcode verify_cert(struct Curl_cfilter *cf,
+ struct Curl_easy *data, const char *cafile,
const struct curl_blob *ca_info_blob,
SSLContextRef ctx)
{
@@ -2414,6 +2382,7 @@
size_t buflen;
if(ca_info_blob) {
+ DEBUGF(LOG_CF(data, cf, "verify_peer, CA from config blob"));
certbuf = (unsigned char *)malloc(ca_info_blob->len + 1);
if(!certbuf) {
return CURLE_OUT_OF_MEMORY;
@@ -2423,6 +2392,7 @@
certbuf[ca_info_blob->len]='\0';
}
else if(cafile) {
+ DEBUGF(LOG_CF(data, cf, "verify_peer, CA from file '%s'", cafile));
if(read_cert(cafile, &certbuf, &buflen) < 0) {
failf(data, "SSL: failed to read or invalid CA certificate");
return CURLE_SSL_CACERT_BADFILE;
@@ -2431,7 +2401,7 @@
else
return CURLE_SSL_CACERT_BADFILE;
- result = verify_cert_buf(data, certbuf, buflen, ctx);
+ result = verify_cert_buf(cf, data, certbuf, buflen, ctx);
free(certbuf);
return result;
}
@@ -2460,11 +2430,15 @@
do {
SecTrustRef trust;
- OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
+ OSStatus ret;
+ SecKeyRef keyRef;
+ OSStatus success;
+
+ ret = SSLCopyPeerTrust(ctx, &trust);
if(ret != noErr || !trust)
break;
- SecKeyRef keyRef = SecTrustCopyPublicKey(trust);
+ keyRef = SecTrustCopyPublicKey(trust);
CFRelease(trust);
if(!keyRef)
break;
@@ -2478,8 +2452,8 @@
#elif SECTRANSP_PINNEDPUBKEY_V2
- OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
- &publicKeyBits);
+ success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
+ &publicKeyBits);
CFRelease(keyRef);
if(success != errSecSuccess || !publicKeyBits)
break;
@@ -2544,23 +2518,25 @@
}
#endif /* SECTRANSP_PINNEDPUBKEY */
-static CURLcode
-sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
OSStatus err;
SSLCipherSuite cipher;
SSLProtocol protocol = 0;
- const char * const hostname = SSL_HOST_NAME();
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|| ssl_connect_2_reading == connssl->connecting_state
|| ssl_connect_2_writing == connssl->connecting_state);
DEBUGASSERT(backend);
+ DEBUGF(LOG_CF(data, cf, "connect_step2"));
/* Here goes nothing: */
+check_handshake:
err = SSLHandshake(backend->ssl_ctx);
if(err != noErr) {
@@ -2573,16 +2549,16 @@
/* The below is errSSLServerAuthCompleted; it's not defined in
Leopard's headers */
case -9841:
- if((SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) &&
- SSL_CONN_CONFIG(verifypeer)) {
- CURLcode result = verify_cert(data, SSL_CONN_CONFIG(CAfile),
- SSL_CONN_CONFIG(ca_info_blob),
+ if((conn_config->CAfile || conn_config->ca_info_blob) &&
+ conn_config->verifypeer) {
+ CURLcode result = verify_cert(cf, data, conn_config->CAfile,
+ conn_config->ca_info_blob,
backend->ssl_ctx);
if(result)
return result;
}
/* the documentation says we need to call SSLHandshake() again */
- return sectransp_connect_step2(data, conn, sockindex);
+ goto check_handshake;
/* Problem with encrypt / decrypt */
case errSSLPeerDecodeError:
@@ -2684,7 +2660,7 @@
host name: */
case errSSLHostNameMismatch:
failf(data, "SSL certificate peer verification failed, the "
- "certificate did not match \"%s\"\n", conn->host.dispname);
+ "certificate did not match \"%s\"\n", connssl->dispname);
return CURLE_PEER_FAILED_VERIFICATION;
/* Problem with SSL / TLS negotiation */
@@ -2751,7 +2727,7 @@
failf(data, "Peer rejected unexpected message");
break;
#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
- /* Treaing non-fatal error as fatal like before */
+ /* Treating non-fatal error as fatal like before */
case errSSLClientHelloReceived:
failf(data, "A non-fatal result for providing a server name "
"indication");
@@ -2776,7 +2752,7 @@
default:
/* May also return codes listed in Security Framework Result Codes */
failf(data, "Unknown SSL protocol error in connection to %s:%d",
- hostname, err);
+ connssl->hostname, err);
break;
}
return CURLE_SSL_CONNECT_ERROR;
@@ -2835,7 +2811,7 @@
}
#if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
- if(conn->bits.tls_enable_alpn) {
+ if(connssl->alpn) {
if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
CFArrayRef alpnArr = NULL;
CFStringRef chosenProtocol = NULL;
@@ -2847,18 +2823,18 @@
#ifdef USE_HTTP2
if(chosenProtocol &&
!CFStringCompare(chosenProtocol, CFSTR(ALPN_H2), 0)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
+ cf->conn->alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(chosenProtocol &&
!CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
+ cf->conn->alpn = CURL_HTTP_VERSION_1_1;
}
else
infof(data, VTLS_INFOF_NO_ALPN);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
/* chosenProtocol is a reference to the string within alpnArr
@@ -2894,11 +2870,12 @@
}
static CURLcode
-collect_server_cert_single(struct Curl_easy *data,
+collect_server_cert_single(struct Curl_cfilter *cf, struct Curl_easy *data,
SecCertificateRef server_cert,
CFIndex idx)
{
CURLcode result = CURLE_OK;
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(data->set.verbose) {
char *certp;
@@ -2909,26 +2886,26 @@
}
}
#endif
- if(data->set.ssl.certinfo)
+ if(ssl_config->certinfo)
result = add_cert_to_certinfo(data, server_cert, (int)idx);
return result;
}
/* This should be called during step3 of the connection at the earliest */
-static CURLcode
-collect_server_cert(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex)
+static CURLcode collect_server_cert(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
#ifndef CURL_DISABLE_VERBOSE_STRINGS
const bool show_verbose_server_cert = data->set.verbose;
#else
const bool show_verbose_server_cert = false;
#endif
- CURLcode result = data->set.ssl.certinfo ?
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ CURLcode result = ssl_config->certinfo ?
CURLE_PEER_FAILED_VERIFICATION : CURLE_OK;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
CFArrayRef server_certs = NULL;
SecCertificateRef server_cert;
OSStatus err;
@@ -2937,7 +2914,7 @@
DEBUGASSERT(backend);
- if(!show_verbose_server_cert && !data->set.ssl.certinfo)
+ if(!show_verbose_server_cert && !ssl_config->certinfo)
return CURLE_OK;
if(!backend->ssl_ctx)
@@ -2951,11 +2928,11 @@
a null trust, so be on guard for that: */
if(err == noErr && trust) {
count = SecTrustGetCertificateCount(trust);
- if(data->set.ssl.certinfo)
+ if(ssl_config->certinfo)
result = Curl_ssl_init_certinfo(data, (int)count);
for(i = 0L ; !result && (i < count) ; i++) {
server_cert = SecTrustGetCertificateAtIndex(trust, i);
- result = collect_server_cert_single(data, server_cert, i);
+ result = collect_server_cert_single(cf, data, server_cert, i);
}
CFRelease(trust);
}
@@ -2973,11 +2950,11 @@
a null trust, so be on guard for that: */
if(err == noErr && trust) {
count = SecTrustGetCertificateCount(trust);
- if(data->set.ssl.certinfo)
+ if(ssl_config->certinfo)
result = Curl_ssl_init_certinfo(data, (int)count);
for(i = 0L ; !result && (i < count) ; i++) {
server_cert = SecTrustGetCertificateAtIndex(trust, i);
- result = collect_server_cert_single(data, server_cert, i);
+ result = collect_server_cert_single(cf, data, server_cert, i);
}
CFRelease(trust);
}
@@ -2988,12 +2965,12 @@
/* Just in case SSLCopyPeerCertificates() returns null too... */
if(err == noErr && server_certs) {
count = CFArrayGetCount(server_certs);
- if(data->set.ssl.certinfo)
+ if(ssl_config->certinfo)
result = Curl_ssl_init_certinfo(data, (int)count);
for(i = 0L ; !result && (i < count) ; i++) {
server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
i);
- result = collect_server_cert_single(data, server_cert, i);
+ result = collect_server_cert_single(cf, data, server_cert, i);
}
CFRelease(server_certs);
}
@@ -3005,11 +2982,11 @@
err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
if(err == noErr) {
count = CFArrayGetCount(server_certs);
- if(data->set.ssl.certinfo)
+ if(ssl_config->certinfo)
result = Curl_ssl_init_certinfo(data, (int)count);
for(i = 0L ; !result && (i < count) ; i++) {
server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
- result = collect_server_cert_single(data, server_cert, i);
+ result = collect_server_cert_single(cf, data, server_cert, i);
}
CFRelease(server_certs);
}
@@ -3017,16 +2994,17 @@
return result;
}
-static CURLcode
-sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static CURLcode sectransp_connect_step3(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
+ CURLcode result;
+ DEBUGF(LOG_CF(data, cf, "connect_step3"));
/* There is no step 3!
* Well, okay, let's collect server certificates, and if verbose mode is on,
* let's print the details of the server certificates. */
- const CURLcode result = collect_server_cert(data, conn, sockindex);
+ result = collect_server_cert(cf, data);
if(result)
return result;
@@ -3034,19 +3012,14 @@
return CURLE_OK;
}
-static Curl_recv sectransp_recv;
-static Curl_send sectransp_send;
-
static CURLcode
-sectransp_connect_common(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
+sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
bool nonblocking,
bool *done)
{
CURLcode result;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
int what;
/* check if the connection has already been established */
@@ -3065,7 +3038,7 @@
return CURLE_OPERATION_TIMEDOUT;
}
- result = sectransp_connect_step1(data, conn, sockindex);
+ result = sectransp_connect_step1(cf, data);
if(result)
return result;
}
@@ -3119,7 +3092,7 @@
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
- result = sectransp_connect_step2(data, conn, sockindex);
+ result = sectransp_connect_step2(cf, data);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -3130,15 +3103,14 @@
if(ssl_connect_3 == connssl->connecting_state) {
- result = sectransp_connect_step3(data, conn, sockindex);
+ result = sectransp_connect_step3(cf, data);
if(result)
return result;
}
if(ssl_connect_done == connssl->connecting_state) {
+ DEBUGF(LOG_CF(data, cf, "connected"));
connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = sectransp_recv;
- conn->send[sockindex] = sectransp_send;
*done = TRUE;
}
else
@@ -3150,20 +3122,20 @@
return CURLE_OK;
}
-static CURLcode sectransp_connect_nonblocking(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode sectransp_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done)
{
- return sectransp_connect_common(data, conn, sockindex, TRUE, done);
+ return sectransp_connect_common(cf, data, TRUE, done);
}
-static CURLcode sectransp_connect(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode sectransp_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
CURLcode result;
bool done = FALSE;
- result = sectransp_connect_common(data, conn, sockindex, FALSE, &done);
+ result = sectransp_connect_common(cf, data, FALSE, &done);
if(result)
return result;
@@ -3173,17 +3145,18 @@
return CURLE_OK;
}
-static void sectransp_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static void sectransp_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
(void) data;
DEBUGASSERT(backend);
if(backend->ssl_ctx) {
+ DEBUGF(LOG_CF(data, cf, "close"));
(void)SSLClose(backend->ssl_ctx);
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
if(SSLCreateContext)
@@ -3197,19 +3170,20 @@
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
backend->ssl_ctx = NULL;
}
- backend->ssl_sockfd = 0;
}
-static int sectransp_shutdown(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static int sectransp_shutdown(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
ssize_t nread;
int what;
int rc;
char buf[120];
int loop = 10; /* avoid getting stuck */
+ CURLcode result;
DEBUGASSERT(backend);
@@ -3221,12 +3195,14 @@
return 0;
#endif
- sectransp_close(data, conn, sockindex);
+ sectransp_close(cf, data);
rc = 0;
- what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
+ what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
+ SSL_SHUTDOWN_TIMEOUT);
+ DEBUGF(LOG_CF(data, cf, "shutdown"));
while(loop--) {
if(what < 0) {
/* anything that gets here is fatally bad */
@@ -3243,19 +3219,17 @@
/* Something to read, let's do it and hope that it is the close
notify alert from the server. No way to SSL_Read now, so use read(). */
- nread = read(conn->sock[sockindex], buf, sizeof(buf));
+ nread = Curl_conn_cf_recv(cf->next, data, buf, sizeof(buf), &result);
if(nread < 0) {
- char buffer[STRERROR_LEN];
- failf(data, "read: %s",
- Curl_strerror(errno, buffer, sizeof(buffer)));
+ failf(data, "read: %s", curl_easy_strerror(result));
rc = -1;
}
if(nread <= 0)
break;
- what = SOCKET_READABLE(conn->sock[sockindex], 0);
+ what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data), 0);
}
return rc;
@@ -3277,43 +3251,20 @@
return msnprintf(buffer, size, "SecureTransport");
}
-/*
- * This function uses SSLGetSessionState to determine connection status.
- *
- * Return codes:
- * 1 means the connection is still in place
- * 0 means the connection has been closed
- * -1 means the connection status is unknown
- */
-static int sectransp_check_cxn(struct connectdata *conn)
+static bool sectransp_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
- struct ssl_backend_data *backend = connssl->backend;
- OSStatus err;
- SSLSessionState state;
-
- DEBUGASSERT(backend);
-
- if(backend->ssl_ctx) {
- err = SSLGetSessionState(backend->ssl_ctx, &state);
- if(err == noErr)
- return state == kSSLConnected || state == kSSLHandshake;
- return -1;
- }
- return 0;
-}
-
-static bool sectransp_data_pending(const struct connectdata *conn,
- int connindex)
-{
- const struct ssl_connect_data *connssl = &conn->ssl[connindex];
- struct ssl_backend_data *backend = connssl->backend;
+ const struct ssl_connect_data *connssl = cf->ctx;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
OSStatus err;
size_t buffer;
+ (void)data;
DEBUGASSERT(backend);
if(backend->ssl_ctx) { /* SSL is in use */
+ DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "data_pending"));
err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
if(err == noErr)
return buffer > 0UL;
@@ -3362,15 +3313,15 @@
return FALSE;
}
-static ssize_t sectransp_send(struct Curl_easy *data,
- int sockindex,
+static ssize_t sectransp_send(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
const void *mem,
size_t len,
CURLcode *curlcode)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
size_t processed = 0UL;
OSStatus err;
@@ -3431,28 +3382,31 @@
return (ssize_t)processed;
}
-static ssize_t sectransp_recv(struct Curl_easy *data,
- int num,
+static ssize_t sectransp_recv(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
char *buf,
size_t buffersize,
CURLcode *curlcode)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[num];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
size_t processed = 0UL;
OSStatus err;
DEBUGASSERT(backend);
- again:
+again:
+ *curlcode = CURLE_OK;
err = SSLRead(backend->ssl_ctx, buf, buffersize, &processed);
if(err != noErr) {
switch(err) {
case errSSLWouldBlock: /* return how much we read (if anything) */
- if(processed)
+ if(processed) {
return (ssize_t)processed;
+ }
*curlcode = CURLE_AGAIN;
return -1L;
break;
@@ -3464,19 +3418,21 @@
case errSSLClosedGraceful:
case errSSLClosedNoNotify:
*curlcode = CURLE_OK;
- return -1L;
+ return 0;
break;
/* The below is errSSLPeerAuthCompleted; it's not defined in
Leopard's headers */
case -9841:
- if((SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) &&
- SSL_CONN_CONFIG(verifypeer)) {
- CURLcode result = verify_cert(data, SSL_CONN_CONFIG(CAfile),
- SSL_CONN_CONFIG(ca_info_blob),
+ if((conn_config->CAfile || conn_config->ca_info_blob) &&
+ conn_config->verifypeer) {
+ CURLcode result = verify_cert(cf, data, conn_config->CAfile,
+ conn_config->ca_info_blob,
backend->ssl_ctx);
- if(result)
- return result;
+ if(result) {
+ *curlcode = result;
+ return -1;
+ }
}
goto again;
default:
@@ -3492,7 +3448,8 @@
static void *sectransp_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
(void)info;
DEBUGASSERT(backend);
return backend->ssl_ctx;
@@ -3504,24 +3461,23 @@
SSLSUPP_CAINFO_BLOB |
SSLSUPP_CERTINFO |
#ifdef SECTRANSP_PINNEDPUBKEY
- SSLSUPP_PINNEDPUBKEY,
-#else
- 0,
+ SSLSUPP_PINNEDPUBKEY |
#endif /* SECTRANSP_PINNEDPUBKEY */
+ SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct st_ssl_backend_data),
Curl_none_init, /* init */
Curl_none_cleanup, /* cleanup */
sectransp_version, /* version */
- sectransp_check_cxn, /* check_cxn */
+ Curl_none_check_cxn, /* check_cxn */
sectransp_shutdown, /* shutdown */
sectransp_data_pending, /* data_pending */
sectransp_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
sectransp_connect, /* connect */
sectransp_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_getsock, /* getsock */
+ Curl_ssl_get_select_socks, /* getsock */
sectransp_get_internals, /* get_internals */
sectransp_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -3532,7 +3488,10 @@
sectransp_false_start, /* false_start */
sectransp_sha256sum, /* sha256sum */
NULL, /* associate_connection */
- NULL /* disassociate_connection */
+ NULL, /* disassociate_connection */
+ NULL, /* free_multi_ssl_backend_data */
+ sectransp_recv, /* recv decrypted data */
+ sectransp_send, /* send data to encrypt */
};
#ifdef __clang__
diff --git a/lib/vtls/sectransp.h b/lib/vtls/sectransp.h
index 2d53b7c..0f1085a 100644
--- a/lib/vtls/sectransp.h
+++ b/lib/vtls/sectransp.h
@@ -7,8 +7,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Nick Zitzmann, <nickzman@gmail.com>.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index faa1b51..510bcfe 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -51,8 +51,10 @@
#endif
#include "urldata.h"
+#include "cfilters.h"
#include "vtls.h" /* generic SSL protos etc */
+#include "vtls_int.h"
#include "slist.h"
#include "sendf.h"
#include "strcase.h"
@@ -71,6 +73,7 @@
#include "curl_memory.h"
#include "memdebug.h"
+
/* convenience macro to check if this handle is using a shared SSL session */
#define SSLSESSION_SHARED(data) (data->share && \
(data->share->specifier & \
@@ -127,6 +130,33 @@
return !memcmp(first->data, second->data, first->len); /* same data */
}
+#ifdef USE_SSL
+static const struct alpn_spec ALPN_SPEC_H10 = {
+ { ALPN_HTTP_1_0 }, 1
+};
+static const struct alpn_spec ALPN_SPEC_H11 = {
+ { ALPN_HTTP_1_1 }, 1
+};
+#ifdef USE_HTTP2
+static const struct alpn_spec ALPN_SPEC_H2_H11 = {
+ { ALPN_H2, ALPN_HTTP_1_1 }, 2
+};
+#endif
+
+static const struct alpn_spec *alpn_get_spec(int httpwant, bool use_alpn)
+{
+ if(!use_alpn)
+ return NULL;
+ if(httpwant == CURL_HTTP_VERSION_1_0)
+ return &ALPN_SPEC_H10;
+#ifdef USE_HTTP2
+ if(httpwant >= CURL_HTTP_VERSION_2)
+ return &ALPN_SPEC_H2_H11;
+#endif
+ return &ALPN_SPEC_H11;
+}
+#endif /* USE_SSL */
+
bool
Curl_ssl_config_matches(struct ssl_primary_config *data,
@@ -146,15 +176,14 @@
Curl_safecmp(data->issuercert, needle->issuercert) &&
Curl_safecmp(data->clientcert, needle->clientcert) &&
#ifdef USE_TLS_SRP
- Curl_safecmp(data->username, needle->username) &&
- Curl_safecmp(data->password, needle->password) &&
- (data->authtype == needle->authtype) &&
+ !Curl_timestrcmp(data->username, needle->username) &&
+ !Curl_timestrcmp(data->password, needle->password) &&
#endif
- Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
- Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
- Curl_safe_strcasecompare(data->curves, needle->curves) &&
- Curl_safe_strcasecompare(data->CRLfile, needle->CRLfile) &&
- Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key))
+ strcasecompare(data->cipher_list, needle->cipher_list) &&
+ strcasecompare(data->cipher_list13, needle->cipher_list13) &&
+ strcasecompare(data->curves, needle->curves) &&
+ strcasecompare(data->CRLfile, needle->CRLfile) &&
+ strcasecompare(data->pinned_key, needle->pinned_key))
return TRUE;
return FALSE;
@@ -171,9 +200,6 @@
dest->verifystatus = source->verifystatus;
dest->sessionid = source->sessionid;
dest->ssl_options = source->ssl_options;
-#ifdef USE_TLS_SRP
- dest->authtype = source->authtype;
-#endif
CLONE_BLOB(cert_blob);
CLONE_BLOB(ca_info_blob);
@@ -219,13 +245,13 @@
static int multissl_setup(const struct Curl_ssl *backend);
#endif
-int Curl_ssl_backend(void)
+curl_sslbackend Curl_ssl_backend(void)
{
#ifdef USE_SSL
multissl_setup(NULL);
return Curl_ssl->info.id;
#else
- return (int)CURLSSLBACKEND_NONE;
+ return CURLSSLBACKEND_NONE;
#endif
}
@@ -270,8 +296,8 @@
static bool ssl_prefs_check(struct Curl_easy *data)
{
/* check for CURLOPT_SSLVERSION invalid parameter value */
- const long sslver = data->set.ssl.primary.version;
- if((sslver < 0) || (sslver >= CURL_SSLVERSION_LAST)) {
+ const unsigned char sslver = data->set.ssl.primary.version;
+ if(sslver >= CURL_SSLVERSION_LAST) {
failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
return FALSE;
}
@@ -291,89 +317,62 @@
return TRUE;
}
-#ifndef CURL_DISABLE_PROXY
-static CURLcode
-ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
+static struct ssl_connect_data *cf_ctx_new(struct Curl_easy *data,
+ const struct alpn_spec *alpn)
{
- DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
- if(ssl_connection_complete == conn->ssl[sockindex].state &&
- !conn->proxy_ssl[sockindex].use) {
- struct ssl_backend_data *pbdata;
+ struct ssl_connect_data *ctx;
- if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
- return CURLE_NOT_BUILT_IN;
+ (void)data;
+ ctx = calloc(1, sizeof(*ctx));
+ if(!ctx)
+ return NULL;
- /* The pointers to the ssl backend data, which is opaque here, are swapped
- rather than move the contents. */
- pbdata = conn->proxy_ssl[sockindex].backend;
- conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
-
- DEBUGASSERT(pbdata != NULL);
-
- memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
- memset(pbdata, 0, Curl_ssl->sizeof_ssl_backend_data);
-
- conn->ssl[sockindex].backend = pbdata;
+ ctx->alpn = alpn;
+ ctx->backend = calloc(1, Curl_ssl->sizeof_ssl_backend_data);
+ if(!ctx->backend) {
+ free(ctx);
+ return NULL;
}
- return CURLE_OK;
+ return ctx;
}
-#endif
-CURLcode
-Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static void cf_ctx_free(struct ssl_connect_data *ctx)
{
- CURLcode result;
-
-#ifndef CURL_DISABLE_PROXY
- if(conn->bits.proxy_ssl_connected[sockindex]) {
- result = ssl_connect_init_proxy(conn, sockindex);
- if(result)
- return result;
+ if(ctx) {
+ free(ctx->backend);
+ free(ctx);
}
-#endif
+}
+
+static CURLcode ssl_connect(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ CURLcode result;
if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl-enabled from here on. */
- conn->ssl[sockindex].use = TRUE;
- conn->ssl[sockindex].state = ssl_connection_negotiating;
+ connssl->state = ssl_connection_negotiating;
- result = Curl_ssl->connect_blocking(data, conn, sockindex);
+ result = Curl_ssl->connect_blocking(cf, data);
- if(!result)
- Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
- else
- conn->ssl[sockindex].use = FALSE;
+ if(!result) {
+ DEBUGASSERT(connssl->state == ssl_connection_complete);
+ }
return result;
}
-CURLcode
-Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
- bool isproxy, int sockindex, bool *done)
+static CURLcode
+ssl_connect_nonblocking(struct Curl_cfilter *cf, struct Curl_easy *data,
+ bool *done)
{
- CURLcode result;
-
-#ifndef CURL_DISABLE_PROXY
- if(conn->bits.proxy_ssl_connected[sockindex]) {
- result = ssl_connect_init_proxy(conn, sockindex);
- if(result)
- return result;
- }
-#endif
if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl requested from here on. */
- conn->ssl[sockindex].use = TRUE;
- result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
- if(result)
- conn->ssl[sockindex].use = FALSE;
- else if(*done && !isproxy)
- Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
- return result;
+ return Curl_ssl->connect_nonblocking(cf, data, done);
}
/*
@@ -398,42 +397,26 @@
* Check if there's a session ID for the given connection in the cache, and if
* there's one suitable, it is provided. Returns TRUE when no entry matched.
*/
-bool Curl_ssl_getsessionid(struct Curl_easy *data,
- struct connectdata *conn,
- const bool isProxy,
+bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
void **ssl_sessionid,
- size_t *idsize, /* set 0 if unknown */
- int sockindex)
+ size_t *idsize) /* set 0 if unknown */
{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
struct Curl_ssl_session *check;
size_t i;
long *general_age;
bool no_match = TRUE;
-#ifndef CURL_DISABLE_PROXY
- struct ssl_primary_config * const ssl_config = isProxy ?
- &conn->proxy_ssl_config :
- &conn->ssl_config;
- const char * const name = isProxy ?
- conn->http_proxy.host.name : conn->host.name;
- int port = isProxy ? (int)conn->port : conn->remote_port;
-#else
- /* no proxy support */
- struct ssl_primary_config * const ssl_config = &conn->ssl_config;
- const char * const name = conn->host.name;
- int port = conn->remote_port;
-#endif
- (void)sockindex;
*ssl_sessionid = NULL;
-
-#ifdef CURL_DISABLE_PROXY
- if(isProxy)
+ if(!ssl_config)
return TRUE;
-#endif
- DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
+ DEBUGASSERT(ssl_config->primary.sessionid);
- if(!SSL_SET_OPTION(primary.sessionid) || !data->state.session)
+ if(!ssl_config->primary.sessionid || !data->state.session)
/* session ID re-use is disabled or the session cache has not been
setup */
return TRUE;
@@ -449,16 +432,16 @@
if(!check->sessionid)
/* not session ID means blank entry */
continue;
- if(strcasecompare(name, check->name) &&
- ((!conn->bits.conn_to_host && !check->conn_to_host) ||
- (conn->bits.conn_to_host && check->conn_to_host &&
- strcasecompare(conn->conn_to_host.name, check->conn_to_host))) &&
- ((!conn->bits.conn_to_port && check->conn_to_port == -1) ||
- (conn->bits.conn_to_port && check->conn_to_port != -1 &&
- conn->conn_to_port == check->conn_to_port)) &&
- (port == check->remote_port) &&
- strcasecompare(conn->handler->scheme, check->scheme) &&
- Curl_ssl_config_matches(ssl_config, &check->ssl_config)) {
+ if(strcasecompare(connssl->hostname, check->name) &&
+ ((!cf->conn->bits.conn_to_host && !check->conn_to_host) ||
+ (cf->conn->bits.conn_to_host && check->conn_to_host &&
+ strcasecompare(cf->conn->conn_to_host.name, check->conn_to_host))) &&
+ ((!cf->conn->bits.conn_to_port && check->conn_to_port == -1) ||
+ (cf->conn->bits.conn_to_port && check->conn_to_port != -1 &&
+ cf->conn->conn_to_port == check->conn_to_port)) &&
+ (connssl->port == check->remote_port) &&
+ strcasecompare(cf->conn->handler->scheme, check->scheme) &&
+ Curl_ssl_config_matches(conn_config, &check->ssl_config)) {
/* yes, we have a session ID! */
(*general_age)++; /* increase general age */
check->age = *general_age; /* set this as used in this age */
@@ -472,8 +455,8 @@
DEBUGF(infof(data, "%s Session ID in cache for %s %s://%s:%d",
no_match? "Didn't find": "Found",
- isProxy ? "proxy" : "host",
- conn->handler->scheme, name, port));
+ Curl_ssl_cf_is_proxy(cf) ? "proxy" : "host",
+ cf->conn->handler->scheme, connssl->hostname, connssl->port));
return no_match;
}
@@ -521,14 +504,15 @@
* layer. Curl_XXXX_session_free() will be called to free/kill the session ID
* later on.
*/
-CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
- struct connectdata *conn,
- const bool isProxy,
+CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
void *ssl_sessionid,
size_t idsize,
- int sockindex,
bool *added)
{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
size_t i;
struct Curl_ssl_session *store;
long oldest_age;
@@ -536,17 +520,6 @@
char *clone_conn_to_host;
int conn_to_port;
long *general_age;
-#ifndef CURL_DISABLE_PROXY
- struct ssl_primary_config * const ssl_config = isProxy ?
- &conn->proxy_ssl_config :
- &conn->ssl_config;
- const char *hostname = isProxy ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- struct ssl_primary_config * const ssl_config = &conn->ssl_config;
- const char *hostname = conn->host.name;
-#endif
- (void)sockindex;
if(added)
*added = FALSE;
@@ -556,14 +529,15 @@
store = &data->state.session[0];
oldest_age = data->state.session[0].age; /* zero if unused */
- DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
+ (void)ssl_config;
+ DEBUGASSERT(ssl_config->primary.sessionid);
- clone_host = strdup(hostname);
+ clone_host = strdup(connssl->hostname);
if(!clone_host)
return CURLE_OUT_OF_MEMORY; /* bail out */
- if(conn->bits.conn_to_host) {
- clone_conn_to_host = strdup(conn->conn_to_host.name);
+ if(cf->conn->bits.conn_to_host) {
+ clone_conn_to_host = strdup(cf->conn->conn_to_host.name);
if(!clone_conn_to_host) {
free(clone_host);
return CURLE_OUT_OF_MEMORY; /* bail out */
@@ -572,8 +546,8 @@
else
clone_conn_to_host = NULL;
- if(conn->bits.conn_to_port)
- conn_to_port = conn->conn_to_port;
+ if(cf->conn->bits.conn_to_port)
+ conn_to_port = cf->conn->conn_to_port;
else
conn_to_port = -1;
@@ -613,10 +587,10 @@
store->conn_to_host = clone_conn_to_host; /* clone connect to host name */
store->conn_to_port = conn_to_port; /* connect to port number */
/* port number */
- store->remote_port = isProxy ? (int)conn->port : conn->remote_port;
- store->scheme = conn->handler->scheme;
+ store->remote_port = connssl->port;
+ store->scheme = cf->conn->handler->scheme;
- if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) {
+ if(!Curl_clone_primary_ssl_config(conn_config, &store->ssl_config)) {
Curl_free_primary_ssl_config(&store->ssl_config);
store->sessionid = NULL; /* let caller free sessionid */
free(clone_host);
@@ -629,30 +603,14 @@
DEBUGF(infof(data, "Added Session ID to cache for %s://%s:%d [%s]",
store->scheme, store->name, store->remote_port,
- isProxy ? "PROXY" : "server"));
+ Curl_ssl_cf_is_proxy(cf) ? "PROXY" : "server"));
return CURLE_OK;
}
-void Curl_ssl_associate_conn(struct Curl_easy *data,
- struct connectdata *conn)
+void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend)
{
- if(Curl_ssl->associate_connection) {
- Curl_ssl->associate_connection(data, conn, FIRSTSOCKET);
- if((conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) &&
- conn->bits.sock_accepted)
- Curl_ssl->associate_connection(data, conn, SECONDARYSOCKET);
- }
-}
-
-void Curl_ssl_detach_conn(struct Curl_easy *data,
- struct connectdata *conn)
-{
- if(Curl_ssl->disassociate_connection) {
- Curl_ssl->disassociate_connection(data, FIRSTSOCKET);
- if((conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) &&
- conn->bits.sock_accepted)
- Curl_ssl->disassociate_connection(data, SECONDARYSOCKET);
- }
+ if(Curl_ssl->free_multi_ssl_backend_data && mbackend)
+ Curl_ssl->free_multi_ssl_backend_data(mbackend);
}
void Curl_ssl_close_all(struct Curl_easy *data)
@@ -671,47 +629,27 @@
Curl_ssl->close_all(data);
}
-int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks)
+int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
+ curl_socket_t *socks)
{
- struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
+ struct ssl_connect_data *connssl = cf->ctx;
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
- if(connssl->connecting_state == ssl_connect_2_writing) {
- /* write mode */
- socks[0] = conn->sock[FIRSTSOCKET];
- return GETSOCK_WRITESOCK(0);
+ if(sock != CURL_SOCKET_BAD) {
+ if(connssl->connecting_state == ssl_connect_2_writing) {
+ /* write mode */
+ socks[0] = sock;
+ return GETSOCK_WRITESOCK(0);
+ }
+ if(connssl->connecting_state == ssl_connect_2_reading) {
+ /* read mode */
+ socks[0] = sock;
+ return GETSOCK_READSOCK(0);
+ }
}
- if(connssl->connecting_state == ssl_connect_2_reading) {
- /* read mode */
- socks[0] = conn->sock[FIRSTSOCKET];
- return GETSOCK_READSOCK(0);
- }
-
return GETSOCK_BLANK;
}
-void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
-{
- DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
- Curl_ssl->close_one(data, conn, sockindex);
- conn->ssl[sockindex].state = ssl_connection_none;
-}
-
-CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
-{
- if(Curl_ssl->shut_down(data, conn, sockindex))
- return CURLE_SSL_SHUTDOWN_FAILED;
-
- conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
- conn->ssl[sockindex].state = ssl_connection_none;
-
- conn->recv[sockindex] = Curl_recv_plain;
- conn->send[sockindex] = Curl_send_plain;
-
- return CURLE_OK;
-}
-
/* Selects an SSL crypto engine
*/
CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine)
@@ -766,25 +704,6 @@
#endif
}
-/*
- * This function tries to determine connection status.
- *
- * Return codes:
- * 1 means the connection is still in place
- * 0 means the connection has been closed
- * -1 means the connection status is unknown
- */
-int Curl_ssl_check_cxn(struct connectdata *conn)
-{
- return Curl_ssl->check_cxn(conn);
-}
-
-bool Curl_ssl_data_pending(const struct connectdata *conn,
- int connindex)
-{
- return Curl_ssl->data_pending(conn, connindex);
-}
-
void Curl_ssl_free_certinfo(struct Curl_easy *data)
{
struct curl_certinfo *ci = &data->info.certs;
@@ -862,20 +781,6 @@
return result;
}
-/*
- * This is a convenience function for push_certinfo_len that takes a zero
- * terminated value.
- */
-CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data,
- int certnum,
- const char *label,
- const char *value)
-{
- size_t valuelen = strlen(value);
-
- return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
-}
-
CURLcode Curl_ssl_random(struct Curl_easy *data,
unsigned char *entropy,
size_t length)
@@ -899,7 +804,7 @@
size_t len = strlen(host);
if(len && (host[len-1] == '.'))
len--;
- if((long)len >= data->set.buffer_size)
+ if(len >= data->set.buffer_size)
return NULL;
Curl_strntolower(data->state.buffer, host, len);
@@ -988,8 +893,8 @@
/* only do this if pinnedpubkey starts with "sha256//", length 8 */
if(strncmp(pinnedpubkey, "sha256//", 8) == 0) {
CURLcode encode;
- size_t encodedlen, pinkeylen;
- char *encoded, *pinkeycopy, *begin_pos, *end_pos;
+ size_t encodedlen = 0, pinkeylen;
+ char *encoded = NULL, *pinkeycopy, *begin_pos, *end_pos;
unsigned char *sha256sumdigest;
if(!Curl_ssl->sha256sum) {
@@ -1002,14 +907,12 @@
if(!sha256sumdigest)
return CURLE_OUT_OF_MEMORY;
encode = Curl_ssl->sha256sum(pubkey, pubkeylen,
- sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
+ sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
- if(encode != CURLE_OK)
- return encode;
-
- encode = Curl_base64_encode((char *)sha256sumdigest,
- CURL_SHA256_DIGEST_LENGTH, &encoded,
- &encodedlen);
+ if(!encode)
+ encode = Curl_base64_encode((char *)sha256sumdigest,
+ CURL_SHA256_DIGEST_LENGTH, &encoded,
+ &encodedlen);
Curl_safefree(sha256sumdigest);
if(encode)
@@ -1138,20 +1041,13 @@
/*
* Check whether the SSL backend supports false start.
*/
-bool Curl_ssl_false_start(void)
+bool Curl_ssl_false_start(struct Curl_easy *data)
{
+ (void)data;
return Curl_ssl->false_start();
}
/*
- * Check whether the SSL backend supports setting TLS 1.3 cipher suites
- */
-bool Curl_ssl_tls13_ciphersuites(void)
-{
- return Curl_ssl->supports & SSLSUPP_TLS13_CIPHERSUITES;
-}
-
-/*
* Default implementations for unsupported functions.
*/
@@ -1163,19 +1059,18 @@
void Curl_none_cleanup(void)
{ }
-int Curl_none_shutdown(struct Curl_easy *data UNUSED_PARAM,
- struct connectdata *conn UNUSED_PARAM,
- int sockindex UNUSED_PARAM)
+int Curl_none_shutdown(struct Curl_cfilter *cf UNUSED_PARAM,
+ struct Curl_easy *data UNUSED_PARAM)
{
(void)data;
- (void)conn;
- (void)sockindex;
+ (void)cf;
return 0;
}
-int Curl_none_check_cxn(struct connectdata *conn UNUSED_PARAM)
+int Curl_none_check_cxn(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- (void)conn;
+ (void)cf;
+ (void)data;
return -1;
}
@@ -1199,11 +1094,11 @@
(void)ptr;
}
-bool Curl_none_data_pending(const struct connectdata *conn UNUSED_PARAM,
- int connindex UNUSED_PARAM)
+bool Curl_none_data_pending(struct Curl_cfilter *cf UNUSED_PARAM,
+ const struct Curl_easy *data UNUSED_PARAM)
{
- (void)conn;
- (void)connindex;
+ (void)cf;
+ (void)data;
return 0;
}
@@ -1244,28 +1139,30 @@
return Curl_ssl->init();
}
-static CURLcode multissl_connect(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode multissl_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
if(multissl_setup(NULL))
return CURLE_FAILED_INIT;
- return Curl_ssl->connect_blocking(data, conn, sockindex);
+ return Curl_ssl->connect_blocking(cf, data);
}
-static CURLcode multissl_connect_nonblocking(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode multissl_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done)
{
if(multissl_setup(NULL))
return CURLE_FAILED_INIT;
- return Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
+ return Curl_ssl->connect_nonblocking(cf, data, done);
}
-static int multissl_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int multissl_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
{
if(multissl_setup(NULL))
return 0;
- return Curl_ssl->getsock(conn, socks);
+ return Curl_ssl->get_select_socks(cf, data, socks);
}
static void *multissl_get_internals(struct ssl_connect_data *connssl,
@@ -1276,12 +1173,30 @@
return Curl_ssl->get_internals(connssl, info);
}
-static void multissl_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static void multissl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
if(multissl_setup(NULL))
return;
- Curl_ssl->close_one(data, conn, sockindex);
+ Curl_ssl->close(cf, data);
+}
+
+static ssize_t multissl_recv_plain(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *code)
+{
+ if(multissl_setup(NULL))
+ return CURLE_FAILED_INIT;
+ return Curl_ssl->recv_plain(cf, data, buf, len, code);
+}
+
+static ssize_t multissl_send_plain(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const void *mem, size_t len,
+ CURLcode *code)
+{
+ if(multissl_setup(NULL))
+ return CURLE_FAILED_INIT;
+ return Curl_ssl->send_plain(cf, data, mem, len, code);
}
static const struct Curl_ssl Curl_ssl_multi = {
@@ -1299,7 +1214,7 @@
Curl_none_cert_status_request, /* cert_status_request */
multissl_connect, /* connect */
multissl_connect_nonblocking, /* connect_nonblocking */
- multissl_getsock, /* getsock */
+ multissl_get_select_socks, /* getsock */
multissl_get_internals, /* get_internals */
multissl_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -1310,7 +1225,10 @@
Curl_none_false_start, /* false_start */
NULL, /* sha256sum */
NULL, /* associate_connection */
- NULL /* disassociate_connection */
+ NULL, /* disassociate_connection */
+ NULL, /* free_multi_ssl_backend_data */
+ multissl_recv_plain, /* recv decrypted data */
+ multissl_send_plain, /* send data to encrypt */
};
const struct Curl_ssl *Curl_ssl =
@@ -1498,3 +1416,635 @@
}
#endif /* !USE_SSL */
+
+#ifdef USE_SSL
+
+static void free_hostname(struct ssl_connect_data *connssl)
+{
+ if(connssl->dispname != connssl->hostname)
+ free(connssl->dispname);
+ free(connssl->hostname);
+ connssl->hostname = connssl->dispname = NULL;
+}
+
+static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ if(connssl) {
+ Curl_ssl->close(cf, data);
+ connssl->state = ssl_connection_none;
+ free_hostname(connssl);
+ }
+ cf->connected = FALSE;
+}
+
+static CURLcode reinit_hostname(struct Curl_cfilter *cf)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ const char *ehostname, *edispname;
+ int eport;
+
+ /* We need the hostname for SNI negotiation. Once handshaked, this
+ * remains the SNI hostname for the TLS connection. But when the
+ * connection is reused, the settings in cf->conn might change.
+ * So we keep a copy of the hostname we use for SNI.
+ */
+#ifndef CURL_DISABLE_PROXY
+ if(Curl_ssl_cf_is_proxy(cf)) {
+ ehostname = cf->conn->http_proxy.host.name;
+ edispname = cf->conn->http_proxy.host.dispname;
+ eport = cf->conn->http_proxy.port;
+ }
+ else
+#endif
+ {
+ ehostname = cf->conn->host.name;
+ edispname = cf->conn->host.dispname;
+ eport = cf->conn->remote_port;
+ }
+
+ /* change if ehostname changed */
+ if(ehostname && (!connssl->hostname
+ || strcmp(ehostname, connssl->hostname))) {
+ free_hostname(connssl);
+ connssl->hostname = strdup(ehostname);
+ if(!connssl->hostname) {
+ free_hostname(connssl);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(!edispname || !strcmp(ehostname, edispname))
+ connssl->dispname = connssl->hostname;
+ else {
+ connssl->dispname = strdup(edispname);
+ if(!connssl->dispname) {
+ free_hostname(connssl);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ }
+ connssl->port = eport;
+ return CURLE_OK;
+}
+
+static void ssl_cf_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ cf_close(cf, data);
+ CF_DATA_RESTORE(cf, save);
+ cf_ctx_free(cf->ctx);
+ cf->ctx = NULL;
+}
+
+static void ssl_cf_close(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ cf_close(cf, data);
+ cf->next->cft->do_close(cf->next, data);
+ CF_DATA_RESTORE(cf, save);
+}
+
+static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct cf_call_data save;
+ CURLcode result;
+
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ CF_DATA_SAVE(save, cf, data);
+ (void)connssl;
+ DEBUGASSERT(data->conn);
+ DEBUGASSERT(data->conn == cf->conn);
+ DEBUGASSERT(connssl);
+ DEBUGASSERT(cf->conn->host.name);
+
+ result = cf->next->cft->do_connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ goto out;
+
+ *done = FALSE;
+ result = reinit_hostname(cf);
+ if(result)
+ goto out;
+
+ if(blocking) {
+ result = ssl_connect(cf, data);
+ *done = (result == CURLE_OK);
+ }
+ else {
+ result = ssl_connect_nonblocking(cf, data, done);
+ }
+
+ if(!result && *done) {
+ cf->connected = TRUE;
+ connssl->handshake_done = Curl_now();
+ DEBUGASSERT(connssl->state == ssl_connection_complete);
+ }
+out:
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static bool ssl_cf_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ struct cf_call_data save;
+ bool result;
+
+ CF_DATA_SAVE(save, cf, data);
+ if(Curl_ssl->data_pending(cf, data))
+ result = TRUE;
+ else
+ result = cf->next->cft->has_data_pending(cf->next, data);
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static ssize_t ssl_cf_send(struct Curl_cfilter *cf,
+ struct Curl_easy *data, const void *buf, size_t len,
+ CURLcode *err)
+{
+ struct cf_call_data save;
+ ssize_t nwritten;
+
+ CF_DATA_SAVE(save, cf, data);
+ *err = CURLE_OK;
+ nwritten = Curl_ssl->send_plain(cf, data, buf, len, err);
+ CF_DATA_RESTORE(cf, save);
+ return nwritten;
+}
+
+static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
+ struct Curl_easy *data, char *buf, size_t len,
+ CURLcode *err)
+{
+ struct cf_call_data save;
+ ssize_t nread;
+
+ CF_DATA_SAVE(save, cf, data);
+ *err = CURLE_OK;
+ nread = Curl_ssl->recv_plain(cf, data, buf, len, err);
+ if(nread > 0) {
+ DEBUGASSERT((size_t)nread <= len);
+ }
+ else if(nread == 0) {
+ /* eof */
+ *err = CURLE_OK;
+ }
+ DEBUGF(LOG_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len, nread, *err));
+ CF_DATA_RESTORE(cf, save);
+ return nread;
+}
+
+static int ssl_cf_get_select_socks(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ curl_socket_t *socks)
+{
+ struct cf_call_data save;
+ int result;
+
+ CF_DATA_SAVE(save, cf, data);
+ result = Curl_ssl->get_select_socks(cf, data, socks);
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
+{
+ struct cf_call_data save;
+
+ (void)arg1;
+ (void)arg2;
+ switch(event) {
+ case CF_CTRL_DATA_ATTACH:
+ if(Curl_ssl->attach_data) {
+ CF_DATA_SAVE(save, cf, data);
+ Curl_ssl->attach_data(cf, data);
+ CF_DATA_RESTORE(cf, save);
+ }
+ break;
+ case CF_CTRL_DATA_DETACH:
+ if(Curl_ssl->detach_data) {
+ CF_DATA_SAVE(save, cf, data);
+ Curl_ssl->detach_data(cf, data);
+ CF_DATA_RESTORE(cf, save);
+ }
+ break;
+ default:
+ break;
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ssl_cf_query(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query, int *pres1, void *pres2)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+
+ switch(query) {
+ case CF_QUERY_TIMER_APPCONNECT: {
+ struct curltime *when = pres2;
+ if(cf->connected && !Curl_ssl_cf_is_proxy(cf))
+ *when = connssl->handshake_done;
+ return CURLE_OK;
+ }
+ default:
+ break;
+ }
+ return cf->next?
+ cf->next->cft->query(cf->next, data, query, pres1, pres2) :
+ CURLE_UNKNOWN_OPTION;
+}
+
+static bool cf_ssl_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data,
+ bool *input_pending)
+{
+ struct cf_call_data save;
+ int result;
+ /*
+ * This function tries to determine connection status.
+ *
+ * Return codes:
+ * 1 means the connection is still in place
+ * 0 means the connection has been closed
+ * -1 means the connection status is unknown
+ */
+ CF_DATA_SAVE(save, cf, data);
+ result = Curl_ssl->check_cxn(cf, data);
+ CF_DATA_RESTORE(cf, save);
+ if(result > 0) {
+ *input_pending = TRUE;
+ return TRUE;
+ }
+ if(result == 0) {
+ *input_pending = FALSE;
+ return FALSE;
+ }
+ /* ssl backend does not know */
+ return cf->next?
+ cf->next->cft->is_alive(cf->next, data, input_pending) :
+ FALSE; /* pessimistic in absence of data */
+}
+
+struct Curl_cftype Curl_cft_ssl = {
+ "SSL",
+ CF_TYPE_SSL,
+ CURL_LOG_DEFAULT,
+ ssl_cf_destroy,
+ ssl_cf_connect,
+ ssl_cf_close,
+ Curl_cf_def_get_host,
+ ssl_cf_get_select_socks,
+ ssl_cf_data_pending,
+ ssl_cf_send,
+ ssl_cf_recv,
+ ssl_cf_cntrl,
+ cf_ssl_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ ssl_cf_query,
+};
+
+struct Curl_cftype Curl_cft_ssl_proxy = {
+ "SSL-PROXY",
+ CF_TYPE_SSL,
+ CURL_LOG_DEFAULT,
+ ssl_cf_destroy,
+ ssl_cf_connect,
+ ssl_cf_close,
+ Curl_cf_def_get_host,
+ ssl_cf_get_select_socks,
+ ssl_cf_data_pending,
+ ssl_cf_send,
+ ssl_cf_recv,
+ ssl_cf_cntrl,
+ cf_ssl_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ Curl_cf_def_query,
+};
+
+static CURLcode cf_ssl_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ struct Curl_cfilter *cf = NULL;
+ struct ssl_connect_data *ctx;
+ CURLcode result;
+
+ DEBUGASSERT(data->conn);
+
+ ctx = cf_ctx_new(data, alpn_get_spec(data->state.httpwant,
+ conn->bits.tls_enable_alpn));
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ result = Curl_cf_create(&cf, &Curl_cft_ssl, ctx);
+
+out:
+ if(result)
+ cf_ctx_free(ctx);
+ *pcf = result? NULL : cf;
+ return result;
+}
+
+CURLcode Curl_ssl_cfilter_add(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result;
+
+ result = cf_ssl_create(&cf, data, conn);
+ if(!result)
+ Curl_conn_cf_add(data, conn, sockindex, cf);
+ return result;
+}
+
+CURLcode Curl_cf_ssl_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result;
+
+ result = cf_ssl_create(&cf, data, cf_at->conn);
+ if(!result)
+ Curl_conn_cf_insert_after(cf_at, cf);
+ return result;
+}
+
+#ifndef CURL_DISABLE_PROXY
+
+static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ struct Curl_cfilter *cf = NULL;
+ struct ssl_connect_data *ctx;
+ CURLcode result;
+ bool use_alpn = conn->bits.tls_enable_alpn;
+ int httpwant = CURL_HTTP_VERSION_1_1;
+
+#ifdef USE_HTTP2
+ if(conn->http_proxy.proxytype == CURLPROXY_HTTPS2) {
+ use_alpn = TRUE;
+ httpwant = CURL_HTTP_VERSION_2;
+ }
+#endif
+
+ ctx = cf_ctx_new(data, alpn_get_spec(httpwant, use_alpn));
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ result = Curl_cf_create(&cf, &Curl_cft_ssl_proxy, ctx);
+
+out:
+ if(result)
+ cf_ctx_free(ctx);
+ *pcf = result? NULL : cf;
+ return result;
+}
+
+CURLcode Curl_cf_ssl_proxy_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data)
+{
+ struct Curl_cfilter *cf;
+ CURLcode result;
+
+ result = cf_ssl_proxy_create(&cf, data, cf_at->conn);
+ if(!result)
+ Curl_conn_cf_insert_after(cf_at, cf);
+ return result;
+}
+
+#endif /* !CURL_DISABLE_PROXY */
+
+bool Curl_ssl_supports(struct Curl_easy *data, int option)
+{
+ (void)data;
+ return (Curl_ssl->supports & option)? TRUE : FALSE;
+}
+
+void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
+ CURLINFO info, int n)
+{
+ void *result = NULL;
+ (void)n;
+ if(data->conn) {
+ struct Curl_cfilter *cf;
+ /* get first filter in chain, if any is present */
+ cf = Curl_ssl_cf_get_ssl(data->conn->cfilter[sockindex]);
+ if(cf) {
+ struct cf_call_data save;
+ CF_DATA_SAVE(save, cf, data);
+ result = Curl_ssl->get_internals(cf->ctx, info);
+ CF_DATA_RESTORE(cf, save);
+ }
+ }
+ return result;
+}
+
+CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
+ int sockindex)
+{
+ struct Curl_cfilter *cf, *head;
+ CURLcode result = CURLE_OK;
+
+ (void)data;
+ head = data->conn? data->conn->cfilter[sockindex] : NULL;
+ for(cf = head; cf; cf = cf->next) {
+ if(cf->cft == &Curl_cft_ssl) {
+ if(Curl_ssl->shut_down(cf, data))
+ result = CURLE_SSL_SHUTDOWN_FAILED;
+ Curl_conn_cf_discard_sub(head, cf, data, FALSE);
+ break;
+ }
+ }
+ return result;
+}
+
+static struct Curl_cfilter *get_ssl_cf_engaged(struct connectdata *conn,
+ int sockindex)
+{
+ struct Curl_cfilter *cf, *lowest_ssl_cf = NULL;
+
+ for(cf = conn->cfilter[sockindex]; cf; cf = cf->next) {
+ if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) {
+ lowest_ssl_cf = cf;
+ if(cf->connected || (cf->next && cf->next->connected)) {
+ /* connected or about to start */
+ return cf;
+ }
+ }
+ }
+ return lowest_ssl_cf;
+}
+
+bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf)
+{
+ return (cf->cft == &Curl_cft_ssl_proxy);
+}
+
+struct ssl_config_data *
+Curl_ssl_cf_get_config(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+#ifdef CURL_DISABLE_PROXY
+ (void)cf;
+ return &data->set.ssl;
+#else
+ return Curl_ssl_cf_is_proxy(cf)? &data->set.proxy_ssl : &data->set.ssl;
+#endif
+}
+
+struct ssl_config_data *
+Curl_ssl_get_config(struct Curl_easy *data, int sockindex)
+{
+ struct Curl_cfilter *cf;
+
+ (void)data;
+ DEBUGASSERT(data->conn);
+ cf = get_ssl_cf_engaged(data->conn, sockindex);
+ return cf? Curl_ssl_cf_get_config(cf, data) : &data->set.ssl;
+}
+
+struct ssl_primary_config *
+Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf)
+{
+#ifdef CURL_DISABLE_PROXY
+ return &cf->conn->ssl_config;
+#else
+ return Curl_ssl_cf_is_proxy(cf)?
+ &cf->conn->proxy_ssl_config : &cf->conn->ssl_config;
+#endif
+}
+
+struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf)
+{
+ for(; cf; cf = cf->next) {
+ if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy)
+ return cf;
+ }
+ return NULL;
+}
+
+CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf,
+ const struct alpn_spec *spec)
+{
+ size_t i, len;
+ int off = 0;
+ unsigned char blen;
+
+ memset(buf, 0, sizeof(*buf));
+ for(i = 0; spec && i < spec->count; ++i) {
+ len = strlen(spec->entries[i]);
+ if(len >= ALPN_NAME_MAX)
+ return CURLE_FAILED_INIT;
+ blen = (unsigned char)len;
+ if(off + blen + 1 >= (int)sizeof(buf->data))
+ return CURLE_FAILED_INIT;
+ buf->data[off++] = blen;
+ memcpy(buf->data + off, spec->entries[i], blen);
+ off += blen;
+ }
+ buf->len = off;
+ return CURLE_OK;
+}
+
+CURLcode Curl_alpn_to_proto_str(struct alpn_proto_buf *buf,
+ const struct alpn_spec *spec)
+{
+ size_t i, len;
+ size_t off = 0;
+
+ memset(buf, 0, sizeof(*buf));
+ for(i = 0; spec && i < spec->count; ++i) {
+ len = strlen(spec->entries[i]);
+ if(len >= ALPN_NAME_MAX)
+ return CURLE_FAILED_INIT;
+ if(off + len + 2 >= sizeof(buf->data))
+ return CURLE_FAILED_INIT;
+ if(off)
+ buf->data[off++] = ',';
+ memcpy(buf->data + off, spec->entries[i], len);
+ off += len;
+ }
+ buf->data[off] = '\0';
+ buf->len = (int)off;
+ return CURLE_OK;
+}
+
+CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const unsigned char *proto,
+ size_t proto_len)
+{
+ int can_multi = 0;
+ unsigned char *palpn =
+#ifndef CURL_DISABLE_PROXY
+ (cf->conn->bits.tunnel_proxy && Curl_ssl_cf_is_proxy(cf))?
+ &cf->conn->proxy_alpn : &cf->conn->alpn
+#else
+ &cf->conn->alpn
+#endif
+ ;
+
+ if(proto && proto_len) {
+ if(proto_len == ALPN_HTTP_1_1_LENGTH &&
+ !memcmp(ALPN_HTTP_1_1, proto, ALPN_HTTP_1_1_LENGTH)) {
+ *palpn = CURL_HTTP_VERSION_1_1;
+ }
+ else if(proto_len == ALPN_HTTP_1_0_LENGTH &&
+ !memcmp(ALPN_HTTP_1_0, proto, ALPN_HTTP_1_0_LENGTH)) {
+ *palpn = CURL_HTTP_VERSION_1_0;
+ }
+#ifdef USE_HTTP2
+ else if(proto_len == ALPN_H2_LENGTH &&
+ !memcmp(ALPN_H2, proto, ALPN_H2_LENGTH)) {
+ *palpn = CURL_HTTP_VERSION_2;
+ can_multi = 1;
+ }
+#endif
+#ifdef USE_HTTP3
+ else if(proto_len == ALPN_H3_LENGTH &&
+ !memcmp(ALPN_H3, proto, ALPN_H3_LENGTH)) {
+ *palpn = CURL_HTTP_VERSION_3;
+ can_multi = 1;
+ }
+#endif
+ else {
+ *palpn = CURL_HTTP_VERSION_NONE;
+ failf(data, "unsupported ALPN protocol: '%.*s'", (int)proto_len, proto);
+ /* TODO: do we want to fail this? Previous code just ignored it and
+ * some vtls backends even ignore the return code of this function. */
+ /* return CURLE_NOT_BUILT_IN; */
+ goto out;
+ }
+ infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, (int)proto_len, proto);
+ }
+ else {
+ *palpn = CURL_HTTP_VERSION_NONE;
+ infof(data, VTLS_INFOF_NO_ALPN);
+ }
+
+out:
+ if(!Curl_ssl_cf_is_proxy(cf))
+ Curl_multiuse_state(data, can_multi?
+ BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ return CURLE_OK;
+}
+
+#endif /* USE_SSL */
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index e1e58f4..3516247 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,7 +26,9 @@
#include "curl_setup.h"
struct connectdata;
-struct ssl_connect_data;
+struct ssl_config_data;
+struct ssl_primary_config;
+struct Curl_ssl_session;
#define SSLSUPP_CA_PATH (1<<0) /* supports CAPATH */
#define SSLSUPP_CERTINFO (1<<1) /* supports CURLOPT_CERTINFO */
@@ -47,98 +49,14 @@
#define VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR \
ALPN_ACCEPTED "%.*s"
-struct Curl_ssl {
- /*
- * This *must* be the first entry to allow returning the list of available
- * backends in curl_global_sslset().
- */
- curl_ssl_backend info;
- unsigned int supports; /* bitfield, see above */
- size_t sizeof_ssl_backend_data;
-
- int (*init)(void);
- void (*cleanup)(void);
-
- size_t (*version)(char *buffer, size_t size);
- int (*check_cxn)(struct connectdata *cxn);
- int (*shut_down)(struct Curl_easy *data, struct connectdata *conn,
- int sockindex);
- bool (*data_pending)(const struct connectdata *conn,
- int connindex);
-
- /* return 0 if a find random is filled in */
- CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy,
- size_t length);
- bool (*cert_status_request)(void);
-
- CURLcode (*connect_blocking)(struct Curl_easy *data,
- struct connectdata *conn, int sockindex);
- CURLcode (*connect_nonblocking)(struct Curl_easy *data,
- struct connectdata *conn, int sockindex,
- bool *done);
-
- /* If the SSL backend wants to read or write on this connection during a
- handshake, set socks[0] to the connection's FIRSTSOCKET, and return
- a bitmap indicating read or write with GETSOCK_WRITESOCK(0) or
- GETSOCK_READSOCK(0). Otherwise return GETSOCK_BLANK.
- Mandatory. */
- int (*getsock)(struct connectdata *conn, curl_socket_t *socks);
-
- void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
- void (*close_one)(struct Curl_easy *data, struct connectdata *conn,
- int sockindex);
- void (*close_all)(struct Curl_easy *data);
- void (*session_free)(void *ptr);
-
- CURLcode (*set_engine)(struct Curl_easy *data, const char *engine);
- CURLcode (*set_engine_default)(struct Curl_easy *data);
- struct curl_slist *(*engines_list)(struct Curl_easy *data);
-
- bool (*false_start)(void);
- CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
- unsigned char *sha256sum, size_t sha256sumlen);
-
- bool (*associate_connection)(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex);
- void (*disassociate_connection)(struct Curl_easy *data, int sockindex);
-};
-
-#ifdef USE_SSL
-extern const struct Curl_ssl *Curl_ssl;
-#endif
-
-int Curl_none_init(void);
-void Curl_none_cleanup(void);
-int Curl_none_shutdown(struct Curl_easy *data, struct connectdata *conn,
- int sockindex);
-int Curl_none_check_cxn(struct connectdata *conn);
-CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy,
- size_t length);
-void Curl_none_close_all(struct Curl_easy *data);
-void Curl_none_session_free(void *ptr);
-bool Curl_none_data_pending(const struct connectdata *conn, int connindex);
-bool Curl_none_cert_status_request(void);
-CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
-CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
-struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
-bool Curl_none_false_start(void);
-bool Curl_ssl_tls13_ciphersuites(void);
+/* Curl_multi SSL backend-specific data; declared differently by each SSL
+ backend */
+struct multi_ssl_backend_data;
+struct Curl_cfilter;
CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
const curl_ssl_backend ***avail);
-#include "openssl.h" /* OpenSSL versions */
-#include "gtls.h" /* GnuTLS versions */
-#include "nssg.h" /* NSS versions */
-#include "gskit.h" /* Global Secure ToolKit versions */
-#include "wolfssl.h" /* wolfSSL versions */
-#include "schannel.h" /* Schannel SSPI version */
-#include "sectransp.h" /* SecureTransport (Darwin) version */
-#include "mbedtls.h" /* mbedTLS versions */
-#include "bearssl.h" /* BearSSL versions */
-#include "rustls.h" /* rustls versions */
-
#ifndef MAX_PINNED_PUBKEY_SIZE
#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */
#endif
@@ -147,78 +65,21 @@
#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
#endif
-/* see https://www.iana.org/assignments/tls-extensiontype-values/ */
-#define ALPN_HTTP_1_1_LENGTH 8
-#define ALPN_HTTP_1_1 "http/1.1"
-#define ALPN_H2_LENGTH 2
-#define ALPN_H2 "h2"
-
-/* set of helper macros for the backends to access the correct fields. For the
- proxy or for the remote host - to properly support HTTPS proxy */
-#ifndef CURL_DISABLE_PROXY
-#define SSL_IS_PROXY() \
- (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \
- ssl_connection_complete != \
- conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \
- CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state)
-#define SSL_SET_OPTION(var) \
- (SSL_IS_PROXY() ? data->set.proxy_ssl.var : data->set.ssl.var)
-#define SSL_SET_OPTION_LVALUE(var) \
- (*(SSL_IS_PROXY() ? &data->set.proxy_ssl.var : &data->set.ssl.var))
-#define SSL_CONN_CONFIG(var) \
- (SSL_IS_PROXY() ? conn->proxy_ssl_config.var : conn->ssl_config.var)
-#define SSL_HOST_NAME() \
- (SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name)
-#define SSL_HOST_DISPNAME() \
- (SSL_IS_PROXY() ? conn->http_proxy.host.dispname : conn->host.dispname)
-#define SSL_HOST_PORT() \
- (SSL_IS_PROXY() ? conn->port : conn->remote_port)
-#define SSL_PINNED_PUB_KEY() (SSL_IS_PROXY() \
- ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] \
- : data->set.str[STRING_SSL_PINNEDPUBLICKEY])
-#else
-#define SSL_IS_PROXY() FALSE
-#define SSL_SET_OPTION(var) data->set.ssl.var
-#define SSL_SET_OPTION_LVALUE(var) data->set.ssl.var
-#define SSL_CONN_CONFIG(var) conn->ssl_config.var
-#define SSL_HOST_NAME() conn->host.name
-#define SSL_HOST_DISPNAME() conn->host.dispname
-#define SSL_HOST_PORT() conn->remote_port
-#define SSL_PINNED_PUB_KEY() \
- data->set.str[STRING_SSL_PINNEDPUBLICKEY]
-#endif
-
char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen);
bool Curl_ssl_config_matches(struct ssl_primary_config *data,
struct ssl_primary_config *needle);
bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
struct ssl_primary_config *dest);
void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc);
-/* An implementation of the getsock field of Curl_ssl that relies
- on the ssl_connect_state enum. Asks for read or write depending
- on whether conn->state is ssl_connect_2_reading or
- ssl_connect_2_writing. */
-int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks);
-int Curl_ssl_backend(void);
+curl_sslbackend Curl_ssl_backend(void);
#ifdef USE_SSL
int Curl_ssl_init(void);
void Curl_ssl_cleanup(void);
-CURLcode Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
- int sockindex);
-CURLcode Curl_ssl_connect_nonblocking(struct Curl_easy *data,
- struct connectdata *conn,
- bool isproxy,
- int sockindex,
- bool *done);
/* tell the SSL stuff to close down all open information regarding
connections (and thus session ID caching etc) */
void Curl_ssl_close_all(struct Curl_easy *data);
-void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex);
-CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
- int sockindex);
CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine);
/* Sets engine as default for all SSL operations */
CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data);
@@ -227,9 +88,6 @@
/* init the SSL session ID cache */
CURLcode Curl_ssl_initsessions(struct Curl_easy *, size_t);
void Curl_ssl_version(char *buffer, size_t size);
-bool Curl_ssl_data_pending(const struct connectdata *conn,
- int connindex);
-int Curl_ssl_check_cxn(struct connectdata *conn);
/* Certificate information list handling. */
@@ -255,30 +113,6 @@
/* Unlock session cache mutex */
void Curl_ssl_sessionid_unlock(struct Curl_easy *data);
-/* extract a session ID
- * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
- * Caller must make sure that the ownership of returned sessionid object
- * is properly taken (e.g. its refcount is incremented
- * under sessionid mutex).
- */
-bool Curl_ssl_getsessionid(struct Curl_easy *data,
- struct connectdata *conn,
- const bool isProxy,
- void **ssl_sessionid,
- size_t *idsize, /* set 0 if unknown */
- int sockindex);
-/* add a new session ID
- * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
- * Caller must ensure that it has properly shared ownership of this sessionid
- * object with cache (e.g. incrementing refcount on success)
- */
-CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
- struct connectdata *conn,
- const bool isProxy,
- void *ssl_sessionid,
- size_t idsize,
- int sockindex,
- bool *added);
/* Kill a single session ID entry in the cache
* Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
* This will call engine-specific curlssl_session_free function, which must
@@ -304,41 +138,79 @@
bool Curl_ssl_cert_status_request(void);
-bool Curl_ssl_false_start(void);
+bool Curl_ssl_false_start(struct Curl_easy *data);
-void Curl_ssl_associate_conn(struct Curl_easy *data,
- struct connectdata *conn);
-void Curl_ssl_detach_conn(struct Curl_easy *data,
- struct connectdata *conn);
+void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend);
#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
+CURLcode Curl_ssl_cfilter_add(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex);
+
+CURLcode Curl_cf_ssl_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data);
+
+CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
+ int sockindex);
+
+#ifndef CURL_DISABLE_PROXY
+CURLcode Curl_cf_ssl_proxy_insert_after(struct Curl_cfilter *cf_at,
+ struct Curl_easy *data);
+#endif /* !CURL_DISABLE_PROXY */
+
+/**
+ * Get the SSL configuration that is used on the connection.
+ * This returns NULL if no SSL is configured.
+ * Otherwise it returns the config of the first (highest) one that is
+ * either connected, in handshake or about to start
+ * (e.g. all filters below it are connected). If SSL filters are present,
+ * but neither can start operating, return the config of the lowest one
+ * that will first come into effect when connecting.
+ */
+struct ssl_config_data *Curl_ssl_get_config(struct Curl_easy *data,
+ int sockindex);
+
+/**
+ * True iff the underlying SSL implementation supports the option.
+ * Option is one of the defined SSLSUPP_* values.
+ * `data` maybe NULL for the features of the default implementation.
+ */
+bool Curl_ssl_supports(struct Curl_easy *data, int ssl_option);
+
+/**
+ * Get the internal ssl instance (like OpenSSL's SSL*) from the filter
+ * chain at `sockindex` of type specified by `info`.
+ * For `n` == 0, the first active (top down) instance is returned.
+ * 1 gives the second active, etc.
+ * NULL is returned when no active SSL filter is present.
+ */
+void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
+ CURLINFO info, int n);
+
+extern struct Curl_cftype Curl_cft_ssl;
+extern struct Curl_cftype Curl_cft_ssl_proxy;
+
#else /* if not USE_SSL */
/* When SSL support is not present, just define away these function calls */
#define Curl_ssl_init() 1
#define Curl_ssl_cleanup() Curl_nop_stmt
-#define Curl_ssl_connect(x,y,z) CURLE_NOT_BUILT_IN
#define Curl_ssl_close_all(x) Curl_nop_stmt
-#define Curl_ssl_close(x,y,z) Curl_nop_stmt
-#define Curl_ssl_shutdown(x,y,z) 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_send(a,b,c,d,e) -1
-#define Curl_ssl_recv(a,b,c,d,e) -1
#define Curl_ssl_initsessions(x,y) CURLE_OK
-#define Curl_ssl_data_pending(x,y) 0
-#define Curl_ssl_check_cxn(x) 0
#define Curl_ssl_free_certinfo(x) Curl_nop_stmt
-#define Curl_ssl_connect_nonblocking(x,y,z,w,a) CURLE_NOT_BUILT_IN
#define Curl_ssl_kill_session(x) Curl_nop_stmt
#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN)
#define Curl_ssl_cert_status_request() FALSE
-#define Curl_ssl_false_start() FALSE
-#define Curl_ssl_tls13_ciphersuites() FALSE
-#define Curl_ssl_associate_conn(a,b) Curl_nop_stmt
-#define Curl_ssl_detach_conn(a,b) Curl_nop_stmt
+#define Curl_ssl_false_start(a) FALSE
+#define Curl_ssl_get_internals(a,b,c,d) NULL
+#define Curl_ssl_supports(a,b) FALSE
+#define Curl_ssl_cfilter_add(a,b,c) CURLE_NOT_BUILT_IN
+#define Curl_ssl_get_config(a,b) NULL
+#define Curl_ssl_cfilter_remove(a,b) CURLE_OK
#endif
#endif /* HEADER_CURL_VTLS_H */
diff --git a/lib/vtls/vtls_int.h b/lib/vtls/vtls_int.h
new file mode 100644
index 0000000..fe0115c
--- /dev/null
+++ b/lib/vtls/vtls_int.h
@@ -0,0 +1,231 @@
+#ifndef HEADER_CURL_VTLS_INT_H
+#define HEADER_CURL_VTLS_INT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+#include "cfilters.h"
+#include "urldata.h"
+
+#ifdef USE_SSL
+
+/* see https://www.iana.org/assignments/tls-extensiontype-values/ */
+#define ALPN_HTTP_1_1_LENGTH 8
+#define ALPN_HTTP_1_1 "http/1.1"
+#define ALPN_HTTP_1_0_LENGTH 8
+#define ALPN_HTTP_1_0 "http/1.0"
+#define ALPN_H2_LENGTH 2
+#define ALPN_H2 "h2"
+#define ALPN_H3_LENGTH 2
+#define ALPN_H3 "h3"
+
+/* conservative sizes on the ALPN entries and count we are handling,
+ * we can increase these if we ever feel the need or have to accommodate
+ * ALPN strings from the "outside". */
+#define ALPN_NAME_MAX 10
+#define ALPN_ENTRIES_MAX 3
+#define ALPN_PROTO_BUF_MAX (ALPN_ENTRIES_MAX * (ALPN_NAME_MAX + 1))
+
+struct alpn_spec {
+ const char entries[ALPN_ENTRIES_MAX][ALPN_NAME_MAX];
+ size_t count; /* number of entries */
+};
+
+struct alpn_proto_buf {
+ unsigned char data[ALPN_PROTO_BUF_MAX];
+ int len;
+};
+
+CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf,
+ const struct alpn_spec *spec);
+CURLcode Curl_alpn_to_proto_str(struct alpn_proto_buf *buf,
+ const struct alpn_spec *spec);
+
+CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const unsigned char *proto,
+ size_t proto_len);
+
+/* Information in each SSL cfilter context: cf->ctx */
+struct ssl_connect_data {
+ ssl_connection_state state;
+ ssl_connect_state connecting_state;
+ char *hostname; /* hostname for verification */
+ char *dispname; /* display version of hostname */
+ const struct alpn_spec *alpn; /* ALPN to use or NULL for none */
+ void *backend; /* vtls backend specific props */
+ struct cf_call_data call_data; /* data handle used in current call */
+ struct curltime handshake_done; /* time when handshake finished */
+ int port; /* remote port at origin */
+ BIT(use_alpn); /* if ALPN shall be used in handshake */
+};
+
+
+#undef CF_CTX_CALL_DATA
+#define CF_CTX_CALL_DATA(cf) \
+ ((struct ssl_connect_data *)(cf)->ctx)->call_data
+
+
+/* Definitions for SSL Implementations */
+
+struct Curl_ssl {
+ /*
+ * This *must* be the first entry to allow returning the list of available
+ * backends in curl_global_sslset().
+ */
+ curl_ssl_backend info;
+ unsigned int supports; /* bitfield, see above */
+ size_t sizeof_ssl_backend_data;
+
+ int (*init)(void);
+ void (*cleanup)(void);
+
+ size_t (*version)(char *buffer, size_t size);
+ int (*check_cxn)(struct Curl_cfilter *cf, struct Curl_easy *data);
+ int (*shut_down)(struct Curl_cfilter *cf,
+ 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,
+ size_t length);
+ bool (*cert_status_request)(void);
+
+ CURLcode (*connect_blocking)(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+ CURLcode (*connect_nonblocking)(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done);
+
+ /* If the SSL backend wants to read or write on this connection during a
+ handshake, set socks[0] to the connection's FIRSTSOCKET, and return
+ a bitmap indicating read or write with GETSOCK_WRITESOCK(0) or
+ GETSOCK_READSOCK(0). Otherwise return GETSOCK_BLANK.
+ Mandatory. */
+ int (*get_select_socks)(struct Curl_cfilter *cf, struct Curl_easy *data,
+ curl_socket_t *socks);
+
+ void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
+ void (*close)(struct Curl_cfilter *cf, struct Curl_easy *data);
+ void (*close_all)(struct Curl_easy *data);
+ void (*session_free)(void *ptr);
+
+ CURLcode (*set_engine)(struct Curl_easy *data, const char *engine);
+ CURLcode (*set_engine_default)(struct Curl_easy *data);
+ struct curl_slist *(*engines_list)(struct Curl_easy *data);
+
+ bool (*false_start)(void);
+ CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
+ unsigned char *sha256sum, size_t sha256sumlen);
+
+ bool (*attach_data)(struct Curl_cfilter *cf, struct Curl_easy *data);
+ void (*detach_data)(struct Curl_cfilter *cf, struct Curl_easy *data);
+
+ void (*free_multi_ssl_backend_data)(struct multi_ssl_backend_data *mbackend);
+
+ ssize_t (*recv_plain)(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *code);
+ ssize_t (*send_plain)(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *mem, size_t len, CURLcode *code);
+
+};
+
+extern const struct Curl_ssl *Curl_ssl;
+
+
+int Curl_none_init(void);
+void Curl_none_cleanup(void);
+int Curl_none_shutdown(struct Curl_cfilter *cf, struct Curl_easy *data);
+int Curl_none_check_cxn(struct Curl_cfilter *cf, struct Curl_easy *data);
+CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy,
+ size_t length);
+void Curl_none_close_all(struct Curl_easy *data);
+void Curl_none_session_free(void *ptr);
+bool Curl_none_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data);
+bool Curl_none_cert_status_request(void);
+CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
+CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
+struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
+bool Curl_none_false_start(void);
+int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
+ curl_socket_t *socks);
+
+/**
+ * Get the ssl_config_data in `data` that is relevant for cfilter `cf`.
+ */
+struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+/**
+ * Get the primary config relevant for the filter from its connection.
+ */
+struct ssl_primary_config *
+ Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf);
+
+/**
+ * Get the first SSL filter in the chain starting with `cf`, or NULL.
+ */
+struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf);
+
+/**
+ * Get the SSL filter below the given one or NULL if there is none.
+ */
+bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf);
+
+/* extract a session ID
+ * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
+ * Caller must make sure that the ownership of returned sessionid object
+ * is properly taken (e.g. its refcount is incremented
+ * under sessionid mutex).
+ */
+bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ void **ssl_sessionid,
+ size_t *idsize); /* set 0 if unknown */
+/* add a new session ID
+ * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
+ * Caller must ensure that it has properly shared ownership of this sessionid
+ * object with cache (e.g. incrementing refcount on success)
+ */
+CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ void *ssl_sessionid,
+ size_t idsize,
+ bool *added);
+
+#include "openssl.h" /* OpenSSL versions */
+#include "gtls.h" /* GnuTLS versions */
+#include "nssg.h" /* NSS versions */
+#include "gskit.h" /* Global Secure ToolKit versions */
+#include "wolfssl.h" /* wolfSSL versions */
+#include "schannel.h" /* Schannel SSPI version */
+#include "sectransp.h" /* SecureTransport (Darwin) version */
+#include "mbedtls.h" /* mbedTLS versions */
+#include "bearssl.h" /* BearSSL versions */
+#include "rustls.h" /* rustls versions */
+
+#endif /* USE_SSL */
+
+#endif /* HEADER_CURL_VTLS_INT_H */
diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
index 50cdb4a..6cfc201 100644
--- a/lib/vtls/wolfssl.c
+++ b/lib/vtls/wolfssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -55,6 +55,7 @@
#include "sendf.h"
#include "inet_pton.h"
#include "vtls.h"
+#include "vtls_int.h"
#include "keylog.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
@@ -84,14 +85,18 @@
#endif
#endif
-struct ssl_backend_data {
+#if defined(HAVE_WOLFSSL_FULL_BIO) && HAVE_WOLFSSL_FULL_BIO
+#define USE_BIO_CHAIN
+#else
+#undef USE_BIO_CHAIN
+#endif
+
+struct wolfssl_ssl_backend_data {
SSL_CTX* ctx;
SSL* handle;
+ CURLcode io_result; /* result of last BIO cfilter operation */
};
-static Curl_recv wolfssl_recv;
-static Curl_send wolfssl_send;
-
#ifdef OPENSSL_EXTRA
/*
* Availability note:
@@ -214,46 +219,149 @@
{ WOLFSSL_KYBER_LEVEL1, "KYBER_LEVEL1" },
{ WOLFSSL_KYBER_LEVEL3, "KYBER_LEVEL3" },
{ WOLFSSL_KYBER_LEVEL5, "KYBER_LEVEL5" },
- { WOLFSSL_NTRU_HPS_LEVEL1, "NTRU_HPS_LEVEL1" },
- { WOLFSSL_NTRU_HPS_LEVEL3, "NTRU_HPS_LEVEL3" },
- { WOLFSSL_NTRU_HPS_LEVEL5, "NTRU_HPS_LEVEL5" },
- { WOLFSSL_NTRU_HRSS_LEVEL3, "NTRU_HRSS_LEVEL3" },
- { WOLFSSL_SABER_LEVEL1, "SABER_LEVEL1" },
- { WOLFSSL_SABER_LEVEL3, "SABER_LEVEL3" },
- { WOLFSSL_SABER_LEVEL5, "SABER_LEVEL5" },
- { WOLFSSL_KYBER_90S_LEVEL1, "KYBER_90S_LEVEL1" },
- { WOLFSSL_KYBER_90S_LEVEL3, "KYBER_90S_LEVEL3" },
- { WOLFSSL_KYBER_90S_LEVEL5, "KYBER_90S_LEVEL5" },
- { WOLFSSL_P256_NTRU_HPS_LEVEL1, "P256_NTRU_HPS_LEVEL1" },
- { WOLFSSL_P384_NTRU_HPS_LEVEL3, "P384_NTRU_HPS_LEVEL3" },
- { WOLFSSL_P521_NTRU_HPS_LEVEL5, "P521_NTRU_HPS_LEVEL5" },
- { WOLFSSL_P384_NTRU_HRSS_LEVEL3, "P384_NTRU_HRSS_LEVEL3" },
- { WOLFSSL_P256_SABER_LEVEL1, "P256_SABER_LEVEL1" },
- { WOLFSSL_P384_SABER_LEVEL3, "P384_SABER_LEVEL3" },
- { WOLFSSL_P521_SABER_LEVEL5, "P521_SABER_LEVEL5" },
{ WOLFSSL_P256_KYBER_LEVEL1, "P256_KYBER_LEVEL1" },
{ WOLFSSL_P384_KYBER_LEVEL3, "P384_KYBER_LEVEL3" },
{ WOLFSSL_P521_KYBER_LEVEL5, "P521_KYBER_LEVEL5" },
- { WOLFSSL_P256_KYBER_90S_LEVEL1, "P256_KYBER_90S_LEVEL1" },
- { WOLFSSL_P384_KYBER_90S_LEVEL3, "P384_KYBER_90S_LEVEL3" },
- { WOLFSSL_P521_KYBER_90S_LEVEL5, "P521_KYBER_90S_LEVEL5" },
{ 0, NULL }
};
#endif
+#ifdef USE_BIO_CHAIN
+
+static int bio_cf_create(WOLFSSL_BIO *bio)
+{
+ wolfSSL_BIO_set_shutdown(bio, 1);
+ wolfSSL_BIO_set_init(bio, 1);
+ wolfSSL_BIO_set_data(bio, NULL);
+ return 1;
+}
+
+static int bio_cf_destroy(WOLFSSL_BIO *bio)
+{
+ if(!bio)
+ return 0;
+ return 1;
+}
+
+static long bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr)
+{
+ struct Curl_cfilter *cf = BIO_get_data(bio);
+ long ret = 1;
+
+ (void)cf;
+ (void)ptr;
+ switch(cmd) {
+ case BIO_CTRL_GET_CLOSE:
+ ret = (long)wolfSSL_BIO_get_shutdown(bio);
+ break;
+ case BIO_CTRL_SET_CLOSE:
+ wolfSSL_BIO_set_shutdown(bio, (int)num);
+ break;
+ case BIO_CTRL_FLUSH:
+ /* we do no delayed writes, but if we ever would, this
+ * needs to trigger it. */
+ ret = 1;
+ break;
+ case BIO_CTRL_DUP:
+ ret = 1;
+ break;
+#ifdef BIO_CTRL_EOF
+ case BIO_CTRL_EOF:
+ /* EOF has been reached on input? */
+ return (!cf->next || !cf->next->connected);
+#endif
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static int 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;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nwritten;
+ CURLcode result = CURLE_OK;
+
+ DEBUGASSERT(data);
+ nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
+ backend->io_result = result;
+ DEBUGF(LOG_CF(data, cf, "bio_write(len=%d) -> %zd, %d",
+ blen, nwritten, result));
+ wolfSSL_BIO_clear_retry_flags(bio);
+ if(nwritten < 0 && CURLE_AGAIN == result)
+ BIO_set_retry_read(bio);
+ return (int)nwritten;
+}
+
+static int bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
+{
+ struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ ssize_t nread;
+ CURLcode result = CURLE_OK;
+
+ DEBUGASSERT(data);
+ /* OpenSSL catches this case, so should we. */
+ if(!buf)
+ return 0;
+
+ nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
+ backend->io_result = result;
+ DEBUGF(LOG_CF(data, cf, "bio_read(len=%d) -> %zd, %d",
+ blen, nread, result));
+ wolfSSL_BIO_clear_retry_flags(bio);
+ if(nread < 0 && CURLE_AGAIN == result)
+ BIO_set_retry_read(bio);
+ return (int)nread;
+}
+
+static WOLFSSL_BIO_METHOD *bio_cf_method = NULL;
+
+static void bio_cf_init_methods(void)
+{
+ bio_cf_method = wolfSSL_BIO_meth_new(BIO_TYPE_MEM, "wolfSSL CF BIO");
+ wolfSSL_BIO_meth_set_write(bio_cf_method, &bio_cf_out_write);
+ wolfSSL_BIO_meth_set_read(bio_cf_method, &bio_cf_in_read);
+ wolfSSL_BIO_meth_set_ctrl(bio_cf_method, &bio_cf_ctrl);
+ wolfSSL_BIO_meth_set_create(bio_cf_method, &bio_cf_create);
+ wolfSSL_BIO_meth_set_destroy(bio_cf_method, &bio_cf_destroy);
+}
+
+static void bio_cf_free_methods(void)
+{
+ wolfSSL_BIO_meth_free(bio_cf_method);
+}
+
+#else /* USE_BIO_CHAIN */
+
+#define bio_cf_init_methods() Curl_nop_stmt
+#define bio_cf_free_methods() Curl_nop_stmt
+
+#endif /* !USE_BIO_CHAIN */
+
/*
* This function loads all the client/CA certificates and CRLs. Setup the TLS
* layer and do all necessary magic.
*/
static CURLcode
-wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
{
char *ciphers, *curves;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+ const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
SSL_METHOD* req_method = NULL;
- curl_socket_t sockfd = conn->sock[sockindex];
#ifdef HAVE_LIBOQS
word16 oqsAlg = 0;
size_t idx = 0;
@@ -264,19 +372,20 @@
#else
#define use_sni(x) Curl_nop_stmt
#endif
+ bool imported_ca_info_blob = false;
DEBUGASSERT(backend);
if(connssl->state == ssl_connection_complete)
return CURLE_OK;
- if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
+ if(conn_config->version_max != CURL_SSLVERSION_MAX_NONE) {
failf(data, "wolfSSL does not support to set maximum SSL/TLS version");
return CURLE_SSL_CONNECT_ERROR;
}
/* check to see if we've been told to use an explicit SSL/TLS version */
- switch(SSL_CONN_CONFIG(version)) {
+ switch(conn_config->version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
#if LIBWOLFSSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
@@ -308,8 +417,13 @@
#endif
break;
case CURL_SSLVERSION_TLSv1_2:
+#ifndef WOLFSSL_NO_TLS12
req_method = TLSv1_2_client_method();
use_sni(TRUE);
+#else
+ failf(data, "wolfSSL does not support TLS 1.2");
+ return CURLE_NOT_BUILT_IN;
+#endif
break;
case CURL_SSLVERSION_TLSv1_3:
#ifdef WOLFSSL_TLS13
@@ -339,7 +453,7 @@
return CURLE_OUT_OF_MEMORY;
}
- switch(SSL_CONN_CONFIG(version)) {
+ switch(conn_config->version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
#if LIBWOLFSSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
@@ -363,7 +477,7 @@
break;
}
- ciphers = SSL_CONN_CONFIG(cipher_list);
+ ciphers = conn_config->cipher_list;
if(ciphers) {
if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) {
failf(data, "failed setting cipher list: %s", ciphers);
@@ -372,7 +486,7 @@
infof(data, "Cipher selection: %s", ciphers);
}
- curves = SSL_CONN_CONFIG(curves);
+ curves = conn_config->curves;
if(curves) {
#ifdef HAVE_LIBOQS
@@ -392,20 +506,35 @@
}
}
}
+
+ if(ca_info_blob) {
+ if(wolfSSL_CTX_load_verify_buffer(
+ backend->ctx, ca_info_blob->data, ca_info_blob->len,
+ SSL_FILETYPE_PEM
+ ) != SSL_SUCCESS) {
+ failf(data, "error importing CA certificate blob");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ imported_ca_info_blob = true;
+ infof(data, "successfully imported CA certificate blob");
+ }
+ }
+
#ifndef NO_FILESYSTEM
/* load trusted cacert */
- if(SSL_CONN_CONFIG(CAfile)) {
+ if(conn_config->CAfile) {
if(1 != SSL_CTX_load_verify_locations(backend->ctx,
- SSL_CONN_CONFIG(CAfile),
- SSL_CONN_CONFIG(CApath))) {
- if(SSL_CONN_CONFIG(verifypeer)) {
+ conn_config->CAfile,
+ conn_config->CApath)) {
+ if(conn_config->verifypeer && !imported_ca_info_blob) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate verify locations:"
" CAfile: %s CApath: %s",
- SSL_CONN_CONFIG(CAfile)?
- SSL_CONN_CONFIG(CAfile): "none",
- SSL_CONN_CONFIG(CApath)?
- SSL_CONN_CONFIG(CApath) : "none");
+ conn_config->CAfile?
+ conn_config->CAfile: "none",
+ conn_config->CApath?
+ conn_config->CApath : "none");
return CURLE_SSL_CACERT_BADFILE;
}
else {
@@ -420,25 +549,25 @@
infof(data, "successfully set certificate verify locations:");
}
infof(data, " CAfile: %s",
- SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile) : "none");
+ conn_config->CAfile ? conn_config->CAfile : "none");
infof(data, " CApath: %s",
- SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath) : "none");
+ conn_config->CApath ? conn_config->CApath : "none");
}
/* Load the client certificate, and private key */
- if(SSL_SET_OPTION(primary.clientcert) && SSL_SET_OPTION(key)) {
- int file_type = do_file_type(SSL_SET_OPTION(cert_type));
+ if(ssl_config->primary.clientcert && ssl_config->key) {
+ int file_type = do_file_type(ssl_config->cert_type);
if(SSL_CTX_use_certificate_file(backend->ctx,
- SSL_SET_OPTION(primary.clientcert),
+ ssl_config->primary.clientcert,
file_type) != 1) {
failf(data, "unable to use client certificate (no key or wrong pass"
" phrase?)");
return CURLE_SSL_CONNECT_ERROR;
}
- file_type = do_file_type(SSL_SET_OPTION(key_type));
- if(SSL_CTX_use_PrivateKey_file(backend->ctx, SSL_SET_OPTION(key),
+ file_type = do_file_type(ssl_config->key_type);
+ if(SSL_CTX_use_PrivateKey_file(backend->ctx, ssl_config->key,
file_type) != 1) {
failf(data, "unable to set private key");
return CURLE_SSL_CONNECT_ERROR;
@@ -451,8 +580,8 @@
* anyway. In the latter case the result of the verification is checked with
* SSL_get_verify_result() below. */
SSL_CTX_set_verify(backend->ctx,
- SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER:
- SSL_VERIFY_NONE,
+ conn_config->verifypeer?SSL_VERIFY_PEER:
+ SSL_VERIFY_NONE,
NULL);
#ifdef HAVE_SNI
@@ -461,16 +590,16 @@
#ifdef ENABLE_IPV6
struct in6_addr addr6;
#endif
- const char * const hostname = SSL_HOST_NAME();
- size_t hostname_len = strlen(hostname);
+ size_t hostname_len = strlen(connssl->hostname);
+
if((hostname_len < USHRT_MAX) &&
- !Curl_inet_pton(AF_INET, hostname, &addr4)
+ !Curl_inet_pton(AF_INET, connssl->hostname, &addr4)
#ifdef ENABLE_IPV6
- && !Curl_inet_pton(AF_INET6, hostname, &addr6)
+ && !Curl_inet_pton(AF_INET6, connssl->hostname, &addr6)
#endif
) {
size_t snilen;
- char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
+ char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen);
if(!snihost ||
wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, snihost,
(unsigned short)snilen) != 1) {
@@ -491,7 +620,7 @@
}
}
#ifdef NO_FILESYSTEM
- else if(SSL_CONN_CONFIG(verifypeer)) {
+ else if(conn_config->verifypeer) {
failf(data, "SSL: Certificates can't be loaded because wolfSSL was built"
" with \"no filesystem\". Either disable peer verification"
" (insecure) or if you are building an application with libcurl you"
@@ -518,29 +647,18 @@
#endif
#ifdef HAVE_ALPN
- if(conn->bits.tls_enable_alpn) {
- char protocols[128];
- *protocols = '\0';
+ if(connssl->alpn) {
+ struct alpn_proto_buf proto;
+ CURLcode result;
- /* wolfSSL's ALPN protocol name list format is a comma separated string of
- protocols in descending order of preference, eg: "h2,http/1.1" */
-
-#ifdef USE_HTTP2
- if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
- strcpy(protocols + strlen(protocols), ALPN_H2 ",");
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
- }
-#endif
-
- strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
- infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
-
- if(wolfSSL_UseALPN(backend->handle, protocols,
- (unsigned)strlen(protocols),
+ result = Curl_alpn_to_proto_str(&proto, connssl->alpn);
+ if(result ||
+ wolfSSL_UseALPN(backend->handle, (char *)proto.data, proto.len,
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
failf(data, "SSL: failed setting ALPN protocols");
return CURLE_SSL_CONNECT_ERROR;
}
+ infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
#endif /* HAVE_ALPN */
@@ -563,13 +681,11 @@
#endif /* HAVE_SECURE_RENEGOTIATION */
/* Check if there's a cached ID we can/should use here! */
- if(SSL_SET_OPTION(primary.sessionid)) {
+ if(ssl_config->primary.sessionid) {
void *ssl_sessionid = NULL;
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(data, conn,
- SSL_IS_PROXY() ? TRUE : FALSE,
- &ssl_sessionid, NULL, sockindex)) {
+ if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) {
/* we got a session id, use it! */
if(!SSL_set_session(backend->handle, ssl_sessionid)) {
Curl_ssl_delsessionid(data, ssl_sessionid);
@@ -581,11 +697,24 @@
Curl_ssl_sessionid_unlock(data);
}
+#ifdef USE_BIO_CHAIN
+ {
+ WOLFSSL_BIO *bio;
+
+ bio = BIO_new(bio_cf_method);
+ if(!bio)
+ return CURLE_OUT_OF_MEMORY;
+
+ wolfSSL_BIO_set_data(bio, cf);
+ wolfSSL_set_bio(backend->handle, bio, bio);
+ }
+#else /* USE_BIO_CHAIN */
/* pass the raw socket into the SSL layer */
- if(!SSL_set_fd(backend->handle, (int)sockfd)) {
+ if(!SSL_set_fd(backend->handle, (int)Curl_conn_cf_get_socket(cf, data))) {
failf(data, "SSL: SSL_set_fd failed");
return CURLE_SSL_CONNECT_ERROR;
}
+#endif /* !USE_BIO_CHAIN */
connssl->connecting_state = ssl_connect_2;
return CURLE_OK;
@@ -593,25 +722,24 @@
static CURLcode
-wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
{
int ret = -1;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- const char * const dispname = SSL_HOST_DISPNAME();
- const char * const pinnedpubkey = SSL_PINNED_PUB_KEY();
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
DEBUGASSERT(backend);
ERR_clear_error();
- conn->recv[sockindex] = wolfssl_recv;
- conn->send[sockindex] = wolfssl_send;
-
/* Enable RFC2818 checks */
- if(SSL_CONN_CONFIG(verifyhost)) {
- char *snihost = Curl_ssl_snihost(data, SSL_HOST_NAME(), NULL);
+ if(conn_config->verifyhost) {
+ char *snihost = Curl_ssl_snihost(data, connssl->hostname, NULL);
if(!snihost ||
(wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE))
return CURLE_SSL_CONNECT_ERROR;
@@ -661,32 +789,32 @@
else if(DOMAIN_NAME_MISMATCH == detail) {
#if 1
failf(data, " subject alt name(s) or common name do not match \"%s\"",
- dispname);
+ connssl->dispname);
return CURLE_PEER_FAILED_VERIFICATION;
#else
/* When the wolfssl_check_domain_name() is used and you desire to
- * continue on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost
+ * continue on a DOMAIN_NAME_MISMATCH, i.e. 'ssl_config.verifyhost
* == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA
* error. The only way to do this is currently to switch the
* Wolfssl_check_domain_name() in and out based on the
- * 'conn->ssl_config.verifyhost' value. */
- if(SSL_CONN_CONFIG(verifyhost)) {
+ * 'ssl_config.verifyhost' value. */
+ if(conn_config->verifyhost) {
failf(data,
" subject alt name(s) or common name do not match \"%s\"\n",
- dispname);
+ connssl->dispname);
return CURLE_PEER_FAILED_VERIFICATION;
}
else {
infof(data,
" subject alt name(s) and/or common name do not match \"%s\"",
- dispname);
+ connssl->dispname);
return CURLE_OK;
}
#endif
}
#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
else if(ASN_NO_SIGNER_E == detail) {
- if(SSL_CONN_CONFIG(verifypeer)) {
+ if(conn_config->verifypeer) {
failf(data, " CA signer not available for verification");
return CURLE_SSL_CACERT_BADFILE;
}
@@ -698,6 +826,9 @@
}
}
#endif
+ else if(backend->io_result == CURLE_AGAIN) {
+ return CURLE_OK;
+ }
else {
failf(data, "SSL_connect failed with error %d: %s", detail,
ERR_error_string(detail, error_buffer));
@@ -751,7 +882,7 @@
}
#ifdef HAVE_ALPN
- if(conn->bits.tls_enable_alpn) {
+ if(connssl->alpn) {
int rc;
char *protocol = NULL;
unsigned short protocol_len = 0;
@@ -759,25 +890,11 @@
rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len);
if(rc == SSL_SUCCESS) {
- infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, protocol_len, protocol);
-
- if(protocol_len == ALPN_HTTP_1_1_LENGTH &&
- !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH))
- conn->negnpn = CURL_HTTP_VERSION_1_1;
-#ifdef USE_HTTP2
- else if(data->state.httpwant >= CURL_HTTP_VERSION_2 &&
- protocol_len == ALPN_H2_LENGTH &&
- !memcmp(protocol, ALPN_H2, ALPN_H2_LENGTH))
- conn->negnpn = CURL_HTTP_VERSION_2;
-#endif
- else
- infof(data, "ALPN, unrecognized protocol %.*s", protocol_len,
- protocol);
- Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ Curl_alpn_set_negotiated(cf, data, (const unsigned char *)protocol,
+ protocol_len);
}
else if(rc == SSL_ALPN_NOT_FOUND)
- infof(data, VTLS_INFOF_NO_ALPN);
+ Curl_alpn_set_negotiated(cf, data, NULL, 0);
else {
failf(data, "ALPN, failure getting protocol, error %d", rc);
return CURLE_SSL_CONNECT_ERROR;
@@ -799,26 +916,27 @@
static CURLcode
-wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
+ const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
DEBUGASSERT(backend);
- if(SSL_SET_OPTION(primary.sessionid)) {
+ if(ssl_config->primary.sessionid) {
bool incache;
+ bool added = FALSE;
void *old_ssl_sessionid = NULL;
- SSL_SESSION *our_ssl_sessionid = SSL_get_session(backend->handle);
- bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE;
+ /* SSL_get1_session allocates memory that has to be freed. */
+ SSL_SESSION *our_ssl_sessionid = SSL_get1_session(backend->handle);
if(our_ssl_sessionid) {
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(data, conn, isproxy,
- &old_ssl_sessionid, NULL, sockindex));
+ incache = !(Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL));
if(incache) {
if(old_ssl_sessionid != our_ssl_sessionid) {
infof(data, "old SSL session ID is stale, removing");
@@ -828,15 +946,23 @@
}
if(!incache) {
- result = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid,
- 0, sockindex, NULL);
+ result = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid, 0, NULL);
if(result) {
Curl_ssl_sessionid_unlock(data);
+ SSL_SESSION_free(our_ssl_sessionid);
failf(data, "failed to store ssl session");
return result;
}
+ else {
+ added = TRUE;
+ }
}
Curl_ssl_sessionid_unlock(data);
+
+ if(!added) {
+ /* If the session info wasn't added to the cache, free our copy. */
+ SSL_SESSION_free(our_ssl_sessionid);
+ }
}
}
@@ -846,15 +972,15 @@
}
-static ssize_t wolfssl_send(struct Curl_easy *data,
- int sockindex,
+static ssize_t wolfssl_send(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
const void *mem,
size_t len,
CURLcode *curlcode)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
int rc;
@@ -864,7 +990,6 @@
ERR_clear_error();
rc = SSL_write(backend->handle, mem, memlen);
-
if(rc <= 0) {
int err = SSL_get_error(backend->handle, rc);
@@ -872,9 +997,17 @@
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
/* there's data pending, re-invoke SSL_write() */
+ DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len));
*curlcode = CURLE_AGAIN;
return -1;
default:
+ if(backend->io_result == CURLE_AGAIN) {
+ DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len));
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ }
+ DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> %d, %d",
+ len, rc, err));
failf(data, "SSL write: %s, errno %d",
ERR_error_string(err, error_buffer),
SOCKERRNO);
@@ -882,14 +1015,15 @@
return -1;
}
}
+ DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> %d", len, rc));
return rc;
}
-static void wolfssl_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static void wolfssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
(void) data;
@@ -910,22 +1044,22 @@
}
}
-static ssize_t wolfssl_recv(struct Curl_easy *data,
- int num,
- char *buf,
- size_t buffersize,
+static ssize_t wolfssl_recv(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ char *buf, size_t blen,
CURLcode *curlcode)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *connssl = &conn->ssl[num];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
- int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
+ int buffsize = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen;
int nread;
DEBUGASSERT(backend);
ERR_clear_error();
+ *curlcode = CURLE_OK;
nread = SSL_read(backend->handle, buf, buffsize);
@@ -934,30 +1068,38 @@
switch(err) {
case SSL_ERROR_ZERO_RETURN: /* no more data */
- break;
+ DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen));
+ *curlcode = CURLE_OK;
+ return 0;
case SSL_ERROR_NONE:
/* FALLTHROUGH */
case SSL_ERROR_WANT_READ:
/* FALLTHROUGH */
case SSL_ERROR_WANT_WRITE:
/* there's data pending, re-invoke SSL_read() */
+ DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen));
*curlcode = CURLE_AGAIN;
return -1;
default:
+ if(backend->io_result == CURLE_AGAIN) {
+ DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen));
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ }
failf(data, "SSL read: %s, errno %d",
ERR_error_string(err, error_buffer), SOCKERRNO);
*curlcode = CURLE_RECV_ERROR;
return -1;
}
}
+ DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> %d", blen, nread));
return nread;
}
static void wolfssl_session_free(void *ptr)
{
- (void)ptr;
- /* wolfSSL reuses sessions on own, no free */
+ SSL_SESSION_free(ptr);
}
@@ -973,15 +1115,20 @@
static int wolfssl_init(void)
{
+ int ret;
+
#ifdef OPENSSL_EXTRA
Curl_tls_keylog_open();
#endif
- return (wolfSSL_Init() == SSL_SUCCESS);
+ ret = (wolfSSL_Init() == SSL_SUCCESS);
+ bio_cf_init_methods();
+ return ret;
}
static void wolfssl_cleanup(void)
{
+ bio_cf_free_methods();
wolfSSL_Cleanup();
#ifdef OPENSSL_EXTRA
Curl_tls_keylog_close();
@@ -989,12 +1136,16 @@
}
-static bool wolfssl_data_pending(const struct connectdata *conn,
- int connindex)
+static bool wolfssl_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
- const struct ssl_connect_data *connssl = &conn->ssl[connindex];
- struct ssl_backend_data *backend = connssl->backend;
- DEBUGASSERT(backend);
+ struct ssl_connect_data *ctx = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend;
+
+ (void)data;
+ DEBUGASSERT(ctx && ctx->backend);
+
+ backend = (struct wolfssl_ssl_backend_data *)ctx->backend;
if(backend->handle) /* SSL is in use */
return (0 != SSL_pending(backend->handle)) ? TRUE : FALSE;
else
@@ -1006,17 +1157,17 @@
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
-static int wolfssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+static int wolfssl_shutdown(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
+ struct ssl_connect_data *ctx = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend;
int retval = 0;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- (void) data;
+ (void)data;
+ DEBUGASSERT(ctx && ctx->backend);
- DEBUGASSERT(backend);
-
+ backend = (struct wolfssl_ssl_backend_data *)ctx->backend;
if(backend->handle) {
ERR_clear_error();
SSL_free(backend->handle);
@@ -1027,15 +1178,14 @@
static CURLcode
-wolfssl_connect_common(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex,
- bool nonblocking,
- bool *done)
+wolfssl_connect_common(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool nonblocking,
+ bool *done)
{
CURLcode result;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
+ curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
int what;
/* check if the connection has already been established */
@@ -1054,7 +1204,7 @@
return CURLE_OPERATION_TIMEDOUT;
}
- result = wolfssl_connect_step1(data, conn, sockindex);
+ result = wolfssl_connect_step1(cf, data);
if(result)
return result;
}
@@ -1109,7 +1259,7 @@
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
- result = wolfssl_connect_step2(data, conn, sockindex);
+ result = wolfssl_connect_step2(cf, data);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -1118,15 +1268,13 @@
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- result = wolfssl_connect_step3(data, conn, sockindex);
+ result = wolfssl_connect_step3(cf, data);
if(result)
return result;
}
if(ssl_connect_done == connssl->connecting_state) {
connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = wolfssl_recv;
- conn->send[sockindex] = wolfssl_send;
*done = TRUE;
}
else
@@ -1139,21 +1287,21 @@
}
-static CURLcode wolfssl_connect_nonblocking(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode wolfssl_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *done)
{
- return wolfssl_connect_common(data, conn, sockindex, TRUE, done);
+ return wolfssl_connect_common(cf, data, TRUE, done);
}
-static CURLcode wolfssl_connect(struct Curl_easy *data,
- struct connectdata *conn, int sockindex)
+static CURLcode wolfssl_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
CURLcode result;
bool done = FALSE;
- result = wolfssl_connect_common(data, conn, sockindex, FALSE, &done);
+ result = wolfssl_connect_common(cf, data, FALSE, &done);
if(result)
return result;
@@ -1194,7 +1342,8 @@
static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
(void)info;
DEBUGASSERT(backend);
return backend->handle;
@@ -1206,9 +1355,13 @@
#ifdef KEEP_PEER_CERT
SSLSUPP_PINNEDPUBKEY |
#endif
+#ifdef USE_BIO_CHAIN
+ SSLSUPP_HTTPS_PROXY |
+#endif
+ SSLSUPP_CAINFO_BLOB |
SSLSUPP_SSL_CTX,
- sizeof(struct ssl_backend_data),
+ sizeof(struct wolfssl_ssl_backend_data),
wolfssl_init, /* init */
wolfssl_cleanup, /* cleanup */
@@ -1220,7 +1373,7 @@
Curl_none_cert_status_request, /* cert_status_request */
wolfssl_connect, /* connect */
wolfssl_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_getsock, /* getsock */
+ Curl_ssl_get_select_socks, /* getsock */
wolfssl_get_internals, /* get_internals */
wolfssl_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -1231,7 +1384,10 @@
Curl_none_false_start, /* false_start */
wolfssl_sha256sum, /* sha256sum */
NULL, /* associate_connection */
- NULL /* disassociate_connection */
+ NULL, /* disassociate_connection */
+ NULL, /* free_multi_ssl_backend_data */
+ wolfssl_recv, /* recv decrypted data */
+ wolfssl_send, /* send data to encrypt */
};
#endif
diff --git a/lib/vtls/wolfssl.h b/lib/vtls/wolfssl.h
index b2e7c3f..a5ed848 100644
--- a/lib/vtls/wolfssl.h
+++ b/lib/vtls/wolfssl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/vtls/x509asn1.c b/lib/vtls/x509asn1.c
index d5661b0..acf8bdb 100644
--- a/lib/vtls/x509asn1.c
+++ b/lib/vtls/x509asn1.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -45,8 +45,10 @@
#include <curl/curl.h>
#include "urldata.h"
#include "strcase.h"
+#include "curl_ctype.h"
#include "hostcheck.h"
#include "vtls/vtls.h"
+#include "vtls/vtls_int.h"
#include "sendf.h"
#include "inet_pton.h"
#include "curl_base64.h"
@@ -170,7 +172,7 @@
* It is intended to support certificate information gathering for SSL backends
* that offer a mean to get certificates as a whole, but do not supply
* entry points to get particular certificate sub-fields.
- * Please note there is no pretention here to rewrite a full SSL library.
+ * Please note there is no pretension here to rewrite a full SSL library.
*/
static const char *getASN1Element(struct Curl_asn1Element *elem,
@@ -181,7 +183,7 @@
const char *beg, const char *end)
{
unsigned char b;
- unsigned long len;
+ size_t len;
struct Curl_asn1Element lelem;
/* Get a single ASN.1 element into `elem', parse ASN.1 string at `beg'
@@ -306,7 +308,7 @@
*/
static const char *int2str(const char *beg, const char *end)
{
- unsigned long val = 0;
+ unsigned int val = 0;
size_t n = end - beg;
if(!n)
@@ -322,7 +324,7 @@
do
val = (val << 8) | *(const unsigned char *) beg++;
while(beg < end);
- return curl_maprintf("%s%lx", val >= 10? "0x": "", val);
+ return curl_maprintf("%s%x", val >= 10? "0x": "", val);
}
/*
@@ -716,7 +718,7 @@
/* Encode delimiter.
If attribute has a short uppercase name, delimiter is ", ". */
if(l) {
- for(p3 = str; isupper(*p3); p3++)
+ for(p3 = str; ISUPPER(*p3); p3++)
;
for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) {
if(l < buflen)
@@ -916,6 +918,20 @@
return OID2str(oid.beg, oid.end, TRUE);
}
+/*
+ * This is a convenience function for push_certinfo_len that takes a zero
+ * terminated value.
+ */
+static CURLcode ssl_push_certinfo(struct Curl_easy *data,
+ int certnum,
+ const char *label,
+ const char *value)
+{
+ size_t valuelen = strlen(value);
+
+ return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
+}
+
/* return 0 on success, 1 on error */
static int do_pubkey_field(struct Curl_easy *data, int certnum,
const char *label, struct Curl_asn1Element *elem)
@@ -928,7 +944,7 @@
output = ASN1tostr(elem, 0);
if(output) {
if(data->set.ssl.certinfo)
- result = Curl_ssl_push_certinfo(data, certnum, label, output);
+ result = ssl_push_certinfo(data, certnum, label, output);
if(!certnum && !result)
infof(data, " %s: %s", label, output);
free((char *) output);
@@ -952,14 +968,13 @@
* ECC public key is all the data, a value of type BIT STRING mapped to
* OCTET STRING and should not be parsed as an ASN.1 value.
*/
- const unsigned long len =
- (unsigned long)((pubkey->end - pubkey->beg - 2) * 4);
+ const size_t len = ((pubkey->end - pubkey->beg - 2) * 4);
if(!certnum)
infof(data, " ECC Public Key (%lu bits)", len);
if(data->set.ssl.certinfo) {
char q[sizeof(len) * 8 / 3 + 1];
(void)msnprintf(q, sizeof(q), "%lu", len);
- if(Curl_ssl_push_certinfo(data, certnum, "ECC Public Key", q))
+ if(ssl_push_certinfo(data, certnum, "ECC Public Key", q))
return 1;
}
return do_pubkey_field(data, certnum, "ecPublicKey", pubkey);
@@ -971,7 +986,7 @@
if(strcasecompare(algo, "rsaEncryption")) {
const char *q;
- unsigned long len;
+ size_t len;
p = getASN1Element(&elem, pk.beg, pk.end);
if(!p)
@@ -980,7 +995,7 @@
/* Compute key length. */
for(q = elem.beg; !*q && q < elem.end; q++)
;
- len = (unsigned long)((elem.end - q) * 8);
+ len = ((elem.end - q) * 8);
if(len) {
unsigned int i;
for(i = *(unsigned char *) q; !(i & 0x80); i <<= 1)
@@ -993,7 +1008,7 @@
if(data->set.ssl.certinfo) {
char r[sizeof(len) * 8 / 3 + 1];
msnprintf(r, sizeof(r), "%lu", len);
- if(Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", r))
+ if(ssl_push_certinfo(data, certnum, "RSA Public Key", r))
return 1;
}
/* Generate coefficients. */
@@ -1072,7 +1087,7 @@
size_t cl1;
char *cp2;
CURLcode result = CURLE_OK;
- unsigned long version;
+ unsigned int version;
size_t i;
size_t j;
@@ -1091,7 +1106,7 @@
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo) {
- result = Curl_ssl_push_certinfo(data, certnum, "Subject", ccp);
+ result = ssl_push_certinfo(data, certnum, "Subject", ccp);
if(result)
return result;
}
@@ -1104,7 +1119,7 @@
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo) {
- result = Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp);
+ result = ssl_push_certinfo(data, certnum, "Issuer", ccp);
}
if(!certnum)
infof(data, " Issuer: %s", ccp);
@@ -1117,23 +1132,23 @@
for(ccp = cert.version.beg; ccp < cert.version.end; ccp++)
version = (version << 8) | *(const unsigned char *) ccp;
if(data->set.ssl.certinfo) {
- ccp = curl_maprintf("%lx", version);
+ ccp = curl_maprintf("%x", version);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
- result = Curl_ssl_push_certinfo(data, certnum, "Version", ccp);
+ result = ssl_push_certinfo(data, certnum, "Version", ccp);
free((char *) ccp);
if(result)
return result;
}
if(!certnum)
- infof(data, " Version: %lu (0x%lx)", version + 1, version);
+ infof(data, " Version: %u (0x%x)", version + 1, version);
/* Serial number. */
ccp = ASN1tostr(&cert.serialNumber, 0);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
- result = Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp);
+ result = ssl_push_certinfo(data, certnum, "Serial Number", ccp);
if(!certnum)
infof(data, " Serial Number: %s", ccp);
free((char *) ccp);
@@ -1146,7 +1161,7 @@
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
- result = Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp);
+ result = ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp);
if(!certnum)
infof(data, " Signature Algorithm: %s", ccp);
free((char *) ccp);
@@ -1158,7 +1173,7 @@
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
- result = Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp);
+ result = ssl_push_certinfo(data, certnum, "Start Date", ccp);
if(!certnum)
infof(data, " Start Date: %s", ccp);
free((char *) ccp);
@@ -1170,7 +1185,7 @@
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
- result = Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp);
+ result = ssl_push_certinfo(data, certnum, "Expire Date", ccp);
if(!certnum)
infof(data, " Expire Date: %s", ccp);
free((char *) ccp);
@@ -1183,7 +1198,7 @@
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
- result = Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm",
+ result = ssl_push_certinfo(data, certnum, "Public Key Algorithm",
ccp);
if(!result) {
int ret;
@@ -1202,7 +1217,7 @@
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
- result = Curl_ssl_push_certinfo(data, certnum, "Signature", ccp);
+ result = ssl_push_certinfo(data, certnum, "Signature", ccp);
if(!certnum)
infof(data, " Signature: %s", ccp);
free((char *) ccp);
@@ -1237,7 +1252,7 @@
cp2[i] = '\0';
free(cp1);
if(data->set.ssl.certinfo)
- result = Curl_ssl_push_certinfo(data, certnum, "Cert", cp2);
+ result = ssl_push_certinfo(data, certnum, "Cert", cp2);
if(!certnum)
infof(data, "%s", cp2);
free(cp2);
@@ -1275,9 +1290,12 @@
return matched? ccp: NULL;
}
-CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+CURLcode Curl_verifyhost(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
const char *beg, const char *end)
{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct Curl_X509certificate cert;
struct Curl_asn1Element dn;
struct Curl_asn1Element elem;
@@ -1289,9 +1307,8 @@
int matched = -1;
size_t addrlen = (size_t) -1;
ssize_t len;
- const char * const hostname = SSL_HOST_NAME();
- const char * const dispname = SSL_HOST_DISPNAME();
- size_t hostlen = strlen(hostname);
+ size_t hostlen;
+
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
@@ -1301,19 +1318,22 @@
/* Verify that connection server matches info in X509 certificate at
`beg'..`end'. */
- if(!SSL_CONN_CONFIG(verifyhost))
+ if(!conn_config->verifyhost)
return CURLE_OK;
if(Curl_parseX509(&cert, beg, end))
return CURLE_PEER_FAILED_VERIFICATION;
+ hostlen = strlen(connssl->hostname);
+
/* Get the server IP address. */
#ifdef ENABLE_IPV6
- if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, hostname, &addr))
+ if(cf->conn->bits.ipv6_ip &&
+ Curl_inet_pton(AF_INET6, connssl->hostname, &addr))
addrlen = sizeof(struct in6_addr);
else
#endif
- if(Curl_inet_pton(AF_INET, hostname, &addr))
+ if(Curl_inet_pton(AF_INET, connssl->hostname, &addr))
addrlen = sizeof(struct in_addr);
/* Process extensions. */
@@ -1347,16 +1367,16 @@
len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
name.beg, name.end);
if(len > 0 && (size_t)len == strlen(dnsname))
- matched = Curl_cert_hostcheck(dnsname,
- (size_t)len, hostname, hostlen);
+ matched = Curl_cert_hostcheck(dnsname, (size_t)len,
+ connssl->hostname, hostlen);
else
matched = 0;
free(dnsname);
break;
case 7: /* IP address. */
- matched = (size_t) (name.end - name.beg) == addrlen &&
- !memcmp(&addr, name.beg, addrlen);
+ matched = (size_t)(name.end - name.beg) == addrlen &&
+ !memcmp(&addr, name.beg, addrlen);
break;
}
}
@@ -1366,12 +1386,12 @@
switch(matched) {
case 1:
/* an alternative name matched the server hostname */
- infof(data, " subjectAltName: %s matched", dispname);
+ infof(data, " subjectAltName: %s matched", connssl->dispname);
return CURLE_OK;
case 0:
/* an alternative name field existed, but didn't match and then
we MUST fail */
- infof(data, " subjectAltName does not match %s", dispname);
+ infof(data, " subjectAltName does not match %s", connssl->dispname);
return CURLE_PEER_FAILED_VERIFICATION;
}
@@ -1408,14 +1428,14 @@
if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */
failf(data, "SSL: illegal cert name field");
else if(Curl_cert_hostcheck((const char *) dnsname,
- len, hostname, hostlen)) {
+ len, connssl->hostname, hostlen)) {
infof(data, " common name: %s (matched)", dnsname);
free(dnsname);
return CURLE_OK;
}
else
failf(data, "SSL: certificate subject name '%s' does not match "
- "target host name '%s'", dnsname, dispname);
+ "target host name '%s'", dnsname, connssl->dispname);
free(dnsname);
}
diff --git a/lib/vtls/x509asn1.h b/lib/vtls/x509asn1.h
index a18fa11..5496de4 100644
--- a/lib/vtls/x509asn1.h
+++ b/lib/vtls/x509asn1.h
@@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,6 +30,7 @@
#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \
defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP)
+#include "cfilters.h"
#include "urldata.h"
/*
@@ -73,7 +74,7 @@
const char *beg, const char *end);
CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum,
const char *beg, const char *end);
-CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+CURLcode Curl_verifyhost(struct Curl_cfilter *cf, struct Curl_easy *data,
const char *beg, const char *end);
#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL
* or USE_SECTRANSP */
diff --git a/lib/warnless.c b/lib/warnless.c
index 51187aa..65c5ec5 100644
--- a/lib/warnless.c
+++ b/lib/warnless.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,10 +35,15 @@
#endif /* __INTEL_COMPILER && __unix__ */
-#define BUILDING_WARNLESS_C 1
-
#include "warnless.h"
+#ifdef WIN32
+#undef read
+#undef write
+#endif
+
+#include <limits.h>
+
#define CURL_MASK_UCHAR ((unsigned char)~0)
#define CURL_MASK_SCHAR (CURL_MASK_UCHAR >> 1)
@@ -374,6 +379,9 @@
return (ssize_t)write(fd, buf, curlx_uztoui(count));
}
+/* Ensure that warnless.h continues to have an effect in "unity" builds. */
+#undef HEADER_CURL_WARNLESS_H
+
#endif /* WIN32 */
#if defined(__INTEL_COMPILER) && defined(__unix__)
diff --git a/lib/warnless.h b/lib/warnless.h
index 4367099..2a53016 100644
--- a/lib/warnless.h
+++ b/lib/warnless.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -75,12 +75,10 @@
ssize_t curlx_write(int fd, const void *buf, size_t count);
-#ifndef BUILDING_WARNLESS_C
-# undef read
-# define read(fd, buf, count) curlx_read(fd, buf, count)
-# undef write
-# define write(fd, buf, count) curlx_write(fd, buf, count)
-#endif
+#undef read
+#define read(fd, buf, count) curlx_read(fd, buf, count)
+#undef write
+#define write(fd, buf, count) curlx_write(fd, buf, count)
#endif /* WIN32 */
diff --git a/lib/wildcard.c b/lib/wildcard.c
deleted file mode 100644
index a3e24b6..0000000
--- a/lib/wildcard.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the 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"
-
-#ifndef CURL_DISABLE_FTP
-
-#include "wildcard.h"
-#include "llist.h"
-#include "fileinfo.h"
-/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
-
-static void fileinfo_dtor(void *user, void *element)
-{
- (void)user;
- Curl_fileinfo_cleanup(element);
-}
-
-CURLcode 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 *wc)
-{
- if(!wc)
- return;
-
- if(wc->dtor) {
- wc->dtor(wc->protdata);
- wc->dtor = ZERO_NULL;
- wc->protdata = NULL;
- }
- DEBUGASSERT(wc->protdata == NULL);
-
- Curl_llist_destroy(&wc->filelist, NULL);
-
-
- free(wc->path);
- wc->path = NULL;
- free(wc->pattern);
- wc->pattern = NULL;
-
- wc->customptr = NULL;
- wc->state = CURLWC_INIT;
-}
-
-#endif /* if disabled */
diff --git a/lib/wildcard.h b/lib/wildcard.h
deleted file mode 100644
index f9d2167..0000000
--- a/lib/wildcard.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef HEADER_CURL_WILDCARD_H
-#define HEADER_CURL_WILDCARD_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the 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"
-
-#ifndef CURL_DISABLE_FTP
-#include "llist.h"
-
-/* list of wildcard process states */
-typedef enum {
- CURLWC_CLEAR = 0,
- CURLWC_INIT = 1,
- CURLWC_MATCHING, /* library is trying to get list of addresses for
- downloading */
- CURLWC_DOWNLOADING,
- CURLWC_CLEAN, /* deallocate resources and reset settings */
- CURLWC_SKIP, /* skip over concrete file */
- CURLWC_ERROR, /* error cases */
- CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop
- will end */
-} wildcard_states;
-
-typedef void (*wildcard_dtor)(void *ptr);
-
-/* struct keeping information about wildcard download process */
-struct WildcardData {
- wildcard_states state;
- char *path; /* path to the directory, where we trying wildcard-match */
- char *pattern; /* wildcard pattern */
- struct Curl_llist filelist; /* llist with struct Curl_fileinfo */
- void *protdata; /* pointer to protocol specific temporary data */
- wildcard_dtor dtor;
- void *customptr; /* for CURLOPT_CHUNK_DATA pointer */
-};
-
-CURLcode Curl_wildcard_init(struct WildcardData *wc);
-void Curl_wildcard_dtor(struct WildcardData *wc);
-
-struct Curl_easy;
-
-#else
-/* FTP is disabled */
-#define Curl_wildcard_dtor(x)
-#endif
-
-#endif /* HEADER_CURL_WILDCARD_H */
diff --git a/lib/ws.c b/lib/ws.c
new file mode 100644
index 0000000..3c1964b
--- /dev/null
+++ b/lib/ws.c
@@ -0,0 +1,1132 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 <curl/curl.h>
+
+#ifdef USE_WEBSOCKETS
+
+#include "urldata.h"
+#include "bufq.h"
+#include "dynbuf.h"
+#include "rand.h"
+#include "curl_base64.h"
+#include "connect.h"
+#include "sendf.h"
+#include "multiif.h"
+#include "ws.h"
+#include "easyif.h"
+#include "transfer.h"
+#include "nonblock.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+
+#define WSBIT_FIN 0x80
+#define WSBIT_OPCODE_CONT 0
+#define WSBIT_OPCODE_TEXT (1)
+#define WSBIT_OPCODE_BIN (2)
+#define WSBIT_OPCODE_CLOSE (8)
+#define WSBIT_OPCODE_PING (9)
+#define WSBIT_OPCODE_PONG (0xa)
+#define WSBIT_OPCODE_MASK (0xf)
+
+#define WSBIT_MASK 0x80
+
+/* buffer dimensioning */
+#define WS_CHUNK_SIZE 65535
+#define WS_CHUNK_COUNT 2
+
+struct ws_frame_meta {
+ char proto_opcode;
+ int flags;
+ const char *name;
+};
+
+static struct ws_frame_meta WS_FRAMES[] = {
+ { WSBIT_OPCODE_CONT, CURLWS_CONT, "CONT" },
+ { WSBIT_OPCODE_TEXT, CURLWS_TEXT, "TEXT" },
+ { WSBIT_OPCODE_BIN, CURLWS_BINARY, "BIN" },
+ { WSBIT_OPCODE_CLOSE, CURLWS_CLOSE, "CLOSE" },
+ { WSBIT_OPCODE_PING, CURLWS_PING, "PING" },
+ { WSBIT_OPCODE_PONG, CURLWS_PONG, "PONG" },
+};
+
+static const char *ws_frame_name_of_op(unsigned char proto_opcode)
+{
+ unsigned char opcode = proto_opcode & WSBIT_OPCODE_MASK;
+ size_t i;
+ for(i = 0; i < sizeof(WS_FRAMES)/sizeof(WS_FRAMES[0]); ++i) {
+ if(WS_FRAMES[i].proto_opcode == opcode)
+ return WS_FRAMES[i].name;
+ }
+ return "???";
+}
+
+static int ws_frame_op2flags(unsigned char proto_opcode)
+{
+ unsigned char opcode = proto_opcode & WSBIT_OPCODE_MASK;
+ size_t i;
+ for(i = 0; i < sizeof(WS_FRAMES)/sizeof(WS_FRAMES[0]); ++i) {
+ if(WS_FRAMES[i].proto_opcode == opcode)
+ return WS_FRAMES[i].flags;
+ }
+ return 0;
+}
+
+static unsigned char ws_frame_flags2op(int flags)
+{
+ size_t i;
+ for(i = 0; i < sizeof(WS_FRAMES)/sizeof(WS_FRAMES[0]); ++i) {
+ if(WS_FRAMES[i].flags & flags)
+ return WS_FRAMES[i].proto_opcode;
+ }
+ return 0;
+}
+
+static void ws_dec_info(struct ws_decoder *dec, struct Curl_easy *data,
+ const char *msg)
+{
+ switch(dec->head_len) {
+ case 0:
+ break;
+ case 1:
+ infof(data, "WS-DEC: %s [%s%s]", msg,
+ ws_frame_name_of_op(dec->head[0]),
+ (dec->head[0] & WSBIT_FIN)? "" : " NON-FINAL");
+ break;
+ default:
+ if(dec->head_len < dec->head_total) {
+ infof(data, "WS-DEC: %s [%s%s](%d/%d)", msg,
+ ws_frame_name_of_op(dec->head[0]),
+ (dec->head[0] & WSBIT_FIN)? "" : " NON-FINAL",
+ dec->head_len, dec->head_total);
+ }
+ else {
+ infof(data, "WS-DEC: %s [%s%s payload=%" CURL_FORMAT_CURL_OFF_T
+ "/%" CURL_FORMAT_CURL_OFF_T "]",
+ msg, ws_frame_name_of_op(dec->head[0]),
+ (dec->head[0] & WSBIT_FIN)? "" : " NON-FINAL",
+ dec->payload_offset, dec->payload_len);
+ }
+ break;
+ }
+}
+
+typedef ssize_t ws_write_payload(const unsigned char *buf, size_t buflen,
+ int frame_age, int frame_flags,
+ curl_off_t payload_offset,
+ curl_off_t payload_len,
+ void *userp,
+ CURLcode *err);
+
+
+static void ws_dec_reset(struct ws_decoder *dec)
+{
+ dec->frame_age = 0;
+ dec->frame_flags = 0;
+ dec->payload_offset = 0;
+ dec->payload_len = 0;
+ dec->head_len = dec->head_total = 0;
+ dec->state = WS_DEC_INIT;
+}
+
+static void ws_dec_init(struct ws_decoder *dec)
+{
+ ws_dec_reset(dec);
+}
+
+static CURLcode ws_dec_read_head(struct ws_decoder *dec,
+ struct Curl_easy *data,
+ struct bufq *inraw)
+{
+ const unsigned char *inbuf;
+ size_t inlen;
+
+ while(Curl_bufq_peek(inraw, &inbuf, &inlen)) {
+ if(dec->head_len == 0) {
+ dec->head[0] = *inbuf;
+ Curl_bufq_skip(inraw, 1);
+
+ dec->frame_flags = ws_frame_op2flags(dec->head[0]);
+ if(!dec->frame_flags) {
+ failf(data, "WS: unknown opcode: %x", dec->head[0]);
+ ws_dec_reset(dec);
+ return CURLE_RECV_ERROR;
+ }
+ dec->head_len = 1;
+ /* ws_dec_info(dec, data, "seeing opcode"); */
+ continue;
+ }
+ else if(dec->head_len == 1) {
+ dec->head[1] = *inbuf;
+ Curl_bufq_skip(inraw, 1);
+ dec->head_len = 2;
+
+ if(dec->head[1] & WSBIT_MASK) {
+ /* A client MUST close a connection if it detects a masked frame. */
+ failf(data, "WS: masked input frame");
+ ws_dec_reset(dec);
+ return CURLE_RECV_ERROR;
+ }
+ /* How long is the frame head? */
+ if(dec->head[1] == 126) {
+ dec->head_total = 4;
+ continue;
+ }
+ else if(dec->head[1] == 127) {
+ dec->head_total = 10;
+ continue;
+ }
+ else {
+ dec->head_total = 2;
+ }
+ }
+
+ if(dec->head_len < dec->head_total) {
+ dec->head[dec->head_len] = *inbuf;
+ Curl_bufq_skip(inraw, 1);
+ ++dec->head_len;
+ if(dec->head_len < dec->head_total) {
+ /* ws_dec_info(dec, data, "decoding head"); */
+ continue;
+ }
+ }
+ /* got the complete frame head */
+ DEBUGASSERT(dec->head_len == dec->head_total);
+ switch(dec->head_total) {
+ case 2:
+ dec->payload_len = dec->head[1];
+ break;
+ case 4:
+ dec->payload_len = (dec->head[2] << 8) | dec->head[3];
+ break;
+ case 10:
+ 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 |
+ dec->head[9];
+ break;
+ default:
+ /* this should never happen */
+ DEBUGASSERT(0);
+ failf(data, "WS: unexpected frame header length");
+ return CURLE_RECV_ERROR;
+ }
+
+ dec->frame_age = 0;
+ dec->payload_offset = 0;
+ ws_dec_info(dec, data, "decoded");
+ return CURLE_OK;
+ }
+ return CURLE_AGAIN;
+}
+
+static CURLcode ws_dec_pass_payload(struct ws_decoder *dec,
+ struct Curl_easy *data,
+ struct bufq *inraw,
+ ws_write_payload *write_payload,
+ void *write_ctx)
+{
+ const unsigned char *inbuf;
+ size_t inlen;
+ ssize_t nwritten;
+ CURLcode result;
+ curl_off_t remain = dec->payload_len - dec->payload_offset;
+
+ (void)data;
+ while(remain && Curl_bufq_peek(inraw, &inbuf, &inlen)) {
+ if((curl_off_t)inlen > remain)
+ inlen = (size_t)remain;
+ nwritten = write_payload(inbuf, inlen, dec->frame_age, dec->frame_flags,
+ dec->payload_offset, dec->payload_len,
+ write_ctx, &result);
+ if(nwritten < 0)
+ return result;
+ Curl_bufq_skip(inraw, (size_t)nwritten);
+ dec->payload_offset += (curl_off_t)nwritten;
+ remain = dec->payload_len - dec->payload_offset;
+ /* infof(data, "WS-DEC: passed %zd bytes payload, %"
+ CURL_FORMAT_CURL_OFF_T " remain",
+ nwritten, remain); */
+ }
+
+ return remain? CURLE_AGAIN : CURLE_OK;
+}
+
+static CURLcode ws_dec_pass(struct ws_decoder *dec,
+ struct Curl_easy *data,
+ struct bufq *inraw,
+ ws_write_payload *write_payload,
+ void *write_ctx)
+{
+ CURLcode result;
+
+ if(Curl_bufq_is_empty(inraw))
+ return CURLE_AGAIN;
+
+ switch(dec->state) {
+ case WS_DEC_INIT:
+ ws_dec_reset(dec);
+ dec->state = WS_DEC_HEAD;
+ /* FALLTHROUGH */
+ case WS_DEC_HEAD:
+ result = ws_dec_read_head(dec, data, inraw);
+ if(result) {
+ if(result != CURLE_AGAIN) {
+ infof(data, "WS: decode error %d", (int)result);
+ break; /* real error */
+ }
+ /* incomplete ws frame head */
+ DEBUGASSERT(Curl_bufq_is_empty(inraw));
+ break;
+ }
+ /* head parsing done */
+ dec->state = WS_DEC_PAYLOAD;
+ if(dec->payload_len == 0) {
+ ssize_t nwritten;
+ const unsigned char tmp = '\0';
+ /* special case of a 0 length frame, need to write once */
+ nwritten = write_payload(&tmp, 0, dec->frame_age, dec->frame_flags,
+ 0, 0, write_ctx, &result);
+ if(nwritten < 0)
+ return result;
+ dec->state = WS_DEC_INIT;
+ break;
+ }
+ /* FALLTHROUGH */
+ case WS_DEC_PAYLOAD:
+ result = ws_dec_pass_payload(dec, data, inraw, write_payload, write_ctx);
+ ws_dec_info(dec, data, "passing");
+ if(result)
+ return result;
+ /* paylod parsing done */
+ dec->state = WS_DEC_INIT;
+ break;
+ default:
+ /* we covered all enums above, but some code analyzers are whimps */
+ result = CURLE_FAILED_INIT;
+ }
+ return result;
+}
+
+static void update_meta(struct websocket *ws,
+ int frame_age, int frame_flags,
+ curl_off_t payload_offset,
+ curl_off_t payload_len,
+ size_t cur_len)
+{
+ ws->frame.age = frame_age;
+ ws->frame.flags = frame_flags;
+ ws->frame.offset = payload_offset;
+ ws->frame.len = cur_len;
+ ws->frame.bytesleft = (payload_len - payload_offset - cur_len);
+}
+
+static void ws_enc_info(struct ws_encoder *enc, struct Curl_easy *data,
+ const char *msg)
+{
+ infof(data, "WS-ENC: %s [%s%s%s payload=%" CURL_FORMAT_CURL_OFF_T
+ "/%" CURL_FORMAT_CURL_OFF_T "]",
+ msg, ws_frame_name_of_op(enc->firstbyte),
+ (enc->firstbyte & WSBIT_OPCODE_MASK) == WSBIT_OPCODE_CONT ?
+ " CONT" : "",
+ (enc->firstbyte & WSBIT_FIN)? "" : " NON-FIN",
+ enc->payload_len - enc->payload_remain, enc->payload_len);
+}
+
+static void ws_enc_reset(struct ws_encoder *enc)
+{
+ enc->payload_remain = 0;
+ enc->xori = 0;
+ enc->contfragment = FALSE;
+}
+
+static void ws_enc_init(struct ws_encoder *enc)
+{
+ ws_enc_reset(enc);
+}
+
+/***
+ RFC 6455 Section 5.2
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-------+-+-------------+-------------------------------+
+ |F|R|R|R| opcode|M| Payload len | Extended payload length |
+ |I|S|S|S| (4) |A| (7) | (16/64) |
+ |N|V|V|V| |S| | (if payload len==126/127) |
+ | |1|2|3| |K| | |
+ +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
+ | Extended payload length continued, if payload len == 127 |
+ + - - - - - - - - - - - - - - - +-------------------------------+
+ | |Masking-key, if MASK set to 1 |
+ +-------------------------------+-------------------------------+
+ | Masking-key (continued) | Payload Data |
+ +-------------------------------- - - - - - - - - - - - - - - - +
+ : Payload Data continued ... :
+ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+ | Payload Data continued ... |
+ +---------------------------------------------------------------+
+*/
+
+static ssize_t ws_enc_write_head(struct Curl_easy *data,
+ struct ws_encoder *enc,
+ unsigned int flags,
+ curl_off_t payload_len,
+ struct bufq *out,
+ CURLcode *err)
+{
+ unsigned char firstbyte = 0;
+ unsigned char opcode;
+ unsigned char head[14];
+ size_t hlen;
+ ssize_t n;
+
+ if(enc->payload_remain > 0) {
+ /* trying to write a new frame before the previous one is finished */
+ failf(data, "WS: starting new frame with %zd bytes from last one"
+ "remaining to be sent", (ssize_t)enc->payload_remain);
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+
+ opcode = ws_frame_flags2op(flags);
+ if(!opcode) {
+ failf(data, "WS: provided flags not recognized '%x'", flags);
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+
+ if(!(flags & CURLWS_CONT)) {
+ if(!enc->contfragment)
+ /* not marked as continuing, this is the final fragment */
+ firstbyte |= WSBIT_FIN | opcode;
+ else
+ /* marked as continuing, this is the final fragment; set CONT
+ opcode and FIN bit */
+ firstbyte |= WSBIT_FIN | WSBIT_OPCODE_CONT;
+
+ enc->contfragment = FALSE;
+ }
+ else if(enc->contfragment) {
+ /* the previous fragment was not a final one and this isn't either, keep a
+ CONT opcode and no FIN bit */
+ firstbyte |= WSBIT_OPCODE_CONT;
+ }
+ else {
+ firstbyte = opcode;
+ enc->contfragment = TRUE;
+ }
+
+ head[0] = enc->firstbyte = firstbyte;
+ 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);
+ 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);
+ hlen = 4;
+ }
+ else {
+ head[1] = (unsigned char)payload_len | WSBIT_MASK;
+ hlen = 2;
+ }
+
+ enc->payload_remain = enc->payload_len = payload_len;
+ ws_enc_info(enc, data, "sending");
+
+ /* add 4 bytes mask */
+ memcpy(&head[hlen], &enc->mask, 4);
+ hlen += 4;
+ /* reset for payload to come */
+ enc->xori = 0;
+
+ n = Curl_bufq_write(out, head, hlen, err);
+ if(n < 0)
+ return -1;
+ if((size_t)n != hlen) {
+ /* We use a bufq with SOFT_LIMIT, writing should always succeed */
+ DEBUGASSERT(0);
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+ return n;
+}
+
+static ssize_t ws_enc_write_payload(struct ws_encoder *enc,
+ struct Curl_easy *data,
+ const unsigned char *buf, size_t buflen,
+ struct bufq *out, CURLcode *err)
+{
+ ssize_t n;
+ size_t i, len;
+
+ if(Curl_bufq_is_full(out)) {
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+
+ /* not the most performant way to do this */
+ len = buflen;
+ if((curl_off_t)len > enc->payload_remain)
+ len = (size_t)enc->payload_remain;
+
+ for(i = 0; i < len; ++i) {
+ unsigned char c = buf[i] ^ enc->mask[enc->xori];
+ n = Curl_bufq_write(out, &c, 1, err);
+ if(n < 0) {
+ if((*err != CURLE_AGAIN) || !i)
+ return -1;
+ break;
+ }
+ enc->xori++;
+ enc->xori &= 3;
+ }
+ enc->payload_remain -= (curl_off_t)i;
+ ws_enc_info(enc, data, "buffered");
+ return (ssize_t)i;
+}
+
+
+struct wsfield {
+ const char *name;
+ const char *val;
+};
+
+CURLcode Curl_ws_request(struct Curl_easy *data, REQTYPE *req)
+{
+ unsigned int i;
+ CURLcode result = CURLE_OK;
+ unsigned char rand[16];
+ char *randstr;
+ size_t randlen;
+ char keyval[40];
+ struct SingleRequest *k = &data->req;
+ struct wsfield heads[]= {
+ {
+ /* The request MUST contain an |Upgrade| header field whose value
+ MUST include the "websocket" keyword. */
+ "Upgrade:", "websocket"
+ },
+ {
+ /* The request MUST contain a |Connection| header field whose value
+ MUST include the "Upgrade" token. */
+ "Connection:", "Upgrade",
+ },
+ {
+ /* The request MUST include a header field with the name
+ |Sec-WebSocket-Version|. The value of this header field MUST be
+ 13. */
+ "Sec-WebSocket-Version:", "13",
+ },
+ {
+ /* The request MUST include a header field with the name
+ |Sec-WebSocket-Key|. The value of this header field MUST be a nonce
+ consisting of a randomly selected 16-byte value that has been
+ base64-encoded (see Section 4 of [RFC4648]). The nonce MUST be
+ selected randomly for each connection. */
+ "Sec-WebSocket-Key:", NULL,
+ }
+ };
+ heads[3].val = &keyval[0];
+
+ /* 16 bytes random */
+ result = Curl_rand(data, (unsigned char *)rand, sizeof(rand));
+ if(result)
+ return result;
+ result = Curl_base64_encode((char *)rand, sizeof(rand), &randstr, &randlen);
+ if(result)
+ return result;
+ DEBUGASSERT(randlen < sizeof(keyval));
+ if(randlen >= sizeof(keyval))
+ return CURLE_FAILED_INIT;
+ strcpy(keyval, randstr);
+ free(randstr);
+ for(i = 0; !result && (i < sizeof(heads)/sizeof(heads[0])); i++) {
+ if(!Curl_checkheaders(data, STRCONST(heads[i].name))) {
+#ifdef USE_HYPER
+ char field[128];
+ msnprintf(field, sizeof(field), "%s %s", heads[i].name,
+ heads[i].val);
+ result = Curl_hyper_header(data, req, field);
+#else
+ (void)data;
+ result = Curl_dyn_addf(req, "%s %s\r\n", heads[i].name,
+ heads[i].val);
+#endif
+ }
+ }
+ k->upgr101 = UPGR101_WS;
+ return result;
+}
+
+/*
+ * 'nread' is number of bytes of websocket data already in the buffer at
+ * 'mem'.
+ */
+CURLcode Curl_ws_accept(struct Curl_easy *data,
+ const char *mem, size_t nread)
+{
+ struct SingleRequest *k = &data->req;
+ struct websocket *ws;
+ CURLcode result;
+
+ DEBUGASSERT(data->conn);
+ ws = data->conn->proto.ws;
+ if(!ws) {
+ ws = calloc(1, sizeof(*ws));
+ if(!ws)
+ return CURLE_OUT_OF_MEMORY;
+ data->conn->proto.ws = ws;
+ Curl_bufq_init(&ws->recvbuf, WS_CHUNK_SIZE, WS_CHUNK_COUNT);
+ Curl_bufq_init2(&ws->sendbuf, WS_CHUNK_SIZE, WS_CHUNK_COUNT,
+ BUFQ_OPT_SOFT_LIMIT);
+ ws_dec_init(&ws->dec);
+ ws_enc_init(&ws->enc);
+ }
+ else {
+ Curl_bufq_reset(&ws->recvbuf);
+ ws_dec_reset(&ws->dec);
+ ws_enc_reset(&ws->enc);
+ }
+ /* Verify the Sec-WebSocket-Accept response.
+
+ The sent value is the base64 encoded version of a SHA-1 hash done on the
+ |Sec-WebSocket-Key| header field concatenated with
+ the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".
+ */
+
+ /* If the response includes a |Sec-WebSocket-Extensions| header field and
+ this header field indicates the use of an extension that was not present
+ in the client's handshake (the server has indicated an extension not
+ requested by the client), the client MUST Fail the WebSocket Connection.
+ */
+
+ /* If the response includes a |Sec-WebSocket-Protocol| header field
+ and this header field indicates the use of a subprotocol that was
+ not present in the client's handshake (the server has indicated a
+ subprotocol not requested by the client), the client MUST Fail
+ the WebSocket Connection. */
+
+ /* 4 bytes random */
+
+ result = Curl_rand(data, (unsigned char *)&ws->enc.mask,
+ sizeof(ws->enc.mask));
+ if(result)
+ return result;
+ infof(data, "Received 101, switch to WebSocket; mask %02x%02x%02x%02x",
+ ws->enc.mask[0], ws->enc.mask[1], ws->enc.mask[2], ws->enc.mask[3]);
+
+ if(data->set.connect_only) {
+ ssize_t nwritten;
+ /* 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. */
+ nwritten = Curl_bufq_write(&ws->recvbuf, (const unsigned char *)mem,
+ nread, &result);
+ if(nwritten < 0)
+ return result;
+ infof(data, "%zu bytes websocket payload", nread);
+ }
+ k->upgr101 = UPGR101_RECEIVED;
+
+ return result;
+}
+
+static ssize_t ws_client_write(const unsigned char *buf, size_t buflen,
+ int frame_age, int frame_flags,
+ curl_off_t payload_offset,
+ curl_off_t payload_len,
+ void *userp,
+ CURLcode *err)
+{
+ struct Curl_easy *data = userp;
+ struct websocket *ws;
+ size_t wrote;
+ curl_off_t remain = (payload_len - (payload_offset + buflen));
+
+ (void)frame_age;
+ if(!data->conn || !data->conn->proto.ws) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
+ ws = data->conn->proto.ws;
+
+ if((frame_flags & CURLWS_PING) && !remain) {
+ /* auto-respond to PINGs, only works for single-frame payloads atm */
+ size_t bytes;
+ infof(data, "WS: auto-respond to PING with a PONG");
+ /* send back the exact same content as a PONG */
+ *err = curl_ws_send(data, buf, buflen, &bytes, 0, CURLWS_PONG);
+ if(*err)
+ return -1;
+ }
+ else if(buflen || !remain) {
+ /* deliver the decoded frame to the user callback. The application
+ * may invoke curl_ws_meta() to access frame information. */
+ update_meta(ws, frame_age, frame_flags, payload_offset,
+ payload_len, buflen);
+ Curl_set_in_callback(data, true);
+ wrote = data->set.fwrite_func((char *)buf, 1,
+ buflen, data->set.out);
+ Curl_set_in_callback(data, false);
+ if(wrote != buflen) {
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+ }
+ *err = CURLE_OK;
+ return (ssize_t)buflen;
+}
+
+/* Curl_ws_writecb() is the write callback for websocket traffic. The
+ websocket data is provided to this raw, in chunks. This function should
+ handle/decode the data and call the "real" underlying callback accordingly.
+*/
+size_t Curl_ws_writecb(char *buffer, size_t size /* 1 */,
+ size_t nitems, void *userp)
+{
+ struct Curl_easy *data = userp;
+
+ if(data->set.ws_raw_mode)
+ return data->set.fwrite_func(buffer, size, nitems, data->set.out);
+ else if(nitems) {
+ struct websocket *ws;
+ CURLcode result;
+
+ if(!data->conn || !data->conn->proto.ws) {
+ failf(data, "WS: not a websocket transfer");
+ return nitems - 1;
+ }
+ ws = data->conn->proto.ws;
+
+ if(buffer) {
+ ssize_t nwritten;
+
+ nwritten = Curl_bufq_write(&ws->recvbuf, (const unsigned char *)buffer,
+ nitems, &result);
+ if(nwritten < 0) {
+ infof(data, "WS: error adding data to buffer %d", (int)result);
+ return nitems - 1;
+ }
+ buffer = NULL;
+ }
+
+ while(!Curl_bufq_is_empty(&ws->recvbuf)) {
+
+ result = ws_dec_pass(&ws->dec, data, &ws->recvbuf,
+ ws_client_write, data);
+ if(result == CURLE_AGAIN)
+ /* insufficient amount of data, keep it for later.
+ * we pretend to have written all since we have a copy */
+ return nitems;
+ else if(result) {
+ infof(data, "WS: decode error %d", (int)result);
+ return nitems - 1;
+ }
+ }
+ }
+ return nitems;
+}
+
+struct ws_collect {
+ struct Curl_easy *data;
+ void *buffer;
+ size_t buflen;
+ size_t bufidx;
+ int frame_age;
+ int frame_flags;
+ curl_off_t payload_offset;
+ curl_off_t payload_len;
+ bool written;
+};
+
+static ssize_t ws_client_collect(const unsigned char *buf, size_t buflen,
+ int frame_age, int frame_flags,
+ curl_off_t payload_offset,
+ curl_off_t payload_len,
+ void *userp,
+ CURLcode *err)
+{
+ struct ws_collect *ctx = userp;
+ size_t nwritten;
+ curl_off_t remain = (payload_len - (payload_offset + buflen));
+
+ if(!ctx->bufidx) {
+ /* first write */
+ ctx->frame_age = frame_age;
+ ctx->frame_flags = frame_flags;
+ ctx->payload_offset = payload_offset;
+ ctx->payload_len = payload_len;
+ }
+
+ if((frame_flags & CURLWS_PING) && !remain) {
+ /* auto-respond to PINGs, only works for single-frame payloads atm */
+ size_t bytes;
+ infof(ctx->data, "WS: auto-respond to PING with a PONG");
+ /* send back the exact same content as a PONG */
+ *err = curl_ws_send(ctx->data, buf, buflen, &bytes, 0, CURLWS_PONG);
+ if(*err)
+ return -1;
+ nwritten = bytes;
+ }
+ else {
+ ctx->written = TRUE;
+ DEBUGASSERT(ctx->buflen >= ctx->bufidx);
+ nwritten = CURLMIN(buflen, ctx->buflen - ctx->bufidx);
+ if(!nwritten) {
+ if(!buflen) { /* 0 length write, we accept that */
+ *err = CURLE_OK;
+ return 0;
+ }
+ *err = CURLE_AGAIN; /* no more space */
+ return -1;
+ }
+ *err = CURLE_OK;
+ memcpy(ctx->buffer, buf, nwritten);
+ ctx->bufidx += nwritten;
+ }
+ return nwritten;
+}
+
+static ssize_t nw_in_recv(void *reader_ctx,
+ unsigned char *buf, size_t buflen,
+ CURLcode *err)
+{
+ struct Curl_easy *data = reader_ctx;
+ size_t nread;
+
+ *err = curl_easy_recv(data, buf, buflen, &nread);
+ if(*err)
+ return -1;
+ return (ssize_t)nread;
+}
+
+CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
+ size_t buflen, size_t *nread,
+ const struct curl_ws_frame **metap)
+{
+ struct connectdata *conn = data->conn;
+ struct websocket *ws;
+ bool done = FALSE; /* not filled passed buffer yet */
+ struct ws_collect ctx;
+ CURLcode result;
+
+ if(!conn) {
+ /* Unhappy hack with lifetimes of transfers and connection */
+ if(!data->set.connect_only) {
+ failf(data, "CONNECT_ONLY is required");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+
+ Curl_getconnectinfo(data, &conn);
+ if(!conn) {
+ failf(data, "connection not found");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ }
+ ws = conn->proto.ws;
+ if(!ws) {
+ failf(data, "connection is not setup for websocket");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ *nread = 0;
+ *metap = NULL;
+ /* get a download buffer */
+ result = Curl_preconnect(data);
+ if(result)
+ return result;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.data = data;
+ ctx.buffer = buffer;
+ ctx.buflen = buflen;
+
+ while(!done) {
+ /* receive more when our buffer is empty */
+ if(Curl_bufq_is_empty(&ws->recvbuf)) {
+ ssize_t n = Curl_bufq_slurp(&ws->recvbuf, nw_in_recv, data, &result);
+ if(n < 0) {
+ return result;
+ }
+ else if(n == 0) {
+ /* connection closed */
+ infof(data, "connection expectedly closed?");
+ return CURLE_GOT_NOTHING;
+ }
+ DEBUGF(infof(data, "curl_ws_recv, added %zu bytes from network",
+ Curl_bufq_len(&ws->recvbuf)));
+ }
+
+ result = ws_dec_pass(&ws->dec, data, &ws->recvbuf,
+ ws_client_collect, &ctx);
+ if(result == CURLE_AGAIN) {
+ if(!ctx.written) {
+ ws_dec_info(&ws->dec, data, "need more input");
+ continue; /* nothing written, try more input */
+ }
+ done = TRUE;
+ break;
+ }
+ else if(result) {
+ return result;
+ }
+ else if(ctx.written) {
+ /* The decoded frame is passed back to our caller.
+ * There are frames like PING were we auto-respond to and
+ * that we do not return. For these `ctx.written` is not set. */
+ done = TRUE;
+ break;
+ }
+ }
+
+ /* update frame information to be passed back */
+ update_meta(ws, ctx.frame_age, ctx.frame_flags, ctx.payload_offset,
+ ctx.payload_len, ctx.bufidx);
+ *metap = &ws->frame;
+ *nread = ws->frame.len;
+ /* infof(data, "curl_ws_recv(len=%zu) -> %zu bytes (frame at %"
+ CURL_FORMAT_CURL_OFF_T ", %" CURL_FORMAT_CURL_OFF_T " left)",
+ buflen, *nread, ws->frame.offset, ws->frame.bytesleft); */
+ return CURLE_OK;
+}
+
+static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws,
+ bool complete)
+{
+ if(!Curl_bufq_is_empty(&ws->sendbuf)) {
+ CURLcode result;
+ const unsigned char *out;
+ size_t outlen;
+ ssize_t n;
+
+ while(Curl_bufq_peek(&ws->sendbuf, &out, &outlen)) {
+ if(data->set.connect_only)
+ result = Curl_senddata(data, out, outlen, &n);
+ else
+ result = Curl_write(data, data->conn->writesockfd, out, outlen, &n);
+ if(result) {
+ if(result == CURLE_AGAIN) {
+ if(!complete) {
+ infof(data, "WS: flush EAGAIN, %zu bytes remain in buffer",
+ Curl_bufq_len(&ws->sendbuf));
+ return result;
+ }
+ /* TODO: the current design does not allow for buffered writes.
+ * We need to flush the buffer now. There is no ws_flush() later */
+ n = 0;
+ continue;
+ }
+ else if(result) {
+ failf(data, "WS: flush, write error %d", result);
+ return result;
+ }
+ }
+ else {
+ infof(data, "WS: flushed %zu bytes", (size_t)n);
+ Curl_bufq_skip(&ws->sendbuf, (size_t)n);
+ }
+ }
+ }
+ return CURLE_OK;
+}
+
+CURL_EXTERN CURLcode curl_ws_send(CURL *data, const void *buffer,
+ size_t buflen, size_t *sent,
+ curl_off_t fragsize,
+ unsigned int flags)
+{
+ struct websocket *ws;
+ ssize_t nwritten, n;
+ size_t space;
+ CURLcode result;
+
+ *sent = 0;
+ if(!data->conn && data->set.connect_only) {
+ result = Curl_connect_only_attach(data);
+ if(result)
+ return result;
+ }
+ if(!data->conn) {
+ failf(data, "No associated connection");
+ return CURLE_SEND_ERROR;
+ }
+ if(!data->conn->proto.ws) {
+ failf(data, "Not a websocket transfer");
+ return CURLE_SEND_ERROR;
+ }
+ ws = data->conn->proto.ws;
+
+ if(data->set.ws_raw_mode) {
+ if(fragsize || flags)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ if(!buflen)
+ /* nothing to do */
+ return CURLE_OK;
+ /* raw mode sends exactly what was requested, and this is from within
+ the write callback */
+ if(Curl_is_in_callback(data)) {
+ result = Curl_write(data, data->conn->writesockfd, buffer, buflen,
+ &nwritten);
+ }
+ else
+ result = Curl_senddata(data, buffer, buflen, &nwritten);
+
+ infof(data, "WS: wanted to send %zu bytes, sent %zu bytes",
+ buflen, nwritten);
+ *sent = (nwritten >= 0)? (size_t)nwritten : 0;
+ return result;
+ }
+
+ /* Not RAW mode, buf we do the frame encoding */
+ result = ws_flush(data, ws, FALSE);
+ if(result)
+ return result;
+
+ /* TODO: the current design does not allow partial writes, afaict.
+ * It is not clear who the application is supposed to react. */
+ space = Curl_bufq_space(&ws->sendbuf);
+ DEBUGF(infof(data, "curl_ws_send(len=%zu), sendbuf len=%zu space %zu",
+ buflen, Curl_bufq_len(&ws->sendbuf), space));
+ if(space < 14)
+ return CURLE_AGAIN;
+
+ if(flags & CURLWS_OFFSET) {
+ if(fragsize) {
+ /* a frame series 'fragsize' bytes big, this is the first */
+ n = ws_enc_write_head(data, &ws->enc, flags, fragsize,
+ &ws->sendbuf, &result);
+ if(n < 0)
+ return result;
+ }
+ else {
+ if((curl_off_t)buflen > ws->enc.payload_remain) {
+ infof(data, "WS: unaligned frame size (sending %zu instead of %"
+ CURL_FORMAT_CURL_OFF_T ")",
+ buflen, ws->enc.payload_remain);
+ }
+ }
+ }
+ else if(!ws->enc.payload_remain) {
+ n = ws_enc_write_head(data, &ws->enc, flags, (curl_off_t)buflen,
+ &ws->sendbuf, &result);
+ if(n < 0)
+ return result;
+ }
+
+ n = ws_enc_write_payload(&ws->enc, data,
+ buffer, buflen, &ws->sendbuf, &result);
+ if(n < 0)
+ return result;
+
+ *sent = (size_t)n;
+ return ws_flush(data, ws, TRUE);
+}
+
+static void ws_free(struct connectdata *conn)
+{
+ if(conn && conn->proto.ws) {
+ Curl_bufq_free(&conn->proto.ws->recvbuf);
+ Curl_bufq_free(&conn->proto.ws->sendbuf);
+ Curl_safefree(conn->proto.ws);
+ }
+}
+
+void Curl_ws_done(struct Curl_easy *data)
+{
+ (void)data;
+}
+
+CURLcode Curl_ws_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection)
+{
+ (void)data;
+ (void)dead_connection;
+ ws_free(conn);
+ return CURLE_OK;
+}
+
+CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
+{
+ /* we only return something for websocket, called from within the callback
+ when not using raw mode */
+ if(GOOD_EASY_HANDLE(data) && Curl_is_in_callback(data) && data->conn &&
+ data->conn->proto.ws && !data->set.ws_raw_mode)
+ return &data->conn->proto.ws->frame;
+ return NULL;
+}
+
+#else
+
+CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
+ size_t *nread,
+ const struct curl_ws_frame **metap)
+{
+ (void)curl;
+ (void)buffer;
+ (void)buflen;
+ (void)nread;
+ (void)metap;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURL_EXTERN CURLcode curl_ws_send(CURL *curl, const void *buffer,
+ size_t buflen, size_t *sent,
+ curl_off_t fragsize,
+ unsigned int flags)
+{
+ (void)curl;
+ (void)buffer;
+ (void)buflen;
+ (void)sent;
+ (void)fragsize;
+ (void)flags;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
+{
+ (void)data;
+ return NULL;
+}
+#endif /* USE_WEBSOCKETS */
diff --git a/lib/ws.h b/lib/ws.h
new file mode 100644
index 0000000..0308a42
--- /dev/null
+++ b/lib/ws.h
@@ -0,0 +1,89 @@
+#ifndef HEADER_CURL_WS_H
+#define HEADER_CURL_WS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_WEBSOCKETS
+
+#ifdef USE_HYPER
+#define REQTYPE void
+#else
+#define REQTYPE struct dynbuf
+#endif
+
+/* a client-side WS frame decoder, parsing frame headers and
+ * payload, keeping track of current position and stats */
+enum ws_dec_state {
+ WS_DEC_INIT,
+ WS_DEC_HEAD,
+ WS_DEC_PAYLOAD
+};
+
+struct ws_decoder {
+ int frame_age; /* zero */
+ 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];
+ int head_len, head_total;
+ enum ws_dec_state state;
+};
+
+/* a client-side WS frame encoder, generating frame headers and
+ * converting payloads, tracking remaining data in current frame */
+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 */
+ bool contfragment; /* set TRUE if the previous fragment sent was not final */
+};
+
+/* A websocket connection with en- and decoder that treat frames
+ * and keep track of boundaries. */
+struct websocket {
+ struct Curl_easy *data; /* used for write callback handling */
+ struct ws_decoder dec; /* decode of we frames */
+ struct ws_encoder enc; /* decode of we frames */
+ struct bufq recvbuf; /* raw data from the server */
+ struct bufq sendbuf; /* raw data to be sent to the server */
+ struct curl_ws_frame frame; /* the current WS FRAME received */
+};
+
+CURLcode Curl_ws_request(struct Curl_easy *data, REQTYPE *req);
+CURLcode Curl_ws_accept(struct Curl_easy *data, const char *mem, size_t len);
+size_t Curl_ws_writecb(char *buffer, size_t size, size_t nitems, void *userp);
+void Curl_ws_done(struct Curl_easy *data);
+CURLcode Curl_ws_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection);
+#else
+#define Curl_ws_request(x,y) CURLE_OK
+#define Curl_ws_done(x) Curl_nop_stmt
+#define Curl_ws_free(x) Curl_nop_stmt
+#endif
+
+#endif /* HEADER_CURL_WS_H */
diff --git a/libcurl.pc.in b/libcurl.pc.in
index 49485f1..9db6b0f 100644
--- a/libcurl.pc.in
+++ b/libcurl.pc.in
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/m4/.gitignore b/m4/.gitignore
index 35001ae..59602da 100644
--- a/m4/.gitignore
+++ b/m4/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/m4/ax_compile_check_sizeof.m4 b/m4/ax_compile_check_sizeof.m4
deleted file mode 100644
index dca9427..0000000
--- a/m4/ax_compile_check_sizeof.m4
+++ /dev/null
@@ -1,117 +0,0 @@
-# ============================================================================
-# https://www.gnu.org/software/autoconf-archive/ax_compile_check_sizeof.html
-# ============================================================================
-#
-# SYNOPSIS
-#
-# AX_COMPILE_CHECK_SIZEOF(TYPE [, HEADERS [, EXTRA_SIZES...]])
-#
-# DESCRIPTION
-#
-# This macro checks for the size of TYPE using compile checks, not run
-# checks. You can supply extra HEADERS to look into. the check will cycle
-# through 1 2 4 8 16 and any EXTRA_SIZES the user supplies. If a match is
-# found, it will #define SIZEOF_`TYPE' to that value. Otherwise it will
-# emit a configure time error indicating the size of the type could not be
-# determined.
-#
-# The trick is that C will not allow duplicate case labels. While this is
-# valid C code:
-#
-# switch (0) case 0: case 1:;
-#
-# The following is not:
-#
-# switch (0) case 0: case 0:;
-#
-# Thus, the AC_TRY_COMPILE will fail if the currently tried size does not
-# match.
-#
-# Here is an example skeleton configure.in script, demonstrating the
-# macro's usage:
-#
-# AC_PROG_CC
-# AC_CHECK_HEADERS(stddef.h unistd.h)
-# AC_TYPE_SIZE_T
-# AC_CHECK_TYPE(ssize_t, int)
-#
-# headers='#ifdef HAVE_STDDEF_H
-# #include <stddef.h>
-# #endif
-# #ifdef HAVE_UNISTD_H
-# #include <unistd.h>
-# #endif
-# '
-#
-# AX_COMPILE_CHECK_SIZEOF(char)
-# AX_COMPILE_CHECK_SIZEOF(short)
-# AX_COMPILE_CHECK_SIZEOF(int)
-# AX_COMPILE_CHECK_SIZEOF(long)
-# AX_COMPILE_CHECK_SIZEOF(unsigned char *)
-# AX_COMPILE_CHECK_SIZEOF(void *)
-# AX_COMPILE_CHECK_SIZEOF(size_t, $headers)
-# AX_COMPILE_CHECK_SIZEOF(ssize_t, $headers)
-# AX_COMPILE_CHECK_SIZEOF(ptrdiff_t, $headers)
-# AX_COMPILE_CHECK_SIZEOF(off_t, $headers)
-#
-# LICENSE
-#
-# Copyright (c) 2008 Kaveh Ghazi <ghazi@caip.rutgers.edu>
-# Copyright (c) 2017 Reini Urban <rurban@cpan.org>
-#
-# This program is free software: you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-# Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# As a special exception, the respective Autoconf Macro's copyright owner
-# gives unlimited permission to copy, distribute and modify the configure
-# scripts that are the output of Autoconf when processing the Macro. You
-# need not follow the terms of the GNU General Public License when using
-# or distributing such scripts, even though portions of the text of the
-# Macro appear in them. The GNU General Public License (GPL) does govern
-# all other use of the material that constitutes the Autoconf Macro.
-#
-# This special exception to the GPL applies to versions of the Autoconf
-# Macro released by the Autoconf Archive. When you make and distribute a
-# modified version of the Autoconf Macro, you may extend this special
-# exception to the GPL to apply to your modified version as well.
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-
-#serial 7
-
-AU_ALIAS([AC_COMPILE_CHECK_SIZEOF], [AX_COMPILE_CHECK_SIZEOF])
-AC_DEFUN([AX_COMPILE_CHECK_SIZEOF],
-[changequote(<<, >>)dnl
-dnl The name to #define.
-define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
-dnl The cache variable name.
-define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
-changequote([, ])dnl
-AC_MSG_CHECKING(size of $1)
-AC_CACHE_VAL(AC_CV_NAME,
-[for ac_size in 4 8 1 2 16 $3 ; do # List sizes in rough order of prevalence.
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#include <sys/types.h>
-$2
-]], [[switch (0) case 0: case (sizeof ($1) == $ac_size):;]])], [AC_CV_NAME=$ac_size])
- if test x$AC_CV_NAME != x ; then break; fi
-done
-])
-if test x$AC_CV_NAME = x ; then
- AC_MSG_ERROR([cannot determine a size for $1])
-fi
-AC_MSG_RESULT($AC_CV_NAME)
-AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1])
-undefine([AC_TYPE_NAME])dnl
-undefine([AC_CV_NAME])dnl
-])
diff --git a/m4/curl-amissl.m4 b/m4/curl-amissl.m4
index df07bdb..95208f0 100644
--- a/m4/curl-amissl.m4
+++ b/m4/curl-amissl.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,21 +23,41 @@
#***************************************************************************
AC_DEFUN([CURL_WITH_AMISSL], [
-AC_MSG_CHECKING([whether to enable Amiga native SSL/TLS (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
ssl_msg=
- if test "x$OPT_AMISSL" != "xno"; then
- AC_MSG_RESULT(yes)
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+ #include <libraries/amisslmaster.h>
+ #include <openssl/opensslv.h>
+ ]],[[
+ #if defined(AMISSL_CURRENT_VERSION) && defined(AMISSL_V3xx) && \
+ defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \
+ defined(PROTO_AMISSL_H)
+ return 0;
+ #else
+ #error not AmiSSL v5 / OpenSSL 3
+ #endif
+ ]])
+ ],[
+ AC_MSG_RESULT([yes])
ssl_msg="AmiSSL"
test amissl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
AMISSL_ENABLED=1
- LIBS="-lamisslauto $LIBS"
+ OPENSSL_ENABLED=1
+ # Use AmiSSL's built-in ca bundle
+ check_for_ca_bundle=1
+ with_ca_fallback=yes
+ LIBS="-lamisslstubs -lamisslauto $LIBS"
AC_DEFINE(USE_AMISSL, 1, [if AmiSSL is in use])
AC_DEFINE(USE_OPENSSL, 1, [if OpenSSL is in use])
- else
- AC_MSG_RESULT(no)
- fi
+ AC_DEFINE_UNQUOTED(HAVE_OPENSSL3, 1, [Define to 1 if using OpenSSL 3 or later.])
+ AC_CHECK_HEADERS(openssl/x509.h openssl/rsa.h openssl/crypto.h \
+ openssl/pem.h openssl/ssl.h openssl/err.h)
+ ],[
+ AC_MSG_RESULT([no])
+ ])
test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
else
AC_MSG_RESULT(no)
diff --git a/m4/curl-bearssl.m4 b/m4/curl-bearssl.m4
index 317a9e9..b8c9750 100644
--- a/m4/curl-bearssl.m4
+++ b/m4/curl-bearssl.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/m4/curl-compilers.m4 b/m4/curl-compilers.m4
index 8d812b5..caa2b14 100644
--- a/m4/curl-compilers.m4
+++ b/m4/curl-compilers.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -107,7 +107,7 @@
compiler_num=`(expr $clangvhi "*" 100 + $clangvlo) 2>/dev/null`
flags_dbg_yes="-g"
flags_opt_all="-O -O0 -O1 -O2 -Os -O3 -O4"
- flags_opt_yes="-Os"
+ flags_opt_yes="-O2"
flags_opt_off="-O0"
else
AC_MSG_RESULT([no])
@@ -507,9 +507,6 @@
dnl warn about compile-time arguments used during link-time, like
dnl -O and -g and -pedantic.
tmp_CFLAGS="$tmp_CFLAGS -Qunused-arguments"
- dnl Disable pointer to bool conversion warnings since they cause
- dnl lib/securetransp.c cause several warnings for checks we want.
- tmp_CFLAGS="$tmp_CFLAGS -Wno-pointer-bool-conversion"
;;
#
DEC_C)
@@ -567,12 +564,14 @@
dnl #147: declaration is incompatible with 'previous one'
dnl #165: too few arguments in function call
dnl #266: function declared implicitly
- tmp_CPPFLAGS="$tmp_CPPFLAGS -we140,147,165,266"
+ tmp_CPPFLAGS="$tmp_CPPFLAGS -diag-error 140,147,165,266"
dnl Disable some remarks
dnl #279: controlling expression is constant
dnl #981: operands are evaluated in unspecified order
+ dnl #1025: zero extending result of unary operation
dnl #1469: "cc" clobber ignored
- tmp_CPPFLAGS="$tmp_CPPFLAGS -wd279,981,1469"
+ dnl #2259: non-pointer conversion from X to Y may lose significant bits
+ tmp_CPPFLAGS="$tmp_CPPFLAGS -diag-disable 279,981,1025,1469,2259"
;;
#
INTEL_WINDOWS_C)
@@ -812,8 +811,19 @@
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [shift-sign-overflow])
fi
#
+ dnl Only clang 3.0 or later (possibly earlier)
+ if test "$compiler_num" -ge "300"; then
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [bad-function-cast])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [conversion])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [empty-body])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [ignored-qualifiers])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [type-limits])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [no-sign-conversion])
+ fi
+ #
dnl Only clang 3.2 or later
if test "$compiler_num" -ge "302"; then
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [enum-conversion])
case $host_os in
cygwin* | mingw*)
dnl skip missing-variable-declarations warnings for cygwin and
@@ -825,6 +835,11 @@
esac
fi
#
+ dnl Only clang 3.4 or later
+ if test "$compiler_num" -ge "304"; then
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-const-variable])
+ fi
+ #
dnl Only clang 3.6 or later
if test "$compiler_num" -ge "306"; then
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [double-promotion])
@@ -845,6 +860,10 @@
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [extra-semi-stmt])
fi
fi
+ dnl Disable pointer to bool conversion warnings since they cause
+ dnl lib/securetransp.c cause several warnings for checks we want.
+ dnl This option should be placed after -Wconversion.
+ tmp_CFLAGS="$tmp_CFLAGS -Wno-pointer-bool-conversion"
;;
#
DEC_C)
@@ -858,6 +877,7 @@
GNU_C)
#
if test "$want_warnings" = "yes"; then
+ tmp_CFLAGS="$tmp_CFLAGS -std=gnu89"
#
dnl Do not enable -pedantic when cross-compiling with a gcc older
dnl than 3.0, to avoid warnings from third party system headers.
diff --git a/m4/curl-confopts.m4 b/m4/curl-confopts.m4
index 2d4ab29..37f7d4c 100644
--- a/m4/curl-confopts.m4
+++ b/m4/curl-confopts.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -421,10 +421,8 @@
AC_DEFUN([CURL_CHECK_NONBLOCKING_SOCKET], [
AC_REQUIRE([CURL_CHECK_FUNC_FCNTL])dnl
- AC_REQUIRE([CURL_CHECK_FUNC_IOCTL])dnl
AC_REQUIRE([CURL_CHECK_FUNC_IOCTLSOCKET])dnl
AC_REQUIRE([CURL_CHECK_FUNC_IOCTLSOCKET_CAMEL])dnl
- AC_REQUIRE([CURL_CHECK_FUNC_SETSOCKOPT])dnl
#
tst_method="unknown"
@@ -460,8 +458,7 @@
AC_MSG_CHECKING([whether hiding of library internal symbols will actually happen])
CFLAG_CURL_SYMBOL_HIDING=""
doing_symbol_hiding="no"
- if test x"$curl_cv_native_windows" != "xyes" &&
- test "$want_symbol_hiding" = "yes" &&
+ if test "$want_symbol_hiding" = "yes" &&
test "$supports_symbol_hiding" = "yes"; then
doing_symbol_hiding="yes"
CFLAG_CURL_SYMBOL_HIDING="$symbol_hiding_CFLAGS"
@@ -478,9 +475,8 @@
dnl CURL_CHECK_LIB_ARES
dnl -------------------------------------------------
-dnl When c-ares library support has been requested,
-dnl performs necessary checks and adjustsments needed
-dnl to enable support of this library.
+dnl When c-ares library support has been requested, performs necessary checks
+dnl and adjustments needed to enable support of this library.
AC_DEFUN([CURL_CHECK_LIB_ARES], [
#
@@ -621,6 +617,9 @@
test "x$SSL_ENABLED" = "x"; then
want_ntlm_wb_file=""
want_ntlm_wb="no"
+ elif test "x$ac_cv_func_fork" != "xyes"; then
+ dnl ntlm_wb requires fork
+ want_ntlm_wb="no"
fi
AC_MSG_RESULT([$want_ntlm_wb])
if test "$want_ntlm_wb" = "yes"; then
diff --git a/m4/curl-functions.m4 b/m4/curl-functions.m4
index ec406f5..bd2ebbd 100644
--- a/m4/curl-functions.m4
+++ b/m4/curl-functions.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -266,27 +266,6 @@
])
-dnl CURL_INCLUDES_STDIO
-dnl -------------------------------------------------
-dnl Set up variable with list of headers that must be
-dnl included when stdio.h is to be included.
-
-AC_DEFUN([CURL_INCLUDES_STDIO], [
-curl_includes_stdio="\
-/* includes start */
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_STDIO_H
-# include <stdio.h>
-#endif
-/* includes end */"
- AC_CHECK_HEADERS(
- sys/types.h stdio.h,
- [], [], [$curl_includes_stdio])
-])
-
-
dnl CURL_INCLUDES_STDLIB
dnl -------------------------------------------------
dnl Set up variable with list of headers that must be
@@ -543,14 +522,24 @@
AC_DEFUN([CURL_INCLUDES_BSDSOCKET], [
curl_includes_bsdsocket="\
/* includes start */
-#ifdef HAVE_PROTO_BSDSOCKET_H
+#if defined(HAVE_PROTO_BSDSOCKET_H)
+# define __NO_NET_API
+# define __USE_INLINE__
# include <proto/bsdsocket.h>
- struct Library *SocketBase = NULL;
+# ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+# endif
+# ifdef __amigaos4__
+struct SocketIFace *ISocket = NULL;
+# else
+struct Library *SocketBase = NULL;
+# endif
+# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
#endif
/* includes end */"
AC_CHECK_HEADERS(
proto/bsdsocket.h,
- [], [], [ $curl_includes_bsdsocket])
+ [], [], [$curl_includes_bsdsocket])
])
dnl CURL_INCLUDES_NETIF
@@ -785,7 +774,6 @@
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_winsock2
- $curl_includes_bsdsocket
$curl_includes_socket
]],[[
if(0 != closesocket(0))
@@ -803,7 +791,6 @@
AC_MSG_CHECKING([if closesocket is prototyped])
AC_EGREP_CPP([closesocket],[
$curl_includes_winsock2
- $curl_includes_bsdsocket
$curl_includes_socket
],[
AC_MSG_RESULT([yes])
@@ -819,7 +806,6 @@
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_winsock2
- $curl_includes_bsdsocket
$curl_includes_socket
]],[[
if(0 != closesocket(0))
@@ -871,6 +857,7 @@
AC_DEFUN([CURL_CHECK_FUNC_CLOSESOCKET_CAMEL], [
AC_REQUIRE([CURL_INCLUDES_SYS_SOCKET])dnl
+ AC_REQUIRE([CURL_INCLUDES_BSDSOCKET])dnl
#
tst_links_closesocket_camel="unknown"
tst_proto_closesocket_camel="unknown"
@@ -880,6 +867,7 @@
AC_MSG_CHECKING([if CloseSocket can be linked])
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
+ $curl_includes_bsdsocket
$curl_includes_sys_socket
]],[[
if(0 != CloseSocket(0))
@@ -896,6 +884,7 @@
if test "$tst_links_closesocket_camel" = "yes"; then
AC_MSG_CHECKING([if CloseSocket is prototyped])
AC_EGREP_CPP([CloseSocket],[
+ $curl_includes_bsdsocket
$curl_includes_sys_socket
],[
AC_MSG_RESULT([yes])
@@ -910,6 +899,7 @@
AC_MSG_CHECKING([if CloseSocket is compilable])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
+ $curl_includes_bsdsocket
$curl_includes_sys_socket
]],[[
if(0 != CloseSocket(0))
@@ -962,6 +952,7 @@
AC_DEFUN([CURL_CHECK_FUNC_CONNECT], [
AC_REQUIRE([CURL_INCLUDES_WINSOCK2])dnl
AC_REQUIRE([CURL_INCLUDES_SYS_SOCKET])dnl
+ AC_REQUIRE([CURL_INCLUDES_BSDSOCKET])dnl
AC_REQUIRE([CURL_INCLUDES_SOCKET])dnl
#
tst_links_connect="unknown"
@@ -1009,7 +1000,7 @@
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_winsock2
- $curl_includes_bsdsocket
+ $curl_includes_bsdsocket
$curl_includes_sys_socket
$curl_includes_socket
]],[[
@@ -2192,7 +2183,7 @@
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_winsock2
- $curl_includes_bsdsocket
+ $curl_includes_bsdsocket
$curl_includes_netdb
]],[[
if(0 != gethostbyname(0))
@@ -2281,6 +2272,7 @@
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_netdb
+ $curl_includes_bsdsocket
]],[[
if(0 != gethostbyname_r(0, 0, 0))
return 1;
@@ -2299,6 +2291,7 @@
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_netdb
+ $curl_includes_bsdsocket
]],[[
if(0 != gethostbyname_r(0, 0, 0, 0, 0))
return 1;
@@ -2317,6 +2310,7 @@
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_netdb
+ $curl_includes_bsdsocket
]],[[
if(0 != gethostbyname_r(0, 0, 0, 0, 0, 0))
return 1;
@@ -2386,9 +2380,9 @@
AC_DEFUN([CURL_CHECK_FUNC_GETHOSTNAME], [
AC_REQUIRE([CURL_INCLUDES_WINSOCK2])dnl
+ AC_REQUIRE([CURL_INCLUDES_BSDSOCKET])dnl
AC_REQUIRE([CURL_INCLUDES_UNISTD])dnl
AC_REQUIRE([CURL_PREPROCESS_CALLCONV])dnl
- AC_REQUIRE([CURL_INCLUDES_BSDSOCKET])dnl
#
tst_links_gethostname="unknown"
tst_proto_gethostname="unknown"
@@ -2399,8 +2393,8 @@
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_winsock2
- $curl_includes_bsdsocket
$curl_includes_unistd
+ $curl_includes_bsdsocket
]],[[
if(0 != gethostname(0, 0))
return 1;
@@ -2417,8 +2411,8 @@
AC_MSG_CHECKING([if gethostname is prototyped])
AC_EGREP_CPP([gethostname],[
$curl_includes_winsock2
- $curl_includes_bsdsocket
$curl_includes_unistd
+ $curl_includes_bsdsocket
],[
AC_MSG_RESULT([yes])
tst_proto_gethostname="yes"
@@ -2433,8 +2427,8 @@
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_winsock2
- $curl_includes_bsdsocket
$curl_includes_unistd
+ $curl_includes_bsdsocket
]],[[
if(0 != gethostname(0, 0))
return 1;
@@ -2457,8 +2451,8 @@
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_winsock2
- $curl_includes_bsdsocket
$curl_includes_unistd
+ $curl_includes_bsdsocket
$curl_preprocess_callconv
extern int FUNCALLCONV gethostname($tst_arg1, $tst_arg2);
]],[[
@@ -3461,93 +3455,6 @@
])
-dnl CURL_CHECK_FUNC_IOCTL
-dnl -------------------------------------------------
-dnl Verify if ioctl is available, prototyped, and
-dnl can be compiled. If all of these are true, and
-dnl usage has not been previously disallowed with
-dnl shell variable curl_disallow_ioctl, then
-dnl HAVE_IOCTL will be defined.
-
-AC_DEFUN([CURL_CHECK_FUNC_IOCTL], [
- AC_REQUIRE([CURL_INCLUDES_STROPTS])dnl
- #
- tst_links_ioctl="unknown"
- tst_proto_ioctl="unknown"
- tst_compi_ioctl="unknown"
- tst_allow_ioctl="unknown"
- #
- AC_MSG_CHECKING([if ioctl can be linked])
- AC_LINK_IFELSE([
- AC_LANG_FUNC_LINK_TRY([ioctl])
- ],[
- AC_MSG_RESULT([yes])
- tst_links_ioctl="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_links_ioctl="no"
- ])
- #
- if test "$tst_links_ioctl" = "yes"; then
- AC_MSG_CHECKING([if ioctl is prototyped])
- AC_EGREP_CPP([ioctl],[
- $curl_includes_stropts
- ],[
- AC_MSG_RESULT([yes])
- tst_proto_ioctl="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_proto_ioctl="no"
- ])
- fi
- #
- if test "$tst_proto_ioctl" = "yes"; then
- AC_MSG_CHECKING([if ioctl is compilable])
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- $curl_includes_stropts
- ]],[[
- if(0 != ioctl(0, 0, 0))
- return 1;
- ]])
- ],[
- AC_MSG_RESULT([yes])
- tst_compi_ioctl="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_compi_ioctl="no"
- ])
- fi
- #
- if test "$tst_compi_ioctl" = "yes"; then
- AC_MSG_CHECKING([if ioctl usage allowed])
- if test "x$curl_disallow_ioctl" != "xyes"; then
- AC_MSG_RESULT([yes])
- tst_allow_ioctl="yes"
- else
- AC_MSG_RESULT([no])
- tst_allow_ioctl="no"
- fi
- fi
- #
- AC_MSG_CHECKING([if ioctl might be used])
- if test "$tst_links_ioctl" = "yes" &&
- test "$tst_proto_ioctl" = "yes" &&
- test "$tst_compi_ioctl" = "yes" &&
- test "$tst_allow_ioctl" = "yes"; then
- AC_MSG_RESULT([yes])
- AC_DEFINE_UNQUOTED(HAVE_IOCTL, 1,
- [Define to 1 if you have the ioctl function.])
- curl_cv_func_ioctl="yes"
- CURL_CHECK_FUNC_IOCTL_FIONBIO
- CURL_CHECK_FUNC_IOCTL_SIOCGIFADDR
- else
- AC_MSG_RESULT([no])
- curl_cv_func_ioctl="no"
- fi
-])
-
-
dnl CURL_CHECK_FUNC_IOCTL_FIONBIO
dnl -------------------------------------------------
dnl Verify if ioctl with the FIONBIO command is
@@ -3681,7 +3588,6 @@
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_winsock2
- $curl_includes_bsdsocket
]],[[
if(0 != ioctlsocket(0, 0, 0))
return 1;
@@ -3698,7 +3604,6 @@
AC_MSG_CHECKING([if ioctlsocket is prototyped])
AC_EGREP_CPP([ioctlsocket],[
$curl_includes_winsock2
- $curl_includes_bsdsocket
],[
AC_MSG_RESULT([yes])
tst_proto_ioctlsocket="yes"
@@ -3713,7 +3618,6 @@
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_winsock2
- $curl_includes_bsdsocket
]],[[
if(0 != ioctlsocket(0, 0, 0))
return 1;
@@ -3772,7 +3676,6 @@
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_winsock2
- $curl_includes_bsdsocket
]],[[
int flags = 0;
if(0 != ioctlsocket(0, FIONBIO, &flags))
@@ -3821,7 +3724,7 @@
dnl then HAVE_IOCTLSOCKET_CAMEL will be defined.
AC_DEFUN([CURL_CHECK_FUNC_IOCTLSOCKET_CAMEL], [
- AC_REQUIRE([CURL_INCLUDES_STROPTS])dnl
+ AC_REQUIRE([CURL_INCLUDES_BSDSOCKET])dnl
#
tst_links_ioctlsocket_camel="unknown"
tst_proto_ioctlsocket_camel="unknown"
@@ -3830,7 +3733,11 @@
#
AC_MSG_CHECKING([if IoctlSocket can be linked])
AC_LINK_IFELSE([
- AC_LANG_FUNC_LINK_TRY([IoctlSocket])
+ AC_LANG_PROGRAM([[
+ $curl_includes_bsdsocket
+ ]],[[
+ IoctlSocket(0, 0, 0);
+ ]])
],[
AC_MSG_RESULT([yes])
tst_links_ioctlsocket_camel="yes"
@@ -3842,7 +3749,7 @@
if test "$tst_links_ioctlsocket_camel" = "yes"; then
AC_MSG_CHECKING([if IoctlSocket is prototyped])
AC_EGREP_CPP([IoctlSocket],[
- $curl_includes_stropts
+ $curl_includes_bsdsocket
],[
AC_MSG_RESULT([yes])
tst_proto_ioctlsocket_camel="yes"
@@ -3856,7 +3763,7 @@
AC_MSG_CHECKING([if IoctlSocket is compilable])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
- $curl_includes_stropts
+ $curl_includes_bsdsocket
]],[[
if(0 != IoctlSocket(0, 0, 0))
return 1;
@@ -3905,6 +3812,7 @@
dnl true, then HAVE_IOCTLSOCKET_CAMEL_FIONBIO will be defined.
AC_DEFUN([CURL_CHECK_FUNC_IOCTLSOCKET_CAMEL_FIONBIO], [
+ AC_REQUIRE([CURL_INCLUDES_BSDSOCKET])dnl
#
tst_compi_ioctlsocket_camel_fionbio="unknown"
tst_allow_ioctlsocket_camel_fionbio="unknown"
@@ -3913,7 +3821,7 @@
AC_MSG_CHECKING([if IoctlSocket FIONBIO is compilable])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
- $curl_includes_stropts
+ $curl_includes_bsdsocket
]],[[
long flags = 0;
if(0 != IoctlSocket(0, FIONBIO, &flags))
@@ -4075,122 +3983,6 @@
])
-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
- ]],[[
- if(0 != localtime_r(0, 0))
- return 1;
- ]])
- ],[
- 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 "x$cross_compiling" != "xyes" &&
- 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);
- if(tmp)
- exit(0);
- else
- exit(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_MEMRCHR
dnl -------------------------------------------------
dnl Verify if memrchr is available, prototyped, and
@@ -4299,10 +4091,7 @@
dnl CURL_CHECK_FUNC_POLL
dnl -------------------------------------------------
dnl Verify if poll 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_poll, then
-dnl HAVE_POLL will be defined.
+dnl be compiled and seems to work.
AC_DEFUN([CURL_CHECK_FUNC_POLL], [
AC_REQUIRE([CURL_INCLUDES_STDLIB])dnl
@@ -4432,8 +4221,6 @@
test "$tst_allow_poll" = "yes" &&
test "$tst_works_poll" != "no"; then
AC_MSG_RESULT([yes])
- AC_DEFINE_UNQUOTED(HAVE_POLL, 1,
- [Define to 1 if you have a working poll function.])
AC_DEFINE_UNQUOTED(HAVE_POLL_FINE, 1,
[If you have a fine poll])
curl_cv_func_poll="yes"
@@ -4566,104 +4353,6 @@
])
-dnl CURL_CHECK_FUNC_SETSOCKOPT
-dnl -------------------------------------------------
-dnl Verify if setsockopt is available, prototyped, and
-dnl can be compiled. If all of these are true, and
-dnl usage has not been previously disallowed with
-dnl shell variable curl_disallow_setsockopt, then
-dnl HAVE_SETSOCKOPT will be defined.
-
-AC_DEFUN([CURL_CHECK_FUNC_SETSOCKOPT], [
- AC_REQUIRE([CURL_INCLUDES_WINSOCK2])dnl
- AC_REQUIRE([CURL_INCLUDES_SYS_SOCKET])dnl
- #
- tst_links_setsockopt="unknown"
- tst_proto_setsockopt="unknown"
- tst_compi_setsockopt="unknown"
- tst_allow_setsockopt="unknown"
- #
- AC_MSG_CHECKING([if setsockopt can be linked])
- AC_LINK_IFELSE([
- AC_LANG_PROGRAM([[
- $curl_includes_winsock2
- $curl_includes_bsdsocket
- $curl_includes_sys_socket
- ]],[[
- if(0 != setsockopt(0, 0, 0, 0, 0))
- return 1;
- ]])
- ],[
- AC_MSG_RESULT([yes])
- tst_links_setsockopt="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_links_setsockopt="no"
- ])
- #
- if test "$tst_links_setsockopt" = "yes"; then
- AC_MSG_CHECKING([if setsockopt is prototyped])
- AC_EGREP_CPP([setsockopt],[
- $curl_includes_winsock2
- $curl_includes_bsdsocket
- $curl_includes_sys_socket
- ],[
- AC_MSG_RESULT([yes])
- tst_proto_setsockopt="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_proto_setsockopt="no"
- ])
- fi
- #
- if test "$tst_proto_setsockopt" = "yes"; then
- AC_MSG_CHECKING([if setsockopt is compilable])
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- $curl_includes_winsock2
- $curl_includes_bsdsocket
- $curl_includes_sys_socket
- ]],[[
- if(0 != setsockopt(0, 0, 0, 0, 0))
- return 1;
- ]])
- ],[
- AC_MSG_RESULT([yes])
- tst_compi_setsockopt="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_compi_setsockopt="no"
- ])
- fi
- #
- if test "$tst_compi_setsockopt" = "yes"; then
- AC_MSG_CHECKING([if setsockopt usage allowed])
- if test "x$curl_disallow_setsockopt" != "xyes"; then
- AC_MSG_RESULT([yes])
- tst_allow_setsockopt="yes"
- else
- AC_MSG_RESULT([no])
- tst_allow_setsockopt="no"
- fi
- fi
- #
- AC_MSG_CHECKING([if setsockopt might be used])
- if test "$tst_links_setsockopt" = "yes" &&
- test "$tst_proto_setsockopt" = "yes" &&
- test "$tst_compi_setsockopt" = "yes" &&
- test "$tst_allow_setsockopt" = "yes"; then
- AC_MSG_RESULT([yes])
- AC_DEFINE_UNQUOTED(HAVE_SETSOCKOPT, 1,
- [Define to 1 if you have the setsockopt function.])
- curl_cv_func_setsockopt="yes"
- CURL_CHECK_FUNC_SETSOCKOPT_SO_NONBLOCK
- else
- AC_MSG_RESULT([no])
- curl_cv_func_setsockopt="no"
- fi
-])
-
-
dnl CURL_CHECK_FUNC_SETSOCKOPT_SO_NONBLOCK
dnl -------------------------------------------------
dnl Verify if setsockopt with the SO_NONBLOCK command is
@@ -4681,7 +4370,7 @@
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_winsock2
- $curl_includes_bsdsocket
+ $curl_includes_bsdsocket
$curl_includes_sys_socket
]],[[
if(0 != setsockopt(0, SOL_SOCKET, SO_NONBLOCK, 0, 0))
@@ -5263,7 +4952,7 @@
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_winsock2
- $curl_includes_bsdsocket
+ $curl_includes_bsdsocket
$curl_includes_sys_socket
$curl_includes_socket
]],[[
@@ -5654,8 +5343,8 @@
dnl Verify if strerror_r is available, prototyped, can be compiled and
dnl seems to work. If all of these are true, and usage has not been
dnl previously disallowed with shell variable curl_disallow_strerror_r,
-dnl then HAVE_STRERROR_R and STRERROR_R_TYPE_ARG3 will be defined, as
-dnl well as one of HAVE_GLIBC_STRERROR_R or HAVE_POSIX_STRERROR_R.
+dnl then HAVE_STRERROR_R will be defined, as well as one of
+dnl HAVE_GLIBC_STRERROR_R or HAVE_POSIX_STRERROR_R.
dnl
dnl glibc-style strerror_r:
dnl
@@ -5889,16 +5578,12 @@
[Define to 1 if you have the strerror_r function.])
AC_DEFINE_UNQUOTED(HAVE_GLIBC_STRERROR_R, 1,
[Define to 1 if you have a working glibc-style strerror_r function.])
- AC_DEFINE_UNQUOTED(STRERROR_R_TYPE_ARG3, $tst_glibc_strerror_r_type_arg3,
- [Define to the type of arg 3 for strerror_r.])
fi
if test "$tst_posix_strerror_r" = "yes"; then
AC_DEFINE_UNQUOTED(HAVE_STRERROR_R, 1,
[Define to 1 if you have the strerror_r function.])
AC_DEFINE_UNQUOTED(HAVE_POSIX_STRERROR_R, 1,
[Define to 1 if you have a working POSIX-style strerror_r function.])
- AC_DEFINE_UNQUOTED(STRERROR_R_TYPE_ARG3, $tst_posix_strerror_r_type_arg3,
- [Define to the type of arg 3 for strerror_r.])
fi
curl_cv_func_strerror_r="yes"
else
@@ -5999,261 +5684,6 @@
])
-dnl CURL_CHECK_FUNC_STRNCMPI
-dnl -------------------------------------------------
-dnl Verify if strncmpi is available, prototyped, and
-dnl can be compiled. If all of these are true, and
-dnl usage has not been previously disallowed with
-dnl shell variable curl_disallow_strncmpi, then
-dnl HAVE_STRNCMPI will be defined.
-
-AC_DEFUN([CURL_CHECK_FUNC_STRNCMPI], [
- AC_REQUIRE([CURL_INCLUDES_STRING])dnl
- #
- tst_links_strncmpi="unknown"
- tst_proto_strncmpi="unknown"
- tst_compi_strncmpi="unknown"
- tst_allow_strncmpi="unknown"
- #
- AC_MSG_CHECKING([if strncmpi can be linked])
- AC_LINK_IFELSE([
- AC_LANG_FUNC_LINK_TRY([strncmpi])
- ],[
- AC_MSG_RESULT([yes])
- tst_links_strncmpi="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_links_strncmpi="no"
- ])
- #
- if test "$tst_links_strncmpi" = "yes"; then
- AC_MSG_CHECKING([if strncmpi is prototyped])
- AC_EGREP_CPP([strncmpi],[
- $curl_includes_string
- ],[
- AC_MSG_RESULT([yes])
- tst_proto_strncmpi="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_proto_strncmpi="no"
- ])
- fi
- #
- if test "$tst_proto_strncmpi" = "yes"; then
- AC_MSG_CHECKING([if strncmpi is compilable])
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- $curl_includes_string
- ]],[[
- if(0 != strncmpi(0, 0))
- return 1;
- ]])
- ],[
- AC_MSG_RESULT([yes])
- tst_compi_strncmpi="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_compi_strncmpi="no"
- ])
- fi
- #
- if test "$tst_compi_strncmpi" = "yes"; then
- AC_MSG_CHECKING([if strncmpi usage allowed])
- if test "x$curl_disallow_strncmpi" != "xyes"; then
- AC_MSG_RESULT([yes])
- tst_allow_strncmpi="yes"
- else
- AC_MSG_RESULT([no])
- tst_allow_strncmpi="no"
- fi
- fi
- #
- AC_MSG_CHECKING([if strncmpi might be used])
- if test "$tst_links_strncmpi" = "yes" &&
- test "$tst_proto_strncmpi" = "yes" &&
- test "$tst_compi_strncmpi" = "yes" &&
- test "$tst_allow_strncmpi" = "yes"; then
- AC_MSG_RESULT([yes])
- AC_DEFINE_UNQUOTED(HAVE_STRNCMPI, 1,
- [Define to 1 if you have the strncmpi function.])
- curl_cv_func_strncmpi="yes"
- else
- AC_MSG_RESULT([no])
- curl_cv_func_strncmpi="no"
- fi
-])
-
-
-dnl CURL_CHECK_FUNC_STRNICMP
-dnl -------------------------------------------------
-dnl Verify if strnicmp is available, prototyped, and
-dnl can be compiled. If all of these are true, and
-dnl usage has not been previously disallowed with
-dnl shell variable curl_disallow_strnicmp, then
-dnl HAVE_STRNICMP will be defined.
-
-AC_DEFUN([CURL_CHECK_FUNC_STRNICMP], [
- AC_REQUIRE([CURL_INCLUDES_STRING])dnl
- #
- tst_links_strnicmp="unknown"
- tst_proto_strnicmp="unknown"
- tst_compi_strnicmp="unknown"
- tst_allow_strnicmp="unknown"
- #
- AC_MSG_CHECKING([if strnicmp can be linked])
- AC_LINK_IFELSE([
- AC_LANG_FUNC_LINK_TRY([strnicmp])
- ],[
- AC_MSG_RESULT([yes])
- tst_links_strnicmp="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_links_strnicmp="no"
- ])
- #
- if test "$tst_links_strnicmp" = "yes"; then
- AC_MSG_CHECKING([if strnicmp is prototyped])
- AC_EGREP_CPP([strnicmp],[
- $curl_includes_string
- ],[
- AC_MSG_RESULT([yes])
- tst_proto_strnicmp="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_proto_strnicmp="no"
- ])
- fi
- #
- if test "$tst_proto_strnicmp" = "yes"; then
- AC_MSG_CHECKING([if strnicmp is compilable])
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- $curl_includes_string
- ]],[[
- if(0 != strnicmp(0, 0))
- return 1;
- ]])
- ],[
- AC_MSG_RESULT([yes])
- tst_compi_strnicmp="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_compi_strnicmp="no"
- ])
- fi
- #
- if test "$tst_compi_strnicmp" = "yes"; then
- AC_MSG_CHECKING([if strnicmp usage allowed])
- if test "x$curl_disallow_strnicmp" != "xyes"; then
- AC_MSG_RESULT([yes])
- tst_allow_strnicmp="yes"
- else
- AC_MSG_RESULT([no])
- tst_allow_strnicmp="no"
- fi
- fi
- #
- AC_MSG_CHECKING([if strnicmp might be used])
- if test "$tst_links_strnicmp" = "yes" &&
- test "$tst_proto_strnicmp" = "yes" &&
- test "$tst_compi_strnicmp" = "yes" &&
- test "$tst_allow_strnicmp" = "yes"; then
- AC_MSG_RESULT([yes])
- AC_DEFINE_UNQUOTED(HAVE_STRNICMP, 1,
- [Define to 1 if you have the strnicmp function.])
- curl_cv_func_strnicmp="yes"
- else
- AC_MSG_RESULT([no])
- curl_cv_func_strnicmp="no"
- fi
-])
-
-
-dnl CURL_CHECK_FUNC_STRSTR
-dnl -------------------------------------------------
-dnl Verify if strstr is available, prototyped, and
-dnl can be compiled. If all of these are true, and
-dnl usage has not been previously disallowed with
-dnl shell variable curl_disallow_strstr, then
-dnl HAVE_STRSTR will be defined.
-
-AC_DEFUN([CURL_CHECK_FUNC_STRSTR], [
- AC_REQUIRE([CURL_INCLUDES_STRING])dnl
- #
- tst_links_strstr="unknown"
- tst_proto_strstr="unknown"
- tst_compi_strstr="unknown"
- tst_allow_strstr="unknown"
- #
- AC_MSG_CHECKING([if strstr can be linked])
- AC_LINK_IFELSE([
- AC_LANG_FUNC_LINK_TRY([strstr])
- ],[
- AC_MSG_RESULT([yes])
- tst_links_strstr="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_links_strstr="no"
- ])
- #
- if test "$tst_links_strstr" = "yes"; then
- AC_MSG_CHECKING([if strstr is prototyped])
- AC_EGREP_CPP([strstr],[
- $curl_includes_string
- ],[
- AC_MSG_RESULT([yes])
- tst_proto_strstr="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_proto_strstr="no"
- ])
- fi
- #
- if test "$tst_proto_strstr" = "yes"; then
- AC_MSG_CHECKING([if strstr is compilable])
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- $curl_includes_string
- ]],[[
- if(0 != strstr(0, 0))
- return 1;
- ]])
- ],[
- AC_MSG_RESULT([yes])
- tst_compi_strstr="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_compi_strstr="no"
- ])
- fi
- #
- if test "$tst_compi_strstr" = "yes"; then
- AC_MSG_CHECKING([if strstr usage allowed])
- if test "x$curl_disallow_strstr" != "xyes"; then
- AC_MSG_RESULT([yes])
- tst_allow_strstr="yes"
- else
- AC_MSG_RESULT([no])
- tst_allow_strstr="no"
- fi
- fi
- #
- AC_MSG_CHECKING([if strstr might be used])
- if test "$tst_links_strstr" = "yes" &&
- test "$tst_proto_strstr" = "yes" &&
- test "$tst_compi_strstr" = "yes" &&
- test "$tst_allow_strstr" = "yes"; then
- AC_MSG_RESULT([yes])
- AC_DEFINE_UNQUOTED(HAVE_STRSTR, 1,
- [Define to 1 if you have the strstr function.])
- curl_cv_func_strstr="yes"
- else
- AC_MSG_RESULT([no])
- curl_cv_func_strstr="no"
- fi
-])
-
-
dnl CURL_CHECK_FUNC_STRTOK_R
dnl -------------------------------------------------
dnl Verify if strtok_r is available, prototyped, and
@@ -6423,91 +5853,6 @@
fi
])
-
-dnl CURL_CHECK_FUNC_WRITEV
-dnl -------------------------------------------------
-dnl Verify if writev is available, prototyped, and
-dnl can be compiled. If all of these are true, and
-dnl usage has not been previously disallowed with
-dnl shell variable curl_disallow_writev, then
-dnl HAVE_WRITEV will be defined.
-
-AC_DEFUN([CURL_CHECK_FUNC_WRITEV], [
- AC_REQUIRE([CURL_INCLUDES_SYS_UIO])dnl
- #
- tst_links_writev="unknown"
- tst_proto_writev="unknown"
- tst_compi_writev="unknown"
- tst_allow_writev="unknown"
- #
- AC_MSG_CHECKING([if writev can be linked])
- AC_LINK_IFELSE([
- AC_LANG_FUNC_LINK_TRY([writev])
- ],[
- AC_MSG_RESULT([yes])
- tst_links_writev="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_links_writev="no"
- ])
- #
- if test "$tst_links_writev" = "yes"; then
- AC_MSG_CHECKING([if writev is prototyped])
- AC_EGREP_CPP([writev],[
- $curl_includes_sys_uio
- ],[
- AC_MSG_RESULT([yes])
- tst_proto_writev="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_proto_writev="no"
- ])
- fi
- #
- if test "$tst_proto_writev" = "yes"; then
- AC_MSG_CHECKING([if writev is compilable])
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- $curl_includes_sys_uio
- ]],[[
- if(0 != writev(0, 0, 0))
- return 1;
- ]])
- ],[
- AC_MSG_RESULT([yes])
- tst_compi_writev="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_compi_writev="no"
- ])
- fi
- #
- if test "$tst_compi_writev" = "yes"; then
- AC_MSG_CHECKING([if writev usage allowed])
- if test "x$curl_disallow_writev" != "xyes"; then
- AC_MSG_RESULT([yes])
- tst_allow_writev="yes"
- else
- AC_MSG_RESULT([no])
- tst_allow_writev="no"
- fi
- fi
- #
- AC_MSG_CHECKING([if writev might be used])
- if test "$tst_links_writev" = "yes" &&
- test "$tst_proto_writev" = "yes" &&
- test "$tst_compi_writev" = "yes" &&
- test "$tst_allow_writev" = "yes"; then
- AC_MSG_RESULT([yes])
- AC_DEFINE_UNQUOTED(HAVE_WRITEV, 1,
- [Define to 1 if you have the writev function.])
- curl_cv_func_writev="yes"
- else
- AC_MSG_RESULT([no])
- curl_cv_func_writev="no"
- fi
-])
-
dnl CURL_RUN_IFELSE
dnl -------------------------------------------------
dnl Wrapper macro to use instead of AC_RUN_IFELSE. It
@@ -6521,11 +5866,14 @@
AC_RUN_IFELSE([AC_LANG_SOURCE([$1])], $2, $3, $4)
;;
*)
+ oldcc=$CC
old=$LD_LIBRARY_PATH
+ CC="sh ./run-compiler"
LD_LIBRARY_PATH=$CURL_LIBRARY_PATH:$old
export LD_LIBRARY_PATH
AC_RUN_IFELSE([AC_LANG_SOURCE([$1])], $2, $3, $4)
LD_LIBRARY_PATH=$old # restore
+ CC=$oldcc
;;
esac
])
@@ -6570,24 +5918,86 @@
])
dnl CURL_ATOMIC
-dnl --------------------------------------------------
-dnl Check if _Atomic works
+dnl -------------------------------------------------------------
+dnl Check if _Atomic works. But only check if stdatomic.h exists.
dnl
AC_DEFUN([CURL_ATOMIC],[
- AC_MSG_CHECKING([if _Atomic is available])
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- $curl_includes_unistd
- ]],[[
- _Atomic int i = 0;
- ]])
- ],[
- AC_MSG_RESULT([yes])
- AC_DEFINE_UNQUOTED(HAVE_ATOMIC, 1,
- [Define to 1 if you have _Atomic support.])
- tst_atomic="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_atomic="no"
+ AC_CHECK_HEADERS(stdatomic.h, [
+ AC_MSG_CHECKING([if _Atomic is available])
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[
+ $curl_includes_unistd
+ ]],[[
+ _Atomic int i = 0;
+ i = 4; // Force an atomic-write operation.
+ ]])
+ ],[
+ AC_MSG_RESULT([yes])
+ AC_DEFINE_UNQUOTED(HAVE_ATOMIC, 1,
+ [Define to 1 if you have _Atomic support.])
+ tst_atomic="yes"
+ ],[
+ AC_MSG_RESULT([no])
+ tst_atomic="no"
+ ])
])
])
+
+# Rewrite inspired by the functionality once provided by
+# AX_COMPILE_CHECK_SIZEOF. Uses the switch() "trick" to find the size of the
+# given type.
+#
+# This code fails to compile:
+#
+# switch() { case 0: case 0: }
+#
+# By making the second case number a boolean check, it fails to compile the
+# test code when the boolean is false and thus creating a zero, making it a
+# duplicated case label. If the boolean equals true, it becomes a one, the
+# code compiles and we know it was a match.
+#
+# The check iterates over all possible sizes and stops as soon it compiles
+# error-free.
+#
+# Usage:
+#
+# CURL_SIZEOF(TYPE, [HEADERS])
+#
+
+AC_DEFUN([CURL_SIZEOF], [
+ dnl The #define name to make autoheader put the name in curl_config.h.in
+ define(TYPE, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
+
+ AC_MSG_CHECKING(size of $1)
+ r=0
+ dnl Check the sizes in a reasonable order
+ for typesize in 8 4 2 16 1; do
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+$2
+]],
+ [switch(0) {
+ case 0:
+ case (sizeof($1) == $typesize):;
+ }
+ ]) ],
+ [
+ r=$typesize],
+ [
+ r=0])
+ dnl get out of the loop once matched
+ if test $r -gt 0; then
+ break;
+ fi
+ done
+ if test $r -eq 0; then
+ AC_MSG_ERROR([Failed to find size of $1])
+ fi
+ AC_MSG_RESULT($r)
+ dnl lowercase and underscore instead of space
+ tname=$(echo "ac_cv_sizeof_$1" | tr A-Z a-z | tr " " "_")
+ eval "$tname=$r"
+
+ AC_DEFINE_UNQUOTED(TYPE, [$r], [Size of $1 in number of bytes])
+
+])
diff --git a/m4/curl-gnutls.m4 b/m4/curl-gnutls.m4
index 2bf6755..48813df 100644
--- a/m4/curl-gnutls.m4
+++ b/m4/curl-gnutls.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -39,7 +39,7 @@
addcflags=""
if test "x$OPT_GNUTLS" = "xyes"; then
- dnl this is with no partiular path given
+ dnl this is with no particular path given
CURL_CHECK_PKGCONFIG(gnutls)
if test "$PKGCONFIG" != "no" ; then
diff --git a/m4/curl-mbedtls.m4 b/m4/curl-mbedtls.m4
index 022d14e..78ed629 100644
--- a/m4/curl-mbedtls.m4
+++ b/m4/curl-mbedtls.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/m4/curl-nss.m4 b/m4/curl-nss.m4
index cb16275..2916c36 100644
--- a/m4/curl-nss.m4
+++ b/m4/curl-nss.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/m4/curl-openssl.m4 b/m4/curl-openssl.m4
index bdcbfde..b3a6322 100644
--- a/m4/curl-openssl.m4
+++ b/m4/curl-openssl.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -102,7 +102,6 @@
SSL_LDFLAGS="-L$LIB_OPENSSL"
SSL_CPPFLAGS="-I$PREFIX_OPENSSL/include"
fi
- SSL_CPPFLAGS="$SSL_CPPFLAGS -I$PREFIX_OPENSSL/include/openssl"
;;
esac
@@ -150,7 +149,7 @@
fi
if test "$PKGCONFIG" = "no" -a -n "$PREFIX_OPENSSL" ; then
# only set this if pkg-config wasn't used
- CPPFLAGS="$CLEANCPPFLAGS -I$PREFIX_OPENSSL/include/openssl -I$PREFIX_OPENSSL/include"
+ CPPFLAGS="$CLEANCPPFLAGS -I$PREFIX_OPENSSL/include"
fi
# Linking previously failed, try extra paths from --with-openssl or
# pkg-config. Use a different function name to avoid reusing the earlier
@@ -280,6 +279,24 @@
AC_MSG_RESULT([no])
])
+ AC_MSG_CHECKING([for AWS-LC])
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+ #include <openssl/base.h>
+ ]],[[
+ #ifndef OPENSSL_IS_AWSLC
+ #error not AWS-LC
+ #endif
+ ]])
+ ],[
+ AC_MSG_RESULT([yes])
+ AC_DEFINE_UNQUOTED(HAVE_AWSLC, 1,
+ [Define to 1 if using AWS-LC.])
+ ssl_msg="AWS-LC"
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+
AC_MSG_CHECKING([for libressl])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
@@ -311,11 +328,6 @@
AC_MSG_RESULT([yes])
AC_DEFINE_UNQUOTED(HAVE_OPENSSL3, 1,
[Define to 1 if using OpenSSL 3 or later.])
- dnl OpenSSLv3 marks the DES functions deprecated but we have no
- dnl replacements (yet) so tell the compiler to not warn for them
- dnl
- dnl Ask OpenSSL to suppress the warnings.
- CPPFLAGS="$CPPFLAGS -DOPENSSL_SUPPRESS_DEPRECATED"
ssl_msg="OpenSSL v3+"
],[
AC_MSG_RESULT([no])
diff --git a/m4/curl-override.m4 b/m4/curl-override.m4
index fb84f67..b4a8df9 100644
--- a/m4/curl-override.m4
+++ b/m4/curl-override.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/m4/curl-reentrant.m4 b/m4/curl-reentrant.m4
index 1992c5e..c1f3339 100644
--- a/m4/curl-reentrant.m4
+++ b/m4/curl-reentrant.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/m4/curl-rustls.m4 b/m4/curl-rustls.m4
index 6fd8235..98283bf 100644
--- a/m4/curl-rustls.m4
+++ b/m4/curl-rustls.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -38,6 +38,14 @@
OPT_RUSTLS=""
fi
+ case $host_os in
+ darwin*)
+ LDFLAGS="$LDFLAGS -framework Security"
+ ;;
+ *)
+ ;;
+ esac
+
if test -z "$OPT_RUSTLS" ; then
dnl check for lib first without setting any new path
diff --git a/m4/curl-schannel.m4 b/m4/curl-schannel.m4
index 49c3877..016bfd4 100644
--- a/m4/curl-schannel.m4
+++ b/m4/curl-schannel.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/m4/curl-sectransp.m4 b/m4/curl-sectransp.m4
index 0c43b13..fc0ad9e 100644
--- a/m4/curl-sectransp.m4
+++ b/m4/curl-sectransp.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/m4/curl-sysconfig.m4 b/m4/curl-sysconfig.m4
index c6cd2f8..cd1e019 100644
--- a/m4/curl-sysconfig.m4
+++ b/m4/curl-sysconfig.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/m4/curl-wolfssl.m4 b/m4/curl-wolfssl.m4
index 1f732e3..f4aea3f 100644
--- a/m4/curl-wolfssl.m4
+++ b/m4/curl-wolfssl.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -95,6 +95,7 @@
They are set up properly later if it is detected. */
#undef SIZEOF_LONG
#undef SIZEOF_LONG_LONG
+#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
]],[[
return wolfSSL_Init();
@@ -122,7 +123,7 @@
check_for_ca_bundle=1
dnl wolfssl/ctaocrypt/types.h needs SIZEOF_LONG_LONG defined!
- AX_COMPILE_CHECK_SIZEOF(long long)
+ CURL_SIZEOF(long long)
LIBS="$addlib -lm $LIBS"
@@ -142,6 +143,15 @@
]
)
+ dnl if this symbol is present, we can make use of BIO filter chains
+ AC_CHECK_FUNC(wolfSSL_BIO_set_shutdown,
+ [
+ AC_DEFINE(HAVE_WOLFSSL_FULL_BIO, 1,
+ [if you have wolfSSL_BIO_set_shutdown])
+ WOLFSSL_FULL_BIO=1
+ ]
+ )
+
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
@@ -153,7 +163,8 @@
AC_MSG_NOTICE([Added $wolfssllibpath to CURL_LIBRARY_PATH])
fi
fi
-
+ else
+ AC_MSG_ERROR([--with-wolfssl but wolfSSL was not found or doesn't work])
fi
fi dnl wolfSSL not disabled
diff --git a/m4/xc-am-iface.m4 b/m4/xc-am-iface.m4
index 621453d..c035f58 100644
--- a/m4/xc-am-iface.m4
+++ b/m4/xc-am-iface.m4
@@ -2,7 +2,7 @@
#
# xc-am-iface.m4
#
-# Copyright (c) 2013 - 2022 Daniel Stenberg <daniel@haxx.se>
+# Copyright (C) Daniel Stenberg <daniel@haxx.se>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -83,172 +83,3 @@
dnl
m4_define([$0], [])[]dnl
])
-
-
-dnl _XC_AMEND_DISTCLEAN_BODY ([LIST-OF-SUBDIRS])
-dnl -------------------------------------------------
-dnl Private macro.
-dnl
-dnl This macro performs shell code embedding into
-dnl configure script in order to modify distclean
-dnl and maintainer-clean targets of makefiles which
-dnl are located in given list of subdirs.
-dnl
-dnl See XC_AMEND_DISTCLEAN comments for details.
-
-m4_define([_XC_AMEND_DISTCLEAN_BODY],
-[dnl
-## ---------------------------------- ##
-## Start of distclean amending code ##
-## ---------------------------------- ##
-
-for xc_subdir in [$1]
-do
-
-if test ! -f "$xc_subdir/Makefile"; then
- echo "$xc_msg_err $xc_subdir/Makefile file not found. $xc_msg_abrt" >&2
- exit 1
-fi
-
-# Fetch dependency tracking file list from Makefile include lines.
-
-xc_inc_lines=`grep '^include .*(DEPDIR)' "$xc_subdir/Makefile" 2>/dev/null`
-xc_cnt_words=`echo "$xc_inc_lines" | wc -w | tr -d "$xc_space$xc_tab"`
-
-# --disable-dependency-tracking might have been used, consequently
-# there is nothing to amend without a dependency tracking file list.
-
-if test $xc_cnt_words -gt 0; then
-
-AC_MSG_NOTICE([amending $xc_subdir/Makefile])
-
-# Build Makefile specific patch hunk.
-
-xc_p="$xc_subdir/xc_patch.tmp"
-
-xc_rm_depfiles=`echo "$xc_inc_lines" \
- | $SED 's%include% -rm -f%' 2>/dev/null`
-
-xc_dep_subdirs=`echo "$xc_inc_lines" \
- | $SED 's%include[[ ]][[ ]]*%%' 2>/dev/null \
- | $SED 's%(DEPDIR)/.*%(DEPDIR)%' 2>/dev/null \
- | sort | uniq`
-
-echo "$xc_rm_depfiles" >$xc_p
-
-for xc_dep_dir in $xc_dep_subdirs; do
- echo "${xc_tab}@xm_dep_cnt=\`ls $xc_dep_dir | wc -l 2>/dev/null\`; \\" >>$xc_p
- echo "${xc_tab}if test \$\$xm_dep_cnt -eq 0 && test -d $xc_dep_dir; then \\" >>$xc_p
- echo "${xc_tab} rm -rf $xc_dep_dir; \\" >>$xc_p
- echo "${xc_tab}fi" >>$xc_p
-done
-
-# Build Makefile patching sed scripts.
-
-xc_s1="$xc_subdir/xc_script_1.tmp"
-xc_s2="$xc_subdir/xc_script_2.tmp"
-xc_s3="$xc_subdir/xc_script_3.tmp"
-
-cat >$xc_s1 <<\_EOT
-/^distclean[[ ]]*:/,/^[[^ ]][[^ ]]*:/{
- s/^.*(DEPDIR)/___xc_depdir_line___/
-}
-/^maintainer-clean[[ ]]*:/,/^[[^ ]][[^ ]]*:/{
- s/^.*(DEPDIR)/___xc_depdir_line___/
-}
-_EOT
-
-cat >$xc_s2 <<\_EOT
-/___xc_depdir_line___$/{
- N
- /___xc_depdir_line___$/D
-}
-_EOT
-
-cat >$xc_s3 <<_EOT
-/^___xc_depdir_line___/{
- r $xc_p
- d
-}
-_EOT
-
-# Apply patch to Makefile and cleanup.
-
-$SED -f "$xc_s1" "$xc_subdir/Makefile" >"$xc_subdir/Makefile.tmp1"
-$SED -f "$xc_s2" "$xc_subdir/Makefile.tmp1" >"$xc_subdir/Makefile.tmp2"
-$SED -f "$xc_s3" "$xc_subdir/Makefile.tmp2" >"$xc_subdir/Makefile.tmp3"
-
-if test -f "$xc_subdir/Makefile.tmp3"; then
- mv -f "$xc_subdir/Makefile.tmp3" "$xc_subdir/Makefile"
-fi
-
-test -f "$xc_subdir/Makefile.tmp1" && rm -f "$xc_subdir/Makefile.tmp1"
-test -f "$xc_subdir/Makefile.tmp2" && rm -f "$xc_subdir/Makefile.tmp2"
-test -f "$xc_subdir/Makefile.tmp3" && rm -f "$xc_subdir/Makefile.tmp3"
-
-test -f "$xc_p" && rm -f "$xc_p"
-test -f "$xc_s1" && rm -f "$xc_s1"
-test -f "$xc_s2" && rm -f "$xc_s2"
-test -f "$xc_s3" && rm -f "$xc_s3"
-
-fi
-
-done
-
-## -------------------------------- ##
-## End of distclean amending code ##
-## -------------------------------- ##
-dnl
-m4_define([$0], [])[]dnl
-])
-
-
-dnl XC_AMEND_DISTCLEAN ([LIST-OF-SUBDIRS])
-dnl -------------------------------------------------
-dnl Public macro.
-dnl
-dnl This macro embeds shell code into configure script
-dnl that amends, at configure runtime, the distclean
-dnl and maintainer-clean targets of Makefiles located
-dnl in all subdirs given in the mandatory white-space
-dnl separated list argument.
-dnl
-dnl Embedding only takes place when using automake 1.14
-dnl or newer, otherwise amending code is not included
-dnl in generated configure script.
-dnl
-dnl distclean and maintainer-clean targets are modified
-dnl to avoid unconditional removal of dependency subdirs
-dnl which triggers distclean and maintainer-clean errors
-dnl when using automake 'subdir-objects' option along
-dnl with per-target objects and source files existing in
-dnl multiple subdirs used for different build targets.
-dnl
-dnl New behavior first removes each dependency tracking
-dnl file independently, and only removes each dependency
-dnl subdir when it finds out that it no longer holds any
-dnl dependency tracking file.
-dnl
-dnl When configure option --disable-dependency-tracking
-dnl is used no amending takes place given that there are
-dnl no dependency tracking files.
-
-AC_DEFUN([XC_AMEND_DISTCLEAN],
-[dnl
-AC_PREREQ([2.50])dnl
-dnl
-m4_ifdef([_AC_OUTPUT_MAIN_LOOP],
- [m4_provide_if([_AC_OUTPUT_MAIN_LOOP], [],
- [m4_fatal([call to AC_OUTPUT needed before $0])])])dnl
-dnl
-m4_if([$#], [1], [], [m4_fatal([$0: wrong number of arguments])])dnl
-m4_if([$1], [], [m4_fatal([$0: missing argument])])dnl
-dnl
-AC_REQUIRE([XC_CONFIGURE_PREAMBLE])dnl
-dnl
-m4_ifdef([_AM_PROG_CC_C_O],
-[
-_XC_AMEND_DISTCLEAN_BODY([$1])
-])dnl
-m4_define([$0], [])[]dnl
-])
diff --git a/m4/xc-cc-check.m4 b/m4/xc-cc-check.m4
index 9eae8a6..a6cfb07 100644
--- a/m4/xc-cc-check.m4
+++ b/m4/xc-cc-check.m4
@@ -2,7 +2,7 @@
#
# xc-cc-check.m4
#
-# Copyright (c) 2013 - 2022, Daniel Stenberg <daniel@haxx.se>
+# Copyright (C), Daniel Stenberg <daniel@haxx.se>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
diff --git a/m4/xc-lt-iface.m4 b/m4/xc-lt-iface.m4
index ebdcb2e..d5e437f 100644
--- a/m4/xc-lt-iface.m4
+++ b/m4/xc-lt-iface.m4
@@ -2,7 +2,7 @@
#
# xc-lt-iface.m4
#
-# Copyright (c) 2013 - 2022, Daniel Stenberg <daniel@haxx.se>
+# Copyright (C), Daniel Stenberg <daniel@haxx.se>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -319,7 +319,7 @@
m4_define([_XC_CHECK_LT_BUILD_WITH_PIC],
[dnl
#
-# Find out whether libtool libraries would be built wit PIC
+# Find out whether libtool libraries would be built with PIC
#
case "x$pic_mode" in @%:@ ((((
diff --git a/m4/xc-translit.m4 b/m4/xc-translit.m4
index 6fc837e..6d66771 100644
--- a/m4/xc-translit.m4
+++ b/m4/xc-translit.m4
@@ -2,7 +2,7 @@
#
# xc-translit.m4
#
-# Copyright (c) 2011 - 2022, Daniel Stenberg <daniel@haxx.se>
+# Copyright (C), Daniel Stenberg <daniel@haxx.se>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
diff --git a/m4/xc-val-flgs.m4 b/m4/xc-val-flgs.m4
index b721c31..c8f7796 100644
--- a/m4/xc-val-flgs.m4
+++ b/m4/xc-val-flgs.m4
@@ -2,7 +2,7 @@
#
# xc-val-flgs.m4
#
-# Copyright (c) 2013 - 2022, Daniel Stenberg <daniel@haxx.se>
+# Copyright (C), Daniel Stenberg <daniel@haxx.se>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
diff --git a/m4/zz40-xc-ovr.m4 b/m4/zz40-xc-ovr.m4
index 30d205b..fa45787 100644
--- a/m4/zz40-xc-ovr.m4
+++ b/m4/zz40-xc-ovr.m4
@@ -2,7 +2,7 @@
#
# zz40-xc-ovr.m4
#
-# Copyright (c) 2013 - 2022 Daniel Stenberg <daniel@haxx.se>
+# Copyright (C) Daniel Stenberg <daniel@haxx.se>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -360,7 +360,7 @@
dnl the user has already set it with a non-empty value.
dnl
dnl This path separator is the symbol used to separate
-dnl or diferentiate paths inside the 'PATH' environment
+dnl or differentiate paths inside the 'PATH' environment
dnl variable.
dnl
dnl Non-empty user provided 'PATH_SEPARATOR' always
@@ -594,7 +594,7 @@
dnl the user has already set it with a non-empty value.
dnl
dnl This path separator is the symbol used to separate
-dnl or diferentiate paths inside the 'PATH' environment
+dnl or differentiate paths inside the 'PATH' environment
dnl variable.
dnl
dnl Non-empty user provided 'PATH_SEPARATOR' always
diff --git a/m4/zz50-xc-ovr.m4 b/m4/zz50-xc-ovr.m4
index ea68e5b..18c1f0a 100644
--- a/m4/zz50-xc-ovr.m4
+++ b/m4/zz50-xc-ovr.m4
@@ -2,7 +2,7 @@
#
# zz50-xc-ovr.m4
#
-# Copyright (c) 2011 - 2022, Daniel Stenberg <daniel@haxx.se>
+# Copyright (C), Daniel Stenberg <daniel@haxx.se>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
diff --git a/m4/zz60-xc-ovr.m4 b/m4/zz60-xc-ovr.m4
index e3e29bf..5316686 100644
--- a/m4/zz60-xc-ovr.m4
+++ b/m4/zz60-xc-ovr.m4
@@ -2,7 +2,7 @@
#
# zz60-xc-ovr.m4
#
-# Copyright (c) 2013 - 2022, Daniel Stenberg <daniel@haxx.se>
+# Copyright (C), Daniel Stenberg <daniel@haxx.se>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
diff --git a/maketgz b/maketgz
index 92ea871..a0fcd87 100755
--- a/maketgz
+++ b/maketgz
@@ -9,7 +9,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -64,6 +64,7 @@
HEADER=include/curl/curlver.h
CHEADER=src/tool_version.h
PLIST=lib/libcurl.plist
+PLISTO=$PLIST
if test -z "$only"; then
ext=".dist"
@@ -94,6 +95,9 @@
sed -i.bak 's/#define CURL_VERSION .*/#define CURL_VERSION "'$curlversion'"/g' $CHEADER
rm -f "$CHEADER.bak"
+# Replace version number in plist file:
+sed "s/@CURL_PLIST_VERSION@/$curlversion/g" < $PLISTO.in >$PLIST
+
if test -n "$only"; then
# done!
exit;
diff --git a/mlc_config.json b/mlc_config.json
deleted file mode 100644
index 252d5bc..0000000
--- a/mlc_config.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "_comment": "Config file for linkcheck: If urls have some issues we can not fix on our end past it in here. MLC will ignore this.",
- "ignorePatterns": [
- {
- "pattern": ""
- }
- ]
-}
diff --git a/packages/Android/Android.mk b/packages/Android/Android.mk
deleted file mode 100644
index f5093b7..0000000
--- a/packages/Android/Android.mk
+++ /dev/null
@@ -1,133 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-# Google Android makefile for curl and libcurl
-#
-# This file can be used when building curl using the full Android source
-# release or the NDK. Most users do not want or need to do this; please
-# instead read the Android section in docs/INSTALL for alternate
-# methods.
-#
-# Place the curl source (including this makefile) into external/curl/ in the
-# Android source tree. Then build them with 'make curl' or just 'make libcurl'
-# from the Android root. Tested with Android versions 1.5, 2.1-2.3
-#
-# Note: you must first create a curl_config.h file by running configure in the
-# Android environment. The only way I've found to do this is tricky. Perform a
-# normal Android build with libcurl in the source tree, providing the target
-# "showcommands" to make. The build will eventually fail (because curl_config.h
-# doesn't exist yet), but the compiler commands used to build curl will be
-# shown. Now, from the external/curl/ directory, run curl's normal configure
-# command with flags that match what Android itself uses. This will mean
-# putting the compiler directory into the PATH, putting the -I, -isystem and
-# -D options into CPPFLAGS, putting the -W, -m, -f, -O and -nostdlib options
-# into CFLAGS, and putting the -Wl, -L and -l options into LIBS, along with the
-# path to the files libgcc.a, crtbegin_dynamic.o, and ccrtend_android.o.
-# Remember that the paths must be absolute since you will not be running
-# configure from the same directory as the Android make. The normal
-# cross-compiler options must also be set. Note that the -c, -o, -MD and
-# similar flags must not be set.
-#
-# To see all the LIBS options, you'll need to do the "showcommands" trick on an
-# executable that's already buildable and watch what flags Android uses to link
-# it (dhcpcd is a good choice to watch). You'll also want to add -L options to
-# LIBS that point to the out/.../obj/lib/ and out/.../obj/system/lib/
-# directories so that additional libraries can be found and used by curl.
-#
-# The end result will be a configure command that looks something like this
-# (the environment variable A is set to the Android root path which makes the
-# command shorter):
-#
-# A=`realpath ../..` && \
-# PATH="$A/prebuilt/linux-x86/toolchain/arm-eabi-X/bin:$PATH" \
-# ./configure --host=arm-linux CC=arm-eabi-gcc \
-# CPPFLAGS="-I $A/system/core/include ..." \
-# CFLAGS="-nostdlib -fno-exceptions -Wno-multichar ..." \
-# LIBS="$A/prebuilt/linux-x86/toolchain/arm-eabi-X/lib/gcc/arm-eabi/X\
-# /interwork/libgcc.a ..."
-#
-# Finally, copy the file COPYING to NOTICE so that the curl license gets put
-# into the right place (but see the note about this below).
-#
-# Dan Fandrich
-# November 2011
-
-LOCAL_PATH:= $(call my-dir)/../..
-
-common_CFLAGS := -Wpointer-arith -Wwrite-strings -Wunused -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wno-system-headers -DHAVE_CONFIG_H
-
-#########################
-# Build the libcurl library
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/lib/Makefile.inc
-CURL_HEADERS := \
- curl.h \
- system.h \
- curlver.h \
- easy.h \
- mprintf.h \
- multi.h \
- stdcheaders.h \
- typecheck-gcc.h
-
-LOCAL_SRC_FILES := $(addprefix lib/,$(CSOURCES))
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/include/
-LOCAL_CFLAGS += $(common_CFLAGS)
-
-LOCAL_COPY_HEADERS_TO := libcurl/curl
-LOCAL_COPY_HEADERS := $(addprefix include/curl/,$(CURL_HEADERS))
-
-LOCAL_MODULE:= libcurl
-LOCAL_MODULE_TAGS := optional
-
-# Copy the licence to a place where Android will find it.
-# Actually, this doesn't quite work because the build system searches
-# for NOTICE files before it gets to this point, so it will only be seen
-# on subsequent builds.
-ALL_PREBUILT += $(LOCAL_PATH)/NOTICE
-$(LOCAL_PATH)/NOTICE: $(LOCAL_PATH)/COPYING | $(ACP)
- $(copy-file-to-target)
-
-include $(BUILD_STATIC_LIBRARY)
-
-
-#########################
-# Build the curl binary
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/src/Makefile.inc
-LOCAL_SRC_FILES := $(addprefix src/,$(CURL_CFILES))
-
-LOCAL_MODULE := curl
-LOCAL_MODULE_TAGS := optional
-LOCAL_STATIC_LIBRARIES := libcurl
-LOCAL_SYSTEM_SHARED_LIBRARIES := libc
-
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/include $(LOCAL_PATH)/lib
-
-# This may also need to include $(CURLX_CFILES) in order to correctly link
-# if libcurl is changed to be built as a dynamic library
-LOCAL_CFLAGS += $(common_CFLAGS)
-
-include $(BUILD_EXECUTABLE)
diff --git a/packages/DOS/README b/packages/DOS/README
deleted file mode 100644
index cc9da37..0000000
--- a/packages/DOS/README
+++ /dev/null
@@ -1,17 +0,0 @@
-Gisle Vanem made curl build fine on DOS (and MingW) with djgpp, OpenSSL and his
-Watt-32 stack.
-
-'make -f Makefile.dist djgpp' in the root curl dir should build it fine.
-Or enter 'lib' and do a 'make -f Makefile.dj clean all' to first delete
-'lib/curl_config.h' which is possibly from a previous incompatible Windows-build.
-
-Note 1: djgpp 2.04 beta has a sscanf() bug so the URL parsing isn't
- done properly. Use djgpp 2.03 until they fix it.
-
-Note 2: Compile Watt-32 (and OpenSSL) with the same version of djgpp.
- Otherwise things go wrong because things like FS-extensions and
- errnos have been changed between releases.
-
-Note 3: Several 'USE_x' variables in 'common.dj' are on the 'USE_x ?= 0'
- form (conditional variable assignment). So one can build like this:
- c:\curl\lib> make -f makefile.dj USE_OPENSSL=1 USE_ZLIB=1 clean all
diff --git a/packages/DOS/common.dj b/packages/DOS/common.dj
deleted file mode 100644
index 78ec522..0000000
--- a/packages/DOS/common.dj
+++ /dev/null
@@ -1,225 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-#
-# Common defines for curl (djgpp/Watt-32)
-#
-# Assumes you've unpacked curl with long-file names
-# I.e use "set LFN=y" before untaring on Win9x/XP.
-# Requires sed, rm and the usual stuff.
-#
-# Define TOPDIR before including this file.
-
-MAKEFILE = Makefile.dj
-OBJ_DIR = djgpp
-
-#
-# Find out if using a Unix-like shell or a DOS command interpreter
-#
-ifneq ($(findstring COMMAND.COM,$(SHELL)),COMMAND.COM)
- ifneq ($(findstring CMD.EXE,$(SHELL)),CMD.EXE)
- ifneq ($(findstring 4DOS.COM,$(SHELL)),4DOS.COM)
- IS_UNIX_SHELL = 1
- endif
- endif
-endif
-
-#
-# Define shell dependent commands and vars
-#
-ifeq ($(IS_UNIX_SHELL),1)
- COPY = cp -f
- DELETE = rm -f
- MKDIR = mkdir
- RMDIR = rm -f -r
- DS = /
-else
- COPY = copy
- DELETE = del
- MKDIR = mkdir
- RMDIR = rmdir
- DS = \$(NOTHING)
-endif
-
-ifeq ($(OS),Windows_NT)
- #
- # Windows hosted djgpp cross compiler. Get it from:
- # https://github.com/andrewwutw/build-djgpp/releases
- #
- DJ_PREFIX ?= c:/some-path/djgpp/bin/i586-pc-msdosdjgpp-
- CC = $(DJ_PREFIX)gcc
-
-else
- #
- # The normal djgpp 'gcc' for MSDOS.
- #
- CC = gcc
-endif
-
-#
-# OpenSSL is available from www.openssl.org and builds okay
-# with djgpp/Watt-32. Set to 0 if you don't need https URLs
-# (reduces curl.exe with approx 700 kB)
-#
-USE_OPENSSL ?= 0
-
-#
-# Use zlib for contents encoding. Needed for 'USE_OPENSSL=1' too.
-#
-USE_ZLIB ?= 0
-
-#
-# Use libidn for international domain names
-#
-USE_IDNA ?= 0
-
-#
-# Use Watt-32 IPv6 stack (only IPv6 name resolution working at the moment)
-#
-USE_IPV6 ?= 0
-
-#
-# Use C-Ares resolver library
-#
-USE_ARES ?= 0
-
-#
-# Enable debug code in libcurl/curl
-#
-USE_DEBUG ?= 0
-
-#
-# Enable memory tracking code in libcurl/curl
-#
-USE_CURLDEBUG ?= 0
-
-#
-# Generate a .map file in 'link_EXE' macro
-#
-MAKE_MAP_FILE ?= 0
-
-default: all
-
-#
-# Root directory for Waterloo tcp/ip etc. Change to suite.
-# WATT_ROOT should be set during Watt-32 install.
-#
-WATT32_ROOT = $(realpath $(WATT_ROOT))
-OPENSSL_ROOT ?= $(TOPDIR)/../crypto/OpenSSL
-ZLIB_ROOT ?= e:/djgpp/contrib/zlib
-LIBIDN_ROOT ?= $(TOPDIR)/../IDN/libidn
-ARES_ROOT ?= $(TOPDIR)/../DNS/c-ares
-
-CFLAGS = -g -O2 -I. -I$(TOPDIR)/include -I$(TOPDIR)/lib \
- -I$(WATT32_ROOT)/inc -Wall -DHAVE_CONFIG_H
-
-ifeq ($(USE_OPENSSL),1)
- CFLAGS += -DUSE_OPENSSL -I$(OPENSSL_ROOT)/include
-
- #
- # Squelch the warnings on deprecated functions.
- #
- CFLAGS += -DOPENSSL_SUPPRESS_DEPRECATED
-
- #
- # Use some of these too?
- #
- # CFLAGS += -DUSE_TLS_SRP=1 \
- # -DHAVE_ENGINE_LOAD_BUILTIN_ENGINES \
- # -DHAVE_OPENSSL_PKCS12_H \
- # -DHAVE_SSLV2_CLIENT_METHOD \
- # -DOPENSSL_NO_DEPRECATED
-
- #
- # 'libcomm.a' is normally 'libcommon.a'. But to keep it 8+3 clean, it's
- # shortened to 'libcomm.a'. The official OpenSSL build was recently changed
- # and this "Common" library was added for several of the Crypto Providers.
- #
- OPENSSL_LIBS = $(OPENSSL_ROOT)/lib/libssl.a \
- $(OPENSSL_ROOT)/lib/libcrypt.a \
- $(OPENSSL_ROOT)/lib/libcomm.a
-endif
-
-ifeq ($(USE_ZLIB),1)
- CFLAGS += -DUSE_ZLIB -I$(ZLIB_ROOT)
-endif
-
-ifeq ($(USE_IPV6),1)
- CFLAGS += -DENABLE_IPV6
-endif
-
-ifeq ($(USE_ARES),1)
- CFLAGS += -DUSE_ARES -I$(ARES_ROOT)/include
-endif
-
-ifeq ($(USE_IDNA),1)
- CFLAGS += -DHAVE_LIBIDN -DHAVE_IDN_FREE_H -DHAVE_IDN_FREE -DHAVE_TLD_H \
- -DHAVE_TLD_STRERROR -I$(LIBIDN_ROOT)/lib
-endif
-
-ifeq ($(USE_DEBUG),1)
- CFLAGS += -DDEBUG=1 -DDEBUGBUILD
-endif
-
-ifeq ($(USE_CURLDEBUG),1)
- CFLAGS += -DCURLDEBUG
-endif
-
-$(OBJ_DIR):
- $(MKDIR) $(OBJ_DIR)
-
-$(OBJ_DIR)/%.o: %.c
- $(CC) $(CFLAGS) -o $@ -c $<
- @echo
-
-#
-# Link-EXE macro:
-# $(1): the .exe
-# $(2): the .o-files and libraries
-#
-ifeq ($(MAKE_MAP_FILE),1)
- define link_EXE
- $(CC) -o $(1) $(LDFLAGS) -Wl,--print-map,--sort-common $(2) > $(1:.exe=.map)
- endef
-else
- define link_EXE
- $(CC) $(LDFLAGS) -o $(1) $(2)
- endef
-endif
-
-$(TOPDIR)/docs/curl.1: $(wildcard $(TOPDIR)/docs/cmdline-opts/*.d)
- cd $(TOPDIR)/docs/cmdline-opts; \
- perl gen.pl mainpage > ../$(TOPDIR)/docs/curl.1
-
-DEP_REPLACE = sed -e 's@\(.*\)\.o: @\n$$(OBJ_DIR)\/\1.o: @' \
- -e 's@$(ARES_ROOT)@$$(ARES_ROOT)@g' \
- -e 's@$(OPENSSL_ROOT)@$$(OPENSSL_ROOT)@g' \
- -e 's@$(WATT32_ROOT)@$$(WATT32_ROOT)@g' \
- -e 's@$(ZLIB_ROOT)@$$(ZLIB_ROOT)@g'
-
-#
-# One may have to do 'make -f Makefile.dj clean' first in case
-# a foreign 'curl_config.h' is making trouble.
-#
-depend: $(DEPEND_PREREQ) $(MAKEFILE)
- $(CC) -MM $(CFLAGS) $(CSOURCES) | $(DEP_REPLACE) > depend.dj
diff --git a/packages/Makefile.am b/packages/Makefile.am
index b379911..1da49f6 100644
--- a/packages/Makefile.am
+++ b/packages/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,10 +23,9 @@
###########################################################################
SUBDIRS = vms
-EXTRA_DIST = README \
- DOS/README \
- DOS/common.dj \
+EXTRA_DIST = README.md \
OS400/README.OS400 \
+ OS400/rpg-examples \
OS400/ccsidcurl.c \
OS400/ccsidcurl.h \
OS400/chkstrings.c \
@@ -38,8 +37,7 @@
OS400/make-tests.sh \
OS400/makefile.sh \
OS400/os400sys.c \
- OS400/os400sys.h \
- Android/Android.mk
+ OS400/os400sys.h
CHECKSRC = $(CS_$(V))
CS_0 = @echo " RUN " $@;
diff --git a/packages/OS400/README.OS400 b/packages/OS400/README.OS400
index e245aff..6790f6f 100644
--- a/packages/OS400/README.OS400
+++ b/packages/OS400/README.OS400
@@ -1,8 +1,8 @@
Implementation notes:
- This is a true OS/400 implementation, not a PASE implementation (for PASE,
-use AIX implementation).
+ This is a true OS/400 ILE implementation, not a PASE implementation (for
+PASE, use AIX implementation).
The biggest problem with OS/400 is EBCDIC. Libcurl implements an internal
conversion mechanism, but it has been designed for computers that have a
@@ -96,6 +96,7 @@
CURLOPT_PASSWORD
CURLOPT_PINNEDPUBLICKEY
CURLOPT_PRE_PROXY
+ CURLOPT_PROTOCOLS_STR
CURLOPT_PROXY
CURLOPT_PROXYPASSWORD
CURLOPT_PROXYUSERNAME
@@ -117,6 +118,7 @@
CURLOPT_PROXY_TLSAUTH_USERNAME
CURLOPT_RANDOM_FILE
CURLOPT_RANGE
+ CURLOPT_REDIR_PROTOCOLS_STR
CURLOPT_REFERER
CURLOPT_REQUEST_TARGET
CURLOPT_RTSP_SESSION_UID
@@ -126,6 +128,7 @@
CURLOPT_SERVICE_NAME
CURLOPT_SOCKS5_GSSAPI_SERVICE
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
+ CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256
CURLOPT_SSH_KNOWNHOSTS
CURLOPT_SSH_PRIVATE_KEYFILE
CURLOPT_SSH_PUBLIC_KEYFILE
@@ -145,11 +148,13 @@
CURLOPT_USERNAME
CURLOPT_USERPWD
CURLOPT_XOAUTH2_BEARER
- Else it is the same as for curl_easy_setopt().
+ All blob options are also supported.
+ In all other cases, it ignores the ccsid parameter and behaves as
+curl_easy_setopt().
Note that CURLOPT_ERRORBUFFER is not in the list above, since it gives the
address of an (empty) character buffer, not the address of a string.
-CURLOPT_POSTFIELDS stores the address of static binary data (of type void *) and
-thus is not converted. If CURLOPT_COPYPOSTFIELDS is issued after
+CURLOPT_POSTFIELDS stores the address of static binary data (of type void *)
+and thus is not converted. If CURLOPT_COPYPOSTFIELDS is issued after
CURLOPT_POSTFIELDSIZE != -1, the data size is adjusted according to the
CCSID conversion result length.
@@ -195,6 +200,13 @@
after use.
Other options are processed like in curl_easy_getinfo().
+_ curl_easy_strerror_ccsid(), curl_multi_strerror_ccsid(),
+curl_share_strerror_ccsid() and curl_url_strerror_ccsid() work as their
+non-ccsid version and return a string encoded in the additional ccsid
+parameter. These strings belong to libcurl and may not be freed by the caller.
+A subsequent call to the same procedure in the same thread invalidates the
+previous result.
+
_ curl_pushheader_bynum_cssid() and curl_pushheader_byname_ccsid()
Although the prototypes are self-explanatory, the returned string pointer
should be released with curl_free() after use, as opposite to the non-ccsid
@@ -208,6 +220,17 @@
supported ccsid. However the caller should release the returned pointer with
curl_free() after use.
+_ curl_easy_header_ccsid() works as its non-CCSID counterpart but requires an
+additional ccsid parameter specifying the name parameter encoding. The output
+hout parameter is kept in libcurl's encoding and should not be altered.
+
+_ curl_from_ccsid() and curl_to_ccsid() are string encoding conversion
+functions between ASCII (latin1) and the given CCSID. The first parameter is
+the source string, the second is the CCSID and the returned value is a pointer
+to the dynamically allocated string. These functions do not impact on Curl's
+behavior and are only provided for user convenience. After use, returned values
+must be released with curl_free().
+
Standard compilation environment does support neither autotools nor make;
in fact, very few common utilities are available. As a consequence, the
@@ -270,7 +293,8 @@
cp initscript.sh makelog): this is intended to create the makelog file with
an ASCII CCSID!
_ Enter the command "sh makefile.sh > makelog 2>&1"
-_ Examine the makelog file to check for compilation errors.
+_ Examine the makelog file to check for compilation errors. CZM0383 warnings on
+ C or system standard API come from QADRT inlining and can safely be ignored.
Leaving file initscript.sh unchanged, this will produce the following OS/400
objects:
@@ -316,9 +340,9 @@
ILE/RPG support:
- Since 95% of the OS/400 programmers use ILE/RPG exclusively, a definition
- /INCLUDE member is provided for this language. To include all libcurl
- definitions in an ILE/RPG module, line
+ Since most of the ILE OS/400 programmers use ILE/RPG exclusively, a
+definition /INCLUDE member is provided for this language. To include all
+libcurl definitions in an ILE/RPG module, line
h bnddir('CURL/CURL')
@@ -331,8 +355,9 @@
No vararg procedure support exists in ILE/RPG: for this reason, the following
considerations apply:
_ Procedures curl_easy_setopt_long(), curl_easy_setopt_object(),
- curl_easy_setopt_function() and curl_easy_setopt_offset() are all alias
- prototypes to curl_easy_setopt(), but with different parameter lists.
+ curl_easy_setopt_function(), curl_easy_setopt_offset() and
+ curl_easy_setopt_blob() are all alias prototypes to curl_easy_setopt(), but
+ with different parameter lists.
_ Procedures curl_easy_getinfo_string(), curl_easy_getinfo_long(),
curl_easy_getinfo_double(), curl_easy_getinfo_slist(),
curl_easy_getinfo_ptr(), curl_easy_getinfo_socket() and
@@ -341,12 +366,22 @@
_ Procedures curl_multi_setopt_long(), curl_multi_setopt_object(),
curl_multi_setopt_function() and curl_multi_setopt_offset() are all alias
prototypes to curl_multi_setopt(), but with different parameter lists.
+_ Procedures curl_share_setopt_int(), curl_share_setopt_ptr() and
+ curl_share_setopt_proc() are all alias prototypes to curl_share_setopt,
+ but with different parameter lists.
+_ Procedure curl_easy_setopt_blob_ccsid() is an alias of
+ curl_easy_setopt_ccsid() supporting blob encoding conversion.
_ The prototype of procedure curl_formadd() allows specifying a pointer option
and the CURLFORM_END option. This makes possible to use an option array
without any additional definition. If some specific incompatible argument
list is used in the ILE/RPG program, the latter must define a specialised
alias. The same applies to curl_formadd_ccsid() too.
+_ Since V7R4M0, procedure overloading is used to emulate limited "vararg-like"
+ definitions of curl_easy_setopt(), curl_multi_setopt(), curl_share_setopt()
+ and curl_easy_getinfo(). Blob and CCSID alternatives are NOT included in
+ overloading.
Since RPG cannot cast a long to a pointer, procedure curl_form_long_value()
-is provided for that purpose: this allows storing a long value in the curl_forms
-array.
+is provided for that purpose: this allows storing a long value in the
+curl_forms array. Please note the form API is deprecated and the MIME API
+should be used instead.
diff --git a/packages/OS400/ccsidcurl.c b/packages/OS400/ccsidcurl.c
index da696ca..c59617e 100644
--- a/packages/OS400/ccsidcurl.c
+++ b/packages/OS400/ccsidcurl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -235,28 +235,50 @@
}
-char *curl_version_ccsid(unsigned int ccsid)
+static char *
+keyed_string(localkey_t key, const char *ascii, unsigned int ccsid)
{
int i;
- char *aversion;
- char *eversion;
+ char *ebcdic;
- aversion = curl_version();
-
- if(!aversion)
- return aversion;
-
- i = strlen(aversion) + 1;
- i *= MAX_CONV_EXPANSION;
-
- eversion = Curl_thread_buffer(LK_CURL_VERSION, i);
- if(!eversion)
+ if(!ascii)
return (char *) NULL;
- if(convert(eversion, i, ccsid, aversion, -1, ASCII_CCSID) < 0)
+ i = MAX_CONV_EXPANSION * (strlen(ascii) + 1);
+
+ ebcdic = Curl_thread_buffer(key, i);
+ if(!ebcdic)
+ return ebcdic;
+
+ if(convert(ebcdic, i, ccsid, ascii, -1, ASCII_CCSID) < 0)
return (char *) NULL;
- return eversion;
+ return ebcdic;
+}
+
+
+const char *
+curl_to_ccsid(const char *s, unsigned int ccsid)
+{
+ if(s)
+ s = dynconvert(ccsid, s, -1, ASCII_CCSID);
+ return s;
+}
+
+
+const char *
+curl_from_ccsid(const char *s, unsigned int ccsid)
+{
+ if(s)
+ s = dynconvert(ASCII_CCSID, s, -1, ccsid);
+ return s;
+}
+
+
+char *
+curl_version_ccsid(unsigned int ccsid)
+{
+ return keyed_string(LK_CURL_VERSION, curl_version(), ccsid);
}
@@ -414,18 +436,19 @@
offsetof(curl_version_info_data, capath),
offsetof(curl_version_info_data, zstd_version),
offsetof(curl_version_info_data, hyper_version),
- offsetof(curl_version_info_data, gsasl_version)
+ offsetof(curl_version_info_data, gsasl_version),
+ offsetof(curl_version_info_data, feature_names)
};
/* The assertion below is possible, because although the second operand
is an enum member, the first is a #define. In that case, the OS/400 C
compiler seems to compare string values after substitution. */
-#if CURLVERSION_NOW != CURLVERSION_TENTH
+#if CURLVERSION_NOW != CURLVERSION_ELEVENTH
#error curl_version_info_data structure has changed: upgrade this procedure.
#endif
- /* If caller has been compiled with a new version, error. */
+ /* If caller has been compiled with a newer version, error. */
if(stamp > CURLVERSION_NOW)
return (curl_version_info_data *) NULL;
@@ -472,7 +495,7 @@
memcpy((char *) id, (char *) p, sizeof(*p));
if(id->protocols) {
- int i = nproto * sizeof(id->protocols[0]);
+ i = nproto * sizeof(id->protocols[0]);
id->protocols = (const char * const *) cp;
memcpy(cp, (char *) p->protocols, i);
@@ -487,7 +510,7 @@
for(i = 0; i < sizeof(charfields) / sizeof(charfields[0]); i++) {
cpp = (const char **) ((char *) p + charfields[i]);
- if (*cpp && convert_version_info_string(cpp, &cp, &n, ccsid))
+ if(*cpp && convert_version_info_string(cpp, &cp, &n, ccsid))
return (curl_version_info_data *) NULL;
}
@@ -498,75 +521,28 @@
const char *
curl_easy_strerror_ccsid(CURLcode error, unsigned int ccsid)
{
- int i;
- const char *s;
- char *buf;
-
- s = curl_easy_strerror(error);
-
- if(!s)
- return s;
-
- i = MAX_CONV_EXPANSION * (strlen(s) + 1);
-
- buf = Curl_thread_buffer(LK_EASY_STRERROR, i);
- if(!buf)
- return (const char *) NULL;
-
- if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0)
- return (const char *) NULL;
-
- return (const char *) buf;
+ return keyed_string(LK_EASY_STRERROR, curl_easy_strerror(error), ccsid);
}
const char *
curl_share_strerror_ccsid(CURLSHcode error, unsigned int ccsid)
{
- int i;
- const char *s;
- char *buf;
-
- s = curl_share_strerror(error);
-
- if(!s)
- return s;
-
- i = MAX_CONV_EXPANSION * (strlen(s) + 1);
-
- buf = Curl_thread_buffer(LK_SHARE_STRERROR, i);
- if(!buf)
- return (const char *) NULL;
-
- if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0)
- return (const char *) NULL;
-
- return (const char *) buf;
+ return keyed_string(LK_SHARE_STRERROR, curl_share_strerror(error), ccsid);
}
const char *
curl_multi_strerror_ccsid(CURLMcode error, unsigned int ccsid)
{
- int i;
- const char *s;
- char *buf;
+ return keyed_string(LK_MULTI_STRERROR, curl_multi_strerror(error), ccsid);
+}
- s = curl_multi_strerror(error);
- if(!s)
- return s;
-
- i = MAX_CONV_EXPANSION * (strlen(s) + 1);
-
- buf = Curl_thread_buffer(LK_MULTI_STRERROR, i);
- if(!buf)
- return (const char *) NULL;
-
- if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0)
- return (const char *) NULL;
-
- return (const char *) buf;
+const char *
+curl_url_strerror_ccsid(CURLUcode error, unsigned int ccsid)
+{
+ return keyed_string(LK_URL_STRERROR, curl_url_strerror(error), ccsid);
}
@@ -1087,17 +1063,15 @@
CURLcode
-curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...)
+curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...)
{
CURLcode result;
va_list arg;
- struct Curl_easy *data;
char *s;
- char *cp;
+ char *cp = NULL;
unsigned int ccsid;
curl_off_t pfsize;
- data = (struct Curl_easy *) curl;
va_start(arg, tag);
switch(tag) {
@@ -1137,6 +1111,7 @@
case CURLOPT_PASSWORD:
case CURLOPT_PINNEDPUBLICKEY:
case CURLOPT_PRE_PROXY:
+ case CURLOPT_PROTOCOLS_STR:
case CURLOPT_PROXY:
case CURLOPT_PROXYPASSWORD:
case CURLOPT_PROXYUSERNAME:
@@ -1158,6 +1133,7 @@
case CURLOPT_PROXY_TLSAUTH_USERNAME:
case CURLOPT_RANDOM_FILE:
case CURLOPT_RANGE:
+ case CURLOPT_REDIR_PROTOCOLS_STR:
case CURLOPT_REFERER:
case CURLOPT_REQUEST_TARGET:
case CURLOPT_RTSP_SESSION_ID:
@@ -1167,6 +1143,7 @@
case CURLOPT_SERVICE_NAME:
case CURLOPT_SOCKS5_GSSAPI_SERVICE:
case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
+ case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256:
case CURLOPT_SSH_KNOWNHOSTS:
case CURLOPT_SSH_PRIVATE_KEYFILE:
case CURLOPT_SSH_PUBLIC_KEYFILE:
@@ -1187,6 +1164,7 @@
case CURLOPT_USERNAME:
case CURLOPT_USERPWD:
case CURLOPT_XOAUTH2_BEARER:
+ case CURLOPT_HAPROXY_CLIENT_IP:
s = va_arg(arg, char *);
ccsid = va_arg(arg, unsigned int);
@@ -1199,7 +1177,7 @@
}
}
- result = curl_easy_setopt(curl, tag, s);
+ result = curl_easy_setopt(easy, tag, s);
free(s);
break;
@@ -1210,10 +1188,10 @@
s = va_arg(arg, char *);
ccsid = va_arg(arg, unsigned int);
- pfsize = data->set.postfieldsize;
+ pfsize = easy->set.postfieldsize;
if(!s || !pfsize || ccsid == NOCONV_CCSID || ccsid == ASCII_CCSID) {
- result = curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, s);
+ result = curl_easy_setopt(easy, CURLOPT_COPYPOSTFIELDS, s);
break;
}
@@ -1251,30 +1229,68 @@
pfsize = convert(cp, pfsize, ASCII_CCSID, s, len, ccsid);
if(pfsize < 0) {
- free(cp);
result = CURLE_OUT_OF_MEMORY;
break;
}
- data->set.postfieldsize = pfsize; /* Replace data size. */
+ easy->set.postfieldsize = pfsize; /* Replace data size. */
s = cp;
}
- result = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, s);
- data->set.str[STRING_COPYPOSTFIELDS] = s; /* Give to library. */
+ result = curl_easy_setopt(easy, CURLOPT_POSTFIELDS, s);
+ easy->set.str[STRING_COPYPOSTFIELDS] = s; /* Give to library. */
break;
- case CURLOPT_ERRORBUFFER: /* This is an output buffer. */
default:
- result = Curl_vsetopt(curl, tag, arg);
+ if(tag / 10000 == CURLOPTTYPE_BLOB) {
+ struct curl_blob *bp = va_arg(arg, struct curl_blob *);
+ struct curl_blob blob;
+
+ ccsid = va_arg(arg, unsigned int);
+
+ if(bp && bp->data && bp->len &&
+ ccsid != NOCONV_CCSID && ccsid != ASCII_CCSID) {
+ pfsize = (curl_off_t) bp->len * MAX_CONV_EXPANSION;
+
+ if(pfsize > SIZE_MAX)
+ pfsize = SIZE_MAX;
+
+ cp = malloc(pfsize);
+
+ if(!cp) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ pfsize = convert(cp, pfsize, ASCII_CCSID, bp->data, bp->len, ccsid);
+
+ if(pfsize < 0) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ blob.data = cp;
+ blob.len = pfsize;
+ blob.flags = bp->flags | CURL_BLOB_COPY;
+ bp = &blob;
+ }
+ result = curl_easy_setopt(easy, tag, &blob);
+ break;
+ }
+ /* FALLTHROUGH */
+ case CURLOPT_ERRORBUFFER: /* This is an output buffer. */
+ result = Curl_vsetopt(easy, tag, arg);
break;
}
va_end(arg);
+ free(cp);
return result;
}
+/* ILE/RPG helper functions. */
+
char *
curl_form_long_value(long value)
{
@@ -1284,6 +1300,29 @@
}
+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, 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, arg);
+}
+
+
char *
curl_pushheader_bynum_cssid(struct curl_pushheaders *h,
size_t num, unsigned int ccsid)
@@ -1460,3 +1499,24 @@
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 result = CURLHE_BAD_ARGUMENT;
+
+ if(name) {
+ char *s = dynconvert(ASCII_CCSID, name, -1, ccsid);
+
+ result = CURLHE_OUT_OF_MEMORY;
+ if(s) {
+ result = curl_easy_header(easy, s, index, origin, request, hout);
+ free(s);
+ }
+ }
+
+ return result;
+}
diff --git a/packages/OS400/ccsidcurl.h b/packages/OS400/ccsidcurl.h
index 9bd2ae7..ab01d32 100644
--- a/packages/OS400/ccsidcurl.h
+++ b/packages/OS400/ccsidcurl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -96,5 +96,18 @@
CURL_EXTERN const char *curl_easy_option_get_name_ccsid(
const struct curl_easyoption *option,
unsigned int ccsid);
+CURL_EXTERN const char *curl_url_strerror_ccsid(CURLUcode error,
+ unsigned int ccsid);
+CURL_EXTERN 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);
+CURL_EXTERN const char *curl_from_ccsid(const char *s, unsigned int ccsid);
+CURL_EXTERN const char *curl_to_ccsid(const char *s, unsigned int ccsid);
+CURL_EXTERN CURLcode curl_easy_setopt_RPGnum_(CURL *easy,
+ CURLoption tag, curl_off_t arg);
+CURL_EXTERN CURLcode curl_multi_setopt_RPGnum_(CURLM *multi, CURLMoption tag,
+ curl_off_t arg);
#endif
diff --git a/packages/OS400/chkstrings.c b/packages/OS400/chkstrings.c
index 6f8d38b..9841ec9 100644
--- a/packages/OS400/chkstrings.c
+++ b/packages/OS400/chkstrings.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,8 +37,8 @@
* made, the EXPECTED_STRING_LASTZEROTERMINATED/EXPECTED_STRING_LAST
* values can be updated to match the latest enum values in urldata.h.
*/
-#define EXPECTED_STRING_LASTZEROTERMINATED (STRING_SSL_EC_CURVES + 1)
-#define EXPECTED_STRING_LAST (STRING_AWS_SIGV4 + 1)
+#define EXPECTED_STRING_LASTZEROTERMINATED (STRING_HAPROXY_CLIENT_IP + 1)
+#define EXPECTED_STRING_LAST (STRING_COPYPOSTFIELDS + 1)
int main(int argc, char *argv[])
{
diff --git a/packages/OS400/curl.inc.in b/packages/OS400/curl.inc.in
index 390c7d0..d1254ce 100644
--- a/packages/OS400/curl.inc.in
+++ b/packages/OS400/curl.inc.in
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -184,12 +184,19 @@
*
d CURL_WRITEFUNC_PAUSE...
d c X'10000001'
+ d CURL_WRITEFUNC_ERROR...
+ d c X'FFFFFFFF'
*
d CURL_TRAILERFUNC_OK...
d c 0
d CURL_TRAILERFUNC_ABORT...
d c 1
*
+ d CURL_PREREQFUNC_OK...
+ d c 0
+ d CURL_PREREQFUNC_ABORT...
+ d c 1
+ *
d CURLAUTH_NONE c X'00000000'
d CURLAUTH_BASIC c X'00000001'
d CURLAUTH_DIGEST...
@@ -278,6 +285,10 @@
d c 4
d CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE...
d c 5
+ d CURL_HTTP_VERSION_3...
+ d c 30
+ d CURL_HTTP_VERSION_3ONLY...
+ d c 31
*
d CURL_NETRC_IGNORED...
d c 0
@@ -330,7 +341,7 @@
d c 7
*
d CURL_ZERO_TERMINATED...
- d c -1
+ d c X'FFFFFFFF'
*
d CURL_POLL_NONE c 0
d CURL_POLL_IN c 1
@@ -340,6 +351,10 @@
d CURL_POLL_REMOVE...
d c 4
*
+ d CURL_BLOB_NOCOPY...
+ d c 0
+ d CURL_BLOB_COPY c 1
+ *
d CURL_CSELECT_IN...
d c X'00000001'
d CURL_CSELECT_OUT...
@@ -424,10 +439,31 @@
d c X'00000200'
d CURLU_NO_AUTHORITY...
d c X'00000400'
+ d CURLU_ALLOW_SPACE...
+ d c X'00000800'
+ d CURLU_PUNYCODE...
+ d c X'00001000'
*
d CURLOT_FLAG_ALIAS...
d c X'00000001'
*
+ d CURLH_HEADER c X'00000001'
+ d CURLH_TRAILER c X'00000002'
+ d CURLH_CONNECT c X'00000004'
+ d CURLH_1XX c X'00000008'
+ d CURLH_PSEUDO c X'00000010'
+ *
+ d CURLWS_TEXT c X'00000001'
+ d CURLWS_BINARY c X'00000002'
+ d CURLWS_CONT c X'00000004'
+ d CURLWS_CLOSE c X'00000008'
+ d CURLWS_PING c X'00000010'
+ d CURLWS_OFFSET c X'00000020'
+ d CURLWS_PONG c X'00000040'
+ *
+ d CURLWS_RAW_MODE...
+ d c X'00000001'
+ *
**************************************************************************
* Types
**************************************************************************
@@ -533,7 +569,7 @@
d c 47
d CURLE_UNKNOWN_OPTION...
d c 48
- d CURLE_TELNET_OPTION_SYNTAX...
+ d CURLE_SETOPT_OPTION_SYNTAX...
d c 49
d CURLE_OBSOLETE50...
d c 50
@@ -559,7 +595,7 @@
d c 60
d CURLE_BAD_CONTENT_ENCODING...
d c 61
- d CURLE_LDAP_INVALID_URL...
+ d CURLE_OBSOLETE62...
d c 62
d CURLE_FILESIZE_EXCEEDED...
d c 63
@@ -585,20 +621,18 @@
d c 73
d CURLE_TFTP_NOSUCHUSER...
d c 74
- d CURLE_CONV_FAILED...
+ d CURLE_OBSOLETE75...
d c 75
- d CURLE_CONV_REQD...
+ d CURLE_OBSOLETE76...
d c 76
d CURLE_SSL_CACERT_BADFILE...
d c 77
d CURLE_REMOTE_FILE_NOT_FOUND...
d c 78
- d CURLE_SSH...
- d c 79
+ d CURLE_SSH c 79
d CURLE_SSL_SHUTDOWN_FAILED...
d c 80
- d CURLE_AGAIN...
- d c 81
+ d CURLE_AGAIN c 81
d CURLE_SSL_CRL_BADFILE...
d c 82
d CURLE_SSL_ISSUER_ERROR...
@@ -625,12 +659,14 @@
d c 93
d CURLE_AUTH_ERROR...
d c 94
- d CURLE_HTTP3...
- d c 95
+ d CURLE_HTTP3 c 95
d CURLE_QUIC_CONNECT_ERROR...
d c 96
- d CURLE_PROXY...
- d c 97
+ d CURLE_PROXY c 97
+ d CURLE_SSL_CLIENTCERT...
+ d c 98
+ d CURLE_UNRECOVERABLE_POLL...
+ d c 99
*
/if not defined(CURL_NO_OLDIES)
d CURLE_URL_MALFORMAT_USER...
@@ -679,6 +715,8 @@
d c 46
d CURLE_UNKNOWN_TELNET_OPTION...
d c 48
+ d CURLE_TELNET_OPTION_SYNTAX...
+ d c 49
d CURLE_OBSOLETE...
d c 50
d CURLE_SHARE_IN_USE...
@@ -687,12 +725,18 @@
d c 60
d CURLE_SSL_PEER_CERTIFICATE...
d c 60
+ d CURLE_LDAP_INVALID_URL...
+ d c 62
d CURLE_FTP_SSL_FAILED...
d c 64
d CURLE_TFTP_DISKFULL...
d c 70
d CURLE_TFTP_EXISTS...
d c 73
+ d CURLE_CONV_FAILED...
+ d c 75
+ d CURLE_CONV_REQD...
+ d c 76
d CURLE_ALREADY_COMPLETE...
d c 99999
/endif
@@ -821,6 +865,8 @@
d c 1
d CURLPROXY_HTTPS...
d c 2
+ d CURLPROXY_HTTPS2...
+ d c 3
d CURLPROXY_SOCKS4...
d c 4
d CURLPROXY_SOCKS5...
@@ -1206,9 +1252,7 @@
d c 00110
d CURLOPT_PROXYAUTH...
d c 00111
- d CURLOPT_FTP_RESPONSE_TIMEOUT...
- d c 00112
- d CURLOPT_SERVER_RESPONSE_TIMEOUT... Alias
+ d CURLOPT_SERVER_RESPONSE_TIMEOUT...
d c 00112
d CURLOPT_IPRESOLVE...
d c 00113
@@ -1545,7 +1589,7 @@
d c 00288
d CURLOPT_SASL_AUTHZID...
d c 10289
- d CURLOPT_MAIL_RCPT_ALLLOWFAILS...
+ d CURLOPT_MAIL_RCPT_ALLOWFAILS...
d c 00290
d CURLOPT_SSLCERT_BLOB...
d c 40291
@@ -1587,10 +1631,30 @@
d c 40309
d CURLOPT_PROXY_CAINFO_BLOB...
d c 40310
+ d CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256...
+ d c 10311
+ d CURLOPT_PREREQFUNCTION...
+ d c 20312
+ d CURLOPT_PREREQDATA...
+ d c 10313
d CURLOPT_MAXLIFETIME_CONN...
d c 00314
d CURLOPT_MIME_OPTIONS...
d c 00315
+ d CURLOPT_SSH_HOSTKEYFUNCTION...
+ d c 20316
+ d CURLOPT_SSH_HOSTKEYDATA...
+ d c 10317
+ d CURLOPT_PROTOCOLS_STR...
+ d c 10318
+ d CURLOPT_REDIR_PROTOCOLS_STR...
+ d c 10319
+ d CURLOPT_WS_OPTIONS...
+ d c 00320
+ d CURLOPT_CA_CACHE_TIMEOUT...
+ d c 00321
+ d CURLOPT_QUICK_EXIT...
+ d c 00322
*
/if not defined(CURL_NO_OLDIES)
d CURLOPT_FILE c 10001
@@ -1618,6 +1682,8 @@
d c 00119
d CURLOPT_POST301...
d c 00161
+ d CURLOPT_FTP_RESPONSE_TIMEOUT...
+ d c 00112
/endif
*
d CURLFORMcode s 10i 0 based(######ptr######) Enum
@@ -1820,6 +1886,10 @@
d c X'0020003B'
d CURLINFO_REFERER... CURLINFO_STRING + 60
d c X'0010003C'
+ d CURLINFO_CAINFO... CURLINFO_STRING + 61
+ d c X'0010003D'
+ d CURLINFO_CAPATH... CURLINFO_STRING + 62
+ d c X'0010003E'
*
d CURLINFO_HTTP_CODE... Old ...RESPONSE_CODE
d c X'00200002'
@@ -1857,10 +1927,12 @@
d CURLSSLBACKEND_RUSTLS...
d c 14
* Aliases for clones.
- d CURLSSLBACKEND_LIBRESSL...
+ d CURLSSLBACKEND_AWSLC...
d c 1
d CURLSSLBACKEND_BORINGSSL...
d c 1
+ d CURLSSLBACKEND_LIBRESSL...
+ d c 1
d CURLSSLBACKEND_WOLFSSL...
d c 6
*
@@ -1893,8 +1965,10 @@
d c 5
d CURL_LOCK_DATA_PSL...
d c 6
- d CURL_LOCK_DATA_LAST...
+ d CURL_LOCK_DATA_HSTS...
d c 7
+ d CURL_LOCK_DATA_LAST...
+ d c 8
*
d curl_lock_access...
d s 10i 0 based(######ptr######) Enum
@@ -1977,8 +2051,27 @@
d c 8
d CURLVERSION_TENTH...
d c 9
+ d CURLVERSION_ELEVENTH...
+ d c 10
d CURLVERSION_NOW...
- d c 9 CURLVERSION_TENTH
+ d c 10 CURLVERSION_ELEVENTH
+ *
+ d CURLHcode s 10i 0 based(######ptr######) Enum
+ d CURLHE_OK c 0
+ d CURLHE_BADINDEX...
+ d c 1
+ d CURLHE_MISSING...
+ d c 2
+ d CURLHE_NOHEADERS...
+ d c 3
+ d CURLHE_NOREQUEST...
+ d c 4
+ d CURLHE_OUT_OF_MEMORY...
+ d c 5
+ d CURLHE_BAD_ARGUMENT...
+ d c 6
+ d CURLHE_NOT_BUILT_IN...
+ d c 7
*
d curlsocktype s 10i 0 based(######ptr######) Enum
d CURLSOCKTYPE_IPCXN...
@@ -2132,6 +2225,32 @@
d c 16
d CURLUE_NO_FRAGMENT...
d c 17
+ d CURLUE_NO_ZONEID...
+ d c 18
+ d CURLUE_BAD_FILE_URL...
+ d c 19
+ d CURLUE_BAD_FRAGMENT...
+ d c 20
+ d CURLUE_BAD_HOSTNAME...
+ d c 21
+ d CURLUE_BAD_IPV6...
+ d c 22
+ d CURLUE_BAD_LOGIN...
+ d c 23
+ d CURLUE_BAD_PASSWORD...
+ d c 24
+ d CURLUE_BAD_PATH...
+ d c 25
+ d CURLUE_BAD_QUERY...
+ d c 26
+ d CURLUE_BAD_SCHEME...
+ d c 27
+ d CURLUE_BAD_SLASHES...
+ d c 28
+ d CURLUE_BAD_USER...
+ d c 29
+ d CURLUE_LACKS_IDN...
+ d c 30
*
d CURLUPart s 10i 0 based(######ptr######) Enum
d CURLUPART_URL c 0
@@ -2162,7 +2281,7 @@
d CURLSTS_DONE c 1
d CURLSTS_FAIL c 2
*
- * Renaming CURLMsg to CURL_Msg to avoid case-insensivity name clash.
+ * Renaming CURLMsg to CURL_Msg to avoid case-insensitivity name clash.
*
d CURL_Msg ds based(######ptr######)
d qualified
@@ -2279,6 +2398,8 @@
d * const char *
d gsasl_version...
d * const char *
+ d feature_names...
+ d * const char *
*
d curl_certinfo ds based(######ptr######)
d qualified
@@ -2337,6 +2458,29 @@
d index 10u 0 size_t
d total 10u 0 size_t
*
+ d curl_header ds based(######ptr######)
+ d qualified
+ d name * char *
+ d value * char *
+ d amount 10u 0 size_t
+ d index 10u 0 size_t
+ d origin 10u 0
+ d anchor * void *
+ *
+ d curl_blob ds based(######ptr######)
+ d qualified
+ d data * void *
+ d len 10u 0 size_t
+ d flags 10u 0
+ *
+ d curl_ws_frame ds based(######ptr######)
+ d qualified
+ d age 10i 0
+ d flags 10i 0
+ d offset like(curl_off_t)
+ d bytesleft like(curl_off_t)
+ d len 10u 0 size_t
+ *
d curl_formget_callback...
d s * based(######ptr######) procptr
*
@@ -2430,6 +2574,15 @@
d curl_hstswrite_callback...
d s * based(######ptr######) procptr
*
+ d curl_prereq_callback...
+ d s * based(######ptr######) procptr
+ *
+ d curl_sshhostkeycallback...
+ d s * based(######ptr######) procptr
+ *
+ d curl_ws_write_callback...
+ d s * based(######ptr######) procptr
+ *
**************************************************************************
* Prototypes
**************************************************************************
@@ -2470,7 +2623,7 @@
d like(CURLcode)
d part * value curl_mimepart *
d data * value options(*string)
- d datasize 10u 0 size_t
+ d datasize 10u 0 value size_t
*
d curl_mime_filedata...
d pr extproc('curl_mime_filedata')
@@ -2671,6 +2824,14 @@
d offsetarg value like(curl_off_t)
d options(*nopass)
*
+ d curl_easy_setopt_blob...
+ d pr extproc('curl_easy_setopt')
+ d like(CURLcode)
+ d curl * value CURL *
+ d option value like(CURLoption)
+ d blob const likeds(curl_blob)
+ d options(*nopass)
+ *
*
d curl_easy_perform...
d pr extproc('curl_easy_perform')
@@ -2940,6 +3101,43 @@
d pr * extproc('curl_easy_next') curl_easyoption *
d prev * value curl_easyoption *
*
+ d curl_ws_recv pr extproc('curl_ws_recv')
+ d like(CURLcode)
+ d curl * value CURL *
+ d buffer * value void *
+ d buflen 10u 0 value size_t
+ d recv 10u 0 size_t *
+ d metap likeds(curl_ws_frame)
+ *
+ d curl_ws_send pr extproc('curl_ws_send')
+ d like(CURLcode)
+ d curl * value CURL *
+ d buffer * value const void *
+ d buflen 10u 0 value size_t
+ d sent 10u 0 size_t *
+ d framesize like(curl_off_t)
+ d sendflags 10u 0 value
+ *
+ d curl_ws_meta pr * extproc('curl_ws_meta') curl_ws_frame *
+ d curl * value CURL *
+ *
+ d curl_easy_header...
+ d pr extproc('curl_easy_header') curl_header *
+ d like(CURLHcode)
+ d curl * value CURL *
+ d name * value options(*string) const char *
+ d index 10u 0 value size_t
+ d origin 10u 0 value
+ d request 10i 0 value
+ d hout * curl_header **
+ *
+ d curl_easy_nextheader...
+ d pr * extproc('curl_easy_nextheader') curl_header *
+ d curl * value CURL *
+ d origin 10u 0 value
+ d request 10i 0 value
+ d prev * value curl_header *
+ *
**************************************************************************
* CCSID wrapper procedure prototypes
**************************************************************************
@@ -3038,6 +3236,15 @@
d objectarg * value options(*string: *nopass)
d ccsid 10u 0 value options(*nopass)
*
+ d curl_easy_setopt_blob_ccsid...
+ d pr extproc('curl_easy_setopt_ccsid')
+ d like(CURLcode)
+ d curl * value CURL *
+ d option value like(CURLoption)
+ d blob const likeds(curl_blob)
+ d options(*nopass)
+ d ccsid 10u 0 value options(*nopass)
+ *
d curl_pushheader_bynum_ccsid...
d pr * extproc( char *
d 'curl_pushheader_bynum_ccsid')
@@ -3086,7 +3293,7 @@
d like(CURLcode)
d part * value curl_mimepart *
d data * value options(*string)
- d datasize 10u 0 size_t
+ d datasize 10u 0 value size_t
d ccsid 10u 0 value
*
d curl_mime_filedata_ccsid...
@@ -3114,6 +3321,11 @@
d flags 10u 0 value
d ccsid 10u 0 value
*
+ d curl_url_strerror_ccsid...
+ d pr * extproc('curl_url_strerror_ccsid') const char *
+ d code value like(CURLUcode)
+ d ccsid 10u 0 value
+ *
d curl_easy_option_by_name_ccsid...
d pr * extproc( curl_easyoption *
d 'curl_easy_option_by_name_ccsid')
@@ -3126,4 +3338,70 @@
d option * value curl_easyoption *
d ccsid 10u 0 value
*
+ d curl_easy_header_ccsid...
+ d pr extproc('curl_easy_header_ccsid') curl_header *
+ d like(CURLHcode)
+ d curl * value CURL *
+ d name * value options(*string) const char *
+ d index 10u 0 value size_t
+ d origin 10u 0 value
+ d request 10i 0 value
+ d hout * curl_header **
+ d ccsid 10u 0 value
+ *
+ d curl_from_ccsid...
+ d pr * extproc('curl_from_ccsid') const char *
+ d s * value options(*string) const char *
+ d ccsid 10u 0 value
+ *
+ d curl_to_ccsid...
+ d pr * extproc('curl_to_ccsid') const char *
+ d s * value options(*string) const char *
+ d ccsid 10u 0 value
+ *
+ **************************************************************************
+ * Procedure overloading
+ **************************************************************************
+ *
+ /if defined(*V7R4M0)
+ d curl_easy_setopt_RPGnum_...
+ d pr extproc('curl_easy_setopt_RPGnum_')
+ d like(CURLcode)
+ d curl * value CURL *
+ d option value like(CURLoption)
+ d numarg 20i 0 value
+ *
+ d curl_easy_setopt...
+ d pr like(CURLcode)
+ d overload(curl_easy_setopt_RPGnum_:
+ d curl_easy_setopt_object:
+ d curl_easy_setopt_function)
+ *
+ d curl_multi_setopt_RPGnum_...
+ d pr extproc('curl_multi_setopt_RPGnum_')
+ d like(CURLcode)
+ d curl * value CURLM *
+ d option value like(CURLMoption)
+ d numarg 20i 0 value
+ *
+ d curl_multi_setopt...
+ d pr like(CURLcode)
+ d overload(curl_multi_setopt_RPGnum_:
+ d curl_multi_setopt_object:
+ d curl_multi_setopt_function)
+ *
+ d curl_share_setopt...
+ d pr like(CURLcode)
+ d overload(curl_share_setopt_int:
+ d curl_share_setopt_ptr:
+ d curl_share_setopt_proc)
+ *
+ d curl_easy_getinfo...
+ d pr like(CURLcode)
+ d overload(curl_easy_getinfo_long:
+ d curl_easy_getinfo_off_t:
+ d curl_easy_getinfo_double:
+ d curl_easy_getinfo_ptr)
+ /endif
+ *
/endif
diff --git a/packages/OS400/initscript.sh b/packages/OS400/initscript.sh
old mode 100644
new mode 100755
index f1d13f4..d275146
--- a/packages/OS400/initscript.sh
+++ b/packages/OS400/initscript.sh
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,9 +23,9 @@
#
###########################################################################
-system ()
+CLcommand()
{
- /usr/bin/system "$@" || exit 1
+ /usr/bin/system "${@}" || exit 1
}
setenv()
@@ -58,8 +58,8 @@
# Extract the SONAME from the library makefile.
-SONAME=`sed -e '/^VERSIONINFO=/!d' -e 's/^.* \([0-9]*\):.*$/\1/' -e 'q' \
- < "${TOPDIR}/lib/Makefile.am"`
+SONAME=`sed -e '/^VERSIONCHANGE=/!d;s/^.*=\([0-9]*\).*/\1/' \
+ < "${TOPDIR}/lib/Makefile.soname"`
export SONAME
@@ -79,6 +79,8 @@
setenv OUTPUT '*NONE' # Compilation output option.
setenv TGTRLS '*CURRENT' # Target OS release.
setenv IFSDIR '/curl' # Installation IFS directory.
+setenv QADRTDIR '/QIBM/ProdData/qadrt' # QADRT IFS directory.
+setenv QADRTLIB 'QADRT' # QADRT object library.
# Define ZLIB availability and locations.
@@ -206,7 +208,7 @@
# putting it in an include file makes it only active
# for that include file.
# Thus we build a temporary file with the pragma prepended to
- # the source file and we compile that themporary file.
+ # the source file and we compile that temporary file.
echo "#line 1 \"${2}\"" > __tmpsrcf.c
echo "#pragma convert(819)" >> __tmpsrcf.c
@@ -216,7 +218,7 @@
# CMD="${CMD} SYSIFCOPT(*IFS64IO) OPTION(*INCDIRFIRST *SHOWINC *SHOWSYS)"
CMD="${CMD} SYSIFCOPT(*IFS64IO) OPTION(*INCDIRFIRST)"
CMD="${CMD} LOCALETYPE(*LOCALE) FLAG(10)"
- CMD="${CMD} INCDIR('/qibm/proddata/qadrt/include'"
+ CMD="${CMD} INCDIR('${QADRTDIR}/include'"
CMD="${CMD} '${TOPDIR}/include/curl' '${TOPDIR}/include' '${SRCDIR}'"
CMD="${CMD} '${TOPDIR}/packages/OS400'"
@@ -234,21 +236,21 @@
CMD="${CMD} OPTIMIZE(${OPTIMIZE})"
CMD="${CMD} DBGVIEW(${DEBUG})"
- DEFINES="${3} BUILDING_LIBCURL"
+ DEFINES="${3} BUILDING_LIBCURL 'qadrt_use_inline'"
if [ "${WITH_ZLIB}" != "0" ]
- then DEFINES="${DEFINES} HAVE_LIBZ HAVE_ZLIB_H"
+ then DEFINES="${DEFINES} HAVE_LIBZ"
fi
if [ "${WITH_LIBSSH2}" != "0" ]
- then DEFINES="${DEFINES} USE_LIBSSH2 HAVE_LIBSSH2_H"
+ then DEFINES="${DEFINES} USE_LIBSSH2"
fi
if [ "${DEFINES}" ]
then CMD="${CMD} DEFINE(${DEFINES})"
fi
- system "${CMD}"
+ CLcommand "${CMD}"
rm -f __tmpsrcf.c
LINK=YES
}
diff --git a/packages/OS400/make-include.sh b/packages/OS400/make-include.sh
old mode 100644
new mode 100755
index daf3262..30235eb
--- a/packages/OS400/make-include.sh
+++ b/packages/OS400/make-include.sh
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -38,7 +38,7 @@
if action_needed "${SRCPF}"
then CMD="CRTSRCPF FILE(${TARGETLIB}/H) RCDLEN(112)"
CMD="${CMD} CCSID(${TGTCCSID}) TEXT('curl: Header files')"
- system "${CMD}"
+ CLcommand "${CMD}"
fi
@@ -98,9 +98,9 @@
if action_needed "${LIBIFSNAME}/CURL.FILE"
then :
-else system "DLTF FILE(${TARGETLIB}/CURL)"
+else CLcommand "DLTF FILE(${TARGETLIB}/CURL)"
fi
CMD="CRTDUPOBJ OBJ(H) FROMLIB(${TARGETLIB}) OBJTYPE(*FILE) TOLIB(*FROMLIB)"
CMD="${CMD} NEWOBJ(CURL) DATA(*YES)"
-system "${CMD}"
+CLcommand "${CMD}"
diff --git a/packages/OS400/make-lib.sh b/packages/OS400/make-lib.sh
old mode 100644
new mode 100755
index 7bbd9fa..66e45fb
--- a/packages/OS400/make-lib.sh
+++ b/packages/OS400/make-lib.sh
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -43,7 +43,7 @@
echo '#pragma comment(user, "libcurl version '"${LIBCURL_VERSION}"'")' > os400.c
echo '#pragma comment(user, __DATE__)' >> os400.c
echo '#pragma comment(user, __TIME__)' >> os400.c
-echo '#pragma comment(copyright, "Copyright (C) 1998-2016 Daniel Stenberg et al. OS/400 version by P. Monnerat")' >> os400.c
+echo '#pragma comment(copyright, "Copyright (C) Daniel Stenberg et al. OS/400 version by P. Monnerat")' >> os400.c
make_module OS400 os400.c
LINK= # No need to rebuild service program yet.
MODULES=
@@ -70,23 +70,21 @@
INCLUDES="'`pwd`'"
# Create a small C program to check ccsidcurl.c is up to date
-if action_needed "${LIBIFSNAME}/CHKSTRINGS.PGM"
-then
- CMD="CRTBNDC PGM(${TARGETLIB}/CHKSTRINGS) SRCSTMF('${SCRIPTDIR}/chkstrings.c')"
- CMD="${CMD} INCDIR('${TOPDIR}/include/curl' '${TOPDIR}/include' '${SRCDIR}' ${INCLUDES})"
- system -i "${CMD}"
- if [ $? -ne 0 ]
- then
- echo "ERROR: Failed to build CHKSTRINGS *PGM object!"
- exit 2
- else
- ${LIBIFSNAME}/CHKSTRINGS.PGM
- if [ $? -ne 0 ]
- then
- echo "ERROR: CHKSTRINGS failed!"
- exit 2
- fi
- fi
+if action_needed "${LIBIFSNAME}/CHKSTRINGS.PGM" "${SCRIPTDIR}/chkstrings.c"
+then CMD="CRTBNDC PGM(${TARGETLIB}/CHKSTRINGS)"
+ CMD="${CMD} SRCSTMF('${SCRIPTDIR}/chkstrings.c')"
+ CMD="${CMD} INCDIR('${TOPDIR}/include/curl' '${TOPDIR}/include'"
+ CMD="${CMD} '${SRCDIR}' ${INCLUDES})"
+ CMD="${CMD} TGTCCSID(${TGTCCSID})"
+ if CLcommand -i "${CMD}"
+ then if "${LIBIFSNAME}/CHKSTRINGS.PGM"
+ then :
+ else echo "ERROR: CHKSTRINGS failed!"
+ exit 2
+ fi
+ else echo "ERROR: Failed to build CHKSTRINGS *PGM object!"
+ exit 2
+ fi
fi
make_module OS400SYS "${SCRIPTDIR}/os400sys.c"
@@ -108,12 +106,12 @@
then rm -rf "${LIBIFSNAME}/${STATBNDDIR}.BNDDIR"
CMD="CRTBNDDIR BNDDIR(${TARGETLIB}/${STATBNDDIR})"
CMD="${CMD} TEXT('LibCurl API static binding directory')"
- system "${CMD}"
+ CLcommand "${CMD}"
for MODULE in ${MODULES}
do CMD="ADDBNDDIRE BNDDIR(${TARGETLIB}/${STATBNDDIR})"
CMD="${CMD} OBJ((${TARGETLIB}/${MODULE} *MODULE))"
- system "${CMD}"
+ CLcommand "${CMD}"
done
fi
@@ -124,20 +122,31 @@
if action_needed "${LIBIFSNAME}/TOOLS.FILE"
then CMD="CRTSRCPF FILE(${TARGETLIB}/TOOLS) RCDLEN(112)"
CMD="${CMD} TEXT('curl: build tools')"
- system "${CMD}"
+ CLcommand "${CMD}"
fi
# Gather the list of symbols to export.
+# First use awk to pull all CURL_EXTERN function prototypes from
+# the header files, pass through to sed to strip CURL_DEPRECATED(..)
+# then back to awk to pull the string immediately to the left of a
+# bracket stripping any spaces or *'s.
-EXPORTS=`grep '^CURL_EXTERN[[:space:]]' \
+EXPORTS=`awk '/^CURL_EXTERN/,/;/' \
"${TOPDIR}"/include/curl/*.h \
"${SCRIPTDIR}/ccsidcurl.h" |
- sed -e 's/^.*CURL_EXTERN[[:space:]]\(.*\)(.*$/\1/' \
- -e 's/[[:space:]]*$//' \
- -e 's/^.*[[:space:]][[:space:]]*//' \
- -e 's/^\*//' \
- -e 's/(\(.*\))/\1/'`
+ sed 's| CURL_DEPRECATED(.*)||g' |
+ awk '{br=index($0,"("); \
+ if (br) { \
+ for(c=br-1; ;c--) { \
+ if (c==1) { \
+ print substr($0,c,br-1); break \
+ } else if (match(substr($0, c, br-c), "[ *]") != 0) { \
+ print substr($0, c+1, br-c-1); break \
+ } \
+ } \
+ } \
+ }'`
# Create the service program exportation file in DB2 member if needed.
@@ -181,7 +190,7 @@
CMD="${CMD} BNDSRVPGM(QADRTTS QGLDCLNT QGLDBRDR)"
CMD="${CMD} TEXT('curl API library')"
CMD="${CMD} TGTRLS(${TGTRLS})"
- system "${CMD}"
+ CLcommand "${CMD}"
LINK=YES
fi
@@ -196,52 +205,8 @@
then rm -rf "${LIBIFSNAME}/${DYNBNDDIR}.BNDDIR"
CMD="CRTBNDDIR BNDDIR(${TARGETLIB}/${DYNBNDDIR})"
CMD="${CMD} TEXT('LibCurl API dynamic binding directory')"
- system "${CMD}"
+ CLcommand "${CMD}"
CMD="ADDBNDDIRE BNDDIR(${TARGETLIB}/${DYNBNDDIR})"
CMD="${CMD} OBJ((*LIBL/${SRVPGM} *SRVPGM))"
- system "${CMD}"
-fi
-
-
-# Rebuild the formdata test if needed.
-
-if [ "${TEST_FORMDATA}" ]
-then MODULES=
- make_module TFORMDATA formdata.c "'_FORM_DEBUG' 'CURLDEBUG'"
- make_module TSTREQUAL strequal.c "'_FORM_DEBUG' 'CURLDEBUG'"
- make_module TMEMDEBUG memdebug.c "'_FORM_DEBUG' 'CURLDEBUG'"
- make_module TMPRINTF mprintf.c "'_FORM_DEBUG' 'CURLDEBUG'"
- make_module TSTRERROR strerror.c "'_FORM_DEBUG' 'CURLDEBUG'"
- # The following modules should not be needed (see comment in
- # formdata.c. However, there are some unsatisfied
- # external references leading in the following
- # modules to be (recursively) needed.
- MODULES="${MODULES} EASY STRDUP SSLGEN GSKIT HOSTIP HOSTIP4 HOSTIP6"
- MODULES="${MODULES} URL HASH TRANSFER GETINFO COOKIE SENDF SELECT"
- MODULES="${MODULES} INET_NTOP SHARE HOSTTHRE MULTI LLIST FTP HTTP"
- MODULES="${MODULES} HTTP_DIGES HTTP_CHUNK HTTP_NEGOT TIMEVAL HOSTSYN"
- MODULES="${MODULES} CONNECT SOCKS PROGRESS ESCAPE INET_PTON GETENV"
- MODULES="${MODULES} DICT LDAP TELNET FILE TFTP NETRC PARSEDATE"
- MODULES="${MODULES} SPEEDCHECK SPLAY BASE64 SECURITY IF2IP MD5"
- MODULES="${MODULES} KRB5 OS400SYS"
-
- PGMIFSNAME="${LIBIFSNAME}/TFORMDATA.PGM"
-
- if action_needed "${PGMIFSNAME}"
- then LINK=YES
- fi
-
- if [ "${LINK}" ]
- then CMD="CRTPGM PGM(${TARGETLIB}/TFORMDATA)"
- CMD="${CMD} ENTMOD(QADRT/QADRTMAIN2)"
- CMD="${CMD} MODULE("
-
- for MODULE in ${MODULES}
- do CMD="${CMD} ${TARGETLIB}/${MODULE}"
- done
-
- CMD="${CMD} ) BNDSRVPGM(QADRTTS)"
- CMD="${CMD} TGTRLS(${TGTRLS})"
- system "${CMD}"
- fi
+ CLcommand "${CMD}"
fi
diff --git a/packages/OS400/make-src.sh b/packages/OS400/make-src.sh
old mode 100644
new mode 100755
index 327857d..62654c3
--- a/packages/OS400/make-src.sh
+++ b/packages/OS400/make-src.sh
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/packages/OS400/make-tests.sh b/packages/OS400/make-tests.sh
old mode 100644
new mode 100755
index 9ac9d46..a5a472c
--- a/packages/OS400/make-tests.sh
+++ b/packages/OS400/make-tests.sh
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -128,10 +128,10 @@
MODULES="`echo \"${MODULES}\" |
sed \"s/[^ ][^ ]*/${TARGETLIB}\/&/g\"`"
CMD="CRTPGM PGM(${TARGETLIB}/${DB2PGM})"
- CMD="${CMD} ENTMOD(QADRT/QADRTMAIN2)"
+ CMD="${CMD} ENTMOD(${QADRTLIB}/QADRTMAIN2)"
CMD="${CMD} MODULE(${MODULES})"
CMD="${CMD} BNDSRVPGM(${TARGETLIB}/${SRVPGM} QADRTTS)"
CMD="${CMD} TGTRLS(${TGTRLS})"
- system "${CMD}"
+ CLcommand "${CMD}"
fi
done
diff --git a/packages/OS400/makefile.sh b/packages/OS400/makefile.sh
old mode 100644
new mode 100755
index b2c1b59..70399cb
--- a/packages/OS400/makefile.sh
+++ b/packages/OS400/makefile.sh
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@
if action_needed "${LIBIFSNAME}"
then CMD="CRTLIB LIB(${TARGETLIB}) TEXT('curl: multiprotocol support API')"
- system "${CMD}"
+ CLcommand "${CMD}"
fi
@@ -46,7 +46,7 @@
if action_needed "${LIBIFSNAME}/DOCS.FILE"
then CMD="CRTSRCPF FILE(${TARGETLIB}/DOCS) RCDLEN(240)"
CMD="${CMD} CCSID(${TGTCCSID}) TEXT('Documentation texts')"
- system "${CMD}"
+ CLcommand "${CMD}"
fi
@@ -66,7 +66,37 @@
if action_needed "${MEMBER}" "${TEXT}"
then CMD="CPY OBJ('${TEXT}') TOOBJ('${MEMBER}') TOCCSID(${TGTCCSID})"
CMD="${CMD} DTAFMT(*TEXT) REPLACE(*YES)"
- system "${CMD}"
+ CLcommand "${CMD}"
+ fi
+done
+
+
+# Create the RPGXAMPLES source file if it does not exist.
+
+if action_needed "${LIBIFSNAME}/RPGXAMPLES.FILE"
+then CMD="CRTSRCPF FILE(${TARGETLIB}/RPGXAMPLES) RCDLEN(240)"
+ CMD="${CMD} CCSID(${TGTCCSID}) TEXT('ILE/RPG examples')"
+ CLcommand "${CMD}"
+fi
+
+
+# Copy RPG examples if needed.
+
+for EXAMPLE in "${SCRIPTDIR}/rpg-examples"/*
+do MEMBER="`basename \"${EXAMPLE}\"`"
+ IFSMEMBER="${LIBIFSNAME}/RPGXAMPLES.FILE/`db2_name \"${MEMBER}\"`.MBR"
+
+ [ -e "${EXAMPLE}" ] || continue
+
+ if action_needed "${IFSMEMBER}" "${EXAMPLE}"
+ then CMD="CPY OBJ('${EXAMPLE}') TOOBJ('${IFSMEMBER}')"
+ CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)"
+ CLcommand "${CMD}"
+ MBRTEXT=`sed -e '1!d;/^ \*/!d;s/^ *\* *//' \
+ -e 's/ *$//;s/'"'"'/&&/g' < "${EXAMPLE}"`
+ CMD="CHGPFM FILE(${TARGETLIB}/RPGXAMPLES) MBR(${MEMBER})"
+ CMD="${CMD} SRCTYPE(RPGLE) TEXT('${MBRTEXT}')"
+ CLcommand "${CMD}"
fi
done
diff --git a/packages/OS400/os400sys.c b/packages/OS400/os400sys.c
index 754d609..c37cdb4 100644
--- a/packages/OS400/os400sys.c
+++ b/packages/OS400/os400sys.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,7 +40,7 @@
#include <qadrt.h>
#include <errno.h>
-#ifdef HAVE_ZLIB_H
+#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
@@ -255,9 +255,9 @@
int
-Curl_getnameinfo_a(const struct sockaddr *sa, curl_socklen_t salen,
- char *nodename, curl_socklen_t nodenamelen,
- char *servname, curl_socklen_t servnamelen,
+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;
@@ -745,7 +745,7 @@
Curl_gss_import_name_a(OM_uint32 *minor_status, gss_buffer_t in_name,
gss_OID in_name_type, gss_name_t *out_name)
{
- int rc;
+ OM_uint32 rc;
unsigned int i;
gss_buffer_desc in;
@@ -859,7 +859,7 @@
gss_ctx_id_t *context_handle,
gss_buffer_t output_token)
{
- int rc;
+ OM_uint32 rc;
rc = gss_delete_sec_context(minor_status, context_handle, output_token);
@@ -886,7 +886,7 @@
void *
Curl_ldap_init_a(char *host, int port)
{
- unsigned int i;
+ size_t i;
char *ehost;
void *result;
@@ -1265,7 +1265,7 @@
int
Curl_os400_sendto(int sd, char *buffer, int buflen, int flags,
- struct sockaddr *dstaddr, int addrlen)
+ const struct sockaddr *dstaddr, int addrlen)
{
int i;
struct sockaddr_storage laddr;
diff --git a/packages/OS400/os400sys.h b/packages/OS400/os400sys.h
index f107238..d5ff412 100644
--- a/packages/OS400/os400sys.h
+++ b/packages/OS400/os400sys.h
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -32,7 +32,6 @@
/* Per-thread item identifiers. */
typedef enum {
- LK_SSL_ERROR,
LK_GSK_ERROR,
LK_LDAP_ERROR,
LK_CURL_VERSION,
@@ -41,6 +40,7 @@
LK_EASY_STRERROR,
LK_SHARE_STRERROR,
LK_MULTI_STRERROR,
+ LK_URL_STRERROR,
LK_ZLIB_VERSION,
LK_ZLIB_MSG,
LK_LAST
diff --git a/packages/OS400/rpg-examples/HEADERAPI b/packages/OS400/rpg-examples/HEADERAPI
new file mode 100644
index 0000000..2c2407e
--- /dev/null
+++ b/packages/OS400/rpg-examples/HEADERAPI
@@ -0,0 +1,146 @@
+ * Curl header API: extract headers post transfer
+ *
+ h DFTACTGRP(*NO) ACTGRP(*NEW)
+ h OPTION(*NOSHOWCPY)
+ h BNDDIR('CURL')
+ *
+ **************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 H,CURL.INC
+ *
+ * Extract headers post transfer with the header API.
+ *
+ d pi
+ d url 120
+ *
+ d urllen s 10u 0 URL length
+ *
+ **************************************************************************
+
+ urllen = trimmed_length(url: %len(url));
+
+ // Do the curl stuff.
+
+ curl_global_init(CURL_GLOBAL_ALL);
+ main();
+ curl_global_cleanup();
+ *inlr = *on; // Exit
+ *
+ **************************************************************************
+ * Main procedure: do the curl job.
+ **************************************************************************
+ *
+ p main b
+ d main pi
+ *
+ d h s * Easy handle
+ d result s like(CURLcode) Curl return code
+ d inz(CURLE_OUT_OF_MEMORY)
+ d header ds likeds(curl_header) based(hp)
+ d strp1 s * Work string pointer
+ d strp2 s * Work string pointer
+ d inout s 52 For error display
+
+ // Create and fill curl handle.
+
+ h = curl_easy_init();
+ if h <> *NULL;
+ curl_easy_setopt_ccsid(h: CURLOPT_URL: %subst(url: 1: urllen): 0);
+ curl_easy_setopt(h: CURLOPT_FOLLOWLOCATION: 1);
+ curl_easy_setopt(h: CURLOPT_WRITEFUNCTION: %paddr(in_data_cb)); // Ignore input data
+
+ // Perform the request.
+
+ result = curl_easy_perform(h);
+ endif;
+
+ // Check for error and report if some.
+
+ if result <> CURLE_OK;
+ inout = %str(curl_easy_strerror_ccsid(result: 0));
+ dsply '' '*EXT' inout;
+ else;
+ if curl_easy_header_ccsid(h: 'Content-Type': 0: CURLH_HEADER: -1:
+ hp: 0) = CURLHE_OK;
+ strp2 = curl_to_ccsid(header.value: 0);
+ inout = 'Content-Type: ' + %str(strp2);
+ dsply inout;
+ curl_free(strp2);
+ endif;
+ dsply ' All server headers:';
+ hp = *NULL;
+ dow *on;
+ hp = curl_easy_nextheader(h: CURLH_HEADER: -1: hp);
+ if hp = *NULL;
+ leave;
+ endif;
+ strp1 = curl_to_ccsid(header.name: 0);
+ strp2 = curl_to_ccsid(header.value: 0);
+ inout = %str(strp1) + ': ' + %str(strp2) +
+ ' (' + %char(header.amount) + ')';
+ curl_free(strp2);
+ curl_free(strp1);
+ dsply inout;
+ enddo;
+ inout = 'Done';
+ dsply '' '*EXT' inout;
+ curl_easy_cleanup(h); // Release handle
+ endif;
+ p main e
+ *
+ **************************************************************************
+ * Dummy data input callback procedure.
+ **************************************************************************
+ *
+ p in_data_cb b
+ d in_data_cb pi 10u 0
+ d ptr * value Input data pointer
+ d size 10u 0 value Data element size
+ d nmemb 10u 0 value Data element count
+ d userdata * value User data pointer
+ *
+ return size * nmemb;
+ p in_data_cb e
+ *
+ **************************************************************************
+ * Get the length of right-trimmed string
+ **************************************************************************
+ *
+ p trimmed_length b
+ d trimmed_length pi 10u 0
+ d string 999999 const options(*varsize)
+ d length 10u 0 value
+ *
+ d len s 10u 0
+ *
+ len = %scan(X'00': string: 1: length); // Limit to zero-terminated string
+ if len = 0;
+ len = length + 1;
+ endif;
+ if len <= 1;
+ return 0;
+ endif;
+ return %checkr(' ': string: len - 1); // Trim right
+ p trimmed_length e
diff --git a/packages/OS400/rpg-examples/HTTPPOST b/packages/OS400/rpg-examples/HTTPPOST
new file mode 100644
index 0000000..21202eb
--- /dev/null
+++ b/packages/OS400/rpg-examples/HTTPPOST
@@ -0,0 +1,129 @@
+ * Curl MIME post data and display response
+ *
+ h DFTACTGRP(*NO) ACTGRP(*NEW)
+ h OPTION(*NOSHOWCPY)
+ h BNDDIR('CURL')
+ *
+ **************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 H,CURL.INC
+ *
+ * Example to HTTP POST data using the MIME API. Displays the response.
+ *
+ d pi
+ d userinput 120 User data to post
+ *
+ d url c 'http://httpbin.org/anything'
+ *
+ *
+ d inputlen s 10u 0 User input length
+ **************************************************************************
+
+ inputlen = trimmed_length(userinput: %len(userinput));
+
+ // Do the curl stuff.
+
+ curl_global_init(CURL_GLOBAL_ALL);
+ main();
+ curl_global_cleanup();
+ *inlr = *on; // Exit
+ *
+ **************************************************************************
+ * Main procedure: do the curl job.
+ **************************************************************************
+ *
+ p main b
+ d main pi
+ *
+ d h s * Easy handle
+ d result s like(CURLcode) Curl return code
+ d inz(CURLE_OUT_OF_MEMORY)
+ d errmsgp s * Error string pointer
+ d response s 52 For error display
+ d mime s * MIME handle
+ d mimepart s * MIME part handle
+ d parthdrs s * inz(*NULL) Part headers
+
+ // Create and fill curl handle.
+
+ h = curl_easy_init();
+ if h <> *NULL;
+ curl_easy_setopt_ccsid(h: CURLOPT_URL: url: 0);
+ curl_easy_setopt(h: CURLOPT_FOLLOWLOCATION: 1);
+ mime = curl_mime_init(h);
+ mimepart = curl_mime_addpart(mime);
+ curl_mime_name_ccsid(mimepart: 'autofield': 0);
+ curl_mime_data_ccsid(mimepart: 'program-generated value':
+ CURL_ZERO_TERMINATED: 0);
+ mimepart = curl_mime_addpart(mime);
+ curl_mime_name_ccsid(mimepart: 'userfield': 0);
+ curl_mime_data_ccsid(mimepart: %subst(userinput: 1: inputlen):
+ CURL_ZERO_TERMINATED: 0);
+ mimepart = curl_mime_addpart(mime);
+ curl_mime_name_ccsid(mimepart: 'ebcdicfield': 0);
+ curl_mime_data(mimepart: %subst(userinput: 1: inputlen): inputlen);
+ curl_mime_encoder_ccsid(mimepart: 'base64': 0);
+ // Avoid server to convert base64 to text.
+ parthdrs = curl_slist_append_ccsid(parthdrs:
+ 'Content-Transfer-Encoding: bit': 0);
+ curl_mime_headers(mimepart: parthdrs: 1);
+ curl_easy_setopt(h: CURLOPT_MIMEPOST: mime);
+
+ // Perform the request.
+
+ result = curl_easy_perform(h);
+ curl_mime_free(mime);
+ curl_easy_cleanup(h); // Release handle
+ endif;
+
+ // Check for error and report if some.
+
+ if result <> CURLE_OK;
+ errmsgp = curl_easy_strerror_ccsid(result: 0);
+ response = %str(errmsgp);
+ dsply '' '*EXT' response;
+ endif;
+ p main e
+ *
+ **************************************************************************
+ * Get the length of right-trimmed string
+ **************************************************************************
+ *
+ p trimmed_length b
+ d trimmed_length pi 10u 0
+ d string 999999 const options(*varsize)
+ d length 10u 0 value
+ *
+ d len s 10u 0
+ *
+ len = %scan(X'00': string: 1: length); // Limit to zero-terminated string
+ if len = 0;
+ len = length + 1;
+ endif;
+ if len <= 1;
+ return 0;
+ endif;
+ return %checkr(' ': string: len - 1); // Trim right
+ p trimmed_length e
diff --git a/packages/OS400/rpg-examples/INMEMORY b/packages/OS400/rpg-examples/INMEMORY
new file mode 100644
index 0000000..e6f43ab
--- /dev/null
+++ b/packages/OS400/rpg-examples/INMEMORY
@@ -0,0 +1,159 @@
+ * Curl get in memory and count HTML tags
+ *
+ h DFTACTGRP(*NO) ACTGRP(*NEW)
+ h OPTION(*NOSHOWCPY)
+ h BNDDIR('CURL')
+ *
+ **************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 H,CURL.INC
+ *
+ * Example to request the URL given as command line parameter and count
+ * HTML tags in its response.
+ *
+ d pi
+ d url 120
+ *
+ d countdata ds qualified based(###dummyptr) User data type
+ d tagcount 10u 0 Tag counter
+ d tagopen n Possible opening tag
+ *
+ d urllen s 10u 0 URL length
+ *
+ **************************************************************************
+
+ urllen = trimmed_length(url: %len(url));
+
+ // Do the curl stuff.
+
+ curl_global_init(CURL_GLOBAL_ALL);
+ main();
+ curl_global_cleanup();
+ *inlr = *on; // Exit
+ *
+ **************************************************************************
+ * Main procedure: do the curl job.
+ **************************************************************************
+ *
+ p main b
+ d main pi
+ *
+ d h s * Easy handle
+ d result s like(CURLcode) Curl return code
+ d inz(CURLE_OUT_OF_MEMORY)
+ d errmsgp s * Error string pointer
+ d response s 52 For error display
+ d counter ds likeds(countdata) HTML tag counter
+
+ counter.tagcount = 0;
+ counter.tagopen = *off;
+
+ // Create and fill curl handle.
+
+ h = curl_easy_init();
+ if h <> *NULL;
+ curl_easy_setopt_ccsid(h: CURLOPT_URL: %subst(url: 1: urllen): 0);
+ curl_easy_setopt(h: CURLOPT_FOLLOWLOCATION: 1);
+ curl_easy_setopt(h: CURLOPT_WRITEFUNCTION: %paddr(in_data_cb));
+ curl_easy_setopt(h: CURLOPT_WRITEDATA: %addr(counter));
+
+ // Perform the request.
+
+ result = curl_easy_perform(h);
+ curl_easy_cleanup(h); // Release handle
+ endif;
+
+ // Check for error and report if some.
+
+ if result <> CURLE_OK;
+ errmsgp = curl_easy_strerror_ccsid(result: 0);
+ response = %str(errmsgp);
+ dsply '' '*EXT' response;
+ else;
+ // Display the tag count.
+
+ response = 'Tag count: ' + %char(counter.tagcount);
+ dsply '' '*EXT' response;
+ endif;
+ p main e
+ *
+ **************************************************************************
+ * Data input callback procedure.
+ **************************************************************************
+ *
+ p in_data_cb b
+ d in_data_cb pi 10u 0
+ d ptr * value Input data pointer
+ d size 10u 0 value Data element size
+ d nmemb 10u 0 value Data element count
+ d userdata * value User data pointer
+ *
+ d counter ds likeds(countdata) based(userdata) HTML tag counter
+ d ebcdata s * EBCDIC data pointer
+ d chars s 1 based(ebcdata) dim(1000000)
+ d i s 10u 0 Character position
+ *
+ size = size * nmemb; // The size in bytes.
+ ebcdata = curl_to_ccsid(%str(ptr: size): 0); // Convert to EBCDIC.
+ i = 1;
+ dow i <= size;
+ if counter.tagopen; // Did we see '<' ?
+ counter.tagopen = *off;
+ if chars(i) <> '/'; // Reject closing tag.
+ counter.tagcount = counter.tagcount + 1; // Count this tag.
+ endif;
+ else;
+ i = %scan('<': %str(ebcdata): i); // Search next possible tag.
+ if i = 0;
+ leave;
+ endif;
+ counter.tagopen = *on; // Found one: flag it.
+ endif;
+ i = i + 1;
+ enddo;
+ curl_free(ebcdata);
+ return size;
+ p in_data_cb e
+ *
+ **************************************************************************
+ * Get the length of right-trimmed string
+ **************************************************************************
+ *
+ p trimmed_length b
+ d trimmed_length pi 10u 0
+ d string 999999 const options(*varsize)
+ d length 10u 0 value
+ *
+ d len s 10u 0
+ *
+ len = %scan(X'00': string: 1: length); // Limit to zero-terminated string
+ if len = 0;
+ len = length + 1;
+ endif;
+ if len <= 1;
+ return 0;
+ endif;
+ return %checkr(' ': string: len - 1); // Trim right
+ p trimmed_length e
diff --git a/packages/OS400/rpg-examples/SIMPLE1 b/packages/OS400/rpg-examples/SIMPLE1
new file mode 100644
index 0000000..52c0c93
--- /dev/null
+++ b/packages/OS400/rpg-examples/SIMPLE1
@@ -0,0 +1,108 @@
+ * Curl simple URL request
+ *
+ h DFTACTGRP(*NO) ACTGRP(*NEW)
+ h OPTION(*NOSHOWCPY)
+ h BNDDIR('CURL')
+ *
+ **************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 H,CURL.INC
+ *
+ * Simple example to request the URL given as command line parameter and
+ * output its response.
+ *
+ d pi
+ d url 120
+ *
+ d urllen s 10u 0 URL length
+ *
+ **************************************************************************
+ *
+ c eval urllen = trimmed_length(url: %len(url))
+ *
+ * Do the curl stuff.
+ *
+ c callp curl_global_init(CURL_GLOBAL_ALL)
+ c callp main
+ c callp curl_global_cleanup()
+ c seton lr Exit
+ *
+ **************************************************************************
+ * Main procedure: do the curl job.
+ **************************************************************************
+ *
+ p main b
+ d main pi
+ *
+ d h s * Easy handle
+ d result s like(CURLcode) Curl return code
+ d inz(CURLE_OUT_OF_MEMORY)
+ d errmsgp s * Error string pointer
+ d response s 52 For error display
+ *
+ * Create and fill curl handle.
+ *
+ c eval h = curl_easy_init()
+ c if h <> *NULL
+ c callp curl_easy_setopt_ccsid(h: CURLOPT_URL:
+ c %subst(url: 1: urllen): 0)
+ c callp curl_easy_setopt_long(h:
+ c CURLOPT_FOLLOWLOCATION: 1)
+ *
+ * Perform the request.
+ *
+ c eval result = curl_easy_perform(h)
+ c callp curl_easy_cleanup(h) Release handle
+ c endif
+ *
+ * Check for error and report if some.
+ *
+ c if result <> CURLE_OK
+ c eval errmsgp = curl_easy_strerror_ccsid(result: 0)
+ c eval response = %str(errmsgp)
+ c dsply response
+ c endif
+ p main e
+ *
+ **************************************************************************
+ * Get the length of right-trimmed string
+ **************************************************************************
+ *
+ p trimmed_length b
+ d trimmed_length pi 10u 0
+ d string 999999 const options(*varsize)
+ d length 10u 0 value
+ *
+ d len s 10u 0
+ *
+ c eval len = %scan(X'00': string: 1: length) Limit 0-terminated
+ c if len = 0
+ c eval len = length + 1
+ c endif
+ c if len <= 1
+ c return 0
+ c endif
+ c return %checkr(' ': string: len - 1) Trim right
+ p trimmed_length e
diff --git a/packages/OS400/rpg-examples/SIMPLE2 b/packages/OS400/rpg-examples/SIMPLE2
new file mode 100644
index 0000000..493c91e
--- /dev/null
+++ b/packages/OS400/rpg-examples/SIMPLE2
@@ -0,0 +1,108 @@
+ * Curl simple URL request (free-format RPG)
+ *
+ ctl-opt dftactgrp(*NO) actgrp(*NEW)
+ option(*NOSHOWCPY)
+ bnddir('CURL');
+ *
+ **************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 H,CURL.INC
+
+ * Simple free-format RPG program to request the URL given as command line
+ * parameter and output its response.
+
+ dcl-pi *N;
+ url char(120);
+ end-pi;
+
+ dcl-s urllen int(10); // URL length
+
+ **************************************************************************
+
+ urllen = trimmed_length(url: %len(url));
+
+ // Do the curl stuff.
+
+ curl_global_init(CURL_GLOBAL_ALL);
+ main();
+ curl_global_cleanup();
+ *inlr = *on; // Exit
+
+ **************************************************************************
+ * Main procedure: do the curl job.
+ **************************************************************************
+
+ dcl-proc main;
+ dcl-pi *N end-pi;
+
+ dcl-s h pointer; // Easy handle
+ dcl-s result like(CURLcode) inz(CURLE_OUT_OF_MEMORY); // Curl return code
+ dcl-s errmsgp pointer; // Error string pointer
+ dcl-s response char(52); // For error display
+
+ // Create and fill curl handle.
+
+ h = curl_easy_init();
+ if h <> *NULL;
+ curl_easy_setopt_ccsid(h: CURLOPT_URL: %subst(url: 1: urllen):
+ 0);
+ curl_easy_setopt(h: CURLOPT_FOLLOWLOCATION: 1);
+
+ // Perform the request.
+
+ result = curl_easy_perform(h);
+ curl_easy_cleanup(h); // Release handle
+ endif;
+
+ // Check for error and report if some.
+
+ if result <> CURLE_OK;
+ errmsgp = curl_easy_strerror_ccsid(result: 0);
+ response = %str(errmsgp);
+ dsply '' '*EXT' response;
+ endif;
+ end-proc;
+ *
+ **************************************************************************
+ * Get the length of right-trimmed string
+ **************************************************************************
+ *
+ dcl-proc trimmed_length;
+ dcl-pi *N uns(10);
+ string char(9999999) const options(*varsize);
+ length uns(10) value;
+ end-pi;
+
+ dcl-s len uns(10);
+
+ len = %scan(X'00': string: 1: length); // Limit to zero-terminated string
+ if len = 0;
+ len = length + 1;
+ endif;
+ if len <= 1;
+ return 0;
+ endif;
+ return %checkr(' ': string: len - 1); // Trim right
+ end-proc;
diff --git a/packages/OS400/rpg-examples/SMTPSRCMBR b/packages/OS400/rpg-examples/SMTPSRCMBR
new file mode 100644
index 0000000..88f4fd2
--- /dev/null
+++ b/packages/OS400/rpg-examples/SMTPSRCMBR
@@ -0,0 +1,239 @@
+ * Curl SMTP send source member as attachment
+ *
+ h DFTACTGRP(*NO) ACTGRP(*NEW)
+ h OPTION(*NOSHOWCPY)
+ h BNDDIR('CURL')
+ *
+ **************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 H,CURL.INC
+ *
+ * Example to SMTP send source member as attachment via SMTP.
+ *
+ fRPGXAMPLESif e disk extmbr(program_name)
+ f rename(RPGXAMPLES: record)
+ d pi
+ d url 60 SMTP server URL
+ d recipient_mail 40 Recipient mail addr
+ *
+ d program_name c 'SMTPSRCMBR' Member name to send
+ d sender_name c 'Curl' Sender name
+ d sender_mail c 'curl@example.com' Sender e-mail
+ d recipient_name c 'WIMC' Recipient name
+ d crlf c X'0D25'
+ *
+ d urllen s 10u 0 URL length
+ d rcptmlen s 10u 0 Recipient mail len
+ *
+ **************************************************************************
+
+ urllen = trimmed_length(url: %len(url));
+ rcptmlen = trimmed_length(recipient_mail: %len(recipient_mail));
+
+ // Do the curl stuff.
+
+ curl_global_init(CURL_GLOBAL_ALL);
+ main();
+ curl_global_cleanup();
+ *inlr = *on; // Exit
+ *
+ **************************************************************************
+ * Main procedure: do the curl job.
+ **************************************************************************
+ *
+ p main b
+ d main pi
+ *
+ d h s * Easy handle
+ d result s like(CURLcode) Curl return code
+ d inz(CURLE_OUT_OF_MEMORY)
+ d errmsgp s * Error string pointer
+ d response s 52 For error display
+ d headers s * inz(*NULL) Mail headers
+ d rcpts s * inz(*NULL) List of recipients
+ d mime s * Mail MIME structure
+ d mimepart s * Mail part
+
+ // Create and fill curl handle.
+
+ h = curl_easy_init();
+ if h <> *NULL;
+ rcpts = curl_slist_append_ccsid(rcpts:
+ %subst(recipient_mail: 1: rcptmlen): 0);
+ headers = curl_slist_append_ccsid(headers: 'From: ' + sender_name +
+ ' <' + sender_mail + '>':
+ 0);
+ headers = curl_slist_append_ccsid(headers: 'To: ' + recipient_name +
+ ' <' + %subst(recipient_mail: 1: rcptmlen) + '>': 0);
+ headers = curl_slist_append_ccsid(headers: 'Subject: An ILE/RPG ' +
+ 'source program': 0);
+ headers = curl_slist_append_ccsid(headers: 'Date: ' + mail_date():
+ 0);
+ curl_easy_setopt_ccsid(h: CURLOPT_URL: %subst(url: 1: urllen): 0);
+ curl_easy_setopt_ccsid(h: CURLOPT_MAIL_FROM: sender_mail: 0);
+ curl_easy_setopt(h: CURLOPT_MAIL_RCPT: rcpts);
+ curl_easy_setopt(h: CURLOPT_HTTPHEADER: headers);
+ mime = curl_mime_init(h);
+ mimepart = curl_mime_addpart(mime);
+ curl_mime_data_ccsid(mimepart: 'Please find the ILE/RPG program ' +
+ program_name + ' source code in ' +
+ 'attachment.' + crlf:
+ CURL_ZERO_TERMINATED: 0);
+ mimepart = curl_mime_addpart(mime);
+ curl_mime_data_cb(mimepart: -1: %paddr(out_data_cb): *NULL: *NULL:
+ *NULL);
+ curl_mime_filename_ccsid(mimepart: program_name: 0);
+ curl_mime_encoder_ccsid(mimepart: 'quoted-printable': 0);
+ curl_easy_setopt(h: CURLOPT_MIMEPOST: mime);
+
+ // Perform the request.
+
+ setll *start RPGXAMPLES;
+ result = curl_easy_perform(h);
+
+ // Cleanup.
+
+ curl_mime_free(mime);
+ curl_slist_free_all(headers);
+ curl_slist_free_all(rcpts);
+ curl_easy_cleanup(h); // Release handle
+ endif;
+
+ // Check for error and report if some.
+
+ if result <> CURLE_OK;
+ errmsgp = curl_easy_strerror_ccsid(result: 0);
+ response = %str(errmsgp);
+ dsply '' '*EXT' response;
+ else;
+ response = 'Mail sent';
+ dsply '' '*EXT' response;
+ endif;
+ p main e
+ *
+ **************************************************************************
+ * Attachment data callback procedure.
+ **************************************************************************
+ *
+ p out_data_cb b
+ d out_data_cb pi 10u 0
+ d ptr * value Output data pointer
+ d size 10u 0 value Data element size
+ d nmemb 10u 0 value Data element count
+ d userdata * value User data pointer
+ *
+ d buffer s 9999999 based(ptr) Output buffer
+ d line s 9999999 based(lineptr) ASCII line pointer
+ d linelen s 10u 0
+ d i s 10u 0 Buffer position
+ *
+ size = size * nmemb; // The size in bytes.
+ i = 0;
+ dow size - i >= %len(SRCDTA) + %len(crlf) and not %eof(RPGXAMPLES);
+ read record;
+ lineptr = curl_from_ccsid(%trimr(SRCDTA) + crlf: 0);
+ linelen = %scan(X'00': line) - 1;
+ %subst(buffer: i + 1: linelen) = %str(lineptr);
+ curl_free(lineptr);
+ i = i + linelen;
+ enddo;
+ return i;
+ p out_data_cb e
+ *
+ **************************************************************************
+ * Mail-formatted date procedure.
+ **************************************************************************
+ *
+ p mail_date b
+ d mail_date pi 50 varying
+ *
+ d sysval ds qualified To retrieve timezone
+ d numsysval 10u 0
+ d offset 10u 0
+ d 100
+ *
+ d get_sysval pr extpgm('QWCRSVAL')
+ d outdata likeds(sysval)
+ d outsize 10u 0 const
+ d numsysval 10u 0 const
+ d name 10 const
+ d errcode 10000 options(*varsize)
+ *
+ d now ds qualified
+ d ts z
+ d year 4s 0 overlay(ts: 1)
+ d month 2s 0 overlay(ts: 6)
+ d day 2s 0 overlay(ts: 9)
+ d hour 2s 0 overlay(ts: 12)
+ d minute 2 overlay(ts: 15)
+ d second 2 overlay(ts: 18)
+ *
+ d sysvalinfo ds qualified based(sysvalinfoptr)
+ d name 10
+ d type 1
+ d status 1
+ d length 10u 0
+ d value 99999
+ *
+ d qusec ds qualified
+ d 10u 0 inz(0)
+ *
+ d weekday s 10u 0
+ *
+ now.ts = %timestamp(*SYS);
+ get_sysval(sysval: %len(sysval): 1: 'QUTCOFFSET': qusec);
+ sysvalinfoptr = %addr(sysval) + sysval.offset;
+ weekday = %rem(%diff(now.ts: %timestamp('2001-01-01-00.00.00.000000'):
+ *DAYS): 7);
+ return %subst('MonTueWedThuFriSatSun': 3 * weekday + 1: 3) + ', ' +
+ %char(now.day) + ' ' +
+ %subst('JanFebMarAprMayJunJulAugSepOctNovDec':
+ 3 * now.month - 2: 3) + ' ' +
+ %char(now.year) + ' ' +
+ %char(now.hour) + ':' + now.minute + ':' + now.second + ' ' +
+ %subst(sysvalinfo.value: 1: sysvalinfo.length);
+ p mail_date e
+ *
+ **************************************************************************
+ * Get the length of right-trimmed string
+ **************************************************************************
+ *
+ p trimmed_length b
+ d trimmed_length pi 10u 0
+ d string 999999 const options(*varsize)
+ d length 10u 0 value
+ *
+ d addrdiff s 10i 0
+ d len s 10u 0
+ *
+ len = %scan(X'00': string: 1: length); // Limit to zero-terminated string
+ if len = 0;
+ len = length + 1;
+ endif;
+ if len <= 1;
+ return 0;
+ endif;
+ return %checkr(' ': string: len - 1); // Trim right
+ p trimmed_length e
diff --git a/packages/README b/packages/README
deleted file mode 100644
index 2487d95..0000000
--- a/packages/README
+++ /dev/null
@@ -1,27 +0,0 @@
- _ _ ____ _
- ___| | | | _ \| |
- / __| | | | |_) | |
- | (__| |_| | _ <| |___
- \___|\___/|_| \_\_____|
-
-PACKAGES
-
- This directory and all its subdirectories are for special package
-information, template, scripts and docs. The files herein should be of use for
-those of you who want to package curl in a binary or source format using one
-of those custom formats.
-
- The hierarchy for these directories is something like this:
-
- packages/[OS]/[FORMAT]/
-
- Currently, we have Win32 and Linux for [OS]. There might be different formats
-for the same OS so for Linux we have RPM as format.
-
- We might need to add some differentiation for CPU as well, as there is
-Linux-RPMs for several CPUs. However, it might not be necessary since the
-packaging should be pretty much the same no matter what CPU that is used.
-
- For each unique OS-FORMAT pair, there's a directory to "fill"! I'd like to
-see a single README with as much details as possible, and then I'd like some
-template files for the package process.
diff --git a/packages/README.md b/packages/README.md
new file mode 100644
index 0000000..f52f8e4
--- /dev/null
+++ b/packages/README.md
@@ -0,0 +1,12 @@
+<!--
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+
+SPDX-License-Identifier: curl
+-->
+
+# Packages
+
+ This directory and all its subdirectories are for special package
+information, templates, scripts and docs. The files herein should be of use
+for those of you who want to package curl in a binary or source format for
+these platforms.
diff --git a/packages/vms/Makefile.am b/packages/vms/Makefile.am
index f4b2d68..e869a89 100644
--- a/packages/vms/Makefile.am
+++ b/packages/vms/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/packages/vms/backup_gnv_curl_src.com b/packages/vms/backup_gnv_curl_src.com
index 900a62b..298f11f 100644
--- a/packages/vms/backup_gnv_curl_src.com
+++ b/packages/vms/backup_gnv_curl_src.com
@@ -1,7 +1,5 @@
$! File: Backup_gnv_curl_src.com
$!
-$! $Id$
-$!
$! Procedure to create backup save sets for installing in a PCSI kit.
$!
$! To comply with most Open Source licenses, the source used for building
@@ -17,7 +15,7 @@
$! easier to port Unix code, particularly open source code to VMS.
$! Therefore permission is freely granted for any use.
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -33,8 +31,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 13-Jun-2009 J. Malmberg
-$!
$!===========================================================================
$!
$! Save default
diff --git a/packages/vms/build_curl-config_script.com b/packages/vms/build_curl-config_script.com
index b6a6575..1667d07 100644
--- a/packages/vms/build_curl-config_script.com
+++ b/packages/vms/build_curl-config_script.com
@@ -2,7 +2,7 @@
$!
$! This generates the curl-config. script from the curl-config.in file.
$!
-$! Copyright 2014 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -18,8 +18,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 16-Dec-2014 J. Malmberg
-$!
$!===========================================================================
$!
$! Skip this if the curl-config. already exists.
diff --git a/packages/vms/build_gnv_curl.com b/packages/vms/build_gnv_curl.com
index 15931fb..36e7281 100644
--- a/packages/vms/build_gnv_curl.com
+++ b/packages/vms/build_gnv_curl.com
@@ -1,10 +1,8 @@
$! File: build_gnv_curl.com
$!
-$! $Id$
-$!
$! All in one build procedure
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -20,7 +18,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 11-Jun-2009 J. Malmberg
$!-----------------------------------------------------------------------
$!
$ @setup_gnv_curl_build.com
diff --git a/packages/vms/build_gnv_curl_pcsi_desc.com b/packages/vms/build_gnv_curl_pcsi_desc.com
index 589de2c..8567426 100644
--- a/packages/vms/build_gnv_curl_pcsi_desc.com
+++ b/packages/vms/build_gnv_curl_pcsi_desc.com
@@ -1,7 +1,5 @@
$! File: Build_GNV_CURL_PCSI_DESC.COM
$!
-$! $Id$
-$!
$! Build the *.pcsi$text file in the following sections:
$! Required software dependencies.
$! install/upgrade/postinstall steps.
@@ -31,7 +29,7 @@
$! created in the GNV$GNU: in the correct case, and to create the alias
$! link [usr.bin]curl. for [usr.bin]curl.exe.
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -47,8 +45,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 15-Jun-2009 J. Malmberg
-$!
$!===========================================================================
$!
$ kit_name = f$trnlnm("GNV_PCSI_KITNAME")
diff --git a/packages/vms/build_gnv_curl_pcsi_text.com b/packages/vms/build_gnv_curl_pcsi_text.com
index 9295ffb..8f109c1 100644
--- a/packages/vms/build_gnv_curl_pcsi_text.com
+++ b/packages/vms/build_gnv_curl_pcsi_text.com
@@ -1,7 +1,5 @@
$! File: Build_GNV_curl_pcsi_text.com
$!
-$! $Id$
-$!
$! Build the *.pcsi$text file from the four components:
$! 1. Generated =product header section
$! 2. [--]readme. file from the Curl distribution, modified to fit
@@ -12,7 +10,7 @@
$!
$! Set the name of the release notes from the GNV_PCSI_FILENAME_BASE
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -28,8 +26,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 15-Jun-2009 J. Malmberg
-$!
$!===========================================================================
$!
$ kit_name = f$trnlnm("GNV_PCSI_KITNAME")
diff --git a/packages/vms/build_gnv_curl_release_notes.com b/packages/vms/build_gnv_curl_release_notes.com
index 7673ab7..0da9445 100644
--- a/packages/vms/build_gnv_curl_release_notes.com
+++ b/packages/vms/build_gnv_curl_release_notes.com
@@ -1,7 +1,5 @@
$! File: Build_GNV_curl_release_notes.com
$!
-$! $Id$
-$!
$! Build the release note file from the four components:
$! 1. The curl_release_note_start.txt
$! 2. The hp_ssl_release_info.txt
@@ -11,7 +9,7 @@
$! Set the name of the release notes from the GNV_PCSI_FILENAME_BASE
$! logical name.
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -27,8 +25,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 14-Jun-2009 J. Malmberg
-$!
$!===========================================================================
$!
$ base_file = f$trnlnm("GNV_PCSI_FILENAME_BASE")
diff --git a/packages/vms/build_libcurl_pc.com b/packages/vms/build_libcurl_pc.com
index e5eef33..294ae08 100644
--- a/packages/vms/build_libcurl_pc.com
+++ b/packages/vms/build_libcurl_pc.com
@@ -1,10 +1,8 @@
$! File: build_libcurl_pc.com
$!
-$! $Id:$
-$!
$! Build the libcurl.pc file from the libcurl.pc.in file
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -20,8 +18,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 15-Jun-2013 J. Malmberg
-$!
$!===========================================================================
$!
$! Skip this if the libcurl.pc already exists.
diff --git a/packages/vms/clean_gnv_curl.com b/packages/vms/clean_gnv_curl.com
index 0fe3117..198c0de 100644
--- a/packages/vms/clean_gnv_curl.com
+++ b/packages/vms/clean_gnv_curl.com
@@ -1,7 +1,5 @@
$! File: clean_gnv_curl.COM
$!
-$! $Id$
-$!
$! The GNV environment leaves behind some during the configure and build
$! procedure that need to be cleaned up.
$!
@@ -15,7 +13,7 @@
$! This removes all build products and brings the environment back to
$! the point where the gnv_curl_configure.sh procedure needs to be run again.
$!
-$! Copyright 2009 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -31,7 +29,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 07-Jul-2009 J. Malmberg
$!============================================================================
$!
$! Save this so we can get back.
diff --git a/packages/vms/compare_curl_source.com b/packages/vms/compare_curl_source.com
index 1801f72..3f7542d 100644
--- a/packages/vms/compare_curl_source.com
+++ b/packages/vms/compare_curl_source.com
@@ -1,7 +1,5 @@
$! Compare_curl_source.com
$!
-$! $Id$
-$!
$! This procedure compares the files in two directories and reports the
$! differences. It is customized for the vmsports repository layout.
$!
@@ -69,7 +67,7 @@
$! This is to make sure that the backup save set for the unmodified
$! source is up to date.
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -85,7 +83,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 18-Aug-2011 J. Malmberg
$!==========================================================================
$!
$! Update missing/changed files.
diff --git a/packages/vms/config_h.com b/packages/vms/config_h.com
index 2a92c20..6e4e039 100644
--- a/packages/vms/config_h.com
+++ b/packages/vms/config_h.com
@@ -1,7 +1,5 @@
$! File: config_h.com
$!
-$! $Id: config_h.com,v 1.1.1.1 2012/12/02 19:25:21 wb8tyw Exp $
-$!
$! This procedure attempts to figure out how to build a config.h file
$! for the current project.
$!
@@ -28,7 +26,7 @@
$! This procedure may not guess the options correctly for all architectures,
$! and is a work in progress.
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -44,15 +42,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 15-Jan-2001 J. Malmberg Original
-$! 29-Apr-2001 J. Malmberg Also look for config.*in* in a [.include]
-$! subdirectory
-$! 30-Apr-2001 J. Malmberg Update for SAMBA checks
-$! 09-Apr-2005 J. Malmberg Update for RSYNC and large file.
-$! 29-Sep-2011 J. Malmberg Update for Bash 4.2
-$! 01-Mar-2012 J. Malmberg Warn about getcwd(0,0)
-$! 21-Dec-2012 J. Malmberg Update for gawk
-$! 29-Dec-2012 J. Malmberg Update for curl
$!============================================================================
$!
$ss_normal = 1
@@ -797,14 +786,6 @@
$ goto cfgh_in_loop1
$ endif
$!
-$ if key2 .eqs. "HAVE_LIBDL"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' 1"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$!
$ if key2b .eqs. "RAND" .and. key2c .nes. "" .and. key2d .eqs. ""
$ then
$ if (key2c .eqs. "EGD") .or. -
@@ -1547,13 +1528,6 @@
$ endif
$ goto cfgh_in_loop1
$ endif
-$ if key2b .eqs. "SHORT"
-$ then
-$ write tf "#ifndef SIZEOF_SHORT"
-$ write tf "#define SIZEOF_SHORT 2"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
$ write tf "/* ", xline, " */"
$ goto cfgh_in_loop1
$ endif
@@ -1669,117 +1643,6 @@
$ endif
$ endif
$!
-$!
-$! Process RECVFROM directives
-$!-------------------------------------
-$ if key2a .eqs. "RECVFROM"
-$ then
-$ if key2 .eqs. "RECVFROM_QUAL_ARG5"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2'"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ if key2 .eqs. "RECVFROM_TYPE_ARG1"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' int"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ if key2 .eqs. "RECVFROM_TYPE_ARG2"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' void *"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ if key2 .eqs. "RECVFROM_TYPE_ARG3"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' size_t"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ if key2 .eqs. "RECVFROM_TYPE_ARG4"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' int"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ if key2 .eqs. "RECVFROM_TYPE_ARG5"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' struct sockaddr"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ if key2 .eqs. "RECVFROM_TYPE_ARG6"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' unsigned int"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ if key2 .eqs. "RECVFROM_TYPE_RETV"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' int"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ endif
-$!
-$! Process SELECT directives
-$!-------------------------------------
-$ if key2a .eqs. "SELECT"
-$ then
-$ if key2 .eqs. "SELECT_QUAL_ARG5"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' const"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ if key2 .eqs. "SELECT_TYPE_ARG1"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' int"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ if key2 .eqs. "SELECT_TYPE_ARG2"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' void *"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ if key2 .eqs. "SELECT_TYPE_ARG234"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' fd_set *"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ if key2 .eqs. "SELECT_TYPE_ARG5"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' struct timeval *"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ if key2 .eqs. "SELECT_TYPE_RETV"
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' int"
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$ endif
-$!
$! Process SEND directives
$!-------------------------------------
$ if key2a .eqs. "SEND"
diff --git a/packages/vms/curl_crtl_init.c b/packages/vms/curl_crtl_init.c
index 8b5da62..6ae7e8c 100644
--- a/packages/vms/curl_crtl_init.c
+++ b/packages/vms/curl_crtl_init.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -39,7 +39,7 @@
* On VMS versions that are too old to use the feature setting API, this
* module falls back to using logical names.
*
- * Copyright 2013, John Malmberg
+ * Copyright (C) John Malmberg
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -130,7 +130,7 @@
status = SYS$TRNLNM(&attr, &table_dsc, &name_dsc, 0, itlst);
- if ($VMS_STATUS_SUCCESS(status)) {
+ if($VMS_STATUS_SUCCESS(status)) {
/* Null terminate and return the string */
/*--------------------------------------*/
@@ -192,7 +192,7 @@
index = decc$feature_get_index(name);
- if (index > 0)
+ if(index > 0)
decc$feature_set_value (index, 0, value);
}
#endif
@@ -205,7 +205,7 @@
status = sys_trnlnm("GNV$UNIX_SHELL",
unix_shell_name, sizeof unix_shell_name -1);
- if (!$VMS_STATUS_SUCCESS(status)) {
+ if(!$VMS_STATUS_SUCCESS(status)) {
use_unix_settings = 0;
}
@@ -249,7 +249,7 @@
/* Fix mv aa.bb aa */
set_feature_default ("DECC$RENAME_NO_INHERIT", ENABLE);
- if (use_unix_settings) {
+ if(use_unix_settings) {
/* POSIX requires that open files be able to be removed */
set_feature_default ("DECC$ALLOW_REMOVE_OPEN_FILES", ENABLE);
diff --git a/packages/vms/curl_gnv_build_steps.txt b/packages/vms/curl_gnv_build_steps.txt
index 6274b7b..b7ea952 100644
--- a/packages/vms/curl_gnv_build_steps.txt
+++ b/packages/vms/curl_gnv_build_steps.txt
@@ -1,6 +1,6 @@
From File: curl_gnv_build_steps.txt
- Copyright 2013 - 2022, John Malmberg
+ Copyright (C) John Malmberg
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -251,7 +251,7 @@
step of backing up the source files will probably hang or fail.
You need to copy the source files to VMS mounted disks and create
- logical names SRC_ROOT1 and VMS_ROOT1 to work around this to to
+ logical names SRC_ROOT1 and VMS_ROOT1 to work around this to
reference local disks. Make sure src_root1:[000000] and
vms_root1:[000000] exist and can be written to.
diff --git a/packages/vms/curl_release_note_start.txt b/packages/vms/curl_release_note_start.txt
index 977dce1..62b2836 100644
--- a/packages/vms/curl_release_note_start.txt
+++ b/packages/vms/curl_release_note_start.txt
@@ -2,7 +2,7 @@
Note: These kits are produced by a hobbyist and are providing any support
or any commitment to supply bug fixes or future releases. This code is
-as-is with no warrantees.
+as-is with no warranties.
The testing of this build of curl was minimal and involved building some of
the sample and test programs, accessing a public HTTPS: website, doing a
@@ -58,12 +58,12 @@
dcl @gnv\$gnu:[vms_bin]curl.com $*
^Z
-Similar work arounds will be needed for any program linked with GNV$LIBCURL
+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
things have been changed so that it can be installed at the same time as
-a production build with out conflicts.
+a production build without conflicts.
The CURL_DAILY_STARTUP.COM will be supplied instead of CURL_STARTUP.COM.
This file is actually not used with the daily package and is provided as
diff --git a/packages/vms/curl_startup.com b/packages/vms/curl_startup.com
index 47849dc..e90bbec 100644
--- a/packages/vms/curl_startup.com
+++ b/packages/vms/curl_startup.com
@@ -1,11 +1,9 @@
$! File: curl_Startup.com
$!
-$! $Id$
-$!
$! Procedure to setup the CURL libraries for use by programs from the
$! VMS SYSTARTUP*.COM procedure.
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -21,8 +19,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 15-Jun-2009 J. Malmberg
-$! 30-Jul-2013 J. Malmberg Update for Curl 7.32
$!========================================================================
$!
$!
diff --git a/packages/vms/curlmsg.h b/packages/vms/curlmsg.h
index 7f7378d..9b5c4c7 100644
--- a/packages/vms/curlmsg.h
+++ b/packages/vms/curlmsg.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/packages/vms/curlmsg.msg b/packages/vms/curlmsg.msg
index 2122495..ac2d508 100644
--- a/packages/vms/curlmsg.msg
+++ b/packages/vms/curlmsg.msg
@@ -5,7 +5,7 @@
! | (__| |_| | _ <| |___
! \___|\___/|_| \_\_____|
!
-! Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+! Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
!
! This software is licensed as described in the file COPYING, which
! you should have received as part of this distribution. The terms
diff --git a/packages/vms/curlmsg_vms.h b/packages/vms/curlmsg_vms.h
index f24a199..982d0c6 100644
--- a/packages/vms/curlmsg_vms.h
+++ b/packages/vms/curlmsg_vms.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/packages/vms/generate_config_vms_h_curl.com b/packages/vms/generate_config_vms_h_curl.com
index 9321da2..904f1df 100644
--- a/packages/vms/generate_config_vms_h_curl.com
+++ b/packages/vms/generate_config_vms_h_curl.com
@@ -1,7 +1,5 @@
$! File: GENERATE_CONFIG_H_CURL.COM
$!
-$! $Id$
-$!
$! 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.
$!
@@ -16,8 +14,7 @@
$! and the [.lib]config-vms.h file do two different tasks and that the
$! filenames are slightly different.
$!
-$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -33,8 +30,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 06-Jan-2013 J. Malmberg
-$!
$!=========================================================================
$!
$! Allow arguments to be grouped together with comma or separated by spaces
@@ -426,12 +421,10 @@
$if libssh2
$then
$ write cvh "#define HAVE_LIBSSH2_EXIT 1"
-$ write cvh "#define HAVE_LIBSSH2_H 1"
$ write cvh "#define HAVE_LIBSSH2_INIT 1"
$ write cvh "#define HAVE_LIBSSH2_SCP_SEND64 1"
$ write cvh "#define HAVE_LIBSSH2_SESSION_HANDSHAKE 1"
$ write cvh "#define HAVE_LIBSSH2_VERSION 1
-$ write cvh "#define HAVE_LIBSSH2 1
$!
$ write cvh "#ifndef USE_LIBSSH2"
$ write cvh "#define USE_LIBSSH2 1"
@@ -447,7 +440,6 @@
$if .not. nozlib
$then
$ write cvh "#define HAVE_LIBZ 1"
-$ write cvh "#define HAVE_ZLIB_H 1"
$endif
$!
$!
diff --git a/packages/vms/generate_vax_transfer.com b/packages/vms/generate_vax_transfer.com
index f9d978b..3ed49cb 100644
--- a/packages/vms/generate_vax_transfer.com
+++ b/packages/vms/generate_vax_transfer.com
@@ -1,7 +1,5 @@
$! File: generate_vax_transfer.com
$!
-$! $Id$
-$!
$! File to generate and compile the VAX transfer vectors from reading in the
$! Alpha/Itanium gnv_libcurl_symbols.opt file.
$!
@@ -14,7 +12,7 @@
$! gnv_libcurl_xfer.opt
$! macro32_exactcase.exe
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -30,7 +28,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 20-Jul-2013 J. Malmberg
$!============================================================================
$!
$! Save this so we can get back.
diff --git a/packages/vms/gnv_conftest.c_first b/packages/vms/gnv_conftest.c_first
index 2ee2447..5b56608 100644
--- a/packages/vms/gnv_conftest.c_first
+++ b/packages/vms/gnv_conftest.c_first
@@ -1,8 +1,6 @@
/* File: GNV$CONFTEST.C_FIRST
*
- * $Id$
- *
- * Copyright 2013 - 2022, John Malmberg
+ * Copyright (C) John Malmberg
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -31,7 +29,7 @@
/* These are to pass the test that does not use headers */
/* Because configure does an #undef which keeps us from using #define */
/* char CRYPTO_add_lock(void) {return 0;} */
-char SSL_connnect(void) {return 0;}
+char SSL_connect(void) {return 0;}
char ENGINE_init(void) {return 0;}
char RAND_status(void) {return 0;}
/* char RAND_screen(void) {return 0;} In headers, but not present */
diff --git a/packages/vms/gnv_curl_configure.sh b/packages/vms/gnv_curl_configure.sh
old mode 100644
new mode 100755
index 1cb0543..2155800
--- a/packages/vms/gnv_curl_configure.sh
+++ b/packages/vms/gnv_curl_configure.sh
@@ -1,11 +1,9 @@
# File: gnv_curl_configure.sh
#
-# $Id$
-#
# Set up and run the configure script for Curl so that it can find the
# proper options for VMS.
#
-# Copyright 2013 - 2022, John Malmberg
+# Copyright (C) John Malmberg
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -21,8 +19,6 @@
#
# SPDX-License-Identifier: ISC
#
-# 06-Jun-2009 J. Malmberg
-# 28-Dec-2012 J. Malmberg Update for Bash 4.2.39
#==========================================================================
#
# POSIX exit mode is needed for Unix shells.
diff --git a/packages/vms/gnv_libcurl_symbols.opt b/packages/vms/gnv_libcurl_symbols.opt
index eff1cbe..5bc2a85 100644
--- a/packages/vms/gnv_libcurl_symbols.opt
+++ b/packages/vms/gnv_libcurl_symbols.opt
@@ -1,7 +1,5 @@
! File GNV$LIBCURL_SYMBOLS.OPT
!
-! $Id$
-!
! This file must be manually maintained to allow upward compatibility
! The SYMBOL_VECTORs are set up so that applications can be compiled
! with either case sensitive symbol names or the default of uppercase.
@@ -41,7 +39,7 @@
! maintaining multiple versions as long as the routine can be called with
! the old number of parameters.
!
-! Copyright 2013 - 2022, John Malmberg
+! Copyright (C) John Malmberg
!
! Permission to use, copy, modify, and/or distribute this software for any
! purpose with or without fee is hereby granted, provided that the above
diff --git a/packages/vms/gnv_link_curl.com b/packages/vms/gnv_link_curl.com
index 6e84229..4959f1b 100644
--- a/packages/vms/gnv_link_curl.com
+++ b/packages/vms/gnv_link_curl.com
@@ -1,10 +1,8 @@
$! File: gnv_link_curl.com
$!
-$! $Id$
-$!
$! File to build images using gnv$libcurl.exe
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -20,7 +18,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 10-Jun-2009 J. Malmberg
$!============================================================================
$!
$! Save this so we can get back.
@@ -412,7 +409,7 @@
[.src]curl-tool_hugehelp.o, [.src]curl-tool_libinfo.o, -
[.src]curl-tool_mfiles.o, -
[.src]curl-tool_msgs.o, [.src]curl-tool_operate.o, -
- [.src]curl-tool_operhlp.o, [.src]curl-tool_panykey.o, -
+ [.src]curl-tool_operhlp.o, -
[.src]curl-tool_paramhlp.o, [.src]curl-tool_parsecfg.o, -
[.src]curl-tool_setopt.o, [.src]curl-tool_sleep.o, -
[.src]curl-tool_urlglob.o, [.src]curl-tool_util.o, -
diff --git a/packages/vms/make_gnv_curl_install.sh b/packages/vms/make_gnv_curl_install.sh
old mode 100644
new mode 100755
index bdc6077..b85ef0c
--- a/packages/vms/make_gnv_curl_install.sh
+++ b/packages/vms/make_gnv_curl_install.sh
@@ -1,13 +1,11 @@
# File: make_gnv_curl_install.sh
#
-# $Id$
-#
# 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).
#
-# Copyright 2013 - 2022, John Malmberg
+# Copyright (C) John Malmberg
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -23,7 +21,6 @@
#
# SPDX-License-Identifier: ISC
#
-# 06-Jun-2009 J. Malmberg
#==========================================================================
#
#
diff --git a/packages/vms/make_pcsi_curl_kit_name.com b/packages/vms/make_pcsi_curl_kit_name.com
index 08d3472..956f7c1 100644
--- a/packages/vms/make_pcsi_curl_kit_name.com
+++ b/packages/vms/make_pcsi_curl_kit_name.com
@@ -1,14 +1,12 @@
$! File: MAKE_PCSI_CURL_KIT_NAME.COM
$!
-$! $Id$
-$!
$! Calculates the PCSI kit name for use in building an installation kit.
$! PCSI is HP's PolyCenter Software Installation Utility.
$!
$! The results are stored in as logical names so that other procedures
$! can use them.
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -24,8 +22,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 11-Jun-2009 J. Malmberg
-$!
$!========================================================================
$!
$! Save default
diff --git a/packages/vms/pcsi_gnv_curl_file_list.txt b/packages/vms/pcsi_gnv_curl_file_list.txt
index 7015a80..586f7e7 100644
--- a/packages/vms/pcsi_gnv_curl_file_list.txt
+++ b/packages/vms/pcsi_gnv_curl_file_list.txt
@@ -1,7 +1,5 @@
! File: PCSI_GNV_CURL_FILE_LIST.TXT
!
-! $Id$
-!
! File list for building a PCSI kit.
! Very simple format so that the parsing logic can be simple.
! links first, directory second, and files third.
@@ -15,7 +13,7 @@
!
! [xxx.yyy]file.ext is a file for the rename and add phases.
!
-! Copyright 2013 - 2022, John Malmberg
+! Copyright (C) John Malmberg
!
! Permission to use, copy, modify, and/or distribute this software for any
! purpose with or without fee is hereby granted, provided that the above
@@ -31,7 +29,6 @@
!
! SPDX-License-Identifier: ISC
!
-! 15-Jun-2009 J. Malmberg
!============================================================================
[gnv.usr.bin]curl. -> [gnv.usr.bin]gnv$curl.exe
[gnv.usr.bin]curl.exe -> [gnv.usr.bin]gnv$curl.exe
diff --git a/packages/vms/pcsi_product_gnv_curl.com b/packages/vms/pcsi_product_gnv_curl.com
index 688c9c0..83d8fa3 100644
--- a/packages/vms/pcsi_product_gnv_curl.com
+++ b/packages/vms/pcsi_product_gnv_curl.com
@@ -1,11 +1,9 @@
$! File: PCSI_PRODUCT_GNV_CURL.COM
$!
-$! $Id$
-$!
$! This command file packages up the product CURL into a sequential
$! format kit
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -21,8 +19,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 16-Jun-2009 J.Malmberg
-$!
$!=========================================================================
$!
$! Save default
diff --git a/packages/vms/report_openssl_version.c b/packages/vms/report_openssl_version.c
index 4939696..64e1ee0 100644
--- a/packages/vms/report_openssl_version.c
+++ b/packages/vms/report_openssl_version.c
@@ -1,7 +1,5 @@
/* File: report_openssl_version.c
*
- * $Id$
- *
* This file dynamically loads the openssl shared image to report the
* version string.
*
@@ -9,7 +7,7 @@
*
* Usage: report_openssl_version <shared_image> [<dcl_symbol>]
*
- * Copyright 2013 - 2022, John Malmberg
+ * Copyright (C) John Malmberg
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -49,7 +47,7 @@
const char * (*ssl_version)(int t);
const char * version;
- if (argc < 1) {
+ if(argc < 1) {
puts("report_openssl_version filename");
exit(1);
}
@@ -57,16 +55,16 @@
libptr = dlopen(argv[1], 0);
ssl_version = (const char * (*)(int))dlsym(libptr, "SSLeay_version");
- if ((void *)ssl_version == NULL) {
+ if(ssl_version == NULL) {
ssl_version = (const char * (*)(int))dlsym(libptr, "ssleay_version");
- if ((void *)ssl_version == NULL) {
+ if(ssl_version == NULL) {
ssl_version = (const char * (*)(int))dlsym(libptr, "SSLEAY_VERSION");
}
}
dlclose(libptr);
- if ((void *)ssl_version == NULL) {
+ if(ssl_version == NULL) {
puts("Unable to lookup version of OpenSSL");
exit(1);
}
@@ -76,7 +74,7 @@
puts(version);
/* Was a symbol argument given? */
- if (argc > 1) {
+ if(argc > 1) {
int status;
struct dsc$descriptor_s symbol_dsc;
struct dsc$descriptor_s value_dsc;
@@ -93,7 +91,7 @@
value_dsc.dsc$b_class = DSC$K_CLASS_S;
status = LIB$SET_SYMBOL(&symbol_dsc, &value_dsc, &table_type);
- if (!$VMS_STATUS_SUCCESS(status)) {
+ if(!$VMS_STATUS_SUCCESS(status)) {
exit(status);
}
}
diff --git a/packages/vms/setup_gnv_curl_build.com b/packages/vms/setup_gnv_curl_build.com
index 69aecc6..8404ec3 100644
--- a/packages/vms/setup_gnv_curl_build.com
+++ b/packages/vms/setup_gnv_curl_build.com
@@ -1,13 +1,11 @@
$! File: setup_gnv_curl_build.com
$!
-$! $Id$
-$!
$! 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.
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -23,8 +21,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 30-May-2009 J. Malmberg
-$!
$!=======================================================================
$!
$! Save this so we can get back.
diff --git a/packages/vms/stage_curl_install.com b/packages/vms/stage_curl_install.com
index 8c4cb05..10ae17a 100644
--- a/packages/vms/stage_curl_install.com
+++ b/packages/vms/stage_curl_install.com
@@ -1,7 +1,5 @@
$! File: stage_curl_install.com
$!
-$! $Id$
-$!
$! This updates or removes the GNV$CURL.EXE and related files for the
$! new_gnu:[*...] directory tree for running the self tests.
$!
@@ -24,7 +22,7 @@
$! [usr.share.man.man3]libcurl*.3
$! Future: A symbolic link to the release notes?
$!
-$! Copyright 2013 - 2022, John Malmberg
+$! Copyright (C) John Malmberg
$!
$! Permission to use, copy, modify, and/or distribute this software for any
$! purpose with or without fee is hereby granted, provided that the above
@@ -40,8 +38,6 @@
$!
$! SPDX-License-Identifier: ISC
$!
-$! 20-Aug-2012 J. Malmberg
-$!
$!===========================================================================
$!
$ arch_type = f$getsyi("ARCH_NAME")
diff --git a/packages/vms/vms_eco_level.h b/packages/vms/vms_eco_level.h
index cf2db53..89f1dfd 100644
--- a/packages/vms/vms_eco_level.h
+++ b/packages/vms/vms_eco_level.h
@@ -1,8 +1,6 @@
/* File: vms_eco_level.h
*
- * $Id$
- *
- * Copyright 2013 - 2022, John Malmberg
+ * Copyright (C) John Malmberg
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/plan9/include/mkfile b/plan9/include/mkfile
index d61682b..a0970e9 100644
--- a/plan9/include/mkfile
+++ b/plan9/include/mkfile
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/plan9/lib/mkfile b/plan9/lib/mkfile
index 4518948..04b54a8 100644
--- a/plan9/lib/mkfile
+++ b/plan9/lib/mkfile
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/plan9/lib/mkfile.inc b/plan9/lib/mkfile.inc
index bf677bd..5c2cc12 100755
--- a/plan9/lib/mkfile.inc
+++ b/plan9/lib/mkfile.inc
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/plan9/mkfile b/plan9/mkfile
index f48d412..2133a49 100644
--- a/plan9/mkfile
+++ b/plan9/mkfile
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/plan9/mkfile.proto b/plan9/mkfile.proto
index 2557de7..4ad41a1 100644
--- a/plan9/mkfile.proto
+++ b/plan9/mkfile.proto
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/plan9/src/mkfile b/plan9/src/mkfile
index 0ec185b..beb98cb 100644
--- a/plan9/src/mkfile
+++ b/plan9/src/mkfile
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/plan9/src/mkfile.inc b/plan9/src/mkfile.inc
index bf677bd..5c2cc12 100755
--- a/plan9/src/mkfile.inc
+++ b/plan9/src/mkfile.inc
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/projects/README.md b/projects/README.md
index a578f9a..9b18ccd 100644
--- a/projects/README.md
+++ b/projects/README.md
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
@@ -92,10 +92,10 @@
## Running DLL based configurations
-If you are a developer and plan to run the curl tool from Visual Studio (eg
-you are debugging) with any third-party libraries (such as OpenSSL, wolfSSL or
-LibSSH2) then you will need to add the search path of these DLLs to the
-configuration's PATH environment. To do that:
+If you are a developer and plan to run the curl tool from Visual Studio with
+any third-party libraries (such as OpenSSL, wolfSSL or LibSSH2) then you will
+need to add the search path of these DLLs to the configuration's PATH
+environment. To do that:
1. Open the 'curl-all.sln' or 'curl.sln' solutions
2. Right-click on the 'curl' project and select Properties
diff --git a/projects/Windows/.gitattributes b/projects/Windows/.gitattributes
index 8849a71..e6cf935 100644
--- a/projects/Windows/.gitattributes
+++ b/projects/Windows/.gitattributes
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/.gitignore b/projects/Windows/.gitignore
index e2f943e..cab49e3 100644
--- a/projects/Windows/.gitignore
+++ b/projects/Windows/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC10/.gitignore b/projects/Windows/VC10/.gitignore
index b3c0e9e..53e3845 100644
--- a/projects/Windows/VC10/.gitignore
+++ b/projects/Windows/VC10/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC10/lib/.gitignore b/projects/Windows/VC10/lib/.gitignore
index 5a33b00..853b57d 100644
--- a/projects/Windows/VC10/lib/.gitignore
+++ b/projects/Windows/VC10/lib/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC10/lib/libcurl.tmpl b/projects/Windows/VC10/lib/libcurl.tmpl
index 2a148d7..7a37c27 100644
--- a/projects/Windows/VC10/lib/libcurl.tmpl
+++ b/projects/Windows/VC10/lib/libcurl.tmpl
@@ -1470,7 +1470,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1537,7 +1537,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1603,7 +1603,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1666,7 +1666,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1696,7 +1696,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC10\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1730,7 +1730,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC10\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1764,7 +1764,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC10\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1796,7 +1796,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC10\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1861,7 +1861,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC10\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1884,7 +1884,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC10\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1924,7 +1924,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1970,7 +1970,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2033,7 +2033,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC10\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2056,7 +2056,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC10\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2120,7 +2120,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC10\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2143,7 +2143,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC10\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2183,7 +2183,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2229,7 +2229,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2292,7 +2292,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC10\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2315,7 +2315,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC10\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
diff --git a/projects/Windows/VC10/src/.gitignore b/projects/Windows/VC10/src/.gitignore
index 5a33b00..853b57d 100644
--- a/projects/Windows/VC10/src/.gitignore
+++ b/projects/Windows/VC10/src/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC11/.gitignore b/projects/Windows/VC11/.gitignore
index b3c0e9e..53e3845 100644
--- a/projects/Windows/VC11/.gitignore
+++ b/projects/Windows/VC11/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC11/lib/.gitignore b/projects/Windows/VC11/lib/.gitignore
index 5a33b00..853b57d 100644
--- a/projects/Windows/VC11/lib/.gitignore
+++ b/projects/Windows/VC11/lib/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC11/lib/libcurl.tmpl b/projects/Windows/VC11/lib/libcurl.tmpl
index 5692ba5..95cc9f6 100644
--- a/projects/Windows/VC11/lib/libcurl.tmpl
+++ b/projects/Windows/VC11/lib/libcurl.tmpl
@@ -1526,7 +1526,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1593,7 +1593,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1659,7 +1659,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1722,7 +1722,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1752,7 +1752,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC11\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1786,7 +1786,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC11\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1820,7 +1820,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC11\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1852,7 +1852,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC11\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1917,7 +1917,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC11\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1940,7 +1940,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC11\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1980,7 +1980,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2026,7 +2026,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2089,7 +2089,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC11\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2112,7 +2112,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC11\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2176,7 +2176,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC11\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2199,7 +2199,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC11\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2239,7 +2239,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2285,7 +2285,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2348,7 +2348,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC11\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2371,7 +2371,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC11\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
diff --git a/projects/Windows/VC11/src/.gitignore b/projects/Windows/VC11/src/.gitignore
index 5a33b00..853b57d 100644
--- a/projects/Windows/VC11/src/.gitignore
+++ b/projects/Windows/VC11/src/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC12/.gitignore b/projects/Windows/VC12/.gitignore
index b3c0e9e..53e3845 100644
--- a/projects/Windows/VC12/.gitignore
+++ b/projects/Windows/VC12/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC12/lib/.gitignore b/projects/Windows/VC12/lib/.gitignore
index 5a33b00..853b57d 100644
--- a/projects/Windows/VC12/lib/.gitignore
+++ b/projects/Windows/VC12/lib/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC12/lib/libcurl.tmpl b/projects/Windows/VC12/lib/libcurl.tmpl
index 1f847e3..a2d666c 100644
--- a/projects/Windows/VC12/lib/libcurl.tmpl
+++ b/projects/Windows/VC12/lib/libcurl.tmpl
@@ -1526,7 +1526,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1593,7 +1593,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1659,7 +1659,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1722,7 +1722,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1752,7 +1752,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC12\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1786,7 +1786,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC12\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1820,7 +1820,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC12\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1852,7 +1852,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC12\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1917,7 +1917,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC12\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1940,7 +1940,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC12\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1980,7 +1980,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2026,7 +2026,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2089,7 +2089,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC12\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2112,7 +2112,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC12\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2176,7 +2176,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC12\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2199,7 +2199,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC12\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2239,7 +2239,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2285,7 +2285,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2348,7 +2348,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC12\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2371,7 +2371,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC12\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
diff --git a/projects/Windows/VC12/src/.gitignore b/projects/Windows/VC12/src/.gitignore
index 5a33b00..853b57d 100644
--- a/projects/Windows/VC12/src/.gitignore
+++ b/projects/Windows/VC12/src/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC14.10/.gitignore b/projects/Windows/VC14.10/.gitignore
index f97107e..11504d2 100644
--- a/projects/Windows/VC14.10/.gitignore
+++ b/projects/Windows/VC14.10/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC14.10/lib/.gitignore b/projects/Windows/VC14.10/lib/.gitignore
index 37168c3..5baee83 100644
--- a/projects/Windows/VC14.10/lib/.gitignore
+++ b/projects/Windows/VC14.10/lib/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC14.10/lib/libcurl.tmpl b/projects/Windows/VC14.10/lib/libcurl.tmpl
index cf91db4..5560ad6 100644
--- a/projects/Windows/VC14.10/lib/libcurl.tmpl
+++ b/projects/Windows/VC14.10/lib/libcurl.tmpl
@@ -1515,7 +1515,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -1580,7 +1580,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -1645,7 +1645,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1708,7 +1708,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1738,7 +1738,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.10\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -1771,7 +1771,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.10\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -1804,7 +1804,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.10\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1836,7 +1836,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.10\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1899,7 +1899,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.10\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -1921,7 +1921,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.10\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -1959,7 +1959,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -2003,7 +2003,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -2063,7 +2063,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.10\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -2085,7 +2085,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.10\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -2148,7 +2148,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.10\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2171,7 +2171,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.10\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2211,7 +2211,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2257,7 +2257,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2320,7 +2320,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.10\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2343,7 +2343,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.10\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
diff --git a/projects/Windows/VC14.10/src/.gitignore b/projects/Windows/VC14.10/src/.gitignore
index 37168c3..5baee83 100644
--- a/projects/Windows/VC14.10/src/.gitignore
+++ b/projects/Windows/VC14.10/src/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC14.30/.gitignore b/projects/Windows/VC14.30/.gitignore
index f97107e..11504d2 100644
--- a/projects/Windows/VC14.30/.gitignore
+++ b/projects/Windows/VC14.30/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC14.30/lib/.gitignore b/projects/Windows/VC14.30/lib/.gitignore
index 37168c3..5baee83 100644
--- a/projects/Windows/VC14.30/lib/.gitignore
+++ b/projects/Windows/VC14.30/lib/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC14.30/lib/libcurl.tmpl b/projects/Windows/VC14.30/lib/libcurl.tmpl
index 7db3818..a7afb4f 100644
--- a/projects/Windows/VC14.30/lib/libcurl.tmpl
+++ b/projects/Windows/VC14.30/lib/libcurl.tmpl
@@ -1515,7 +1515,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -1580,7 +1580,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -1645,7 +1645,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1708,7 +1708,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1738,7 +1738,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.30\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -1771,7 +1771,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.30\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -1804,7 +1804,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.30\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1836,7 +1836,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.30\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1899,7 +1899,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.30\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -1921,7 +1921,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.30\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -1959,7 +1959,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -2003,7 +2003,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -2063,7 +2063,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.30\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -2085,7 +2085,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.30\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level4</WarningLevel>
@@ -2148,7 +2148,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.30\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2171,7 +2171,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.30\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2211,7 +2211,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2257,7 +2257,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2320,7 +2320,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.30\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2343,7 +2343,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.30\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
diff --git a/projects/Windows/VC14.30/src/.gitignore b/projects/Windows/VC14.30/src/.gitignore
index 37168c3..5baee83 100644
--- a/projects/Windows/VC14.30/src/.gitignore
+++ b/projects/Windows/VC14.30/src/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC14/.gitignore b/projects/Windows/VC14/.gitignore
index f97107e..11504d2 100644
--- a/projects/Windows/VC14/.gitignore
+++ b/projects/Windows/VC14/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC14/lib/.gitignore b/projects/Windows/VC14/lib/.gitignore
index 37168c3..5baee83 100644
--- a/projects/Windows/VC14/lib/.gitignore
+++ b/projects/Windows/VC14/lib/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/Windows/VC14/lib/libcurl.tmpl b/projects/Windows/VC14/lib/libcurl.tmpl
index 2ff92d2..07823b2 100644
--- a/projects/Windows/VC14/lib/libcurl.tmpl
+++ b/projects/Windows/VC14/lib/libcurl.tmpl
@@ -1526,7 +1526,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1593,7 +1593,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1659,7 +1659,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1722,7 +1722,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1752,7 +1752,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1786,7 +1786,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1820,7 +1820,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1852,7 +1852,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -1917,7 +1917,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1940,7 +1940,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -1980,7 +1980,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2026,7 +2026,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2089,7 +2089,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2112,7 +2112,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -2176,7 +2176,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2199,7 +2199,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2239,7 +2239,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2285,7 +2285,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;WANT_IDN_PROTOTYPES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2348,7 +2348,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -2371,7 +2371,7 @@
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;HAVE_LIBSSH2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
diff --git a/projects/Windows/VC14/src/.gitignore b/projects/Windows/VC14/src/.gitignore
index 37168c3..5baee83 100644
--- a/projects/Windows/VC14/src/.gitignore
+++ b/projects/Windows/VC14/src/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/projects/build-openssl.bat b/projects/build-openssl.bat
index 1d75444..b645383 100644
--- a/projects/build-openssl.bat
+++ b/projects/build-openssl.bat
@@ -6,7 +6,7 @@
rem * | (__| |_| | _ <| |___
rem * \___|\___/|_| \_\_____|
rem *
-rem * Copyright (C) 2012 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+rem * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
rem *
rem * This software is licensed as described in the file COPYING, which
rem * you should have received as part of this distribution. The terms
@@ -18,7 +18,7 @@
rem *
rem * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
rem * KIND, either express or implied.
-rem *
+rem *
rem * SPDX-License-Identifier: curl
rem *
rem ***************************************************************************
@@ -589,8 +589,13 @@
)
move "%TMP_INSTALL_PATH%\lib\*.lib" "%OUTDIR%\DLL Debug" 1>nul
- move "%TMP_INSTALL_PATH%\lib\engines-1_1\*.dll" "%OUTDIR%\DLL Debug" 1>nul
- move "%TMP_INSTALL_PATH%\lib\engines-1_1\*.pdb" "%OUTDIR%\DLL Debug" 1>nul
+ if exist "%TMP_INSTALL_PATH%\lib\engines-3" (
+ move "%TMP_INSTALL_PATH%\lib\engines-3\*.dll" "%OUTDIR%\DLL Debug" 1>nul
+ move "%TMP_INSTALL_PATH%\lib\engines-3\*.pdb" "%OUTDIR%\DLL Debug" 1>nul
+ ) else if exist "%TMP_INSTALL_PATH%\lib\engines-1_1" (
+ move "%TMP_INSTALL_PATH%\lib\engines-1_1\*.dll" "%OUTDIR%\DLL Debug" 1>nul
+ move "%TMP_INSTALL_PATH%\lib\engines-1_1\*.pdb" "%OUTDIR%\DLL Debug" 1>nul
+ )
move "%TMP_INSTALL_PATH%\bin\*.dll" "%OUTDIR%\DLL Debug" 1>nul
move "%TMP_INSTALL_PATH%\bin\*.exe" "%OUTDIR%\DLL Debug" 1>nul
move "%TMP_INSTALL_PATH%\bin\*.pdb" "%OUTDIR%\DLL Debug" 1>nul
@@ -615,8 +620,13 @@
)
move "%TMP_INSTALL_PATH%\lib\*.lib" "%OUTDIR%\DLL Release" 1>nul
- move "%TMP_INSTALL_PATH%\lib\engines-1_1\*.dll" "%OUTDIR%\DLL Release" 1>nul
- move "%TMP_INSTALL_PATH%\lib\engines-1_1\*.pdb" "%OUTDIR%\DLL Release" 1>nul
+ if exist "%TMP_INSTALL_PATH%\lib\engines-3" (
+ move "%TMP_INSTALL_PATH%\lib\engines-3\*.dll" "%OUTDIR%\DLL Release" 1>nul
+ move "%TMP_INSTALL_PATH%\lib\engines-3\*.pdb" "%OUTDIR%\DLL Release" 1>nul
+ ) else if exist "%TMP_INSTALL_PATH%\lib\engines-1_1" (
+ move "%TMP_INSTALL_PATH%\lib\engines-1_1\*.dll" "%OUTDIR%\DLL Release" 1>nul
+ move "%TMP_INSTALL_PATH%\lib\engines-1_1\*.pdb" "%OUTDIR%\DLL Release" 1>nul
+ )
move "%TMP_INSTALL_PATH%\bin\*.dll" "%OUTDIR%\DLL Release" 1>nul
move "%TMP_INSTALL_PATH%\bin\*.exe" "%OUTDIR%\DLL Release" 1>nul
move "%TMP_INSTALL_PATH%\bin\*.pdb" "%OUTDIR%\DLL Release" 1>nul
diff --git a/projects/build-wolfssl.bat b/projects/build-wolfssl.bat
index 61f4a03..6f9bad9 100644
--- a/projects/build-wolfssl.bat
+++ b/projects/build-wolfssl.bat
@@ -6,8 +6,8 @@
rem * | (__| |_| | _ <| |___
rem * \___|\___/|_| \_\_____|
rem *
-rem * Copyright (C) 2012 - 2020, Steve Holme, <steve_holme@hotmail.com>.
-rem * Copyright (C) 2015 - 2022, Jay Satiro, <raysatiro@yahoo.com>.
+rem * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
+rem * Copyright (C) Jay Satiro, <raysatiro@yahoo.com>.
rem *
rem * This software is licensed as described in the file COPYING, which
rem * you should have received as part of this distribution. The terms
@@ -19,7 +19,7 @@
rem *
rem * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
rem * KIND, either express or implied.
-rem *
+rem *
rem * SPDX-License-Identifier: curl
rem *
rem ***************************************************************************
diff --git a/projects/checksrc.bat b/projects/checksrc.bat
index 89577e3..018dc59 100644
--- a/projects/checksrc.bat
+++ b/projects/checksrc.bat
@@ -6,7 +6,7 @@
rem * | (__| |_| | _ <| |___
rem * \___|\___/|_| \_\_____|
rem *
-rem * Copyright (C) 2014 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+rem * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
rem *
rem * This software is licensed as described in the file COPYING, which
rem * you should have received as part of this distribution. The terms
@@ -18,7 +18,7 @@
rem *
rem * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
rem * KIND, either express or implied.
-rem *
+rem *
rem * SPDX-License-Identifier: curl
rem *
rem ***************************************************************************
diff --git a/projects/generate.bat b/projects/generate.bat
index b48ca94..a9ee6d0 100644
--- a/projects/generate.bat
+++ b/projects/generate.bat
@@ -6,7 +6,7 @@
rem * | (__| |_| | _ <| |___
rem * \___|\___/|_| \_\_____|
rem *
-rem * Copyright (C) 2014 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+rem * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
rem *
rem * This software is licensed as described in the file COPYING, which
rem * you should have received as part of this distribution. The terms
@@ -18,7 +18,7 @@
rem *
rem * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
rem * KIND, either express or implied.
-rem *
+rem *
rem * SPDX-License-Identifier: curl
rem *
rem ***************************************************************************
@@ -214,7 +214,6 @@
call :element %1 lib "timediff.c" %3
call :element %1 lib "nonblock.c" %3
call :element %1 lib "warnless.c" %3
- call :element %1 lib "curl_ctype.c" %3
call :element %1 lib "curl_multibyte.c" %3
call :element %1 lib "version_win32.c" %3
call :element %1 lib "dynbuf.c" %3
diff --git a/projects/wolfssl_options.h b/projects/wolfssl_options.h
index c30d097..3ef23fb 100644
--- a/projects/wolfssl_options.h
+++ b/projects/wolfssl_options.h
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -301,7 +301,7 @@
#ifdef __cplusplus
-}
+} /* end of extern "C" */
#endif
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index ed9819b..fcb78ea 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/scripts/checksrc.pl b/scripts/checksrc.pl
index 651b4b7..c44dbce 100755
--- a/scripts/checksrc.pl
+++ b/scripts/checksrc.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2011 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -53,54 +53,59 @@
);
my %warnings = (
- 'LONGLINE' => "Line longer than $max_column",
- 'TABS' => 'TAB characters not allowed',
- 'TRAILINGSPACE' => 'Trailing whitespace on the line',
+ 'ASSIGNWITHINCONDITION' => 'assignment within conditional expression',
+ 'ASTERISKNOSPACE' => 'pointer declared without space before asterisk',
+ 'ASTERISKSPACE' => 'pointer declared with space after asterisk',
+ 'BADCOMMAND' => 'bad !checksrc! instruction',
+ 'BANNEDFUNC' => 'a banned function was used',
+ 'BRACEELSE' => '} else on the same line',
+ 'BRACEPOS' => 'wrong position for an open brace',
+ 'BRACEWHILE' => 'A single space between open brace and while',
+ 'COMMANOSPACE' => 'comma without following space',
+ 'COMMENTNOSPACEEND' => 'no space before */',
+ 'COMMENTNOSPACESTART' => 'no space following /*',
+ 'COPYRIGHT' => 'file missing a copyright statement',
'CPPCOMMENTS' => '// comment detected',
- 'SPACEBEFOREPAREN' => 'space before an open parenthesis',
+ 'DOBRACE' => 'A single space between do and open brace',
+ 'EMPTYLINEBRACE' => 'Empty line before the open brace',
+ 'EQUALSNOSPACE' => 'equals sign without following space',
+ 'EQUALSNULL' => 'if/while comparison with == NULL',
+ 'EXCLAMATIONSPACE' => 'Whitespace after exclamation mark in expression',
+ 'FOPENMODE' => 'fopen needs a macro for the mode string',
+ 'INCLUDEDUP', => 'same file is included again',
+ 'INDENTATION' => 'wrong start column for code',
+ 'LONGLINE' => "Line longer than $max_column",
+ 'SPACEBEFORELABEL' => 'labels not at the start of the line',
+ 'MULTISPACE' => 'multiple spaces used when not suitable',
+ 'NOSPACEEQUALS' => 'equals sign without preceding space',
+ 'NOTEQUALSZERO', => 'if/while comparison with != 0',
+ 'ONELINECONDITION' => 'conditional block on the same line as the if()',
+ 'OPENCOMMENT' => 'file ended with a /* comment still "open"',
+ 'PARENBRACE' => '){ without sufficient space',
+ 'RETURNNOSPACE' => 'return without space',
+ 'SEMINOSPACE' => 'semicolon without following space',
+ 'SIZEOFNOPAREN' => 'use of sizeof without parentheses',
+ 'SNPRINTF' => 'use of snprintf',
'SPACEAFTERPAREN' => 'space after open parenthesis',
'SPACEBEFORECLOSE' => 'space before a close parenthesis',
'SPACEBEFORECOMMA' => 'space before a comma',
- 'RETURNNOSPACE' => 'return without space',
- 'COMMANOSPACE' => 'comma without following space',
- 'BRACEELSE' => '} else on the same line',
- 'PARENBRACE' => '){ without sufficient space',
+ 'SPACEBEFOREPAREN' => 'space before an open parenthesis',
'SPACESEMICOLON' => 'space before semicolon',
- 'BANNEDFUNC' => 'a banned function was used',
- 'FOPENMODE' => 'fopen needs a macro for the mode string',
- 'BRACEPOS' => 'wrong position for an open brace',
- 'INDENTATION' => 'wrong start column for code',
- 'COPYRIGHT' => 'file missing a copyright statement',
- 'BADCOMMAND' => 'bad !checksrc! instruction',
- 'UNUSEDIGNORE' => 'a warning ignore was not used',
- 'OPENCOMMENT' => 'file ended with a /* comment still "open"',
- 'ASTERISKSPACE' => 'pointer declared with space after asterisk',
- 'ASTERISKNOSPACE' => 'pointer declared without space before asterisk',
- 'ASSIGNWITHINCONDITION' => 'assignment within conditional expression',
- 'EQUALSNOSPACE' => 'equals sign without following space',
- 'NOSPACEEQUALS' => 'equals sign without preceding space',
- 'SEMINOSPACE' => 'semicolon without following space',
- 'MULTISPACE' => 'multiple spaces used when not suitable',
- 'SIZEOFNOPAREN' => 'use of sizeof without parentheses',
- 'SNPRINTF' => 'use of snprintf',
- 'ONELINECONDITION' => 'conditional block on the same line as the if()',
+ 'SPACESWITCHCOLON' => 'space before colon of switch label',
+ 'TABS' => 'TAB characters not allowed',
+ 'TRAILINGSPACE' => 'Trailing whitespace on the line',
'TYPEDEFSTRUCT' => 'typedefed struct',
- 'DOBRACE' => 'A single space between do and open brace',
- 'BRACEWHILE' => 'A single space between open brace and while',
- 'EXCLAMATIONSPACE' => 'Whitespace after exclamation mark in expression',
- 'EMPTYLINEBRACE' => 'Empty line before the open brace',
- 'EQUALSNULL' => 'if/while comparison with == NULL',
- 'NOTEQUALSZERO', => 'if/while comparison with != 0',
+ 'UNUSEDIGNORE' => 'a warning ignore was not used',
);
sub readskiplist {
- open(W, "<$dir/checksrc.skip") or return;
- my @all=<W>;
+ open(my $W, '<', "$dir/checksrc.skip") or return;
+ my @all=<$W>;
for(@all) {
$windows_os ? $_ =~ s/\r?\n$// : chomp;
$skiplist{$_}=1;
}
- close(W);
+ close($W);
}
# Reads the .checksrc in $dir for any extended warnings to enable locally.
@@ -376,14 +381,15 @@
my $l = "";
my $prep = 0;
my $prevp = 0;
- open(R, "<$file") || die "failed to open $file";
+ open(my $R, '<', $file) || die "failed to open $file";
my $incomment=0;
my @copyright=();
+ my %includes;
checksrc_clear(); # for file based ignores
accept_violations();
- while(<R>) {
+ while(<$R>) {
$windows_os ? $_ =~ s/\r?\n$// : chomp;
my $l = $_;
my $ol = $l; # keep the unmodified line for error reporting
@@ -396,7 +402,8 @@
}
# check for a copyright statement and save the years
- if($l =~ /\* +copyright .* \d\d\d\d/i) {
+ if($l =~ /\* +copyright .* (\d\d\d\d|)/i) {
+ my $count = 0;
while($l =~ /([\d]{4})/g) {
push @copyright, {
year => $1,
@@ -404,6 +411,16 @@
col => index($l, $1),
code => $l
};
+ $count++;
+ }
+ if(!$count) {
+ # year-less
+ push @copyright, {
+ year => -1,
+ line => $line,
+ col => index($l, $1),
+ code => $l
+ };
}
}
@@ -423,6 +440,18 @@
$line, length($1), $file, $l, "Trailing whitespace");
}
+ # no space after comment start
+ if($l =~ /^(.*)\/\*\w/) {
+ checkwarn("COMMENTNOSPACESTART",
+ $line, length($1) + 2, $file, $l,
+ "Missing space after comment start");
+ }
+ # no space at comment end
+ if($l =~ /^(.*)\w\*\//) {
+ checkwarn("COMMENTNOSPACEEND",
+ $line, length($1) + 1, $file, $l,
+ "Missing space end comment end");
+ }
# ------------------------------------------------------------
# Above this marker, the checks were done on lines *including*
# comments
@@ -472,6 +501,15 @@
$line, length($1), $file, $l, "\/\/ comment");
}
+ if($l =~ /^(\#\s*include\s+)([\">].*[>}"])/) {
+ my ($pre, $path) = ($1, $2);
+ if($includes{$path}) {
+ checkwarn("INCLUDEDUP",
+ $line, length($1), $file, $l, "duplicated include");
+ }
+ $includes{$path} = $l;
+ }
+
# detect and strip preprocessor directives
if($l =~ /^[ \t]*\#/) {
# preprocessor line
@@ -481,7 +519,8 @@
my $nostr = nostrings($l);
# check spaces after for/if/while/function call
- if($nostr =~ /^(.*)(for|if|while| ([a-zA-Z0-9_]+)) \((.)/) {
+ if($nostr =~ /^(.*)(for|if|while|switch| ([a-zA-Z0-9_]+)) \((.)/) {
+ my ($leading, $word, $extra, $first)=($1,$2,$3,$4);
if($1 =~ / *\#/) {
# this is a #if, treat it differently
}
@@ -491,15 +530,16 @@
elsif(defined $3 && $3 eq "case") {
# case must have a space
}
- elsif($4 eq "*") {
- # (* beginning makes the space OK!
+ elsif(($first eq "*") && ($word !~ /(for|if|while|switch)/)) {
+ # A "(*" beginning makes the space OK because it wants to
+ # allow funcion pointer declared
}
elsif($1 =~ / *typedef/) {
# typedefs can use space-paren
}
else {
- checkwarn("SPACEBEFOREPAREN", $line, length($1)+length($2), $file, $l,
- "$2 with space");
+ checkwarn("SPACEBEFOREPAREN", $line, length($leading)+length($word), $file, $l,
+ "$word with space");
}
}
# check for '== NULL' in if/while conditions but not if the thing on
@@ -652,6 +692,17 @@
$line, length($1), $file, $ol, "no space before semicolon");
}
+ # check for space before the colon in a switch label
+ if($l =~ /^( *(case .+|default)) :/) {
+ checkwarn("SPACESWITCHCOLON",
+ $line, length($1), $file, $ol, "no space before colon of switch label");
+ }
+
+ if($prevl !~ /\?\z/ && $l =~ /^ +([A-Za-z_][A-Za-z0-9_]*):$/ && $1 ne 'default') {
+ checkwarn("SPACEBEFORELABEL",
+ $line, length($1), $file, $ol, "no space before label");
+ }
+
# scan for use of banned functions
if($l =~ /^(.*\W)
(gmtime|localtime|
@@ -720,6 +771,32 @@
}
}
+ # 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
+ # parentheses, check that this line is indented $indent more steps, if
+ # not a cpp line
+ elsif(!$prevp && ($prevl =~ /^( *)(if|while|for)(\(.*\))\z/)) {
+ my $first = length($1);
+ my $op = $3;
+ my $cl = $3;
+
+ $op =~ s/[^(]//g;
+ $cl =~ s/[^)]//g;
+
+ if(length($op) == length($cl)) {
+ # this line has some character besides spaces
+ if($l =~ /^( *)[^ ]/) {
+ my $second = length($1);
+ my $expect = $first+$indent;
+ if($expect != $second) {
+ my $diff = $second - $first;
+ checkwarn("INDENTATION", $line, length($1), $file, $ol,
+ "not indented $indent steps (uses $diff)");
+ }
+ }
+ }
+ }
+
# check for 'char * name'
if(($l =~ /(^.*(char|int|long|void|CURL|CURLM|CURLMsg|[cC]url_[A-Za-z_]+|struct [a-zA-Z_]+) *(\*+)) (\w+)/) && ($4 !~ /^(const|volatile)$/)) {
checkwarn("ASTERISKSPACE",
@@ -835,12 +912,12 @@
@copyright = sort {$$b{year} cmp $$a{year}} @copyright;
# if the file is modified, assume commit year this year
- if(`git status -s -- $file` =~ /^ [MARCU]/) {
+ if(`git status -s -- "$file"` =~ /^ [MARCU]/) {
$commityear = (localtime(time))[5] + 1900;
}
else {
# min-parents=1 to ignore wrong initial commit in truncated repos
- my $grl = `git rev-list --max-count=1 --min-parents=1 --timestamp HEAD -- $file`;
+ my $grl = `git rev-list --max-count=1 --min-parents=1 --timestamp HEAD -- "$file"`;
if($grl) {
chomp $grl;
$commityear = (localtime((split(/ /, $grl))[0]))[5] + 1900;
@@ -862,7 +939,7 @@
checksrc_endoffile($file);
- close(R);
+ close($R);
}
diff --git a/scripts/ciconfig.pl b/scripts/ciconfig.pl
index 9d4d0bb..a3ac4f6 100755
--- a/scripts/ciconfig.pl
+++ b/scripts/ciconfig.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/scripts/cijobs.pl b/scripts/cijobs.pl
index 4282675..a73b3f5 100755
--- a/scripts/cijobs.pl
+++ b/scripts/cijobs.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -71,13 +71,16 @@
elsif($r =~ /macos/) {
$os = "macos";
}
+ elsif($r =~ /windows/) {
+ $os = "windows";
+ }
# commit previously counted jobs
$c += $j;
# non-matrix job
$j = 1;
}
- elsif($_ =~ /matrix:/) {
+ elsif($_ =~ /^\s*matrix:/) {
# switch to matrix mode
$m = 0;
$j = 0;
@@ -125,7 +128,7 @@
push @cc, $1;
$m++;
}
- elsif($_ =~ /steps:/) {
+ elsif($_ =~ /^\s*steps:/) {
# disable matrix mode
$m = -1;
}
@@ -237,7 +240,7 @@
}
}
$job{'line'} = $line;
- if($_ =~ /^ - APPVEYOR_BUILD_WORKER_IMAGE: \"(.*)\"/) {
+ if($_ =~ /^ APPVEYOR_BUILD_WORKER_IMAGE: \"(.*)\"/) {
$job{'image'}= $1;
}
elsif($_ =~ /^ BUILD_SYSTEM: (.*)/) {
diff --git a/scripts/completion.pl b/scripts/completion.pl
index c2eb774..00c7368 100755
--- a/scripts/completion.pl
+++ b/scripts/completion.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/scripts/contributors.sh b/scripts/contributors.sh
index 6be35d5..90ea5c9 100755
--- a/scripts/contributors.sh
+++ b/scripts/contributors.sh
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2013 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -60,17 +60,17 @@
git log --pretty=full --use-mailmap $start..HEAD
if [ -d "$CURLWWW" ]
then
- git -C ../curl-www log --pretty=full --use-mailmap $start..HEAD
+ git -C "$CURLWWW" log --pretty=full --use-mailmap $start..HEAD
fi
) | \
-egrep -ai '(^Author|^Commit|by):' | \
+grep -Eai '(^Author|^Commit|by):' | \
cut -d: -f2- | \
cut '-d(' -f1 | \
cut '-d<' -f1 | \
tr , '\012' | \
sed 's/ at github/ on github/' | \
sed 's/ and /\n/' | \
-sed -e 's/^ //' -e 's/ $//g' -e 's/@users.noreply.github.com$/ on github/'
+sed -e 's/^ *//' -e 's/ $//g' -e 's/@users.noreply.github.com$/ on github/'
grep -a "^ [^ \(]" RELEASE-NOTES| \
sed 's/, */\n/g'| \
@@ -78,18 +78,18 @@
)| \
sed -f ./docs/THANKS-filter | \
-grep -a ' ' | \
sort -fu | \
awk '{
- num++;
- n = sprintf("%s%s%s,", n, length(n)?" ":"", $0);
- #print n;
- if(length(n) > 77) {
- printf(" %s\n", p);
- n=sprintf("%s,", $0);
+ if(length($0)) {
+ num++;
+ n = sprintf("%s%s%s,", n, length(n)?" ":"", $0);
+ #print n;
+ if(length(n) > 77) {
+ printf(" %s\n", p);
+ n=sprintf("%s,", $0);
+ }
+ p=n;
}
- p=n;
-
}
END {
diff --git a/scripts/contrithanks.sh b/scripts/contrithanks.sh
index 38c7b89..b188422 100755
--- a/scripts/contrithanks.sh
+++ b/scripts/contrithanks.sh
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2013 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -55,7 +55,7 @@
fi
) | \
-egrep -ai '(^Author|^Commit|by):' | \
+grep -Eai '(^Author|^Commit|by):' | \
cut -d: -f2- | \
cut '-d(' -f1 | \
cut '-d<' -f1 | \
@@ -73,6 +73,5 @@
)| \
sed -f ./docs/THANKS-filter | \
-grep -a ' ' | \
sort -fu | \
grep -aixvf ./docs/THANKS
diff --git a/scripts/copyright.pl b/scripts/copyright.pl
index 89f6b78..c83b7eb 100755
--- a/scripts/copyright.pl
+++ b/scripts/copyright.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -39,17 +39,10 @@
# License texts
"LICENSES/BSD-3-Clause.txt" => "<built-in>",
"LICENSES/BSD-4-Clause-UC.txt" => "<built-in>",
- "LICENSES/GPL-3.0-or-later.txt" => "<built-in>",
"LICENSES/ISC.txt" => "<built-in>",
- "LICENSES/LicenseRef-OpenEvidence.txt" => "<built-in>",
"LICENSES/curl.txt" => "<built-in>",
"COPYING" => "<built-in>",
- # imported, leave be
- 'm4/ax_compile_check_sizeof.m4' => "<built-in>",
-
- # an empty control file
- "zuul.d/playbooks/.zuul.ignore" => "<built-in>",
);
sub scanfile {
@@ -61,7 +54,8 @@
chomp;
my $l = $_;
# check for a copyright statement and save the years
- if($l =~ /.* ?copyright .* *\d\d\d\d/i) {
+ if($l =~ /.* ?copyright .* (\d\d\d\d|)/i) {
+ my $count = 0;
while($l =~ /([\d]{4})/g) {
push @copyright, {
year => $1,
@@ -69,8 +63,19 @@
col => index($l, $1),
code => $l
};
- $found++;
+ $count++;
}
+ if(!$count) {
+ # year-less
+ push @copyright, {
+ year => -1,
+ line => $line,
+ col => index($l, $1),
+ code => $l
+ };
+ $count++;
+ }
+ $found = $count;
}
if($l =~ /SPDX-License-Identifier:/) {
$spdx = 1;
@@ -86,8 +91,6 @@
sub checkfile {
my ($file, $skipped, $pattern) = @_;
- my $fine = 0;
- @copyright=();
$spdx = 0;
my $found = scanfile($file);
@@ -115,38 +118,12 @@
return 2;
}
- my $commityear = undef;
- @copyright = sort {$$b{year} cmp $$a{year}} @copyright;
-
- # if the file is modified, assume commit year this year
- if(`git status -s -- $file` =~ /^ [MARCU]/) {
- $commityear = (localtime(time))[5] + 1900;
- }
- else {
- # min-parents=1 to ignore wrong initial commit in truncated repos
- my $grl = `git rev-list --max-count=1 --min-parents=1 --timestamp HEAD -- $file`;
- if($grl) {
- chomp $grl;
- $commityear = (localtime((split(/ /, $grl))[0]))[5] + 1900;
- }
- }
-
- if(defined($commityear) && scalar(@copyright) &&
- $copyright[0]{year} != $commityear) {
- printf "$file:%d: copyright year out of date, should be $commityear, " .
- "is $copyright[0]{year}\n",
- $copyright[0]{line} if(!$skipped || $verbose);
- $skips{$pattern}++ if($skipped);
- }
- else {
- $fine = 1;
- }
- if($skipped && $fine) {
+ if($skipped) {
print "$file:1: ignored superfluously by $pattern\n" if($verbose);
$superf{$pattern}++;
}
- return $fine;
+ return 1;
}
sub dep5 {
@@ -185,6 +162,7 @@
dep5(".reuse/dep5");
+my $checkall = 0;
my @all;
my $verbose;
if($ARGV[0] eq "-v") {
@@ -196,6 +174,7 @@
}
else {
@all = `git ls-files`;
+ $checkall = 1;
}
for my $f (@all) {
@@ -208,6 +187,7 @@
$pattern = $skip;
$skiplisted++;
$skipped = 1;
+ $skip{$f}++;
}
my $r = checkfile($f, $skipped, $pattern);
@@ -236,4 +216,12 @@
}
}
+if($checkall) {
+ for(keys %skiplist) {
+ if(!$skip{$_}) {
+ printf STDERR "$_ is marked for SKIP but is missing!\n";
+ }
+ }
+}
+
exit 1 if($missing || $wrong);
diff --git a/scripts/coverage.sh b/scripts/coverage.sh
index f3db9af..0a7c782 100755
--- a/scripts/coverage.sh
+++ b/scripts/coverage.sh
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/scripts/delta b/scripts/delta
index 3c6a823..3920a79 100755
--- a/scripts/delta
+++ b/scripts/delta
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2018-2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -59,8 +59,20 @@
$contribs = $acontribs - $bcontribs;
# number of setops:
-$asetopts=`grep '^ CURLOPT(' include/curl/curl.h | grep -cv OBSOLETE`;
-$bsetopts=`git show $start:include/curl/curl.h | grep '^ CURLOPT(' | grep -cv OBSOLETE`;
+sub setopts {
+ my ($f)=@_;
+ open(H, "$f");
+ my $opts;
+ while(<H>) {
+ if(/^ CURLOPT(|DEPRECATED)\(/ && ($_ !~ /OBSOLETE/)) {
+ $opts++;
+ }
+ }
+ close(H);
+ return $opts;
+}
+$asetopts = setopts("<include/curl/curl.h");
+$bsetopts = setopts("git show $start:include/curl/curl.h|");
$nsetopts = $asetopts - $bsetopts;
# Number of command line options:
@@ -73,8 +85,8 @@
chomp $branch;
# Number of files in git
$afiles=`git ls-files | wc -l`;
-$deletes=`git diff-tree --diff-filter=A -r --summary origin/$branch $start | wc -l`;
-$creates=`git diff-tree --diff-filter=D -r --summary origin/$branch $start | wc -l`;
+$deletes=`git diff-tree --diff-filter=A -r --summary origin/$branch $start 2>/dev/null | wc -l`;
+$creates=`git diff-tree --diff-filter=D -r --summary origin/$branch $start 2>/dev/null| wc -l`;
# Time since that tag
$tagged=`git for-each-ref --format="%(refname:short) | %(taggerdate:unix)" refs/tags/* | grep ^$start | cut "-d|" -f2`; # unix timestamp
@@ -150,7 +162,7 @@
printf "Deleted files: %d (delta: %d)\n", $deletes,
$creates - $deletes;
print "Diffstat:$diffstat" if(!$fileschanged);
-printf "Files changed: %d\n", $fileschanged;
+printf "Files changed: %d (%.2f%%)\n", $fileschanged, $fileschanged*100/$afiles;
printf "Lines inserted: %d\n", $insertions;
printf "Lines deleted: %d (delta: %d)\n", $deletions,
$insertions - $deletions;
diff --git a/scripts/firefox-db2pem.sh b/scripts/firefox-db2pem.sh
index 36c2de9..f78f415 100755
--- a/scripts/firefox-db2pem.sh
+++ b/scripts/firefox-db2pem.sh
@@ -6,7 +6,7 @@
# * | (__| |_| | _ <| |___
# * \___|\___/|_| \_\_____|
# *
-# * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
# *
# * This software is licensed as described in the file COPYING, which
# * you should have received as part of this distribution. The terms
diff --git a/scripts/installcheck.sh b/scripts/installcheck.sh
old mode 100644
new mode 100755
index f7df595..433420e
--- a/scripts/installcheck.sh
+++ b/scripts/installcheck.sh
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/scripts/log2changes.pl b/scripts/log2changes.pl
index 1af7057..3554183 100755
--- a/scripts/log2changes.pl
+++ b/scripts/log2changes.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -37,6 +37,18 @@
return $date;
}
+sub printmsg {
+ my ($p, $msg)=@_;
+ while(length($msg) > 77) {
+ print $p.substr($msg, 0, 77, "")."\n";
+ $p=" ";
+ }
+ if($msg eq "") {
+ $p = "";
+ }
+ print "$p$msg\n";
+}
+
print
' _ _ ____ _
___| | | | _ \| |
@@ -47,7 +59,6 @@
Changelog
';
-my $line;
my $tag;
while(<STDIN>) {
my $l = $_;
@@ -61,44 +72,32 @@
}
}
elsif($l =~ /^Author: *(.*) +</) {
- $a = $1;
- }
- elsif($l =~ /^Commit: *(.*) +</) {
$c = $1;
}
elsif($l =~ /^CommitDate: (.*)/) {
$date = nicedate($1);
}
elsif($l =~ /^( )(.*)/) {
- my $extra;
+ my $pref = " ";
if ($tag) {
# Version entries have a special format
print "\nVersion " . $tag." ($date)\n";
$oldc = "";
$tag = "";
}
- if($a ne $c) {
- $extra=sprintf("\n- [%s brought this change]\n\n ", $a);
- }
- else {
- $extra="\n- ";
- }
if($co ne $oldco) {
if($c ne $oldc) {
- print "\n$c ($date)$extra";
+ print "\n$c ($date)\n\n";
}
else {
- print "$extra";
+ print "\n";
}
- $line =0;
+ $pref = "- ";
}
$oldco = $co;
$oldc = $c;
$olddate = $date;
- if($line++ && $2 ne "") {
- print " ";
- }
- print $2."\n";
+ printmsg($pref, $2);
}
}
diff --git a/scripts/mk-ca-bundle.pl b/scripts/mk-ca-bundle.pl
index 926478f..83027a4 100755
--- a/scripts/mk-ca-bundle.pl
+++ b/scripts/mk-ca-bundle.pl
@@ -6,7 +6,7 @@
# * | (__| |_| | _ <| |___
# * \___|\___/|_| \_\_____|
# *
-# * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
# *
# * This software is licensed as described in the file COPYING, which
# * you should have received as part of this distribution. The terms
diff --git a/scripts/release-notes.pl b/scripts/release-notes.pl
index 6afd533..136b48f 100755
--- a/scripts/release-notes.pl
+++ b/scripts/release-notes.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -88,6 +88,7 @@
# 'num'
# 'https://github.com/curl/curl/issues/6939'
# 'https://github.com/curl/curl-www/issues/69'
+# 'https://elsewhere.example.com/discussion'
sub extract {
my ($ref)=@_;
@@ -99,10 +100,11 @@
# return the plain number
return $1;
}
- else {
- # return the URL
+ elsif($ref =~ /:\/\//) {
+ # contains a '://', return the URL
return $ref;
}
+ # false alarm, not a valid line
}
my $short;
@@ -123,6 +125,7 @@
elsif(($l =~ /^ (.*)/) && !$first) {
# first line
$short = $1;
+ $short =~ s/ ?\[(ci skip|skip ci)\]//g;
$first = 1;
push @line, $short;
}
@@ -131,13 +134,16 @@
my $line = $1;
if($line =~ /^Fixes(:|) *(.*)/i) {
- push @fixes, extract($2);
+ my $ref = extract($2);
+ push @fixes, $ref if($ref);
}
elsif($line =~ /^Clo(s|)es(:|) *(.*)/i) {
- push @closes, extract($3);
+ my $ref = extract($3);
+ push @closes, $ref if($ref);
}
elsif($line =~ /^Bug: (.*)/i) {
- push @bug, extract($1);
+ my $ref = extract($1);
+ push @bug, $ref if($ref);
}
}
}
diff --git a/scripts/singleuse.pl b/scripts/singleuse.pl
index 0b707f4..3ed171a 100755
--- a/scripts/singleuse.pl
+++ b/scripts/singleuse.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -150,6 +150,11 @@
'curl_url_strerror' => 'API',
'curl_version' => 'API',
'curl_version_info' => 'API',
+ 'curl_easy_header' => 'API',
+ 'curl_easy_nextheader' => 'API',
+ 'curl_ws_meta' => 'API',
+ 'curl_ws_recv' => 'API',
+ 'curl_ws_send' => 'API',
# the following functions are provided globally in debug builds
'curl_easy_perform_ev' => 'debug-build',
diff --git a/scripts/updatemanpages.pl b/scripts/updatemanpages.pl
index fd461e4..58a8755 100755
--- a/scripts/updatemanpages.pl
+++ b/scripts/updatemanpages.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/scripts/zuul/before_script.sh b/scripts/zuul/before_script.sh
deleted file mode 100755
index a40bf6e..0000000
--- a/scripts/zuul/before_script.sh
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/bin/bash
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-set -eo pipefail
-
-autoreconf -fi
-
-if [ "$NGTCP2" = yes ]; then
- if [ "$TRAVIS_OS_NAME" = linux -a "$GNUTLS" ]; then
- cd $HOME
- git clone --depth 1 https://gitlab.com/gnutls/nettle.git
- cd nettle
- ./.bootstrap
- ./configure LDFLAGS="-Wl,-rpath,$HOME/ngbuild/lib" --disable-documentation --prefix=$HOME/ngbuild
- make
- make install
-
- cd $HOME
- git clone --depth 1 -b 3.7.4 https://gitlab.com/gnutls/gnutls.git pgtls
- cd pgtls
- ./bootstrap
- ./configure PKG_CONFIG_PATH=$HOME/ngbuild/lib/pkgconfig LDFLAGS="-Wl,-rpath,$HOME/ngbuild/lib" --with-included-libtasn1 --with-included-unistring --disable-guile --disable-doc --disable-tools --without-zstd --disable-psk-authentication --prefix=$HOME/ngbuild
- make
- make install
- else
- cd $HOME
- git clone --depth 1 -b OpenSSL_1_1_1j+quic https://github.com/quictls/openssl possl
- cd possl
- ./config enable-tls1_3 --prefix=$HOME/ngbuild
- make
- make install_sw
- fi
-
- cd $HOME
- git clone --depth 1 https://github.com/ngtcp2/nghttp3
- cd nghttp3
- autoreconf -i
- ./configure --prefix=$HOME/ngbuild --enable-lib-only
- make
- make install
-
- cd $HOME
- git clone --depth 1 https://github.com/ngtcp2/ngtcp2
- cd ngtcp2
- autoreconf -i
- if test -n "$GNUTLS"; then
- WITHGNUTLS="--with-gnutls"
- fi
- ./configure PKG_CONFIG_PATH=$HOME/ngbuild/lib/pkgconfig LDFLAGS="-Wl,-rpath,$HOME/ngbuild/lib" --prefix=$HOME/ngbuild --enable-lib-only $WITHGNUTLS
- make
- make install
-fi
-
-if [ "$TRAVIS_OS_NAME" = linux -a "$BORINGSSL" ]; then
- cd $HOME
- git clone --depth=1 https://boringssl.googlesource.com/boringssl
- cd boringssl
- mkdir -p build
- cd ./build
- CXX="g++" CC="gcc" cmake .. -GNinja -DCMAKE_BUILD_TYPE=release -DBUILD_SHARED_LIBS=1
- cd ..
- cmake --build build
- mkdir lib
- cp ./build/crypto/libcrypto.so ./lib/
- cp ./build/ssl/libssl.so ./lib/
- echo "BoringSSL lib dir: "`pwd`"/lib"
- cmake --build build --target clean
- rm -f build/CMakeCache.txt
- cd ./build
- CXX="g++" CC="gcc" cmake .. -GNinja -DCMAKE_POSITION_INDEPENDENT_CODE=on
- cd ..
- cmake --build build
- export LIBS=-lpthread
-fi
-
-if [ "$TRAVIS_OS_NAME" = linux -a "$LIBRESSL" ]; then
- cd $HOME
- git clone --depth=1 -b v3.1.4 https://github.com/libressl-portable/portable.git libressl-git
- cd libressl-git
- ./autogen.sh
- ./configure --prefix=$HOME/libressl
- make
- make install
-fi
-
-if [ "$TRAVIS_OS_NAME" = linux -a "$QUICHE" ]; then
- cd $HOME
- git clone --depth=1 --recursive https://github.com/cloudflare/quiche.git
- curl https://sh.rustup.rs -sSf | sh -s -- -y
- source $HOME/.cargo/env
- cd $HOME/quiche
-
- #### Work-around https://github.com/curl/curl/issues/7927 #######
- #### See https://github.com/alexcrichton/cmake-rs/issues/131 ####
- sed -i -e 's/cmake = "0.1"/cmake = "=0.1.45"/' quiche/Cargo.toml
-
- cargo build -v --package quiche --release --features ffi,pkg-config-meta,qlog
- mkdir -v quiche/deps/boringssl/src/lib
- ln -vnf $(find target/release -name libcrypto.a -o -name libssl.a) quiche/deps/boringssl/src/lib/
-fi
diff --git a/scripts/zuul/script.sh b/scripts/zuul/script.sh
deleted file mode 100755
index 8a80023..0000000
--- a/scripts/zuul/script.sh
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/bin/bash
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-set -eo pipefail
-
-autoreconf -fi
-
-if [ "$T" = "coverage" ]; then
- ./configure --enable-debug --disable-shared --disable-threaded-resolver --enable-code-coverage --enable-werror --with-libssh2
- make
- make TFLAGS=-n test-nonflaky
- make "TFLAGS=-n -e" test-nonflaky
- tests="1 200 300 500 700 800 900 1000 1100 1200 1302 1400 1502 3000"
- make "TFLAGS=-n -t $tests" test-nonflaky
- coveralls --gcov /usr/bin/gcov-8 --gcov-options '\-lp' -i src -e lib -e tests -e docs -b $PWD/src
- coveralls --gcov /usr/bin/gcov-8 --gcov-options '\-lp' -e src -i lib -e tests -e docs -b $PWD/lib
-fi
-
-if [ "$T" = "torture" ]; then
- ./configure --enable-debug --disable-shared --disable-threaded-resolver --enable-code-coverage --enable-werror --with-libssh2 --with-openssl
- make
- tests="!TLS-SRP !FTP"
- make "TFLAGS=-n --shallow=20 -t $tests" test-nonflaky
-fi
-
-if [ "$T" = "debug" ]; then
- ./configure --enable-debug --enable-werror $C
- make
- make examples
- if [ -z $NOTESTS ]; then
- make test-nonflaky
- fi
-fi
-
-if [ "$T" = "debug-bearssl" ]; then
- ./configure --enable-debug --enable-werror $C
- make
- make "TFLAGS=-n !313" test-nonflaky
-fi
-
-if [ "$T" = "novalgrind" ]; then
- ./configure --enable-werror $C
- make
- make examples
- make TFLAGS=-n test-nonflaky
-fi
-
-if [ "$T" = "normal" ]; then
- if [ $TRAVIS_OS_NAME = linux ]; then
- # Remove system curl to make sure we don't rely on it.
- # Only done on Linux since we're not permitted to on mac.
- sudo rm -f /usr/bin/curl
- fi
- ./configure --enable-warnings --enable-werror $C
- make
- make examples
- if [ -z $NOTESTS ]; then
- make test-nonflaky
- fi
- if [ -n "$CHECKSRC" ]; then
- make checksrc
- fi
-fi
-
-if [ "$T" = "tidy" ]; then
- ./configure --enable-warnings --enable-werror $C
- make
- make tidy
-fi
-
-if [ "$T" = "cmake" ]; then
- mkdir -p build
- cd ./build
- cmake .. -DCURL_WERROR=ON $C
- cd ..
- cmake --build build
- env TFLAGS="!1139 $TFLAGS" cmake --build build --target test-nonflaky
-fi
-
-if [ "$T" = "fuzzer" ]; then
- # Download the fuzzer to a temporary folder
- ./tests/fuzz/download_fuzzer.sh /tmp/curl_fuzzer
-
- export CURLSRC=$PWD
-
- # Run the mainline fuzzer test
- pushd /tmp/curl_fuzzer
- ./mainline.sh ${CURLSRC}
- popd
-fi
diff --git a/src/.gitignore b/src/.gitignore
index 5662162..124b474 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 56d5d53..bbe79be 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -47,9 +47,7 @@
else()
add_custom_command(
OUTPUT tool_hugehelp.c
- COMMAND ${CMAKE_COMMAND} -E echo "/* built-in manual is disabled, blank function */" > tool_hugehelp.c
- COMMAND ${CMAKE_COMMAND} -E echo "#include \"tool_hugehelp.h\"" >> tool_hugehelp.c
- COMMAND ${CMAKE_COMMAND} -E echo "void hugehelp(void) {}" >> tool_hugehelp.c
+ COMMAND ${CMAKE_COMMAND} -E echo "#include \"tool_hugehelp.h\"" > tool_hugehelp.c
DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/tool_hugehelp.h"
VERBATIM)
@@ -60,13 +58,17 @@
include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake)
if(WIN32)
- list(APPEND CURL_FILES curl.rc)
+ list(APPEND CURL_CFILES curl.rc)
endif()
-# CURL_FILES comes from Makefile.inc
+# CURL_CFILES, CURLX_CFILES, CURL_HFILES come from Makefile.inc
+if(NOT BUILD_SHARED_LIBS)
+ set(CURLX_CFILES ../lib/dynbuf.c)
+endif()
+
add_executable(
${EXE_NAME}
- ${CURL_FILES}
+ ${CURL_CFILES} ${CURLX_CFILES} ${CURL_HFILES}
)
add_executable(
@@ -74,6 +76,14 @@
ALIAS ${EXE_NAME}
)
+add_library(
+ curltool # special libcurltool library just for unittests
+ STATIC
+ EXCLUDE_FROM_ALL
+ ${CURL_CFILES} ${CURLX_CFILES} ${CURL_HFILES}
+)
+target_compile_definitions(curltool PUBLIC UNITTESTS CURL_STATICLIB)
+
if(CURL_HAS_LTO)
set_target_properties(${EXE_NAME} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
@@ -82,8 +92,6 @@
if(ENABLE_UNICODE AND MINGW)
target_link_libraries(${EXE_NAME} -municode)
- # GCC doesn't know about wmain
- set_source_files_properties(tool_main.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes -Wno-missing-declarations")
endif()
source_group("curlX source files" FILES ${CURLX_CFILES})
@@ -111,6 +119,6 @@
install(TARGETS ${EXE_NAME} EXPORT ${TARGETS_EXPORT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
export(TARGETS ${EXE_NAME}
- APPEND FILE ${PROJECT_BINARY_DIR}/curl-target.cmake
+ FILE ${PROJECT_BINARY_DIR}/curl-target.cmake
NAMESPACE ${PROJECT_NAME}::
)
diff --git a/src/Makefile.am b/src/Makefile.am
index 706f0aa..63f2916 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -55,6 +55,10 @@
# CURL_FILES comes from Makefile.inc
curl_SOURCES = $(CURL_FILES)
+if HAVE_WINDRES
+curl_SOURCES += $(CURL_RCFILES)
+$(CURL_RCFILES): tool_version.h
+endif
# This might hold -Werror
CFLAGS += @CURL_CFLAG_EXTRAS@
@@ -75,16 +79,16 @@
-DCURL_STATICLIB -DUNITTESTS
libcurltool_la_CFLAGS =
libcurltool_la_LDFLAGS = -static $(LINKFLAGS)
-libcurltool_la_SOURCES = $(curl_SOURCES)
+libcurltool_la_SOURCES = $(CURL_FILES)
endif
CLEANFILES = tool_hugehelp.c
# Use the C locale to ensure that only ASCII characters appear in the
# embedded text.
-NROFF=env LC_ALL=C @NROFF@ @MANOPT@ # figured out by the configure script
+NROFF=env LC_ALL=C @NROFF@ @MANOPT@ 2>/dev/null # figured out by the configure script
-EXTRA_DIST = mkhelp.pl makefile.dj \
- Makefile.m32 makefile.amiga curl.rc Makefile.inc CMakeLists.txt
+EXTRA_DIST = mkhelp.pl \
+ Makefile.mk curl.rc Makefile.inc CMakeLists.txt
# Use absolute directory to disable VPATH
MANPAGE=$(abs_top_builddir)/docs/curl.1
@@ -127,9 +131,7 @@
else # USE_MANUAL
# built-in manual has been disabled, make a blank file
$(HUGE):
- $(HUGECMD)(echo "/* built-in manual is disabled, blank function */" > $(HUGE); \
- echo '#include "tool_hugehelp.h"' >> $(HUGE); \
- echo "void hugehelp(void) {}" >>$(HUGE) )
+ echo '#include "tool_hugehelp.h"' >> $(HUGE)
endif
# ignore tool_hugehelp.c since it is generated source code and it plays
@@ -153,3 +155,8 @@
listhelp:
(cd $(top_srcdir)/docs/cmdline-opts && ./gen.pl listhelp *.d) > tool_listhelp.c
+
+if HAVE_WINDRES
+.rc.o:
+ $(RC) -I$(top_srcdir)/include -DCURL_EMBED_MANIFEST $(RCFLAGS) -i $< -o $@
+endif
diff --git a/src/Makefile.inc b/src/Makefile.inc
index 92c1207..ec822c8 100644
--- a/src/Makefile.inc
+++ b/src/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -36,7 +36,6 @@
../lib/timediff.c \
../lib/nonblock.c \
../lib/warnless.c \
- ../lib/curl_ctype.c \
../lib/curl_multibyte.c \
../lib/version_win32.c \
../lib/dynbuf.c
@@ -80,10 +79,10 @@
tool_msgs.c \
tool_operate.c \
tool_operhlp.c \
- tool_panykey.c \
tool_paramhlp.c \
tool_parsecfg.c \
tool_progress.c \
+ tool_stderr.c \
tool_strdup.c \
tool_setopt.c \
tool_sleep.c \
@@ -121,7 +120,6 @@
tool_msgs.h \
tool_operate.h \
tool_operhlp.h \
- tool_panykey.h \
tool_paramhlp.h \
tool_parsecfg.h \
tool_progress.h \
@@ -129,6 +127,7 @@
tool_setopt.h \
tool_setup.h \
tool_sleep.h \
+ tool_stderr.h \
tool_strdup.h \
tool_urlglob.h \
tool_util.h \
diff --git a/src/Makefile.m32 b/src/Makefile.m32
deleted file mode 100644
index b3d3cf9..0000000
--- a/src/Makefile.m32
+++ /dev/null
@@ -1,444 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1999 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-#***************************************************************************
-
-###########################################################################
-#
-## Makefile for building curl.exe with MingW (GCC-3.2 or later or LLVM/Clang)
-## and optionally OpenSSL (1.0.2a), libssh2 (1.5), zlib (1.2.8), librtmp (2.4),
-## brotli (1.0.1), zstd (1.4.5)
-##
-## Usage: mingw32-make -f Makefile.m32 CFG=-feature1[-feature2][-feature3][...]
-## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-sspi-winidn
-##
-## Hint: you can also set environment vars to control the build, f.e.:
-## set ZLIB_PATH=c:/zlib-1.2.8
-## set ZLIB=1
-#
-###########################################################################
-
-# Edit the path below to point to the base of your Zlib sources.
-ifndef ZLIB_PATH
-ZLIB_PATH = ../../zlib-1.2.8
-endif
-# Edit the path below to point to the base of your Zstandard sources.
-ifndef ZSTD_PATH
-ZSTD_PATH = ../../zstd-1.4.5
-endif
-# Edit the path below to point to the base of your Brotli sources.
-ifndef BROTLI_PATH
-BROTLI_PATH = ../../brotli-1.0.1
-endif
-# Edit the path below to point to the base of your OpenSSL package.
-ifndef OPENSSL_PATH
-OPENSSL_PATH = ../../openssl-1.0.2a
-endif
-# Edit the path below to point to the base of your LibSSH2 package.
-ifndef LIBSSH2_PATH
-LIBSSH2_PATH = ../../libssh2-1.5.0
-endif
-# Edit the path below to point to the base of your librtmp package.
-ifndef LIBRTMP_PATH
-LIBRTMP_PATH = ../../librtmp-2.4
-endif
-# Edit the path below to point to the base of your libexpat package.
-ifndef LIBEXPAT_PATH
-LIBEXPAT_PATH = ../../expat-2.1.0
-endif
-# Edit the path below to point to the base of your libxml2 package.
-ifndef LIBXML2_PATH
-LIBXML2_PATH = ../../libxml2-2.9.2
-endif
-# Edit the path below to point to the base of your libgsasl package.
-ifndef LIBGSASL_PATH
-LIBGSASL_PATH = ../../libgsasl-1.10.0
-endif
-# Edit the path below to point to the base of your libidn2 package.
-ifndef LIBIDN2_PATH
-LIBIDN2_PATH = ../../libidn2-2.0.3
-endif
-# Edit the path below to point to the base of your MS IDN package.
-# Microsoft Internationalized Domain Names (IDN) Mitigation APIs 1.1
-# https://www.microsoft.com/en-us/download/details.aspx?id=734
-ifndef WINIDN_PATH
-WINIDN_PATH = ../../Microsoft IDN Mitigation APIs
-endif
-# Edit the path below to point to the base of your Novell LDAP NDK.
-ifndef LDAP_SDK
-LDAP_SDK = c:/novell/ndk/cldapsdk/win32
-endif
-# Edit the path below to point to the base of your nghttp2 package.
-ifndef NGHTTP2_PATH
-NGHTTP2_PATH = ../../nghttp2-1.0.0
-endif
-# Edit the path below to point to the base of your nghttp3 package.
-ifndef NGHTTP3_PATH
-NGHTTP3_PATH = ../../nghttp3-1.0.0
-endif
-# Edit the path below to point to the base of your ngtcp2 package.
-ifndef NGTCP2_PATH
-NGTCP2_PATH = ../../ngtcp2-1.0.0
-endif
-
-PROOT = ..
-
-# Edit the path below to point to the base of your c-ares package.
-ifndef LIBCARES_PATH
-LIBCARES_PATH = $(PROOT)/ares
-endif
-
-ifeq ($(CURL_CC),)
-CURL_CC := $(CROSSPREFIX)gcc
-endif
-ifeq ($(CURL_AR),)
-CURL_AR := $(CROSSPREFIX)ar
-endif
-
-CC = $(CURL_CC)
-CFLAGS = -O3 $(CURL_CFLAG_EXTRAS) -W -Wall
-LDFLAGS = $(CURL_LDFLAG_EXTRAS) $(CURL_LDFLAG_EXTRAS_EXE)
-AR = $(CURL_AR)
-RC = $(CROSSPREFIX)windres
-RCFLAGS = --include-dir=$(PROOT)/include -O coff -DCURL_EMBED_MANIFEST
-STRIP = $(CROSSPREFIX)strip -g
-
-# We may need these someday
-# PERL = perl
-# NROFF = nroff
-
-# Set environment var ARCH to your architecture to override autodetection.
-ifndef ARCH
-ifeq ($(findstring x86_64,$(shell $(CC) -dumpmachine)),x86_64)
-ARCH = w64
-else
-ARCH = w32
-endif
-endif
-
-ifeq ($(ARCH),w64)
-CFLAGS += -m64
-LDFLAGS += -m64
-RCFLAGS += -F pe-x86-64
-else
-CFLAGS += -m32
-LDFLAGS += -m32
-RCFLAGS += -F pe-i386
-endif
-
-# Platform-dependent helper tool macros
-ifeq ($(findstring /sh,$(SHELL)),/sh)
-DEL = rm -f $1
-RMDIR = rm -fr $1
-MKDIR = mkdir -p $1
-COPY = -cp -afv $1 $2
-#COPYR = -cp -afr $1/* $2
-COPYR = -rsync -aC $1/* $2
-TOUCH = touch $1
-CAT = cat
-ECHONL = echo ""
-DL = '
-else
-ifeq "$(OS)" "Windows_NT"
-DEL = -del 2>NUL /q /f $(subst /,\,$1)
-RMDIR = -rd 2>NUL /q /s $(subst /,\,$1)
-else
-DEL = -del 2>NUL $(subst /,\,$1)
-RMDIR = -deltree 2>NUL /y $(subst /,\,$1)
-endif
-MKDIR = -md 2>NUL $(subst /,\,$1)
-COPY = -copy 2>NUL /y $(subst /,\,$1) $(subst /,\,$2)
-COPYR = -xcopy 2>NUL /q /y /e $(subst /,\,$1) $(subst /,\,$2)
-TOUCH = copy 2>&1>NUL /b $(subst /,\,$1) +,,
-CAT = type
-ECHONL = $(ComSpec) /c echo.
-endif
-
-########################################################
-## Nothing more to do below this line!
-
-ifneq ($(findstring -dyn,$(CFG)),)
-DYN = 1
-endif
-ifneq ($(findstring -ares,$(CFG)),)
-ARES = 1
-endif
-ifneq ($(findstring -sync,$(CFG)),)
-SYNC = 1
-endif
-ifneq ($(findstring -rtmp,$(CFG)),)
-RTMP = 1
-ZLIB = 1
-endif
-ifneq ($(findstring -ssh2,$(CFG)),)
-SSH2 = 1
-ZLIB = 1
-endif
-ifneq ($(findstring -ssl,$(CFG)),)
-SSL = 1
-endif
-ifneq ($(findstring -zlib,$(CFG)),)
-ZLIB = 1
-endif
-ifneq ($(findstring -zstd,$(CFG)),)
-ZSTD = 1
-endif
-ifneq ($(findstring -brotli,$(CFG)),)
-BROTLI = 1
-endif
-ifneq ($(findstring -gsasl,$(CFG)),)
-GSASL = 1
-endif
-ifneq ($(findstring -idn2,$(CFG)),)
-IDN2 = 1
-endif
-ifneq ($(findstring -winidn,$(CFG)),)
-WINIDN = 1
-endif
-ifneq ($(findstring -sspi,$(CFG)),)
-SSPI = 1
-endif
-ifneq ($(findstring -ldaps,$(CFG)),)
-LDAPS = 1
-endif
-ifneq ($(findstring -ipv6,$(CFG)),)
-IPV6 = 1
-endif
-ifneq ($(findstring -schannel,$(CFG))$(findstring -winssl,$(CFG)),)
-SCHANNEL = 1
-SSPI = 1
-endif
-ifneq ($(findstring -nghttp2,$(CFG)),)
-NGHTTP2 = 1
-endif
-ifneq ($(findstring -nghttp3,$(CFG)),)
-NGHTTP3 = 1
-endif
-ifneq ($(findstring -ngtcp2,$(CFG)),)
-NGTCP2 = 1
-endif
-ifneq ($(findstring -unicode,$(CFG)),)
-UNICODE = 1
-endif
-
-# SSH2 and RTMP require an SSL library; assume OpenSSL if none specified
-ifneq ($(SSH2)$(RTMP),)
- ifeq ($(SSL)$(SCHANNEL),)
- SSL = 1
- endif
-endif
-
-INCLUDES = -I. -I../include -I../lib
-ifdef SSL
- ifdef SCHANNEL
- CFLAGS += -DCURL_WITH_MULTI_SSL
- endif
-endif
-ifdef UNICODE
- CFLAGS += -DUNICODE -D_UNICODE
- LDFLAGS += -municode
-endif
-
-ifdef DYN
- curl_DEPENDENCIES = $(PROOT)/lib/libcurldll.a $(PROOT)/lib/libcurl.dll
- curl_LDADD = -L$(PROOT)/lib -lcurldll
-else
- curl_DEPENDENCIES = $(PROOT)/lib/libcurl.a
- curl_LDADD = -L$(PROOT)/lib -lcurl
- CFLAGS += -DCURL_STATICLIB
- LDFLAGS += -static
-endif
-ifdef SYNC
- CFLAGS += -DUSE_SYNC_DNS
-else
- ifdef ARES
- ifndef DYN
- curl_DEPENDENCIES += $(LIBCARES_PATH)/libcares.a
- endif
- CFLAGS += -DUSE_ARES -DCARES_STATICLIB
- curl_LDADD += -L"$(LIBCARES_PATH)" -lcares
- endif
-endif
-ifdef RTMP
- CFLAGS += -DUSE_LIBRTMP
- curl_LDADD += -L"$(LIBRTMP_PATH)/librtmp" -lrtmp -lwinmm
-endif
-ifdef NGHTTP2
- CFLAGS += -DUSE_NGHTTP2
- curl_LDADD += -L"$(NGHTTP2_PATH)/lib" -lnghttp2
-endif
-ifdef SSH2
- CFLAGS += -DUSE_LIBSSH2 -DHAVE_LIBSSH2_H
- curl_LDADD += -L"$(LIBSSH2_PATH)/win32" -lssh2
- ifdef SCHANNEL
- ifndef DYN
- curl_LDADD += -lbcrypt -lcrypt32
- endif
- endif
-endif
-ifdef SSL
- ifdef NGHTTP3
- CFLAGS += -DUSE_NGHTTP3
- curl_LDADD += -L"$(NGHTTP3_PATH)/lib" -lnghttp3
- ifdef NGTCP2
- CFLAGS += -DUSE_NGTCP2
- curl_LDADD += -L"$(NGTCP2_PATH)/lib" -lngtcp2 -lngtcp2_crypto_openssl
- endif
- endif
-
- ifndef OPENSSL_INCLUDE
- ifeq "$(wildcard $(OPENSSL_PATH)/outinc)" "$(OPENSSL_PATH)/outinc"
- OPENSSL_INCLUDE = $(OPENSSL_PATH)/outinc
- endif
- ifeq "$(wildcard $(OPENSSL_PATH)/include)" "$(OPENSSL_PATH)/include"
- OPENSSL_INCLUDE = $(OPENSSL_PATH)/include
- endif
- endif
- ifneq "$(wildcard $(OPENSSL_INCLUDE)/openssl/opensslv.h)" "$(OPENSSL_INCLUDE)/openssl/opensslv.h"
- $(error Invalid path to OpenSSL package: $(OPENSSL_PATH))
- endif
- ifndef OPENSSL_LIBPATH
- OPENSSL_LIBS = -lssl -lcrypto
- ifeq "$(wildcard $(OPENSSL_PATH)/out)" "$(OPENSSL_PATH)/out"
- OPENSSL_LIBPATH = $(OPENSSL_PATH)/out
- ifdef DYN
- OPENSSL_LIBS = -lssl32 -leay32
- endif
- endif
- ifeq "$(wildcard $(OPENSSL_PATH)/lib)" "$(OPENSSL_PATH)/lib"
- OPENSSL_LIBPATH = $(OPENSSL_PATH)/lib
- endif
- endif
- ifndef DYN
- OPENSSL_LIBS += -lgdi32 -lcrypt32
- endif
- INCLUDES += -I"$(OPENSSL_INCLUDE)"
- CFLAGS += -DUSE_OPENSSL
- curl_LDADD += -L"$(OPENSSL_LIBPATH)" $(OPENSSL_LIBS)
-endif
-ifdef SCHANNEL
- CFLAGS += -DUSE_SCHANNEL
- curl_LDADD += -lcrypt32
-endif
-ifdef ZLIB
- INCLUDES += -I"$(ZLIB_PATH)"
- CFLAGS += -DHAVE_LIBZ -DHAVE_ZLIB_H
- curl_LDADD += -L"$(ZLIB_PATH)" -lz
-endif
-ifdef ZSTD
- INCLUDES += -I"$(ZSTD_PATH)/include"
- CFLAGS += -DHAVE_ZSTD
- curl_LDADD += -L"$(ZSTD_PATH)/lib"
- ifdef ZSTD_LIBS
- curl_LDADD += $(ZSTD_LIBS)
- else
- curl_LDADD += -lzstd
- endif
-endif
-ifdef BROTLI
- INCLUDES += -I"$(BROTLI_PATH)/include"
- CFLAGS += -DHAVE_BROTLI
- curl_LDADD += -L"$(BROTLI_PATH)/lib"
- ifdef BROTLI_LIBS
- curl_LDADD += $(BROTLI_LIBS)
- else
- curl_LDADD += -lbrotlidec
- endif
-endif
-ifdef GSASL
- CFLAGS += -DUSE_GSASL
- curl_LDADD += -L"$(LIBGSASL_PATH)/lib" -lgsasl
-endif
-ifdef IDN2
- CFLAGS += -DUSE_LIBIDN2
- curl_LDADD += -L"$(LIBIDN2_PATH)/lib" -lidn2
-else
-ifdef WINIDN
- CFLAGS += -DUSE_WIN32_IDN
- curl_LDADD += -L"$(WINIDN_PATH)" -lnormaliz
-endif
-endif
-ifdef SSPI
- CFLAGS += -DUSE_WINDOWS_SSPI
-endif
-ifdef IPV6
- CFLAGS += -DENABLE_IPV6
-endif
-ifdef LDAPS
- CFLAGS += -DHAVE_LDAP_SSL
-endif
-ifdef USE_LDAP_NOVELL
- CFLAGS += -DCURL_HAS_NOVELL_LDAPSDK
- curl_LDADD += -L"$(LDAP_SDK)/lib/mscvc" -lldapsdk -lldapssl -lldapx
-endif
-ifdef USE_LDAP_OPENLDAP
- CFLAGS += -DCURL_HAS_OPENLDAP_LDAPSDK
- curl_LDADD += -L"$(LDAP_SDK)/lib" -lldap -llber
-endif
-ifndef USE_LDAP_NOVELL
-ifndef USE_LDAP_OPENLDAP
-curl_LDADD += -lwldap32
-endif
-endif
-curl_LDADD += -lws2_32
-
-# Makefile.inc provides the CSOURCES and HHEADERS defines
-include Makefile.inc
-
-curl_PROGRAMS = curl.exe
-curl_OBJECTS := $(patsubst %.c,%.o,$(strip $(CURL_CFILES)))
-curlx_OBJECTS := $(patsubst %.c,%.o,$(notdir $(strip $(CURLX_CFILES))))
-curl_OBJECTS += $(curlx_OBJECTS)
-vpath %.c $(PROOT)/lib
-
-RESOURCE = curl.res
-
-
-all: $(curl_PROGRAMS)
-
-curl.exe: $(RESOURCE) $(curl_OBJECTS) $(curl_DEPENDENCIES)
- $(call DEL, $@)
- $(CC) $(LDFLAGS) -o $@ $< $(curl_OBJECTS) $(curl_LDADD)
-
-# We don't have nroff normally under win32
-# tool_hugehelp.c: $(PROOT)/docs/MANUAL $(PROOT)/docs/curl.1 mkhelp.pl
-# @$(call DEL, tool_hugehelp.c)
-# $(NROFF) -man $(PROOT)/docs/curl.1 | $(PERL) mkhelp.pl $(PROOT)/docs/MANUAL > tool_hugehelp.c
-
-tool_hugehelp.c:
- @echo Creating $@
- @$(call COPY, $@.cvs, $@)
-
-%.o: %.c
- $(CC) $(INCLUDES) $(CFLAGS) -c $<
-
-%.res: %.rc
- $(RC) $(RCFLAGS) -i $< -o $@
-
-clean:
-ifeq "$(wildcard tool_hugehelp.c.cvs)" "tool_hugehelp.c.cvs"
- @$(call DEL, tool_hugehelp.c)
-endif
- @$(call DEL, $(curl_OBJECTS) $(curlx_OBJECTS) $(RESOURCE))
-
-distclean vclean: clean
- @$(call DEL, $(curl_PROGRAMS))
diff --git a/src/Makefile.mk b/src/Makefile.mk
new file mode 100644
index 0000000..66882b3
--- /dev/null
+++ b/src/Makefile.mk
@@ -0,0 +1,111 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+#***************************************************************************
+
+# See usage in lib/Makefile.mk
+
+PROOT := ..
+
+### Common
+
+include $(PROOT)/lib/Makefile.mk
+
+### Local
+
+RCFLAGS += -DCURL_EMBED_MANIFEST
+CPPFLAGS += -I$(PROOT)/lib
+LDFLAGS += -L$(PROOT)/lib
+LIBS := -lcurl $(LIBS)
+
+ifdef WIN32
+ ifneq ($(findstring -dyn,$(CFG)),)
+ DYN := 1
+ endif
+endif
+
+ifdef DYN
+ curl_DEPENDENCIES := $(PROOT)/lib/libcurl$(CURL_DLL_SUFFIX).dll
+ curl_DEPENDENCIES += $(PROOT)/lib/libcurl.dll.a
+else
+ curl_DEPENDENCIES := $(PROOT)/lib/libcurl.a
+ ifdef WIN32
+ CPPFLAGS += -DCURL_STATICLIB
+ LDFLAGS += -static
+ endif
+endif
+
+### Sources and targets
+
+# Provides CURL_CFILES, CURLX_CFILES, CURL_RCFILES
+include Makefile.inc
+
+TARGETS := curl$(BIN_EXT)
+
+CURL_CFILES += $(notdir $(CURLX_CFILES))
+
+curl_OBJECTS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(strip $(CURL_CFILES)))
+ifdef WIN32
+curl_OBJECTS += $(patsubst %.rc,$(OBJ_DIR)/%.res,$(strip $(CURL_RCFILES)))
+endif
+ifdef MAP
+CURL_MAP := curl.map
+CURL_LDFLAGS_BIN += -Wl,-Map,$(CURL_MAP)
+TOVCLEAN := $(CURL_MAP)
+endif
+vpath %.c $(PROOT)/lib
+
+TOCLEAN := $(curl_OBJECTS)
+
+### Rules
+
+ifneq ($(wildcard tool_hugehelp.c.cvs),)
+PERL ?= perl
+NROFF ?= groff
+
+TOCLEAN += tool_hugehelp.c
+
+ifneq ($(shell $(call WHICH, $(NROFF))),)
+$(PROOT)/docs/curl.1: $(wildcard $(PROOT)/docs/cmdline-opts/*.d)
+ cd $(PROOT)/docs/cmdline-opts && \
+ $(PERL) gen.pl mainpage $(notdir $^) > ../curl.1
+
+# Necessary for the generated tools_hugehelp.c
+CPPFLAGS += -DUSE_MANUAL
+
+ifdef ZLIB
+_MKHELPOPT += -c
+endif
+tool_hugehelp.c: $(PROOT)/docs/curl.1 mkhelp.pl
+ $(NROFF) -man -Tascii $(MANOPT) $< | \
+ $(PERL) mkhelp.pl $(_MKHELPOPT) $< > $@
+else
+tool_hugehelp.c:
+ @echo Creating $@
+ @$(call COPY, $@.cvs, $@)
+endif
+endif
+
+$(TARGETS): $(curl_OBJECTS) $(curl_DEPENDENCIES)
+ $(CC) $(LDFLAGS) $(CURL_LDFLAGS_BIN) -o $@ $(curl_OBJECTS) $(LIBS)
+
+all: $(OBJ_DIR) $(TARGETS)
diff --git a/src/curl.rc b/src/curl.rc
index b0e3287..11d5284 100644
--- a/src/curl.rc
+++ b/src/curl.rc
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/makefile.amiga b/src/makefile.amiga
deleted file mode 100644
index 70ad277..0000000
--- a/src/makefile.amiga
+++ /dev/null
@@ -1,52 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-#
-# curl Makefile for AmigaOS ...
-#
-
-# change the follow to where you have the AmiTCP SDK v4.3 includes:
-
-ATCPSDKI= /GG/netinclude
-
-
-CC = m68k-amigaos-gcc
-CFLAGS = -I$(ATCPSDKI) -m68020-60 -O2 -msoft-float -noixemul -g -I. -I../include -W -Wall
-LIBS = ../lib/libcurl.a -lssl -lcrypto -lz
-MANPAGE = ../docs/curl.1
-README = ../docs/MANUAL
-MKHELP = ../src/mkhelp.pl
-
-include Makefile.inc
-
-OBJS = $(CURL_CFILES:.c=.o) $(CURLX_CFILES:.c=.o)
-
-all: tool_hugehelp.c $(OBJS)
- $(CC) $(CFLAGS) -o curl $(OBJS) $(LIBS) -Wl,-Map,curl.map,--cref
-
-tool_hugehelp.c: $(README) $(MANPAGE) mkhelp.pl
- rm -f tool_hugehelp.c
- /bin/nroff -man $(MANPAGE) | /bin/perl $(MKHELP) -c $(README) > tool_hugehelp.c
-
-install:
- $(INSTALL) -c curl /c/curl
diff --git a/src/makefile.dj b/src/makefile.dj
deleted file mode 100644
index 84c127b..0000000
--- a/src/makefile.dj
+++ /dev/null
@@ -1,101 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 2003 - 2022, Gisle Vanem <gvanem@yahoo.no>.
-# Copyright (C) 2003 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-#***************************************************************************
-
-#
-# Adapted for djgpp2 / Watt-32 / DOS
-#
-
-DEPEND_PREREQ = # tool_hugehelp.c
-
-TOPDIR = ..
-
-vpath %.c ../lib
-
-include ../packages/DOS/common.dj
-include Makefile.inc
-
-CSOURCES = $(CURL_CFILES) $(CURLX_CFILES)
-
-ifeq ($(USE_OPENSSL),1)
- EX_LIBS += $(OPENSSL_LIBS)
-endif
-
-ifeq ($(USE_ARES),1)
- EX_LIBS += $(ARES_ROOT)/libcares.a
-endif
-
-ifeq ($(USE_ZLIB),1)
- EX_LIBS += $(ZLIB_ROOT)/libz.a
- CFLAGS += -DUSE_MANUAL
-endif
-
-ifeq ($(USE_IDNA),1)
- EX_LIBS += $(LIBIDN_ROOT)/lib/dj_obj/libidn.a -liconv
-endif
-
-EX_LIBS += $(WATT32_ROOT)/lib/libwatt.a
-
-PROGRAM = curl.exe
-OBJECTS = $(addprefix $(OBJ_DIR)/, $(notdir $(CSOURCES:.c=.o)))
-
-all: $(OBJ_DIR) $(PROGRAM)
- @echo Welcome to curl
-
-$(PROGRAM): $(OBJECTS) ../lib/libcurl.a
- $(CC) -o $@ $^ $(LDFLAGS) $(EX_LIBS)
-
-#
-# groff 1.18+ requires "-P -c"
-# If 'USE_ZLIB = 1', create a compressed help-file.
-#
-ifeq ($(USE_ZLIB),1)
- COMPRESS_OPT = -c
-endif
-
-tool_hugehelp.c: ../docs/curl.1 mkhelp.pl Makefile.dj
- groff -Tascii -man $< | perl -w mkhelp.pl $(COMPRESS_OPT) $< > $@
-
-# clean generated files
-#
-genclean:
- - $(DELETE) tool_hugehelp.c
-
-# clean object files and subdir
-#
-objclean: genclean
- - $(DELETE) $(OBJ_DIR)$(DS)*.o
- - $(RMDIR) $(OBJ_DIR)
-
-# clean without removing built program
-#
-clean: objclean
- - $(DELETE) depend.dj
-
-# clean everything
-#
-realclean vclean: clean
- - $(DELETE) $(PROGRAM)
-
--include depend.dj
diff --git a/src/mkhelp.pl b/src/mkhelp.pl
index 6760243..19a30e2 100755
--- a/src/mkhelp.pl
+++ b/src/mkhelp.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -51,6 +51,7 @@
# remove trailing CR from line. msysgit checks out files as line+CRLF
$line =~ s/\r$//;
+ $line =~ s/\x1b\x5b[0-9]+m//g; # escape sequence
if($line =~ /^([ \t]*\n|curl)/i) {
# cut off headers and empty lines
$wline++; # count number of cut off lines
@@ -227,10 +228,6 @@
sub foot {
print <<FOOT
-#else /* !USE_MANUAL */
-/* built-in manual is disabled, blank function */
-#include "tool_hugehelp.h"
-void hugehelp(void) {}
#endif /* USE_MANUAL */
FOOT
;
diff --git a/src/slist_wc.c b/src/slist_wc.c
index 68021e6..7f1e8f1 100644
--- a/src/slist_wc.c
+++ b/src/slist_wc.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/slist_wc.h b/src/slist_wc.h
index e309fd5..dd7b8c1 100644
--- a/src/slist_wc.h
+++ b/src/slist_wc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_binmode.c b/src/tool_binmode.c
index 68c6c36..e27ce96 100644
--- a/src/tool_binmode.c
+++ b/src/tool_binmode.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_binmode.h b/src/tool_binmode.h
index 0b3d24b..bee837b 100644
--- a/src/tool_binmode.h
+++ b/src/tool_binmode.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_bname.c b/src/tool_bname.c
index e70f7d7..4ba1a3b 100644
--- a/src/tool_bname.c
+++ b/src/tool_bname.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_bname.h b/src/tool_bname.h
index 0efd7f1..d091c22 100644
--- a/src/tool_bname.h
+++ b/src/tool_bname.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_cb_dbg.c b/src/tool_cb_dbg.c
index ebeb8ed..d53a439 100644
--- a/src/tool_cb_dbg.c
+++ b/src/tool_cb_dbg.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,53 +34,110 @@
#include "memdebug.h" /* keep this as LAST include */
-static void dump(const char *timebuf, const char *text,
+static void dump(const char *timebuf, const char *idsbuf, const char *text,
FILE *stream, const unsigned char *ptr, size_t size,
trace tracetype, curl_infotype infotype);
/*
+ * Return the formatted HH:MM:SS for the tv_sec given.
+ * NOT thread safe.
+ */
+static const char *hms_for_sec(time_t tv_sec)
+{
+ static time_t cached_tv_sec;
+ static char hms_buf[12];
+ static time_t epoch_offset;
+ static int known_epoch;
+
+ if(tv_sec != cached_tv_sec) {
+ struct tm *now;
+ time_t secs;
+ /* recalculate */
+ if(!known_epoch) {
+ epoch_offset = time(NULL) - tv_sec;
+ known_epoch = 1;
+ }
+ secs = epoch_offset + tv_sec;
+ /* !checksrc! disable BANNEDFUNC 1 */
+ now = localtime(&secs); /* not thread safe but we don't care */
+ msnprintf(hms_buf, sizeof(hms_buf), "%02d:%02d:%02d",
+ now->tm_hour, now->tm_min, now->tm_sec);
+ cached_tv_sec = tv_sec;
+ }
+ return hms_buf;
+}
+
+static void log_line_start(FILE *log, const char *timebuf,
+ const char *idsbuf, curl_infotype type)
+{
+ /*
+ * This is the trace look that is similar to what libcurl makes on its
+ * own.
+ */
+ static const char * const s_infotype[] = {
+ "* ", "< ", "> ", "{ ", "} ", "{ ", "} "
+ };
+ if((timebuf && *timebuf) || (idsbuf && *idsbuf))
+ fprintf(log, "%s%s%s", timebuf, idsbuf, s_infotype[type]);
+ else
+ fputs(s_infotype[type], log);
+}
+
+#define TRC_IDS_FORMAT_IDS_1 "[%" CURL_FORMAT_CURL_OFF_T "-x] "
+#define TRC_IDS_FORMAT_IDS_2 "[%" CURL_FORMAT_CURL_OFF_T "-%" \
+ CURL_FORMAT_CURL_OFF_T "] "
+/*
** callback for CURLOPT_DEBUGFUNCTION
*/
-
int tool_debug_cb(CURL *handle, curl_infotype type,
char *data, size_t size,
void *userdata)
{
struct OperationConfig *operation = userdata;
struct GlobalConfig *config = operation->global;
- FILE *output = config->errors;
+ FILE *output = stderr;
const char *text;
struct timeval tv;
char timebuf[20];
- time_t secs;
+ /* largest signed 64bit is: 9,223,372,036,854,775,807
+ * max length in decimal: 1 + (6*3) = 19
+ * formatted via TRC_IDS_FORMAT_IDS_2 this becomes 2 + 19 + 1 + 19 + 2 = 43
+ * negative xfer-id are not printed, negative conn-ids use TRC_IDS_FORMAT_1
+ */
+ char idsbuf[60];
+ curl_off_t xfer_id, conn_id;
(void)handle; /* not used */
if(config->tracetime) {
- struct tm *now;
- static time_t epoch_offset;
- static int known_offset;
tv = tvnow();
- if(!known_offset) {
- epoch_offset = time(NULL) - tv.tv_sec;
- known_offset = 1;
- }
- secs = epoch_offset + tv.tv_sec;
- /* !checksrc! disable BANNEDFUNC 1 */
- now = localtime(&secs); /* not thread safe but we don't care */
- msnprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ",
- now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec);
+ msnprintf(timebuf, sizeof(timebuf), "%s.%06ld ",
+ hms_for_sec(tv.tv_sec), (long)tv.tv_usec);
}
else
timebuf[0] = 0;
+ if(handle && config->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) {
+ msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2,
+ xfer_id, conn_id);
+ }
+ else {
+ msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
+ }
+ }
+ else
+ idsbuf[0] = 0;
+
if(!config->trace_stream) {
/* open for append */
if(!strcmp("-", config->trace_dump))
config->trace_stream = stdout;
else if(!strcmp("%", config->trace_dump))
/* Ok, this is somewhat hackish but we do it undocumented for now */
- config->trace_stream = config->errors; /* aka stderr */
+ config->trace_stream = stderr;
else {
config->trace_stream = fopen(config->trace_dump, FOPEN_WRITETEXT);
config->trace_fopened = TRUE;
@@ -96,13 +153,6 @@
}
if(config->tracetype == TRACE_PLAIN) {
- /*
- * This is the trace look that is similar to what libcurl makes on its
- * own.
- */
- static const char * const s_infotype[] = {
- "*", "<", ">", "{", "}", "{", "}"
- };
static bool newl = FALSE;
static bool traced_data = FALSE;
@@ -114,7 +164,7 @@
for(i = 0; i < size - 1; i++) {
if(data[i] == '\n') { /* LF */
if(!newl) {
- fprintf(output, "%s%s ", timebuf, s_infotype[type]);
+ log_line_start(output, timebuf, idsbuf, type);
}
(void)fwrite(data + st, i - st + 1, 1, output);
st = i + 1;
@@ -122,7 +172,7 @@
}
}
if(!newl)
- fprintf(output, "%s%s ", timebuf, s_infotype[type]);
+ log_line_start(output, timebuf, idsbuf, type);
(void)fwrite(data + st, i - st + 1, 1, output);
}
newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
@@ -131,7 +181,7 @@
case CURLINFO_TEXT:
case CURLINFO_HEADER_IN:
if(!newl)
- fprintf(output, "%s%s ", timebuf, s_infotype[type]);
+ log_line_start(output, timebuf, idsbuf, type);
(void)fwrite(data, size, 1, output);
newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
traced_data = FALSE;
@@ -147,7 +197,7 @@
function */
if(!config->isatty || ((output != stderr) && (output != stdout))) {
if(!newl)
- fprintf(output, "%s%s ", timebuf, s_infotype[type]);
+ log_line_start(output, timebuf, idsbuf, type);
fprintf(output, "[%zu bytes data]\n", size);
newl = FALSE;
traced_data = TRUE;
@@ -165,7 +215,7 @@
switch(type) {
case CURLINFO_TEXT:
- fprintf(output, "%s== Info: %.*s", timebuf, (int)size, data);
+ fprintf(output, "%s%s== Info: %.*s", timebuf, idsbuf, (int)size, data);
/* FALLTHROUGH */
default: /* in case a new one is introduced to shock us */
return 0;
@@ -190,12 +240,12 @@
break;
}
- dump(timebuf, text, output, (unsigned char *) data, size, config->tracetype,
- type);
+ dump(timebuf, idsbuf, text, output, (unsigned char *) data, size,
+ config->tracetype, type);
return 0;
}
-static void dump(const char *timebuf, const char *text,
+static void dump(const char *timebuf, const char *idsbuf, const char *text,
FILE *stream, const unsigned char *ptr, size_t size,
trace tracetype, curl_infotype infotype)
{
@@ -208,7 +258,8 @@
/* without the hex output, we can fit more on screen */
width = 0x40;
- fprintf(stream, "%s%s, %zu bytes (0x%zx)\n", timebuf, text, size, size);
+ fprintf(stream, "%s%s%s, %zu bytes (0x%zx)\n", timebuf, idsbuf,
+ text, size, size);
for(i = 0; i < size; i += width) {
@@ -232,7 +283,7 @@
break;
}
(void)infotype;
- fprintf(stream, "%c", ((ptr[i + c] >= 0x20) && (ptr[i + c] < 0x80)) ?
+ fprintf(stream, "%c", ((ptr[i + c] >= 0x20) && (ptr[i + c] < 0x7F)) ?
ptr[i + c] : UNPRINTABLE_CHAR);
/* check again for 0D0A, to avoid an extra \n if it's at width */
if((tracetype == TRACE_ASCII) &&
diff --git a/src/tool_cb_dbg.h b/src/tool_cb_dbg.h
index bc69e56..d78afb3 100644
--- a/src/tool_cb_dbg.h
+++ b/src/tool_cb_dbg.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c
index 64b2bb2..dc6069f 100644
--- a/src/tool_cb_hdr.c
+++ b/src/tool_cb_hdr.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,6 +35,7 @@
#include "tool_cb_hdr.h"
#include "tool_cb_wrt.h"
#include "tool_operate.h"
+#include "tool_libinfo.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -74,24 +75,15 @@
const char *str = ptr;
const size_t cb = size * nmemb;
const char *end = (char *)ptr + cb;
- long protocol = 0;
-
- /*
- * Once that libcurl has called back tool_header_cb() the returned value
- * is checked against the amount that was intended to be written, if
- * it does not match then it fails with CURLE_WRITE_ERROR. So at this
- * point returning a value different from sz*nmemb indicates failure.
- */
- size_t failure = (size && nmemb) ? 0 : 1;
+ const char *scheme = NULL;
if(!per->config)
- return failure;
+ return CURL_WRITEFUNC_ERROR;
#ifdef DEBUGBUILD
if(size * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
- warnf(per->config->global, "Header data exceeds single call write "
- "limit!\n");
- return failure;
+ warnf(per->config->global, "Header data exceeds single call write limit");
+ return CURL_WRITEFUNC_ERROR;
}
#endif
@@ -116,7 +108,7 @@
const char *etag_h = &str[5];
const char *eot = end - 1;
if(*eot == '\n') {
- while(ISSPACE(*etag_h) && (etag_h < eot))
+ while(ISBLANK(*etag_h) && (etag_h < eot))
etag_h++;
while(ISSPACE(*eot))
eot--;
@@ -139,10 +131,11 @@
* Content-Disposition header specifying a filename property.
*/
- curl_easy_getinfo(per->curl, CURLINFO_PROTOCOL, &protocol);
+ curl_easy_getinfo(per->curl, CURLINFO_SCHEME, &scheme);
+ scheme = proto_token(scheme);
if(hdrcbdata->honor_cd_filename &&
(cb > 20) && checkprefix("Content-disposition:", str) &&
- (protocol & (CURLPROTO_HTTPS|CURLPROTO_HTTP))) {
+ (scheme == proto_http || scheme == proto_https)) {
const char *p = str + 20;
/* look for the 'filename=' parameter
@@ -173,7 +166,7 @@
if(outs->stream) {
/* indication of problem, get out! */
free(filename);
- return failure;
+ return CURL_WRITEFUNC_ERROR;
}
outs->is_cd_filename = TRUE;
@@ -183,12 +176,12 @@
outs->alloc_filename = TRUE;
hdrcbdata->honor_cd_filename = FALSE; /* done now! */
if(!tool_create_output_file(outs, per->config))
- return failure;
+ return CURL_WRITEFUNC_ERROR;
}
break;
}
if(!outs->stream && !tool_create_output_file(outs, per->config))
- return failure;
+ return CURL_WRITEFUNC_ERROR;
}
if(hdrcbdata->config->writeout) {
char *value = memchr(ptr, ':', cb);
@@ -202,13 +195,13 @@
per->was_last_header_empty = TRUE;
}
if(hdrcbdata->config->show_headers &&
- (protocol &
- (CURLPROTO_HTTP|CURLPROTO_HTTPS|CURLPROTO_RTSP|CURLPROTO_FILE))) {
+ (scheme == proto_http || scheme == proto_https ||
+ scheme == proto_rtsp || scheme == proto_file)) {
/* bold headers only for selected protocols */
char *value = NULL;
if(!outs->stream && !tool_create_output_file(outs, per->config))
- return failure;
+ return CURL_WRITEFUNC_ERROR;
if(hdrcbdata->global->isatty && hdrcbdata->global->styled_output)
value = memchr(ptr, ':', cb);
@@ -350,6 +343,15 @@
char *copyloc = NULL, *locurl = NULL, *scheme = NULL, *finalurl = NULL;
const char *loc = location;
size_t llen = loclen;
+ char *vver = getenv("VTE_VERSION");
+
+ if(vver) {
+ long vvn = strtol(vver, NULL, 10);
+ /* Skip formatting for old versions of VTE <= 0.48.1 (Mar 2017) since some
+ of those versions have formatting bugs. (#10428) */
+ if(0 < vvn && vvn <= 4801)
+ goto locout;
+ }
/* Strip leading whitespace of the redirect URL */
while(llen && *loc == ' ') {
diff --git a/src/tool_cb_hdr.h b/src/tool_cb_hdr.h
index 01175bb..a855052 100644
--- a/src/tool_cb_hdr.h
+++ b/src/tool_cb_hdr.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_cb_prg.c b/src/tool_cb_prg.c
index 3532c31..9c8ffb2 100644
--- a/src/tool_cb_prg.c
+++ b/src/tool_cb_prg.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -116,8 +116,8 @@
#define MAX_BARLENGTH 256
-#if (SIZEOF_CURL_OFF_T == 4)
-# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF)
+#if (SIZEOF_CURL_OFF_T < 8)
+#error "too small curl_off_t"
#else
/* assume SIZEOF_CURL_OFF_T == 8 */
# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
@@ -274,7 +274,7 @@
else if(bar->width > MAX_BARLENGTH)
bar->width = MAX_BARLENGTH;
- bar->out = config->global->errors;
+ bar->out = stderr;
bar->tick = 150;
bar->barmove = 1;
}
diff --git a/src/tool_cb_prg.h b/src/tool_cb_prg.h
index 7d8fbae..565ad56 100644
--- a/src/tool_cb_prg.h
+++ b/src/tool_cb_prg.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_cb_rea.c b/src/tool_cb_rea.c
index 4aed55c..d70a9b9 100644
--- a/src/tool_cb_rea.c
+++ b/src/tool_cb_rea.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,6 +23,10 @@
***************************************************************************/
#include "tool_setup.h"
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
@@ -30,6 +34,8 @@
#include "tool_cfgable.h"
#include "tool_cb_rea.h"
#include "tool_operate.h"
+#include "tool_util.h"
+#include "tool_msgs.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -39,20 +45,65 @@
size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
{
- ssize_t rc;
- struct InStruct *in = userdata;
+ ssize_t rc = 0;
+ struct per_transfer *per = userdata;
+ struct OperationConfig *config = per->config;
- rc = read(in->fd, buffer, sz*nmemb);
+ if((per->uploadfilesize != -1) &&
+ (per->uploadedsofar == per->uploadfilesize)) {
+ /* done */
+ return 0;
+ }
+
+ if(config->timeout_ms) {
+ struct timeval now = tvnow();
+ long msdelta = tvdiff(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);
+ FD_SET(per->infd, &bits);
+ if(!select(per->infd + 1, &bits, NULL, NULL, &timeout))
+ return 0; /* timeout */
+ }
+#endif
+ }
+
+ rc = read(per->infd, buffer, sz*nmemb);
if(rc < 0) {
if(errno == EAGAIN) {
errno = 0;
- in->config->readbusy = TRUE;
+ config->readbusy = TRUE;
return CURL_READFUNC_PAUSE;
}
/* since size_t is unsigned we can't return negative values fine */
rc = 0;
}
- in->config->readbusy = FALSE;
+ if((per->uploadfilesize != -1) &&
+ (per->uploadedsofar + rc > per->uploadfilesize)) {
+ /* do not allow uploading more than originally set out to do */
+ curl_off_t delta = per->uploadedsofar + rc - per->uploadfilesize;
+ warnf(per->config->global, "File size larger in the end than when "
+ "started. Dropping at least %" CURL_FORMAT_CURL_OFF_T " bytes",
+ delta);
+ rc = (ssize_t)(per->uploadfilesize - per->uploadedsofar);
+ }
+ config->readbusy = FALSE;
+
+ /* when select() returned zero here, it timed out */
return (size_t)rc;
}
diff --git a/src/tool_cb_rea.h b/src/tool_cb_rea.h
index 81b5f87..06899d3 100644
--- a/src/tool_cb_rea.h
+++ b/src/tool_cb_rea.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_cb_see.c b/src/tool_cb_see.c
index d24d526..8351473 100644
--- a/src/tool_cb_see.c
+++ b/src/tool_cb_see.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,6 +28,7 @@
#include "curlx.h"
#include "tool_cfgable.h"
+#include "tool_operate.h"
#include "tool_cb_see.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -48,7 +49,7 @@
int tool_seek_cb(void *userdata, curl_off_t offset, int whence)
{
- struct InStruct *in = userdata;
+ struct per_transfer *per = userdata;
#if(SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(USE_WIN32_LARGE_FILES)
@@ -66,13 +67,13 @@
/* this code path doesn't support other types */
return CURL_SEEKFUNC_FAIL;
- if(LSEEK_ERROR == lseek(in->fd, 0, SEEK_SET))
+ if(LSEEK_ERROR == lseek(per->infd, 0, SEEK_SET))
/* couldn't rewind to beginning */
return CURL_SEEKFUNC_FAIL;
while(left) {
long step = (left > OUR_MAX_SEEK_O) ? OUR_MAX_SEEK_L : (long)left;
- if(LSEEK_ERROR == lseek(in->fd, step, SEEK_CUR))
+ if(LSEEK_ERROR == lseek(per->infd, step, SEEK_CUR))
/* couldn't seek forwards the desired amount */
return CURL_SEEKFUNC_FAIL;
left -= step;
@@ -81,7 +82,7 @@
}
#endif
- if(LSEEK_ERROR == lseek(in->fd, offset, whence))
+ if(LSEEK_ERROR == lseek(per->infd, offset, whence))
/* couldn't rewind, the reason is in errno but errno is just not portable
enough and we don't actually care that much why we failed. We'll let
libcurl know that it may try other means if it wants to. */
diff --git a/src/tool_cb_see.h b/src/tool_cb_see.h
index 4af0b0a..14bbc42 100644
--- a/src/tool_cb_see.h
+++ b/src/tool_cb_see.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c
index f943889..94d82cb 100644
--- a/src/tool_cb_wrt.c
+++ b/src/tool_cb_wrt.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -62,14 +62,14 @@
DEBUGASSERT(config);
global = config->global;
if(!fname || !*fname) {
- warnf(global, "Remote filename has no length!\n");
+ warnf(global, "Remote filename has no length");
return FALSE;
}
if(config->output_dir && outs->is_cd_filename) {
aname = aprintf("%s/%s", config->output_dir, fname);
if(!aname) {
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
return FALSE;
}
fname = aname;
@@ -95,12 +95,12 @@
/* Guard against wraparound in new filename */
if(newlen < len) {
free(aname);
- errorf(global, "overflow in filename generation\n");
+ errorf(global, "overflow in filename generation");
return FALSE;
}
newname = malloc(newlen);
if(!newname) {
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
free(aname);
return FALSE;
}
@@ -133,7 +133,7 @@
}
if(!file) {
- warnf(global, "Failed to open the file %s: %s\n", fname,
+ warnf(global, "Failed to open the file %s: %s", fname,
strerror(errno));
free(aname);
return FALSE;
@@ -164,14 +164,6 @@
intptr_t fhnd;
#endif
- /*
- * Once that libcurl has called back tool_write_cb() the returned value
- * is checked against the amount that was intended to be written, if
- * it does not match then it fails with CURLE_WRITE_ERROR. So at this
- * point returning a value different from sz*nmemb indicates failure.
- */
- const size_t failure = bytes ? 0 : 1;
-
#ifdef DEBUGBUILD
{
char *tty = curlx_getenv("CURL_ISATTY");
@@ -184,14 +176,14 @@
if(config->show_headers) {
if(bytes > (size_t)CURL_MAX_HTTP_HEADER) {
warnf(config->global, "Header data size exceeds single call write "
- "limit!\n");
- return failure;
+ "limit");
+ return CURL_WRITEFUNC_ERROR;
}
}
else {
if(bytes > (size_t)CURL_MAX_WRITE_SIZE) {
- warnf(config->global, "Data size exceeds single call write limit!\n");
- return failure;
+ warnf(config->global, "Data size exceeds single call write limit");
+ return CURL_WRITEFUNC_ERROR;
}
}
@@ -219,23 +211,23 @@
check_fails = TRUE;
}
if(check_fails) {
- warnf(config->global, "Invalid output struct data for write callback\n");
- return failure;
+ warnf(config->global, "Invalid output struct data for write callback");
+ return CURL_WRITEFUNC_ERROR;
}
}
#endif
if(!outs->stream && !tool_create_output_file(outs, per->config))
- return failure;
+ return CURL_WRITEFUNC_ERROR;
if(is_tty && (outs->bytes < 2000) && !config->terminal_binary_ok) {
/* binary output to terminal? */
if(memchr(buffer, 0, bytes)) {
warnf(config->global, "Binary output can mess up your terminal. "
"Use \"--output -\" to tell curl to output it to your terminal "
- "anyway, or consider \"--output <FILE>\" to save to a file.\n");
- config->synthetic_error = ERR_BINARY_TERMINAL;
- return failure;
+ "anyway, or consider \"--output <FILE>\" to save to a file.");
+ config->synthetic_error = TRUE;
+ return CURL_WRITEFUNC_ERROR;
}
}
@@ -251,13 +243,13 @@
wc_len = MultiByteToWideChar(CP_UTF8, 0, buffer, in_len, NULL, 0);
wc_buf = (wchar_t*) malloc(wc_len * sizeof(wchar_t));
if(!wc_buf)
- return failure;
+ return CURL_WRITEFUNC_ERROR;
/* calculate buffer size for multi-byte characters */
wc_len = MultiByteToWideChar(CP_UTF8, 0, buffer, in_len, wc_buf, wc_len);
if(!wc_len) {
free(wc_buf);
- return failure;
+ return CURL_WRITEFUNC_ERROR;
}
if(!WriteConsoleW(
@@ -267,7 +259,7 @@
&wc_len,
NULL)) {
free(wc_buf);
- return failure;
+ return CURL_WRITEFUNC_ERROR;
}
free(wc_buf);
rc = bytes;
@@ -289,7 +281,7 @@
/* output buffering disabled */
int res = fflush(outs->stream);
if(res)
- return failure;
+ return CURL_WRITEFUNC_ERROR;
}
return rc;
diff --git a/src/tool_cb_wrt.h b/src/tool_cb_wrt.h
index 0cbbcee..55502f4 100644
--- a/src/tool_cb_wrt.h
+++ b/src/tool_cb_wrt.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
index 27232eb..04f0b05 100644
--- a/src/tool_cfgable.c
+++ b/src/tool_cfgable.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,6 +24,7 @@
#include "tool_setup.h"
#include "tool_cfgable.h"
+#include "tool_formparse.h"
#include "tool_main.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -36,11 +37,7 @@
config->use_httpget = FALSE;
config->create_dirs = FALSE;
config->maxredirs = DEFAULT_MAXREDIRS;
- config->proto = CURLPROTO_ALL;
config->proto_present = FALSE;
- config->proto_redir = CURLPROTO_ALL & /* All except FILE, SCP and SMB */
- ~(CURLPROTO_FILE | CURLPROTO_SCP | CURLPROTO_SMB |
- CURLPROTO_SMBS);
config->proto_redir_present = FALSE;
config->proto_default = NULL;
config->tcp_nodelay = TRUE; /* enabled by default */
@@ -57,11 +54,13 @@
Curl_safefree(config->useragent);
Curl_safefree(config->altsvc);
Curl_safefree(config->hsts);
+ Curl_safefree(config->haproxy_clientip);
curl_slist_free_all(config->cookies);
Curl_safefree(config->cookiejar);
curl_slist_free_all(config->cookiefiles);
Curl_safefree(config->postfields);
+ Curl_safefree(config->query);
Curl_safefree(config->referer);
Curl_safefree(config->headerfile);
@@ -93,6 +92,8 @@
Curl_safefree(config->netrc_file);
Curl_safefree(config->output_dir);
+ Curl_safefree(config->proto_str);
+ Curl_safefree(config->proto_redir_str);
urlnode = config->url_list;
while(urlnode) {
@@ -136,13 +137,12 @@
Curl_safefree(config->engine);
Curl_safefree(config->etag_save_file);
Curl_safefree(config->etag_compare_file);
+ Curl_safefree(config->ssl_ec_curves);
Curl_safefree(config->request_target);
Curl_safefree(config->customrequest);
Curl_safefree(config->krblevel);
-
Curl_safefree(config->oauth_bearer);
Curl_safefree(config->sasl_authzid);
-
Curl_safefree(config->unix_socket_path);
Curl_safefree(config->writeout);
Curl_safefree(config->proto_default);
@@ -172,6 +172,8 @@
Curl_safefree(config->ftp_alternative_to_user);
Curl_safefree(config->aws_sigv4);
+ Curl_safefree(config->proto_str);
+ Curl_safefree(config->proto_redir_str);
}
void config_free(struct OperationConfig *config)
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index 7e43fe7..b35abaf 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,13 +26,6 @@
#include "tool_setup.h"
#include "tool_sdecls.h"
#include "tool_urlglob.h"
-#include "tool_formparse.h"
-
-typedef enum {
- ERR_NONE,
- ERR_BINARY_TERMINAL = 1, /* binary to terminal detected */
- ERR_LAST
-} curl_error;
struct GlobalConfig;
@@ -43,11 +36,11 @@
char *outfiles;
char *httpgetfields;
char *uploadfile;
- unsigned long infilenum; /* number of files to upload */
- unsigned long up; /* upload file counter within a single upload glob */
- unsigned long urlnum; /* how many iterations this single URL has with ranges
+ curl_off_t infilenum; /* number of files to upload */
+ curl_off_t up; /* upload file counter within a single upload glob */
+ curl_off_t urlnum; /* how many iterations this single URL has with ranges
etc */
- unsigned long li;
+ curl_off_t li;
};
struct OperationConfig {
@@ -67,17 +60,18 @@
bool disable_epsv;
bool disable_eprt;
bool ftp_pret;
- long proto;
+ char *proto_str;
bool proto_present;
- long proto_redir;
+ char *proto_redir_str;
bool proto_redir_present;
char *proto_default;
curl_off_t resume_from;
char *postfields;
curl_off_t postfieldsize;
char *referer;
- double timeout;
- double connecttimeout;
+ char *query;
+ long timeout_ms;
+ long connecttimeout_ms;
long maxredirs;
curl_off_t max_filesize;
char *output_dir;
@@ -123,7 +117,7 @@
bool dirlistonly; /* only get the FTP dir list */
bool followlocation; /* follow http redirects */
bool unrestricted_auth; /* Continue to send authentication (user+password)
- when following ocations, even when hostname
+ when following redirects, even when hostname
changed */
bool netrc_opt;
bool netrc;
@@ -221,7 +215,7 @@
bool ftp_ssl_ccc;
int ftp_ssl_ccc_mode;
char *preproxy;
- int socks5_gssapi_nec; /* The NEC reference server does not protect the
+ bool socks5_gssapi_nec; /* The NEC reference server does not protect the
encryption type exchange */
unsigned long socks5_auth;/* auth bitmask for socks5 proxies */
char *proxy_service_name; /* set authentication service name for HTTP and
@@ -260,34 +254,31 @@
bool xattr; /* store metadata in extended attributes */
long gssapi_delegation;
bool ssl_allow_beast; /* allow this SSL vulnerability */
- bool proxy_ssl_allow_beast; /* allow this SSL vulnerability for proxy*/
-
+ bool proxy_ssl_allow_beast; /* allow this SSL vulnerability for proxy */
bool ssl_no_revoke; /* disable SSL certificate revocation checks */
- /*bool proxy_ssl_no_revoke; */
-
bool ssl_revoke_best_effort; /* ignore SSL revocation offline/missing
revocation list errors */
- bool native_ca_store; /* use the native os ca store */
+ bool native_ca_store; /* use the native OS CA store */
+ bool proxy_native_ca_store; /* use the native OS CA store for proxy */
bool ssl_auto_client_cert; /* automatically locate and use a client
certificate for authentication (Schannel) */
bool proxy_ssl_auto_client_cert; /* proxy version of ssl_auto_client_cert */
char *oauth_bearer; /* OAuth 2.0 bearer token */
- bool nonpn; /* enable/disable TLS NPN extension */
bool noalpn; /* enable/disable TLS ALPN extension */
char *unix_socket_path; /* path to Unix domain socket */
bool abstract_unix_socket; /* path to an abstract Unix domain socket */
bool falsestart;
bool path_as_is;
- double expect100timeout;
+ long expect100timeout_ms;
bool suppress_connect_headers; /* suppress proxy CONNECT response headers
from user callbacks */
- curl_error synthetic_error; /* if non-zero, it overrides any libcurl
- error */
+ bool synthetic_error; /* if TRUE, this is tool-internal error */
bool ssh_compression; /* enable/disable SSH compression */
long happy_eyeballs_timeout_ms; /* happy eyeballs timeout in milliseconds.
0 is valid. default: CURL_HET_DEFAULT. */
bool haproxy_protocol; /* whether to send HAProxy protocol v1 */
+ char *haproxy_clientip; /* client IP for HAProxy protocol */
bool disallow_username_in_url; /* disallow usernames in URLs */
char *aws_sigv4;
enum {
@@ -308,19 +299,16 @@
};
struct GlobalConfig {
- int showerror; /* -1 == unset, default => show errors
- 0 => -s is used to NOT show errors
- 1 => -S has been used to show errors */
- bool mute; /* don't show messages, --silent given */
- bool noprogress; /* don't show progress bar --silent given */
+ bool showerror; /* show errors when silent */
+ bool silent; /* don't show messages, --silent given */
+ bool noprogress; /* don't show progress bar */
bool isatty; /* Updated internally if output is a tty */
- FILE *errors; /* Error stream, defaults to stderr */
- bool errors_fopened; /* Whether error stream isn't stderr */
char *trace_dump; /* file to dump the network trace to */
FILE *trace_stream;
bool trace_fopened;
trace tracetype;
bool tracetime; /* include timestamp? */
+ bool traceids; /* include xfer-/conn-id? */
int progressmode; /* CURL_PROGRESS_BAR / CURL_PROGRESS_STATS */
char *libcurl; /* Output libcurl code to this file name */
bool fail_early; /* exit on first transfer error */
@@ -331,7 +319,7 @@
bool test_event_based;
#endif
bool parallel;
- long parallel_max;
+ unsigned short parallel_max; /* MAX_PARALLEL is the maximum */
bool parallel_connect;
char *help_category; /* The help category, if set */
struct OperationConfig *first;
diff --git a/src/tool_dirhie.c b/src/tool_dirhie.c
index 1b6ac17..c01c19c 100644
--- a/src/tool_dirhie.c
+++ b/src/tool_dirhie.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,15 +34,10 @@
#include "curlx.h"
#include "tool_dirhie.h"
+#include "tool_msgs.h"
#include "memdebug.h" /* keep this as LAST include */
-#ifdef NETWARE
-# ifndef __NOVELL_LIBC__
-# define mkdir mkdir_510
-# endif
-#endif
-
#if defined(WIN32) || (defined(MSDOS) && !defined(__DJGPP__))
# define mkdir(x,y) (mkdir)((x))
# ifndef F_OK
@@ -50,38 +45,38 @@
# endif
#endif
-static void show_dir_errno(FILE *errors, const char *name)
+static void show_dir_errno(struct GlobalConfig *global, const char *name)
{
switch(errno) {
#ifdef EACCES
case EACCES:
- fprintf(errors, "You don't have permission to create %s.\n", name);
+ errorf(global, "You don't have permission to create %s", name);
break;
#endif
#ifdef ENAMETOOLONG
case ENAMETOOLONG:
- fprintf(errors, "The directory name %s is too long.\n", name);
+ errorf(global, "The directory name %s is too long", name);
break;
#endif
#ifdef EROFS
case EROFS:
- fprintf(errors, "%s resides on a read-only file system.\n", name);
+ errorf(global, "%s resides on a read-only file system", name);
break;
#endif
#ifdef ENOSPC
case ENOSPC:
- fprintf(errors, "No space left on the file system that will "
- "contain the directory %s.\n", name);
+ errorf(global, "No space left on the file system that will "
+ "contain the directory %s", name);
break;
#endif
#ifdef EDQUOT
case EDQUOT:
- fprintf(errors, "Cannot create directory %s because you "
- "exceeded your quota.\n", name);
+ errorf(global, "Cannot create directory %s because you "
+ "exceeded your quota", name);
break;
#endif
- default :
- fprintf(errors, "Error creating directory %s.\n", name);
+ default:
+ errorf(global, "Error creating directory %s", name);
break;
}
}
@@ -101,7 +96,7 @@
#endif
-CURLcode create_dir_hierarchy(const char *outfile, FILE *errors)
+CURLcode create_dir_hierarchy(const char *outfile, struct GlobalConfig *global)
{
char *tempdir;
char *tempdir2;
@@ -157,7 +152,7 @@
/* Create directory. Ignore access denied error to allow traversal. */
if(!skip && (-1 == mkdir(dirbuildup, (mode_t)0000750)) &&
(errno != EACCES) && (errno != EEXIST)) {
- show_dir_errno(errors, dirbuildup);
+ show_dir_errno(global, dirbuildup);
result = CURLE_WRITE_ERROR;
break; /* get out of loop */
}
diff --git a/src/tool_dirhie.h b/src/tool_dirhie.h
index 954f3e2..0ee407f 100644
--- a/src/tool_dirhie.h
+++ b/src/tool_dirhie.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,7 +24,9 @@
*
***************************************************************************/
#include "tool_setup.h"
+#include "tool_cfgable.h"
-CURLcode create_dir_hierarchy(const char *outfile, FILE *errors);
+CURLcode create_dir_hierarchy(const char *outfile,
+ struct GlobalConfig *global);
#endif /* HEADER_CURL_TOOL_DIRHIE_H */
diff --git a/src/tool_doswin.c b/src/tool_doswin.c
index d8695e9..e9347d2 100644
--- a/src/tool_doswin.c
+++ b/src/tool_doswin.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -626,8 +626,7 @@
* ignored. We allow setting CA location for schannel only when explicitly
* specified by the user via CURLOPT_CAINFO / --cacert.
*/
- if((curlinfo->features & CURL_VERSION_SSL) &&
- backend != CURLSSLBACKEND_SCHANNEL) {
+ if(feature_ssl && backend != CURLSSLBACKEND_SCHANNEL) {
DWORD res_len;
TCHAR buf[PATH_MAX];
diff --git a/src/tool_doswin.h b/src/tool_doswin.h
index ff9bad9..669fdb6 100644
--- a/src/tool_doswin.h
+++ b/src/tool_doswin.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_easysrc.c b/src/tool_easysrc.c
index e653b31..6ef2be7 100644
--- a/src/tool_easysrc.c
+++ b/src/tool_easysrc.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -186,7 +186,7 @@
else
out = stdout;
if(!out)
- warnf(config, "Failed to open %s to write libcurl code!\n", o);
+ warnf(config, "Failed to open %s to write libcurl code", o);
else {
int i;
const char *c;
diff --git a/src/tool_easysrc.h b/src/tool_easysrc.h
index d7a629a..8c8d131 100644
--- a/src/tool_easysrc.h
+++ b/src/tool_easysrc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -46,6 +46,13 @@
void dumpeasysrc(struct GlobalConfig *config);
+#else /* CURL_DISABLE_LIBCURL_OPTION is defined */
+
+#define easysrc_init() CURLE_OK
+#define easysrc_cleanup()
+#define dumpeasysrc(x)
+#define easysrc_perform() CURLE_OK
+
#endif /* CURL_DISABLE_LIBCURL_OPTION */
#endif /* HEADER_CURL_TOOL_EASYSRC_H */
diff --git a/src/tool_filetime.c b/src/tool_filetime.c
index c095a49..054d34f 100644
--- a/src/tool_filetime.c
+++ b/src/tool_filetime.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -39,7 +39,7 @@
/* Windows stat() may attempt to adjust the unix GMT file time by a daylight
saving time offset and since it's GMT that is bad behavior. When we have
access to a 64-bit type we can bypass stat and get the times directly. */
-#if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)
+#if defined(WIN32)
HANDLE hfile;
TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar((char *)filename);
@@ -55,7 +55,7 @@
| ((curl_off_t)ft.dwHighDateTime) << 32;
if(converted < CURL_OFF_T_C(116444736000000000)) {
- warnf(global, "Failed to get filetime: underflow\n");
+ warnf(global, "Failed to get filetime: underflow");
}
else {
result = (converted - CURL_OFF_T_C(116444736000000000)) / 10000000;
@@ -63,14 +63,14 @@
}
else {
warnf(global, "Failed to get filetime: "
- "GetFileTime failed: GetLastError %u\n",
+ "GetFileTime failed: GetLastError %u",
(unsigned int)GetLastError());
}
CloseHandle(hfile);
}
else if(GetLastError() != ERROR_FILE_NOT_FOUND) {
warnf(global, "Failed to get filetime: "
- "CreateFile failed: GetLastError %u\n",
+ "CreateFile failed: GetLastError %u",
(unsigned int)GetLastError());
}
#else
@@ -79,14 +79,13 @@
result = (curl_off_t)statbuf.st_mtime;
}
else if(errno != ENOENT) {
- warnf(global, "Failed to get filetime: %s\n", strerror(errno));
+ warnf(global, "Failed to get filetime: %s", strerror(errno));
}
#endif
return result;
}
-#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
- (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8))
+#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || defined(WIN32)
void setfiletime(curl_off_t filetime, const char *filename,
struct GlobalConfig *global)
{
@@ -94,7 +93,7 @@
/* Windows utime() may attempt to adjust the unix GMT file time by a daylight
saving time offset and since it's GMT that is bad behavior. When we have
access to a 64-bit type we can bypass utime and set the times directly. */
-#if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)
+#if defined(WIN32)
HANDLE hfile;
TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar((char *)filename);
@@ -102,7 +101,7 @@
Windows FILETIME without overflow: 30827-12-31T23:59:59. */
if(filetime > CURL_OFF_T_C(910670515199)) {
warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
- " on outfile: overflow\n", filetime);
+ " on outfile: overflow", filetime);
curlx_unicodefree(tchar_filename);
return;
}
@@ -120,14 +119,14 @@
ft.dwHighDateTime = (DWORD)(converted >> 32);
if(!SetFileTime(hfile, NULL, &ft, &ft)) {
warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
- " on outfile: SetFileTime failed: GetLastError %u\n",
+ " on outfile: SetFileTime failed: GetLastError %u",
filetime, (unsigned int)GetLastError());
}
CloseHandle(hfile);
}
else {
warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
- " on outfile: CreateFile failed: GetLastError %u\n",
+ " on outfile: CreateFile failed: GetLastError %u",
filetime, (unsigned int)GetLastError());
}
@@ -137,7 +136,7 @@
times[0].tv_usec = times[1].tv_usec = 0;
if(utimes(filename, times)) {
warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
- " on '%s': %s\n", filetime, filename, strerror(errno));
+ " on '%s': %s", filetime, filename, strerror(errno));
}
#elif defined(HAVE_UTIME)
@@ -146,10 +145,10 @@
times.modtime = (time_t)filetime;
if(utime(filename, ×)) {
warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
- " on '%s': %s\n", filetime, filename, strerror(errno));
+ " on '%s': %s", filetime, filename, strerror(errno));
}
#endif
}
}
-#endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
- (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */
+#endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
+ defined(WIN32) */
diff --git a/src/tool_filetime.h b/src/tool_filetime.h
index 3d88d89..923ec06 100644
--- a/src/tool_filetime.h
+++ b/src/tool_filetime.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_findfile.c b/src/tool_findfile.c
index 51a45ff..201d8f0 100644
--- a/src/tool_findfile.c
+++ b/src/tool_findfile.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -49,7 +49,7 @@
/* The order of the variables below is important, as the index number is used
in the findfile() function */
-static const struct finder list[] = {
+static const struct finder conf_list[] = {
{ "CURL_HOME", NULL, FALSE },
{ "XDG_CONFIG_HOME", NULL, FALSE }, /* index == 1, used in the code */
{ "HOME", NULL, FALSE },
@@ -109,8 +109,8 @@
if(!fname[0])
return NULL;
- for(i = 0; list[i].env; i++) {
- char *home = curl_getenv(list[i].env);
+ for(i = 0; conf_list[i].env; i++) {
+ char *home = curl_getenv(conf_list[i].env);
if(home) {
char *path;
const char *filename = fname;
@@ -120,14 +120,14 @@
curl_free(home);
continue;
}
- if(list[i].append) {
- char *c = curl_maprintf("%s%s", home, list[i].append);
+ if(conf_list[i].append) {
+ char *c = curl_maprintf("%s%s", home, conf_list[i].append);
curl_free(home);
if(!c)
return NULL;
home = c;
}
- if(list[i].withoutdot) {
+ if(conf_list[i].withoutdot) {
if(!dotscore || xdg) {
/* this is not looking for .curlrc, or the XDG_CONFIG_HOME was
defined so we skip the extended check */
diff --git a/src/tool_findfile.h b/src/tool_findfile.h
index 5bae579..faafd71 100644
--- a/src/tool_findfile.h
+++ b/src/tool_findfile.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_formparse.c b/src/tool_formparse.c
index dcd7a13..fa38698 100644
--- a/src/tool_formparse.c
+++ b/src/tool_formparse.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -38,10 +38,6 @@
#include "memdebug.h" /* keep this as LAST include */
-/* Macros to free const pointers. */
-#define CONST_FREE(x) free((void *) (x))
-#define CONST_SAFEFREE(x) Curl_safefree(*((void **) &(x)))
-
/* tool_mime functions. */
static struct tool_mime *tool_mime_new(struct tool_mime *parent,
toolmimekind kind)
@@ -65,17 +61,18 @@
}
static struct tool_mime *tool_mime_new_data(struct tool_mime *parent,
- const char *data)
+ char *mime_data)
{
+ char *mime_data_copy;
struct tool_mime *m = NULL;
- data = strdup(data);
- if(data) {
+ mime_data_copy = strdup(mime_data);
+ if(mime_data_copy) {
m = tool_mime_new(parent, TOOLMIME_DATA);
if(!m)
- CONST_FREE(data);
+ free(mime_data_copy);
else
- m->data = data;
+ m->data = mime_data_copy;
}
return m;
}
@@ -91,13 +88,13 @@
*errcode = CURLE_OUT_OF_MEMORY;
if(strcmp(filename, "-")) {
/* This is a normal file. */
- filename = strdup(filename);
- if(filename) {
+ char *filedup = strdup(filename);
+ if(filedup) {
m = tool_mime_new(parent, TOOLMIME_FILE);
if(!m)
- CONST_FREE(filename);
+ free(filedup);
else {
- m->data = filename;
+ m->data = filedup;
if(!isremotefile)
m->kind = TOOLMIME_FILEDATA;
*errcode = CURLE_OK;
@@ -168,11 +165,11 @@
tool_mime_free(mime->subparts);
if(mime->prev)
tool_mime_free(mime->prev);
- CONST_SAFEFREE(mime->name);
- CONST_SAFEFREE(mime->filename);
- CONST_SAFEFREE(mime->type);
- CONST_SAFEFREE(mime->encoder);
- CONST_SAFEFREE(mime->data);
+ Curl_safefree(mime->name);
+ Curl_safefree(mime->filename);
+ Curl_safefree(mime->type);
+ Curl_safefree(mime->encoder);
+ Curl_safefree(mime->data);
curl_slist_free_all(mime->headers);
free(mime);
}
@@ -205,7 +202,7 @@
if(ferror(stdin)) {
/* Show error only once. */
if(sip->config) {
- warnf(sip->config, "stdin: %s\n", strerror(errno));
+ warnf(sip->config, "stdin: %s", strerror(errno));
sip->config = NULL;
}
return CURL_READFUNC_ABORT;
@@ -372,7 +369,7 @@
++ptr;
}
if(trailing_data)
- warnf(config->global, "Trailing data after quoted form parameter\n");
+ warnf(config->global, "Trailing data after quoted form parameter");
*str = ptr;
return word_begin + 1;
}
@@ -409,7 +406,7 @@
size_t pos = 0;
bool incomment = FALSE;
int lineno = 1;
- char hdrbuf[999]; /* Max. header length + 1. */
+ char hdrbuf[999] = ""; /* Max. header length + 1. */
for(;;) {
int c = getc(fp);
@@ -420,8 +417,7 @@
if(hdrlen) {
hdrbuf[hdrlen] = '\0';
if(slist_append(pheaders, hdrbuf)) {
- fprintf(config->global->errors,
- "Out of memory for field headers!\n");
+ errorf(config->global, "Out of memory for field headers");
return -1;
}
hdrlen = 0;
@@ -431,8 +427,8 @@
switch(c) {
case EOF:
if(ferror(fp)) {
- fprintf(config->global->errors,
- "Header file %s read error: %s\n", filename, strerror(errno));
+ errorf(config->global, "Header file %s read error: %s", filename,
+ strerror(errno));
return -1;
}
return 0; /* Done. */
@@ -452,7 +448,7 @@
pos++;
if(!incomment) {
if(hdrlen == sizeof(hdrbuf) - 1) {
- warnf(config->global, "File %s line %d: header too long (truncated)\n",
+ warnf(config->global, "File %s line %d: header too long (truncated)",
filename, lineno);
c = ' ';
}
@@ -499,7 +495,7 @@
sep = *p;
*endpos = '\0';
while(sep == ';') {
- while(ISSPACE(*++p))
+ while(p++ && ISSPACE(*p))
;
if(!endct && checkprefix("type=", p)) {
@@ -510,7 +506,7 @@
/* verify that this is a fine type specifier */
if(2 != sscanf(type, "%127[^/ ]/%127[^;, \n]", type_major, type_minor)) {
- warnf(config->global, "Illegally formatted content-type field!\n");
+ warnf(config->global, "Illegally formatted content-type field");
curl_slist_free_all(headers);
return -1; /* illegal content-type syntax! */
}
@@ -562,7 +558,7 @@
*endpos = '\0';
fp = fopen(hdrfile, FOPEN_READTEXT);
if(!fp)
- warnf(config->global, "Cannot read from %s: %s\n", hdrfile,
+ warnf(config->global, "Cannot read from %s: %s", hdrfile,
strerror(errno));
else {
int i = read_field_headers(config, hdrfile, fp, &headers);
@@ -588,7 +584,7 @@
sep = *p;
*endpos = '\0';
if(slist_append(&headers, hdr)) {
- fprintf(config->global->errors, "Out of memory for field header!\n");
+ errorf(config->global, "Out of memory for field header");
curl_slist_free_all(headers);
return -1;
}
@@ -624,7 +620,7 @@
sep = *p;
*endpos = '\0';
if(*unknown)
- warnf(config->global, "skip unknown form field: %s\n", unknown);
+ warnf(config->global, "skip unknown form field: %s", unknown);
}
}
@@ -635,25 +631,25 @@
if(ptype)
*ptype = type;
else if(type)
- warnf(config->global, "Field content type not allowed here: %s\n", type);
+ warnf(config->global, "Field content type not allowed here: %s", type);
if(pfilename)
*pfilename = filename;
else if(filename)
warnf(config->global,
- "Field file name not allowed here: %s\n", filename);
+ "Field file name not allowed here: %s", filename);
if(pencoder)
*pencoder = encoder;
else if(encoder)
warnf(config->global,
- "Field encoder not allowed here: %s\n", encoder);
+ "Field encoder not allowed here: %s", encoder);
if(pheaders)
*pheaders = headers;
else if(headers) {
warnf(config->global,
- "Field headers not allowed here: %s\n", headers->data);
+ "Field headers not allowed here: %s", headers->data);
curl_slist_free_all(headers);
}
@@ -709,24 +705,15 @@
*
***************************************************************************/
-/* Convenience macros for null pointer check. */
-#define NULL_CHECK(ptr, init, retcode) \
+#define SET_TOOL_MIME_PTR(m, field) \
do { \
- (ptr) = (init); \
- if(!(ptr)) { \
- warnf(config->global, "out of memory!\n"); \
- curl_slist_free_all(headers); \
- Curl_safefree(contents); \
- return retcode; \
+ if(field) { \
+ (m)->field = strdup(field); \
+ if(!(m)->field) \
+ goto fail; \
} \
} while(0)
-#define SET_TOOL_MIME_PTR(m, field, retcode) \
- do { \
- if(field) \
- NULL_CHECK((m)->field, strdup(field), retcode); \
- } while(0)
-
int formparse(struct OperationConfig *config,
const char *input,
struct tool_mime **mimeroot,
@@ -745,15 +732,20 @@
struct curl_slist *headers = NULL;
struct tool_mime *part = NULL;
CURLcode res;
+ int err = 1;
/* Allocate the main mime structure if needed. */
if(!*mimecurrent) {
- NULL_CHECK(*mimeroot, tool_mime_new_parts(NULL), 1);
+ *mimeroot = tool_mime_new_parts(NULL);
+ if(!*mimeroot)
+ goto fail;
*mimecurrent = *mimeroot;
}
/* Make a copy we can overwrite. */
- NULL_CHECK(contents, strdup(input), 2);
+ contents = strdup(input);
+ if(!contents)
+ goto fail;
/* Scan for the end of the name. */
contp = strchr(contents, '=');
@@ -767,23 +759,22 @@
/* Starting a multipart. */
sep = get_param_part(config, '\0',
&contp, &data, &type, NULL, NULL, &headers);
- if(sep < 0) {
- Curl_safefree(contents);
- return 3;
- }
- NULL_CHECK(part, tool_mime_new_parts(*mimecurrent), 4);
+ if(sep < 0)
+ goto fail;
+ part = tool_mime_new_parts(*mimecurrent);
+ if(!part)
+ goto fail;
*mimecurrent = part;
part->headers = headers;
headers = NULL;
- SET_TOOL_MIME_PTR(part, type, 5);
+ SET_TOOL_MIME_PTR(part, type);
}
else if(!name && !strcmp(contp, ")") && !literal_value) {
/* Ending a multipart. */
if(*mimecurrent == *mimeroot) {
- warnf(config->global, "no multipart to terminate!\n");
- Curl_safefree(contents);
- return 6;
- }
+ warnf(config->global, "no multipart to terminate");
+ goto fail;
+ }
*mimecurrent = (*mimecurrent)->parent;
}
else if('@' == contp[0] && !literal_value) {
@@ -799,8 +790,7 @@
sep = get_param_part(config, ',', &contp,
&data, &type, &filename, &encoder, &headers);
if(sep < 0) {
- Curl_safefree(contents);
- return 7;
+ goto fail;
}
/* now contp point to comma or string end.
@@ -808,13 +798,17 @@
if(!subparts) {
if(sep != ',') /* If there is a single file. */
subparts = *mimecurrent;
- else
- NULL_CHECK(subparts, tool_mime_new_parts(*mimecurrent), 8);
+ else {
+ subparts = tool_mime_new_parts(*mimecurrent);
+ if(!subparts)
+ goto fail;
+ }
}
/* Store that file in a part. */
- NULL_CHECK(part,
- tool_mime_new_filedata(subparts, data, TRUE, &res), 9);
+ part = tool_mime_new_filedata(subparts, data, TRUE, &res);
+ if(!part)
+ goto fail;
part->headers = headers;
headers = NULL;
part->config = config->global;
@@ -824,18 +818,17 @@
libcurl. */
if(part->size > 0) {
warnf(config->global,
- "error while reading standard input\n");
- Curl_safefree(contents);
- return 10;
+ "error while reading standard input");
+ goto fail;
}
- CONST_SAFEFREE(part->data);
+ Curl_safefree(part->data);
part->data = NULL;
part->size = -1;
res = CURLE_OK;
}
- SET_TOOL_MIME_PTR(part, filename, 11);
- SET_TOOL_MIME_PTR(part, type, 12);
- SET_TOOL_MIME_PTR(part, encoder, 13);
+ SET_TOOL_MIME_PTR(part, filename);
+ SET_TOOL_MIME_PTR(part, type);
+ SET_TOOL_MIME_PTR(part, encoder);
/* *contp could be '\0', so we just check with the delimiter */
} while(sep); /* loop if there's another file name */
@@ -846,13 +839,13 @@
++contp;
sep = get_param_part(config, '\0', &contp,
&data, &type, NULL, &encoder, &headers);
- if(sep < 0) {
- Curl_safefree(contents);
- return 14;
- }
+ if(sep < 0)
+ goto fail;
- NULL_CHECK(part, tool_mime_new_filedata(*mimecurrent, data, FALSE,
- &res), 15);
+ part = tool_mime_new_filedata(*mimecurrent, data, FALSE,
+ &res);
+ if(!part)
+ goto fail;
part->headers = headers;
headers = NULL;
part->config = config->global;
@@ -862,11 +855,10 @@
libcurl. */
if(part->size > 0) {
warnf(config->global,
- "error while reading standard input\n");
- Curl_safefree(contents);
- return 16;
+ "error while reading standard input");
+ goto fail;
}
- CONST_SAFEFREE(part->data);
+ Curl_safefree(part->data);
part->data = NULL;
part->size = -1;
res = CURLE_OK;
@@ -878,36 +870,38 @@
else {
sep = get_param_part(config, '\0', &contp,
&data, &type, &filename, &encoder, &headers);
- if(sep < 0) {
- Curl_safefree(contents);
- return 17;
- }
+ if(sep < 0)
+ goto fail;
}
- NULL_CHECK(part, tool_mime_new_data(*mimecurrent, data), 18);
+ part = tool_mime_new_data(*mimecurrent, data);
+ if(!part)
+ goto fail;
part->headers = headers;
headers = NULL;
}
- SET_TOOL_MIME_PTR(part, filename, 19);
- SET_TOOL_MIME_PTR(part, type, 20);
- SET_TOOL_MIME_PTR(part, encoder, 21);
+ SET_TOOL_MIME_PTR(part, filename);
+ SET_TOOL_MIME_PTR(part, type);
+ SET_TOOL_MIME_PTR(part, encoder);
if(sep) {
*contp = (char) sep;
warnf(config->global,
- "garbage at end of field specification: %s\n", contp);
+ "garbage at end of field specification: %s", contp);
}
}
/* Set part name. */
- SET_TOOL_MIME_PTR(part, name, 22);
+ SET_TOOL_MIME_PTR(part, name);
}
else {
- warnf(config->global, "Illegally formatted input field!\n");
- Curl_safefree(contents);
- return 23;
+ warnf(config->global, "Illegally formatted input field");
+ goto fail;
}
+ err = 0;
+fail:
Curl_safefree(contents);
- return 0;
+ curl_slist_free_all(headers);
+ return err;
}
diff --git a/src/tool_formparse.h b/src/tool_formparse.h
index 260bcf4..35d5c95 100644
--- a/src/tool_formparse.h
+++ b/src/tool_formparse.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -43,11 +43,11 @@
struct tool_mime *parent; /* Parent item. */
struct tool_mime *prev; /* Previous sibling (reverse order link). */
/* Common fields. */
- const char *data; /* Actual data or data filename. */
- const char *name; /* Part name. */
- const char *filename; /* Part's filename. */
- const char *type; /* Part's mime type. */
- const char *encoder; /* Part's requested encoding. */
+ char *data; /* Actual data or data filename. */
+ char *name; /* Part name. */
+ char *filename; /* Part's filename. */
+ char *type; /* Part's mime type. */
+ char *encoder; /* Part's requested encoding. */
struct curl_slist *headers; /* User-defined headers. */
/* TOOLMIME_PARTS fields. */
struct tool_mime *subparts; /* Part's subparts. */
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index 27e801a..ac1a98c 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -41,6 +41,8 @@
#include "tool_paramhlp.h"
#include "tool_parsecfg.h"
#include "tool_main.h"
+#include "dynbuf.h"
+#include "tool_stderr.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -120,6 +122,7 @@
{"*x", "krb4", ARG_STRING},
/* 'krb4' is the previous name */
{"*X", "haproxy-protocol", ARG_BOOL},
+ {"*P", "haproxy-clientip", ARG_STRING},
{"*y", "max-filesize", ARG_STRING},
{"*z", "disable-eprt", ARG_BOOL},
{"*Z", "eprt", ARG_BOOL},
@@ -202,12 +205,15 @@
{"$Z", "compressed-ssh", ARG_BOOL},
{"$~", "happy-eyeballs-timeout-ms", ARG_STRING},
{"$!", "retry-all-errors", ARG_BOOL},
+ {"$%", "trace-ids", ARG_BOOL},
{"0", "http1.0", ARG_NONE},
{"01", "http1.1", ARG_NONE},
{"02", "http2", ARG_NONE},
{"03", "http2-prior-knowledge", ARG_NONE},
{"04", "http3", ARG_NONE},
+ {"05", "http3-only", ARG_NONE},
{"09", "http0.9", ARG_BOOL},
+ {"0a", "proxy-http2", ARG_BOOL},
{"1", "tlsv1", ARG_NONE},
{"10", "tlsv1.0", ARG_NONE},
{"11", "tlsv1.1", ARG_NONE},
@@ -233,6 +239,7 @@
{"db", "data-binary", ARG_STRING},
{"de", "data-urlencode", ARG_STRING},
{"df", "json", ARG_STRING},
+ {"dg", "url-query", ARG_STRING},
{"D", "dump-header", ARG_FILENAME},
{"e", "referer", ARG_STRING},
{"E", "cert", ARG_FILENAME},
@@ -242,6 +249,8 @@
{"Ed", "key-type", ARG_STRING},
{"Ee", "pass", ARG_STRING},
{"Ef", "engine", ARG_STRING},
+ {"EG", "ca-native", ARG_BOOL},
+ {"EH", "proxy-ca-native", ARG_BOOL},
{"Eg", "capath", ARG_FILENAME},
{"Eh", "pubkey", ARG_STRING},
{"Ei", "hostpubmd5", ARG_STRING},
@@ -291,7 +300,7 @@
{"F", "form", ARG_STRING},
{"Fs", "form-string", ARG_STRING},
{"g", "globoff", ARG_BOOL},
- {"G", "get", ARG_NONE},
+ {"G", "get", ARG_BOOL},
{"Ga", "request-target", ARG_STRING},
{"h", "help", ARG_BOOL},
{"H", "header", ARG_STRING},
@@ -487,7 +496,6 @@
Curl_safefree(*password);
*password = passphrase;
}
- cleanarg(nextarg);
}
/* Get a size parameter for '--limit-rate' or '--max-filesize'.
@@ -501,8 +509,8 @@
char *unit;
curl_off_t value;
- if(curlx_strtoofft(arg, &unit, 0, &value)) {
- warnf(global, "invalid number specified for %s\n", which);
+ if(curlx_strtoofft(arg, &unit, 10, &value)) {
+ warnf(global, "invalid number specified for %s", which);
return PARAM_BAD_USE;
}
@@ -535,15 +543,141 @@
/* for plain bytes, leave as-is */
break;
default:
- warnf(global, "unsupported %s unit. Use G, M, K or B!\n", which);
+ warnf(global, "unsupported %s unit. Use G, M, K or B", which);
return PARAM_BAD_USE;
}
*value_out = value;
return PARAM_OK;
}
+#ifdef HAVE_WRITABLE_ARGV
+static void cleanarg(argv_item_t str)
+{
+ /* now that GetStr has copied the contents of nextarg, wipe the next
+ * argument out so that the username:password isn't displayed in the
+ * system process list */
+ if(str) {
+ size_t len = strlen(str);
+ memset(str, ' ', len);
+ }
+}
+#else
+#define cleanarg(x)
+#endif
+
+/* --data-urlencode */
+static ParameterError data_urlencode(struct GlobalConfig *global,
+ char *nextarg,
+ char **postp,
+ size_t *lenp)
+{
+ /* [name]=[content], we encode the content part only
+ * [name]@[file name]
+ *
+ * Case 2: we first load the file using that name and then encode
+ * the content.
+ */
+ ParameterError err;
+ const char *p = strchr(nextarg, '=');
+ size_t nlen;
+ char is_file;
+ char *postdata = NULL;
+ size_t size = 0;
+ if(!p)
+ /* there was no '=' letter, check for a '@' instead */
+ p = strchr(nextarg, '@');
+ if(p) {
+ nlen = p - nextarg; /* length of the name part */
+ is_file = *p++; /* pass the separator */
+ }
+ else {
+ /* neither @ nor =, so no name and it isn't a file */
+ nlen = is_file = 0;
+ p = nextarg;
+ }
+ if('@' == is_file) {
+ FILE *file;
+ /* a '@' letter, it means that a file name or - (stdin) follows */
+ if(!strcmp("-", p)) {
+ file = stdin;
+ set_binmode(stdin);
+ }
+ else {
+ file = fopen(p, "rb");
+ if(!file)
+ warnf(global,
+ "Couldn't read data from file \"%s\", this makes "
+ "an empty POST.", nextarg);
+ }
+
+ err = file2memory(&postdata, &size, file);
+
+ if(file && (file != stdin))
+ fclose(file);
+ if(err)
+ return err;
+ }
+ else {
+ GetStr(&postdata, p);
+ if(postdata)
+ size = strlen(postdata);
+ }
+
+ if(!postdata) {
+ /* no data from the file, point to a zero byte string to make this
+ get sent as a POST anyway */
+ postdata = strdup("");
+ if(!postdata)
+ return PARAM_NO_MEM;
+ size = 0;
+ }
+ else {
+ char *enc = curl_easy_escape(NULL, postdata, (int)size);
+ Curl_safefree(postdata); /* no matter if it worked or not */
+ if(enc) {
+ /* replace (in-place) '%20' by '+' according to RFC1866 */
+ size_t enclen = replace_url_encoded_space_by_plus(enc);
+ /* now make a string with the name from above and append the
+ encoded string */
+ size_t outlen = nlen + enclen + 2;
+ char *n = malloc(outlen);
+ if(!n) {
+ curl_free(enc);
+ return PARAM_NO_MEM;
+ }
+ if(nlen > 0) { /* only append '=' if we have a name */
+ msnprintf(n, outlen, "%.*s=%s", (int)nlen, nextarg, enc);
+ size = outlen-1;
+ }
+ else {
+ strcpy(n, enc);
+ size = outlen-2; /* since no '=' was inserted */
+ }
+ curl_free(enc);
+ postdata = n;
+ }
+ else
+ return PARAM_NO_MEM;
+ }
+ *postp = postdata;
+ *lenp = size;
+ return PARAM_OK;
+}
+
+static void sethttpver(struct GlobalConfig *global,
+ struct OperationConfig *config,
+ long httpversion)
+{
+ if(config->httpversion &&
+ (config->httpversion != httpversion))
+ warnf(global, "Overrides previous HTTP version option");
+
+ config->httpversion = httpversion;
+}
+
ParameterError getparameter(const char *flag, /* f or -long-flag */
char *nextarg, /* NULL if unset */
+ argv_item_t cleararg,
bool *usedarg, /* set to TRUE if the arg
has been used */
struct GlobalConfig *global,
@@ -561,6 +695,18 @@
ParameterError err;
bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled
by using --OPTION or --no-OPTION */
+ static const char *redir_protos[] = {
+ "http",
+ "https",
+ "ftp",
+ "ftps",
+ NULL
+ };
+#ifdef HAVE_WRITABLE_ARGV
+ argv_item_t clearthis = NULL;
+#else
+ (void)cleararg;
+#endif
*usedarg = FALSE; /* default is that we don't use the arg */
@@ -641,13 +787,17 @@
}
else if(!nextarg)
return PARAM_REQUIRES_PARAMETER;
- else
+ else {
+#ifdef HAVE_WRITABLE_ARGV
+ clearthis = cleararg;
+#endif
*usedarg = TRUE; /* mark it as used */
+ }
if((aliases[hit].desc == ARG_FILENAME) &&
(nextarg[0] == '-') && nextarg[1]) {
/* if the file name looks like a command line option */
- warnf(global, "The file name argument '%s' looks like a flag.\n",
+ warnf(global, "The file name argument '%s' looks like a flag.",
nextarg);
}
}
@@ -675,17 +825,19 @@
break;
case 'B': /* OAuth 2.0 bearer token */
GetStr(&config->oauth_bearer, nextarg);
- cleanarg(nextarg);
+ cleanarg(clearthis);
config->authtype |= CURLAUTH_BEARER;
break;
case 'c': /* connect-timeout */
- err = str2udouble(&config->connecttimeout, nextarg,
- LONG_MAX/1000);
+ err = secs2ms(&config->connecttimeout_ms, nextarg);
if(err)
return err;
break;
case 'C': /* doh-url */
GetStr(&config->doh_url, nextarg);
+ if(config->doh_url && !config->doh_url[0])
+ /* if given a blank string, we make it NULL again */
+ Curl_safefree(config->doh_url);
break;
case 'd': /* ciphers */
GetStr(&config->cipher_list, nextarg);
@@ -714,17 +866,17 @@
case 'g': /* --trace */
GetStr(&global->trace_dump, nextarg);
if(global->tracetype && (global->tracetype != TRACE_BIN))
- warnf(global, "--trace overrides an earlier trace/verbose option\n");
+ warnf(global, "--trace overrides an earlier trace/verbose option");
global->tracetype = TRACE_BIN;
break;
case 'G': /* --npn */
- config->nonpn = (!toggle)?TRUE:FALSE;
+ warnf(global, "--npn is no longer supported");
break;
case 'h': /* --trace-ascii */
GetStr(&global->trace_dump, nextarg);
if(global->tracetype && (global->tracetype != TRACE_ASCII))
warnf(global,
- "--trace-ascii overrides an earlier trace/verbose option\n");
+ "--trace-ascii overrides an earlier trace/verbose option");
global->tracetype = TRACE_ASCII;
break;
case 'H': /* --alpn */
@@ -736,7 +888,7 @@
ParameterError pe = GetSizeParameter(global, nextarg, "rate", &value);
if(pe != PARAM_OK)
- return pe;
+ return pe;
config->recvpersecond = value;
config->sendpersecond = value;
}
@@ -779,7 +931,7 @@
numerator = 24*60*60*1000;
break;
default:
- errorf(global, "unsupported --rate unit\n");
+ errorf(global, "unsupported --rate unit");
return PARAM_BAD_USE;
}
}
@@ -788,9 +940,7 @@
break;
case 'j': /* --compressed */
- if(toggle &&
- !(curlinfo->features & (CURL_VERSION_LIBZ |
- CURL_VERSION_BROTLI | CURL_VERSION_ZSTD)))
+ if(toggle && !(feature_libz || feature_brotli || feature_zstd))
return PARAM_LIBCURL_DOESNT_SUPPORT;
config->encoding = toggle;
break;
@@ -807,36 +957,30 @@
break;
case 'l': /* --negotiate */
- if(toggle) {
- if(curlinfo->features & CURL_VERSION_SPNEGO)
- config->authtype |= CURLAUTH_NEGOTIATE;
- else
- return PARAM_LIBCURL_DOESNT_SUPPORT;
- }
- else
+ if(!toggle)
config->authtype &= ~CURLAUTH_NEGOTIATE;
+ else if(feature_spnego)
+ config->authtype |= CURLAUTH_NEGOTIATE;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
break;
case 'm': /* --ntlm */
- if(toggle) {
- if(curlinfo->features & CURL_VERSION_NTLM)
- config->authtype |= CURLAUTH_NTLM;
- else
- return PARAM_LIBCURL_DOESNT_SUPPORT;
- }
- else
+ if(!toggle)
config->authtype &= ~CURLAUTH_NTLM;
+ else if(feature_ntlm)
+ config->authtype |= CURLAUTH_NTLM;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
break;
case 'M': /* --ntlm-wb */
- if(toggle) {
- if(curlinfo->features & CURL_VERSION_NTLM_WB)
- config->authtype |= CURLAUTH_NTLM_WB;
- else
- return PARAM_LIBCURL_DOESNT_SUPPORT;
- }
- else
+ if(!toggle)
config->authtype &= ~CURLAUTH_NTLM_WB;
+ else if(feature_ntlm_wb)
+ config->authtype |= CURLAUTH_NTLM_WB;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
break;
case 'n': /* --basic for completeness */
@@ -882,10 +1026,9 @@
break;
case 't': /* --proxy-ntlm */
- if(curlinfo->features & CURL_VERSION_NTLM)
- config->proxyntlm = toggle;
- else
+ if(!feature_ntlm)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->proxyntlm = toggle;
break;
case 'u': /* --crlf */
@@ -899,19 +1042,7 @@
break;
case 'v': /* --stderr */
- if(strcmp(nextarg, "-")) {
- FILE *newfile = fopen(nextarg, FOPEN_WRITETEXT);
- if(!newfile)
- warnf(global, "Failed to open %s!\n", nextarg);
- else {
- if(global->errors_fopened)
- fclose(global->errors);
- global->errors = newfile;
- global->errors_fopened = TRUE;
- }
- }
- else
- global->errors = stdout;
+ tool_set_stderr_file(global, nextarg);
break;
case 'w': /* --interface */
/* interface */
@@ -919,14 +1050,16 @@
break;
case 'x': /* --krb */
/* kerberos level string */
- if(curlinfo->features & CURL_VERSION_SPNEGO)
- GetStr(&config->krblevel, nextarg);
- else
+ if(!feature_spnego)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ GetStr(&config->krblevel, nextarg);
break;
case 'X': /* --haproxy-protocol */
config->haproxy_protocol = toggle;
break;
+ case 'P': /* --haproxy-clientip */
+ GetStr(&config->haproxy_clientip, nextarg);
+ break;
case 'y': /* --max-filesize */
{
curl_off_t value;
@@ -934,7 +1067,7 @@
GetSizeParameter(global, nextarg, "max-filesize", &value);
if(pe != PARAM_OK)
- return pe;
+ return pe;
config->max_filesize = value;
}
break;
@@ -982,9 +1115,12 @@
case '$': /* more options without a short option */
switch(subletter) {
case 'a': /* --ssl */
- if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+ if(toggle && !feature_ssl)
return PARAM_LIBCURL_DOESNT_SUPPORT;
config->ftp_ssl = toggle;
+ if(config->ftp_ssl)
+ warnf(global,
+ "--ssl is an insecure option, consider --ssl-reqd instead");
break;
case 'b': /* --ftp-pasv */
Curl_safefree(config->ftpport);
@@ -1039,10 +1175,9 @@
break;
case 'k': /* --proxy-negotiate */
- if(curlinfo->features & CURL_VERSION_SPNEGO)
- config->proxynegotiate = toggle;
- else
+ if(!feature_spnego)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->proxynegotiate = toggle;
break;
case 'l': /* --form-escape */
@@ -1103,7 +1238,7 @@
GetStr(&config->ftp_alternative_to_user, nextarg);
break;
case 'v': /* --ssl-reqd */
- if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+ if(toggle && !feature_ssl)
return PARAM_LIBCURL_DOESNT_SUPPORT;
config->ftp_ssl_reqd = toggle;
break;
@@ -1111,7 +1246,7 @@
config->disable_sessionid = (!toggle)?TRUE:FALSE;
break;
case 'x': /* --ftp-ssl-control */
- if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+ if(toggle && !feature_ssl)
return PARAM_LIBCURL_DOESNT_SUPPORT;
config->ftp_ssl_control = toggle;
break;
@@ -1127,7 +1262,7 @@
case 'z': /* --libcurl */
#ifdef CURL_DISABLE_LIBCURL_OPTION
warnf(global,
- "--libcurl option was disabled at build-time!\n");
+ "--libcurl option was disabled at build-time");
return PARAM_OPTION_UNKNOWN;
#else
GetStr(&global->libcurl, nextarg);
@@ -1157,7 +1292,7 @@
/* This specifies the noproxy list */
GetStr(&config->noproxy, nextarg);
break;
- case '7': /* --socks5-gssapi-nec*/
+ case '7': /* --socks5-gssapi-nec */
config->socks5_gssapi_nec = toggle;
break;
case '8': /* --proxy1.0 */
@@ -1184,12 +1319,13 @@
break;
case 'D': /* --proto */
config->proto_present = TRUE;
- if(proto2num(config, &config->proto, nextarg))
- return PARAM_BAD_USE;
+ err = proto2num(config, built_in_protos, &config->proto_str, nextarg);
+ if(err)
+ return err;
break;
case 'E': /* --proto-redir */
config->proto_redir_present = TRUE;
- if(proto2num(config, &config->proto_redir, nextarg))
+ if(proto2num(config, redir_protos, &config->proto_redir_str, nextarg))
return PARAM_BAD_USE;
break;
case 'F': /* --resolve */
@@ -1204,7 +1340,7 @@
GetStr(&config->mail_auth, nextarg);
break;
case 'J': /* --metalink */
- errorf(global, "--metalink is disabled\n");
+ errorf(global, "--metalink is disabled");
return PARAM_BAD_USE;
case '6': /* --sasl-authzid */
GetStr(&config->sasl_authzid, nextarg);
@@ -1216,7 +1352,7 @@
#ifdef CURLDEBUG
global->test_event_based = toggle;
#else
- warnf(global, "--test-event is ignored unless a debug build!\n");
+ warnf(global, "--test-event is ignored unless a debug build");
#endif
break;
case 'M': /* --unix-socket */
@@ -1239,7 +1375,7 @@
return err;
break;
case 'R': /* --expect100-timeout */
- err = str2udouble(&config->expect100timeout, nextarg, LONG_MAX/1000);
+ err = secs2ms(&config->expect100timeout_ms, nextarg);
if(err)
return err;
break;
@@ -1272,6 +1408,9 @@
return err;
/* 0 is a valid value for this timeout */
break;
+ case '%': /* --trace-ids */
+ global->traceids = toggle;
+ break;
}
break;
case '#':
@@ -1291,31 +1430,46 @@
switch(subletter) {
case '\0':
/* HTTP version 1.0 */
- config->httpversion = CURL_HTTP_VERSION_1_0;
+ sethttpver(global, config, CURL_HTTP_VERSION_1_0);
break;
case '1':
/* HTTP version 1.1 */
- config->httpversion = CURL_HTTP_VERSION_1_1;
+ sethttpver(global, config, CURL_HTTP_VERSION_1_1);
break;
case '2':
/* HTTP version 2.0 */
- config->httpversion = CURL_HTTP_VERSION_2_0;
+ if(!feature_http2)
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ sethttpver(global, config, CURL_HTTP_VERSION_2_0);
break;
case '3': /* --http2-prior-knowledge */
- /* HTTP version 2.0 over clean TCP*/
- config->httpversion = CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE;
+ /* HTTP version 2.0 over clean TCP */
+ if(!feature_http2)
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ sethttpver(global, config, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
break;
case '4': /* --http3 */
- /* HTTP version 3 go over QUIC - at once */
- if(curlinfo->features & CURL_VERSION_HTTP3)
- config->httpversion = CURL_HTTP_VERSION_3;
- else
+ /* Try HTTP/3, allow fallback */
+ if(!feature_http3)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ sethttpver(global, config, CURL_HTTP_VERSION_3);
+ break;
+ case '5': /* --http3-only */
+ /* Try HTTP/3 without fallback */
+ if(!feature_http3)
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ sethttpver(global, config, CURL_HTTP_VERSION_3ONLY);
break;
case '9':
/* Allow HTTP/0.9 responses! */
config->http09_allowed = toggle;
break;
+ case 'a':
+ /* --proxy-http2 */
+ if(!feature_httpsproxy || !feature_http2)
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->proxyver = CURLPROXY_HTTPS2;
+ break;
}
break;
case '1': /* --tlsv1* options */
@@ -1350,11 +1504,11 @@
break;
case '2':
/* SSL version 2 */
- warnf(global, "Ignores instruction to use SSLv2\n");
+ warnf(global, "Ignores instruction to use SSLv2");
break;
case '3':
/* SSL version 3 */
- warnf(global, "Ignores instruction to use SSLv3\n");
+ warnf(global, "Ignores instruction to use SSLv3");
break;
case '4':
/* IPv4 */
@@ -1375,16 +1529,14 @@
case 'b':
switch(subletter) {
case 'a': /* --alt-svc */
- if(curlinfo->features & CURL_VERSION_ALTSVC)
- GetStr(&config->altsvc, nextarg);
- else
+ if(!feature_altsvc)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ GetStr(&config->altsvc, nextarg);
break;
case 'b': /* --hsts */
- if(curlinfo->features & CURL_VERSION_HSTS)
- GetStr(&config->hsts, nextarg);
- else
+ if(!feature_hsts)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ GetStr(&config->hsts, nextarg);
break;
default: /* --cookie string coming up: */
if(nextarg[0] == '@') {
@@ -1433,91 +1585,42 @@
size_t size = 0;
bool raw_mode = (subletter == 'r');
- if(subletter == 'e') { /* --data-urlencode */
- /* [name]=[content], we encode the content part only
- * [name]@[file name]
- *
- * Case 2: we first load the file using that name and then encode
- * the content.
- */
- const char *p = strchr(nextarg, '=');
- size_t nlen;
- char is_file;
- if(!p)
- /* there was no '=' letter, check for a '@' instead */
- p = strchr(nextarg, '@');
- if(p) {
- nlen = p - nextarg; /* length of the name part */
- is_file = *p++; /* pass the separator */
+ if(subletter == 'g') { /* --url-query */
+#define MAX_QUERY_LEN 100000 /* larger is not likely to ever work */
+ char *query;
+ struct curlx_dynbuf dyn;
+ curlx_dyn_init(&dyn, MAX_QUERY_LEN);
+
+ if(*nextarg == '+') {
+ /* use without encoding */
+ query = strdup(&nextarg[1]);
+ if(!query)
+ return PARAM_NO_MEM;
}
else {
- /* neither @ nor =, so no name and it isn't a file */
- nlen = is_file = 0;
- p = nextarg;
- }
- if('@' == is_file) {
- /* a '@' letter, it means that a file name or - (stdin) follows */
- if(!strcmp("-", p)) {
- file = stdin;
- set_binmode(stdin);
- }
- else {
- file = fopen(p, "rb");
- if(!file)
- warnf(global,
- "Couldn't read data from file \"%s\", this makes "
- "an empty POST.\n", nextarg);
- }
-
- err = file2memory(&postdata, &size, file);
-
- if(file && (file != stdin))
- fclose(file);
+ err = data_urlencode(global, nextarg, &query, &size);
if(err)
return err;
}
- else {
- GetStr(&postdata, p);
- if(postdata)
- size = strlen(postdata);
- }
- if(!postdata) {
- /* no data from the file, point to a zero byte string to make this
- get sent as a POST anyway */
- postdata = strdup("");
- if(!postdata)
+ if(config->query) {
+ CURLcode result =
+ curlx_dyn_addf(&dyn, "%s&%s", config->query, query);
+ free(query);
+ if(result)
return PARAM_NO_MEM;
- size = 0;
+ free(config->query);
+ config->query = curlx_dyn_ptr(&dyn);
}
- else {
- char *enc = curl_easy_escape(NULL, postdata, (int)size);
- Curl_safefree(postdata); /* no matter if it worked or not */
- if(enc) {
- /* replace (in-place) '%20' by '+' according to RFC1866 */
- size_t enclen = replace_url_encoded_space_by_plus(enc);
- /* now make a string with the name from above and append the
- encoded string */
- size_t outlen = nlen + enclen + 2;
- char *n = malloc(outlen);
- if(!n) {
- curl_free(enc);
- return PARAM_NO_MEM;
- }
- if(nlen > 0) { /* only append '=' if we have a name */
- msnprintf(n, outlen, "%.*s=%s", nlen, nextarg, enc);
- size = outlen-1;
- }
- else {
- strcpy(n, enc);
- size = outlen-2; /* since no '=' was inserted */
- }
- curl_free(enc);
- postdata = n;
- }
- else
- return PARAM_NO_MEM;
- }
+ else
+ config->query = query;
+
+ break; /* this is not a POST argument at all */
+ }
+ else if(subletter == 'e') { /* --data-urlencode */
+ err = data_urlencode(global, nextarg, &postdata, &size);
+ if(err)
+ return err;
}
else if('@' == *nextarg && !raw_mode) {
/* the data begins with a '@' letter, it means that a file name
@@ -1533,7 +1636,7 @@
file = fopen(nextarg, "rb");
if(!file)
warnf(global, "Couldn't read data from file \"%s\", this makes "
- "an empty POST.\n", nextarg);
+ "an empty POST.", nextarg);
}
if((subletter == 'b') || /* --data-binary */
@@ -1633,11 +1736,18 @@
case 'E':
switch(subletter) {
case '\0': /* certificate file */
+ cleanarg(clearthis);
GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
break;
- case 'a': /* CA info PEM file */
+ case 'a': /* --cacert CA info PEM file */
GetStr(&config->cacert, nextarg);
break;
+ case 'G': /* --ca-native */
+ config->native_ca_store = toggle;
+ break;
+ case 'H': /* --proxy-ca-native */
+ config->proxy_native_ca_store = toggle;
+ break;
case 'b': /* cert file type */
GetStr(&config->cert_type, nextarg);
break;
@@ -1649,7 +1759,7 @@
break;
case 'e': /* private key passphrase */
GetStr(&config->key_passwd, nextarg);
- cleanarg(nextarg);
+ cleanarg(clearthis);
break;
case 'f': /* crypto engine */
GetStr(&config->engine, nextarg);
@@ -1674,42 +1784,40 @@
GetStr(&config->crlfile, nextarg);
break;
case 'k': /* TLS username */
- if(!(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)) {
- cleanarg(nextarg);
+ if(!feature_tls_srp) {
+ cleanarg(clearthis);
return PARAM_LIBCURL_DOESNT_SUPPORT;
}
GetStr(&config->tls_username, nextarg);
- cleanarg(nextarg);
+ cleanarg(clearthis);
break;
case 'l': /* TLS password */
- if(!(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)) {
- cleanarg(nextarg);
+ if(!feature_tls_srp) {
+ cleanarg(clearthis);
return PARAM_LIBCURL_DOESNT_SUPPORT;
}
GetStr(&config->tls_password, nextarg);
- cleanarg(nextarg);
+ cleanarg(clearthis);
break;
case 'm': /* TLS authentication type */
- if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
- GetStr(&config->tls_authtype, nextarg);
- if(!curl_strequal(config->tls_authtype, "SRP"))
- return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
- }
- else
+ if(!feature_tls_srp)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ GetStr(&config->tls_authtype, nextarg);
+ if(!curl_strequal(config->tls_authtype, "SRP"))
+ return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
break;
case 'n': /* no empty SSL fragments, --ssl-allow-beast */
- if(curlinfo->features & CURL_VERSION_SSL)
+ if(feature_ssl)
config->ssl_allow_beast = toggle;
break;
case 'o': /* --ssl-auto-client-cert */
- if(curlinfo->features & CURL_VERSION_SSL)
+ if(feature_ssl)
config->ssl_auto_client_cert = toggle;
break;
case 'O': /* --proxy-ssl-auto-client-cert */
- if(curlinfo->features & CURL_VERSION_SSL)
+ if(feature_ssl)
config->proxy_ssl_auto_client_cert = toggle;
break;
@@ -1734,12 +1842,12 @@
break;
case 's': /* --ssl-no-revoke */
- if(curlinfo->features & CURL_VERSION_SSL)
+ if(feature_ssl)
config->ssl_no_revoke = TRUE;
break;
case 'S': /* --ssl-revoke-best-effort */
- if(curlinfo->features & CURL_VERSION_SSL)
+ if(feature_ssl)
config->ssl_revoke_best_effort = TRUE;
break;
@@ -1748,34 +1856,29 @@
break;
case 'u': /* TLS username for proxy */
- if(!(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)) {
- cleanarg(nextarg);
+ cleanarg(clearthis);
+ if(!feature_tls_srp)
return PARAM_LIBCURL_DOESNT_SUPPORT;
- }
GetStr(&config->proxy_tls_username, nextarg);
- cleanarg(nextarg);
break;
case 'v': /* TLS password for proxy */
- if(!(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)) {
- cleanarg(nextarg);
+ cleanarg(clearthis);
+ if(!feature_tls_srp)
return PARAM_LIBCURL_DOESNT_SUPPORT;
- }
GetStr(&config->proxy_tls_password, nextarg);
- cleanarg(nextarg);
break;
case 'w': /* TLS authentication type for proxy */
- if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
- GetStr(&config->proxy_tls_authtype, nextarg);
- if(!curl_strequal(config->proxy_tls_authtype, "SRP"))
- return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
- }
- else
+ if(!feature_tls_srp)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ GetStr(&config->proxy_tls_authtype, nextarg);
+ if(!curl_strequal(config->proxy_tls_authtype, "SRP"))
+ return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
break;
case 'x': /* certificate file for proxy */
+ cleanarg(clearthis);
GetFileAndPassword(nextarg, &config->proxy_cert,
&config->proxy_key_passwd);
break;
@@ -1794,7 +1897,7 @@
case '1': /* private key passphrase for proxy */
GetStr(&config->proxy_key_passwd, nextarg);
- cleanarg(nextarg);
+ cleanarg(clearthis);
break;
case '2': /* ciphers for proxy */
@@ -1806,7 +1909,7 @@
break;
case '4': /* no empty SSL fragments for proxy */
- if(curlinfo->features & CURL_VERSION_SSL)
+ if(feature_ssl)
config->proxy_ssl_allow_beast = toggle;
break;
@@ -1886,7 +1989,7 @@
}
if(config->failonerror && config->failwithbody) {
errorf(config->global, "You must select either --fail or "
- "--fail-with-body, not both.\n");
+ "--fail-with-body, not both.");
return PARAM_BAD_USE;
}
break;
@@ -1912,7 +2015,7 @@
GetStr(&config->request_target, nextarg);
}
else
- config->use_httpget = TRUE;
+ config->use_httpget = toggle;
break;
case 'h': /* h for help */
@@ -1935,7 +2038,7 @@
bool use_stdin = !strcmp(&nextarg[1], "-");
FILE *file = use_stdin?stdin:fopen(&nextarg[1], FOPEN_READTEXT);
if(!file)
- warnf(global, "Failed to open %s!\n", &nextarg[1]);
+ warnf(global, "Failed to open %s", &nextarg[1]);
else {
err = file2memory(&string, &len, file);
if(!err && string) {
@@ -1994,7 +2097,7 @@
break;
case 'K': /* parse config file */
if(parseconfig(nextarg, global)) {
- errorf(global, "cannot read config from '%s'\n", nextarg);
+ errorf(global, "cannot read config from '%s'", nextarg);
return PARAM_READ_ERROR;
}
break;
@@ -2013,19 +2116,17 @@
break;
case 'm':
/* specified max time */
- err = str2udouble(&config->timeout, nextarg, LONG_MAX/1000);
+ err = secs2ms(&config->timeout_ms, nextarg);
if(err)
return err;
break;
case 'M': /* M for manual, huge help */
if(toggle) { /* --no-manual shows no manual... */
-#ifdef USE_MANUAL
- return PARAM_MANUAL_REQUESTED;
-#else
+#ifndef USE_MANUAL
warnf(global,
- "built-in manual was disabled at build-time!\n");
- return PARAM_OPTION_UNKNOWN;
+ "built-in manual was disabled at build-time");
#endif
+ return PARAM_MANUAL_REQUESTED;
}
break;
case 'n':
@@ -2080,9 +2181,12 @@
if(config->url_out)
/* existing node */
url = config->url_out;
- else
+ else {
+ if(!toggle && !config->default_node_flags)
+ break;
/* there was no free node, create one! */
config->url_out = url = new_getout(config);
+ }
if(!url)
return PARAM_NO_MEM;
@@ -2090,7 +2194,7 @@
/* fill in the outfile */
if('o' == letter) {
if(!*nextarg) {
- warnf(global, "output file name has no length\n");
+ warnf(global, "output file name has no length");
return PARAM_BAD_USE;
}
GetStr(&url->outfile, nextarg);
@@ -2151,12 +2255,12 @@
char buffer[32];
curl_off_t off;
if(curlx_strtoofft(nextarg, NULL, 10, &off)) {
- warnf(global, "unsupported range point\n");
+ warnf(global, "unsupported range point");
return PARAM_BAD_USE;
}
warnf(global,
"A specified range MUST include at least one dash (-). "
- "Appending one for you!\n");
+ "Appending one for you");
msnprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-", off);
Curl_safefree(config->range);
config->range = strdup(buffer);
@@ -2171,7 +2275,7 @@
warnf(global, "Invalid character is found in given range. "
"A specified range MUST have only digits in "
"\'start\'-\'stop\'. The server's response to this "
- "request is uncertain.\n");
+ "request is uncertain.");
break;
}
tmp_range++;
@@ -2183,21 +2287,11 @@
/* use remote file's time */
config->remote_time = toggle;
break;
- case 's':
- /* don't show progress meter, don't show errors : */
- if(toggle)
- global->mute = global->noprogress = TRUE;
- else
- global->mute = global->noprogress = FALSE;
- if(global->showerror < 0)
- /* if still on the default value, set showerror to the reverse of
- toggle. This is to allow -S and -s to be used in an independent
- order but still have the same effect. */
- global->showerror = (!toggle)?TRUE:FALSE; /* toggle off */
+ case 's': /* --silent */
+ global->silent = toggle;
break;
- case 'S':
- /* show errors */
- global->showerror = toggle?1:0; /* toggle on if used with -s */
+ case 'S': /* --show-error */
+ global->showerror = toggle;
break;
case 't':
/* Telnet options */
@@ -2242,12 +2336,12 @@
case 'u':
/* user:password */
GetStr(&config->userpwd, nextarg);
- cleanarg(nextarg);
+ cleanarg(clearthis);
break;
case 'U':
/* Proxy user:password */
GetStr(&config->proxyuserpwd, nextarg);
- cleanarg(nextarg);
+ cleanarg(clearthis);
break;
case 'v':
if(toggle) {
@@ -2258,7 +2352,7 @@
return PARAM_NO_MEM;
if(global->tracetype && (global->tracetype != TRACE_PLAIN))
warnf(global,
- "-v, --verbose overrides an earlier trace/verbose option\n");
+ "-v, --verbose overrides an earlier trace/verbose option");
global->tracetype = TRACE_PLAIN;
}
else
@@ -2306,7 +2400,8 @@
default:
/* --proxy */
GetStr(&config->proxy, nextarg);
- config->proxyver = CURLPROXY_HTTP;
+ if(config->proxyver != CURLPROXY_HTTPS2)
+ config->proxyver = CURLPROXY_HTTP;
break;
}
break;
@@ -2335,16 +2430,20 @@
case '\0': /* --parallel */
global->parallel = toggle;
break;
- case 'b': /* --parallel-max */
- err = str2unum(&global->parallel_max, nextarg);
+ case 'b': { /* --parallel-max */
+ long val;
+ err = str2unum(&val, nextarg);
if(err)
return err;
- if(global->parallel_max > MAX_PARALLEL)
+ if(val > MAX_PARALLEL)
global->parallel_max = MAX_PARALLEL;
- else if(global->parallel_max < 1)
+ else if(val < 1)
global->parallel_max = PARALLEL_DEFAULT;
+ else
+ global->parallel_max = (unsigned short)val;
break;
- case 'c': /* --parallel-connect */
+ }
+ case 'c': /* --parallel-immediate */
global->parallel_connect = toggle;
break;
}
@@ -2384,7 +2483,7 @@
warnf(global,
"Illegal date format for -z, --time-cond (and not "
"a file name). Disabling time condition. "
- "See curl_getdate(3) for valid date syntax.\n");
+ "See curl_getdate(3) for valid date syntax.");
}
}
break;
@@ -2420,11 +2519,17 @@
following (URL) argument to start with -. */
stillflags = FALSE;
else {
- char *nextarg = (i < (argc - 1))
- ? curlx_convert_tchar_to_UTF8(argv[i + 1])
- : NULL;
+ char *nextarg = NULL;
+ if(i < (argc - 1)) {
+ nextarg = curlx_convert_tchar_to_UTF8(argv[i + 1]);
+ if(!nextarg) {
+ curlx_unicodefree(orig_opt);
+ return PARAM_NO_MEM;
+ }
+ }
- result = getparameter(orig_opt, nextarg, &passarg, global, config);
+ result = getparameter(orig_opt, nextarg, argv[i + 1], &passarg,
+ global, config);
curlx_unicodefree(nextarg);
config = global->last;
@@ -2453,6 +2558,10 @@
else
result = PARAM_NO_MEM;
}
+ else {
+ errorf(global, "missing URL before --next");
+ result = PARAM_BAD_USE;
+ }
}
else if(!result && passarg)
i++; /* we're supposed to skip this */
@@ -2462,8 +2571,7 @@
bool used;
/* Just add the URL please */
- result = getparameter("--url", orig_opt, &used, global,
- config);
+ result = getparameter("--url", orig_opt, argv[i], &used, global, config);
}
if(!result)
@@ -2484,9 +2592,9 @@
const char *reason = param2text(result);
if(orig_opt && strcmp(":", orig_opt))
- helpf(global->errors, "option %s: %s\n", orig_opt, reason);
+ helpf(stderr, "option %s: %s", orig_opt, reason);
else
- helpf(global->errors, "%s\n", reason);
+ helpf(stderr, "%s", reason);
}
curlx_unicodefree(orig_opt);
diff --git a/src/tool_getparam.h b/src/tool_getparam.h
index ef98335..827a04e 100644
--- a/src/tool_getparam.h
+++ b/src/tool_getparam.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -54,7 +54,9 @@
struct GlobalConfig;
struct OperationConfig;
-ParameterError getparameter(const char *flag, char *nextarg, bool *usedarg,
+ParameterError getparameter(const char *flag, char *nextarg,
+ argv_item_t cleararg,
+ bool *usedarg,
struct GlobalConfig *global,
struct OperationConfig *operation);
diff --git a/src/tool_getpass.c b/src/tool_getpass.c
index c959c5a..a4fb351 100644
--- a/src/tool_getpass.c
+++ b/src/tool_getpass.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -50,14 +50,6 @@
# include <conio.h>
#endif
-#ifdef NETWARE
-# ifdef __NOVELL_LIBC__
-# include <screen.h>
-# else
-# include <nwconio.h>
-# endif
-#endif
-
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -132,45 +124,6 @@
#define DONE
#endif /* WIN32 */
-#ifdef NETWARE
-/* NetWare implementation */
-#ifdef __NOVELL_LIBC__
-char *getpass_r(const char *prompt, char *buffer, size_t buflen)
-{
- return getpassword(prompt, buffer, buflen);
-}
-#else
-char *getpass_r(const char *prompt, char *buffer, size_t buflen)
-{
- size_t i = 0;
-
- printf("%s", prompt);
- do {
- buffer[i++] = getch();
- if(buffer[i-1] == '\b') {
- /* remove this letter and if this is not the first key,
- remove the previous one as well */
- if(i > 1) {
- printf("\b \b");
- i = i - 2;
- }
- else {
- RingTheBell();
- i = i - 1;
- }
- }
- else if(buffer[i-1] != 13)
- putchar('*');
-
- } while((buffer[i-1] != 13) && (i < buflen));
- buffer[i-1] = '\0';
- printf("\r\n");
- return buffer;
-}
-#endif /* __NOVELL_LIBC__ */
-#define DONE
-#endif /* NETWARE */
-
#ifndef DONE /* not previously provided */
#ifdef HAVE_TERMIOS_H
diff --git a/src/tool_getpass.h b/src/tool_getpass.h
index 01dc464..b93585d 100644
--- a/src/tool_getpass.h
+++ b/src/tool_getpass.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_help.c b/src/tool_help.c
index 75400d9..729b78c 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,16 +22,13 @@
*
***************************************************************************/
#include "tool_setup.h"
-#if defined(HAVE_STRCASECMP) && defined(HAVE_STRINGS_H)
-#include <strings.h>
-#endif
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
-#include "tool_panykey.h"
#include "tool_help.h"
#include "tool_libinfo.h"
+#include "tool_util.h"
#include "tool_version.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -78,42 +75,6 @@
extern const struct helptxt helptext[];
-struct feat {
- const char *name;
- int bitmask;
-};
-
-static const struct feat feats[] = {
- {"AsynchDNS", CURL_VERSION_ASYNCHDNS},
- {"Debug", CURL_VERSION_DEBUG},
- {"TrackMemory", CURL_VERSION_CURLDEBUG},
- {"IDN", CURL_VERSION_IDN},
- {"IPv6", CURL_VERSION_IPV6},
- {"Largefile", CURL_VERSION_LARGEFILE},
- {"Unicode", CURL_VERSION_UNICODE},
- {"SSPI", CURL_VERSION_SSPI},
- {"GSS-API", CURL_VERSION_GSSAPI},
- {"Kerberos", CURL_VERSION_KERBEROS5},
- {"SPNEGO", CURL_VERSION_SPNEGO},
- {"NTLM", CURL_VERSION_NTLM},
- {"NTLM_WB", CURL_VERSION_NTLM_WB},
- {"SSL", CURL_VERSION_SSL},
- {"libz", CURL_VERSION_LIBZ},
- {"brotli", CURL_VERSION_BROTLI},
- {"zstd", CURL_VERSION_ZSTD},
- {"CharConv", CURL_VERSION_CONV},
- {"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
- {"HTTP2", CURL_VERSION_HTTP2},
- {"HTTP3", CURL_VERSION_HTTP3},
- {"UnixSockets", CURL_VERSION_UNIX_SOCKETS},
- {"HTTPS-proxy", CURL_VERSION_HTTPS_PROXY},
- {"MultiSSL", CURL_VERSION_MULTI_SSL},
- {"PSL", CURL_VERSION_PSL},
- {"alt-svc", CURL_VERSION_ALTSVC},
- {"HSTS", CURL_VERSION_HSTS},
- {"gsasl", CURL_VERSION_GSASL},
- {"threadsafe", CURL_VERSION_THREADSAFE},
-};
static void print_category(curlhelp_t category)
{
@@ -190,26 +151,21 @@
free(category);
}
-static int
-featcomp(const void *p1, const void *p2)
+static bool is_debug(void)
{
- /* The arguments to this function are "pointers to pointers to char", but
- the comparison arguments are "pointers to char", hence the following cast
- plus dereference */
-#ifdef HAVE_STRCASECMP
- return strcasecmp(* (char * const *) p1, * (char * const *) p2);
-#elif defined(HAVE_STRCMPI)
- return strcmpi(* (char * const *) p1, * (char * const *) p2);
-#elif defined(HAVE_STRICMP)
- return stricmp(* (char * const *) p1, * (char * const *) p2);
-#else
- return strcmp(* (char * const *) p1, * (char * const *) p2);
-#endif
+ const char *const *builtin;
+ for(builtin = feature_names; *builtin; ++builtin)
+ if(curl_strequal("debug", *builtin))
+ return TRUE;
+ return FALSE;
}
void tool_version_info(void)
{
- const char *const *proto;
+ const char *const *builtin;
+ if(is_debug())
+ fprintf(stderr, "WARNING: this libcurl is Debug-enabled, "
+ "do not use in production\n\n");
printf(CURL_ID "%s\n", curl_version());
#ifdef CURL_PATCHSTAMP
@@ -218,25 +174,20 @@
#else
printf("Release-Date: %s\n", LIBCURL_TIMESTAMP);
#endif
- if(curlinfo->protocols) {
- printf("Protocols: ");
- for(proto = curlinfo->protocols; *proto; ++proto) {
- printf("%s ", *proto);
+ if(built_in_protos[0]) {
+ printf("Protocols:");
+ for(builtin = built_in_protos; *builtin; ++builtin) {
+ /* Special case: do not list rtmp?* protocols.
+ They may only appear together with "rtmp" */
+ if(!curl_strnequal(*builtin, "rtmp", 4) || !builtin[0][4])
+ printf(" %s", *builtin);
}
puts(""); /* newline */
}
- if(curlinfo->features) {
- char *featp[ sizeof(feats) / sizeof(feats[0]) + 1];
- size_t numfeat = 0;
- unsigned int i;
+ if(feature_names[0]) {
printf("Features:");
- for(i = 0; i < sizeof(feats)/sizeof(feats[0]); i++) {
- if(curlinfo->features & feats[i].bitmask)
- featp[numfeat++] = (char *)feats[i].name;
- }
- qsort(&featp[0], numfeat, sizeof(char *), featcomp);
- for(i = 0; i< numfeat; i++)
- printf(" %s", featp[i]);
+ for(builtin = feature_names; *builtin; ++builtin)
+ printf(" %s", *builtin);
puts(""); /* newline */
}
if(strcmp(CURL_VERSION, curlinfo->version)) {
diff --git a/src/tool_help.h b/src/tool_help.h
index 6fe244e..fe497ed 100644
--- a/src/tool_help.h
+++ b/src/tool_help.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_helpers.c b/src/tool_helpers.c
index 3b2fe9d..1e36f06 100644
--- a/src/tool_helpers.c
+++ b/src/tool_helpers.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -99,7 +99,7 @@
return 0;
}
warnf(config->global, "You can only select one HTTP request method! "
- "You asked for both %s and %s.\n",
+ "You asked for both %s and %s.",
reqname[req], reqname[*store]);
return 1;
@@ -122,11 +122,11 @@
;
else if(curl_strequal(method, dflt[req])) {
notef(config->global, "Unnecessary use of -X or --request, %s is already "
- "inferred.\n", dflt[req]);
+ "inferred.", dflt[req]);
}
else if(curl_strequal(method, "head")) {
warnf(config->global,
"Setting custom HTTP method to HEAD with -X/--request may not work "
- "the way you want. Consider using -I/--head instead.\n");
+ "the way you want. Consider using -I/--head instead.");
}
}
diff --git a/src/tool_helpers.h b/src/tool_helpers.h
index cdc8410..2cfbad2 100644
--- a/src/tool_helpers.h
+++ b/src/tool_helpers.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_hugehelp.c.cvs b/src/tool_hugehelp.c.cvs
index f9fabab..06b132f 100644
--- a/src/tool_hugehelp.c.cvs
+++ b/src/tool_hugehelp.c.cvs
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_hugehelp.h b/src/tool_hugehelp.h
index 9d10280..ce9af0c 100644
--- a/src/tool_hugehelp.h
+++ b/src/tool_hugehelp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,6 +25,11 @@
***************************************************************************/
#include "tool_setup.h"
+#ifdef USE_MANUAL
void hugehelp(void);
+#else
+/* do nothing if not there */
+#define hugehelp()
+#endif
#endif /* HEADER_CURL_TOOL_HUGEHELP_H */
diff --git a/src/tool_libinfo.c b/src/tool_libinfo.c
index 039443e..a2d30fc 100644
--- a/src/tool_libinfo.c
+++ b/src/tool_libinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,85 +35,172 @@
/* global variable definitions, for libcurl run-time info */
-curl_version_info_data *curlinfo = NULL;
-long built_in_protos = 0;
+static const char *no_protos = NULL;
-static struct proto_name_pattern {
- const char *proto_name;
- long proto_pattern;
+curl_version_info_data *curlinfo = NULL;
+const char * const *built_in_protos = &no_protos;
+
+size_t proto_count = 0;
+
+const char *proto_file = NULL;
+const char *proto_ftp = NULL;
+const char *proto_ftps = NULL;
+const char *proto_http = NULL;
+const char *proto_https = NULL;
+const char *proto_rtsp = NULL;
+const char *proto_scp = NULL;
+const char *proto_sftp = NULL;
+const char *proto_tftp = NULL;
+
+static struct proto_name_tokenp {
+ const char *proto_name;
+ const char **proto_tokenp;
} const possibly_built_in[] = {
- { "dict", CURLPROTO_DICT },
- { "file", CURLPROTO_FILE },
- { "ftp", CURLPROTO_FTP },
- { "ftps", CURLPROTO_FTPS },
- { "gopher", CURLPROTO_GOPHER },
- { "gophers",CURLPROTO_GOPHERS},
- { "http", CURLPROTO_HTTP },
- { "https", CURLPROTO_HTTPS },
- { "imap", CURLPROTO_IMAP },
- { "imaps", CURLPROTO_IMAPS },
- { "ldap", CURLPROTO_LDAP },
- { "ldaps", CURLPROTO_LDAPS },
- { "mqtt", CURLPROTO_MQTT },
- { "pop3", CURLPROTO_POP3 },
- { "pop3s", CURLPROTO_POP3S },
- { "rtmp", CURLPROTO_RTMP },
- { "rtmps", CURLPROTO_RTMPS },
- { "rtsp", CURLPROTO_RTSP },
- { "scp", CURLPROTO_SCP },
- { "sftp", CURLPROTO_SFTP },
- { "smb", CURLPROTO_SMB },
- { "smbs", CURLPROTO_SMBS },
- { "smtp", CURLPROTO_SMTP },
- { "smtps", CURLPROTO_SMTPS },
- { "telnet", CURLPROTO_TELNET },
- { "tftp", CURLPROTO_TFTP },
- { NULL, 0 }
+ { "file", &proto_file },
+ { "ftp", &proto_ftp },
+ { "ftps", &proto_ftps },
+ { "http", &proto_http },
+ { "https", &proto_https },
+ { "rtsp", &proto_rtsp },
+ { "scp", &proto_scp },
+ { "sftp", &proto_sftp },
+ { "tftp", &proto_tftp },
+ { NULL, NULL }
};
+bool feature_altsvc = FALSE;
+bool feature_brotli = FALSE;
+bool feature_hsts = FALSE;
+bool feature_http2 = FALSE;
+bool feature_http3 = FALSE;
+bool feature_httpsproxy = FALSE;
+bool feature_libz = FALSE;
+bool feature_ntlm = FALSE;
+bool feature_ntlm_wb = FALSE;
+bool feature_spnego = FALSE;
+bool feature_ssl = FALSE;
+bool feature_tls_srp = FALSE;
+bool feature_zstd = FALSE;
+
+static struct feature_name_presentp {
+ const char *feature_name;
+ bool *feature_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},
+ {"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},
+ {"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[sizeof(maybe_feature) / sizeof(maybe_feature[0])];
+const char * const *feature_names = fnames;
+
/*
* libcurl_info_init: retrieves run-time information about libcurl,
* setting a global pointer 'curlinfo' to libcurl's run-time info
- * struct, and a global bit pattern 'built_in_protos' composed of
- * CURLPROTO_* bits indicating which protocols are actually built
- * into library being used.
+ * struct, count protocols and flag those we are interested in.
+ * Global pointer feature_names is set to the feature names array. If
+ * the latter is not returned by curl_version_info(), it is built from
+ * the returned features bit mask.
*/
CURLcode get_libcurl_info(void)
{
- const char *const *proto;
+ CURLcode result = CURLE_OK;
+ const char *const *builtin;
/* Pointer to libcurl's run-time version information */
curlinfo = curl_version_info(CURLVERSION_NOW);
if(!curlinfo)
return CURLE_FAILED_INIT;
- /* Build CURLPROTO_* bit pattern with libcurl's built-in protocols */
- built_in_protos = 0;
if(curlinfo->protocols) {
- for(proto = curlinfo->protocols; *proto; proto++) {
- struct proto_name_pattern const *p;
- for(p = possibly_built_in; p->proto_name; p++) {
- if(curl_strequal(*proto, p->proto_name)) {
- built_in_protos |= p->proto_pattern;
+ const struct proto_name_tokenp *p;
+
+ built_in_protos = curlinfo->protocols;
+
+ for(builtin = built_in_protos; !result && *builtin; builtin++) {
+ /* Identify protocols we are interested in. */
+ for(p = possibly_built_in; p->proto_name; p++)
+ if(curl_strequal(p->proto_name, *builtin)) {
+ *p->proto_tokenp = *builtin;
break;
}
- }
}
+ proto_count = builtin - built_in_protos;
+ }
+
+ if(curlinfo->age >= CURLVERSION_ELEVENTH && curlinfo->feature_names)
+ feature_names = curlinfo->feature_names;
+ else {
+ const struct feature_name_presentp *p;
+ const char **cpp = fnames;
+
+ for(p = maybe_feature; p->feature_name; p++)
+ if(curlinfo->features & p->feature_bitmask)
+ *cpp++ = p->feature_name;
+ *cpp = NULL;
+ }
+
+ /* Identify features we are interested in. */
+ for(builtin = feature_names; *builtin; builtin++) {
+ const struct feature_name_presentp *p;
+
+ for(p = maybe_feature; p->feature_name; p++)
+ if(curl_strequal(p->feature_name, *builtin)) {
+ if(p->feature_presentp)
+ *p->feature_presentp = TRUE;
+ break;
+ }
}
return CURLE_OK;
}
-/*
- * scheme2protocol() returns the protocol bit for the specified URL scheme
+/* Tokenize a protocol name.
+ * Return the address of the protocol name listed by the library, or NULL if
+ * not found.
+ * Although this may seem useless, this always returns the same address for
+ * a given protocol and thus allows comparing pointers rather than strings.
+ * In addition, the returned pointer is not deallocated until the program ends.
*/
-long scheme2protocol(const char *scheme)
+
+const char *proto_token(const char *proto)
{
- struct proto_name_pattern const *p;
- for(p = possibly_built_in; p->proto_name; p++) {
- if(curl_strequal(scheme, p->proto_name))
- return p->proto_pattern;
- }
- return 0;
+ const char * const *builtin;
+
+ if(!proto)
+ return NULL;
+ for(builtin = built_in_protos; *builtin; builtin++)
+ if(curl_strequal(*builtin, proto))
+ break;
+ return *builtin;
}
diff --git a/src/tool_libinfo.h b/src/tool_libinfo.h
index ba6fc0e..4937e4f 100644
--- a/src/tool_libinfo.h
+++ b/src/tool_libinfo.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,10 +27,39 @@
/* global variable declarations, for libcurl run-time info */
+
extern curl_version_info_data *curlinfo;
-extern long built_in_protos;
+
+extern const char * const *built_in_protos;
+extern size_t proto_count;
+
+extern const char * const *feature_names;
+
+extern const char *proto_file;
+extern const char *proto_ftp;
+extern const char *proto_ftps;
+extern const char *proto_http;
+extern const char *proto_https;
+extern const char *proto_rtsp;
+extern const char *proto_scp;
+extern const char *proto_sftp;
+extern const char *proto_tftp;
+
+extern bool feature_altsvc;
+extern bool feature_brotli;
+extern bool feature_hsts;
+extern bool feature_http2;
+extern bool feature_http3;
+extern bool feature_httpsproxy;
+extern bool feature_libz;
+extern bool feature_ntlm;
+extern bool feature_ntlm_wb;
+extern bool feature_spnego;
+extern bool feature_ssl;
+extern bool feature_tls_srp;
+extern bool feature_zstd;
CURLcode get_libcurl_info(void);
-long scheme2protocol(const char *scheme);
+const char *proto_token(const char *proto);
#endif /* HEADER_CURL_TOOL_LIBINFO_H */
diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c
index 266f9b0..b1eaf60 100644
--- a/src/tool_listhelp.c
+++ b/src/tool_listhelp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -51,6 +51,9 @@
{" --basic",
"Use HTTP Basic Authentication",
CURLHELP_AUTH},
+ {" --ca-native",
+ "Use CA certificates from the native OS",
+ CURLHELP_TLS},
{" --cacert <file>",
"CA certificate to verify peer against",
CURLHELP_TLS},
@@ -197,7 +200,7 @@
CURLHELP_HTTP | CURLHELP_UPLOAD},
{" --form-escape",
"Escape multipart form field/file names using backslash",
- CURLHELP_HTTP | CURLHELP_POST},
+ CURLHELP_HTTP | CURLHELP_UPLOAD},
{" --form-string <name=string>",
"Specify multipart MIME data",
CURLHELP_HTTP | CURLHELP_UPLOAD},
@@ -246,12 +249,15 @@
{" --haproxy-protocol",
"Send HAProxy PROXY protocol v1 header",
CURLHELP_HTTP | CURLHELP_PROXY},
+ {" --haproxy-clientip",
+ "Sets the HAProxy PROXY protocol v1 client IP",
+ CURLHELP_HTTP | CURLHELP_PROXY},
{"-I, --head",
"Show document info only",
CURLHELP_HTTP | CURLHELP_FTP | CURLHELP_FILE},
{"-H, --header <header/@file>",
"Pass custom header(s) to server",
- CURLHELP_HTTP},
+ CURLHELP_HTTP | CURLHELP_IMAP | CURLHELP_SMTP},
{"-h, --help <category>",
"Get help for commands",
CURLHELP_IMPORTANT | CURLHELP_CURL},
@@ -274,7 +280,7 @@
"Use HTTP 1.1",
CURLHELP_HTTP},
{" --http2",
- "Use HTTP 2",
+ "Use HTTP/2",
CURLHELP_HTTP},
{" --http2-prior-knowledge",
"Use HTTP 2 without HTTP/1.1 Upgrade",
@@ -282,6 +288,9 @@
{" --http3",
"Use HTTP v3",
CURLHELP_HTTP},
+ {" --http3-only",
+ "Use HTTP v3 only",
+ CURLHELP_HTTP},
{" --ignore-content-length",
"Ignore the size of the remote resource",
CURLHELP_HTTP | CURLHELP_FTP},
@@ -471,6 +480,9 @@
{" --proxy-basic",
"Use Basic authentication on the proxy",
CURLHELP_PROXY | CURLHELP_AUTH},
+ {" --proxy-ca-native",
+ "Use CA certificates from the native OS for proxy",
+ CURLHELP_TLS},
{" --proxy-cacert <file>",
"CA certificate to verify peer against for proxy",
CURLHELP_PROXY | CURLHELP_TLS},
@@ -495,6 +507,9 @@
{" --proxy-header <header/@file>",
"Pass custom header(s) to proxy",
CURLHELP_PROXY},
+ {" --proxy-http2",
+ "Use HTTP/2 with HTTPS proxy",
+ CURLHELP_HTTP | CURLHELP_PROXY},
{" --proxy-insecure",
"Do HTTPS proxy connections without verifying the proxy",
CURLHELP_PROXY | CURLHELP_TLS},
@@ -593,7 +608,7 @@
CURLHELP_HTTP},
{" --resolve <[+]host:port:addr[,addr]...>",
"Resolve the host+port to this address",
- CURLHELP_CONNECTION},
+ CURLHELP_CONNECTION | CURLHELP_DNS},
{" --retry <num>",
"Retry request if transient problems occur",
CURLHELP_CURL},
@@ -744,6 +759,9 @@
{" --trace-ascii <file>",
"Like --trace, but without hex output",
CURLHELP_VERBOSE},
+ {" --trace-ids",
+ "Add transfer/connection identifiers to trace/verbose output",
+ CURLHELP_VERBOSE},
{" --trace-time",
"Add time stamps to trace/verbose output",
CURLHELP_VERBOSE},
@@ -756,6 +774,9 @@
{" --url <url>",
"URL to work with",
CURLHELP_CURL},
+ {" --url-query <data>",
+ "Add a URL query part",
+ CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
{"-B, --use-ascii",
"Use ASCII/text transfer",
CURLHELP_MISC},
diff --git a/src/tool_main.c b/src/tool_main.c
index 2274bd0..21c86db 100644
--- a/src/tool_main.c
+++ b/src/tool_main.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,6 +33,10 @@
#include <signal.h>
#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
#ifdef USE_NSS
#include <nspr.h>
#include <plarenas.h>
@@ -46,10 +50,10 @@
#include "tool_doswin.h"
#include "tool_msgs.h"
#include "tool_operate.h"
-#include "tool_panykey.h"
#include "tool_vms.h"
#include "tool_main.h"
#include "tool_libinfo.h"
+#include "tool_stderr.h"
/*
* This is low-level hard-hacking memory leak tracking and similar. Using
@@ -74,35 +78,37 @@
* when command-line argument globbing is enabled under the MSYS shell, so turn
* it off.
*/
+extern int _CRT_glob;
int _CRT_glob = 0;
#endif /* __MINGW32__ */
/* if we build a static library for unit tests, there is no main() function */
#ifndef UNITTESTS
+#if defined(HAVE_PIPE) && defined(HAVE_FCNTL)
/*
* Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are
* open before starting to run. Otherwise, the first three network
* sockets opened by curl could be used for input sources, downloaded data
* or error logs as they will effectively be stdin, stdout and/or stderr.
+ *
+ * fcntl's F_GETFD instruction returns -1 if the file descriptor is closed,
+ * otherwise it returns "the file descriptor flags (which typically can only
+ * be FD_CLOEXEC, which is not set here).
*/
-static void main_checkfds(void)
+static int main_checkfds(void)
{
-#ifdef HAVE_PIPE
- int fd[2] = { STDIN_FILENO, STDIN_FILENO };
- while(fd[0] == STDIN_FILENO ||
- fd[0] == STDOUT_FILENO ||
- fd[0] == STDERR_FILENO ||
- fd[1] == STDIN_FILENO ||
- fd[1] == STDOUT_FILENO ||
- fd[1] == STDERR_FILENO)
- if(pipe(fd) < 0)
- return; /* Out of handles. This isn't really a big problem now, but
- will be when we try to create a socket later. */
- close(fd[0]);
- close(fd[1]);
-#endif
+ int fd[2];
+ while((fcntl(STDIN_FILENO, F_GETFD) == -1) ||
+ (fcntl(STDOUT_FILENO, F_GETFD) == -1) ||
+ (fcntl(STDERR_FILENO, F_GETFD) == -1))
+ if(pipe(fd))
+ return 1;
+ return 0;
}
+#else
+#define main_checkfds() 0
+#endif
#ifdef CURLDEBUG
static void memory_tracking_init(void)
@@ -151,8 +157,7 @@
#endif
/* Initialise the global config */
- config->showerror = -1; /* Will show errors */
- config->errors = stderr; /* Default errors to stderr */
+ config->showerror = FALSE; /* show errors when silent */
config->styled_output = TRUE; /* enable detection */
config->parallel_max = PARALLEL_DEFAULT;
@@ -171,17 +176,17 @@
config->first->global = config;
}
else {
- errorf(config, "error retrieving curl library information\n");
+ errorf(config, "error retrieving curl library information");
free(config->first);
}
}
else {
- errorf(config, "error initializing curl library\n");
+ errorf(config, "error initializing curl library");
free(config->first);
}
}
else {
- errorf(config, "error initializing curl\n");
+ errorf(config, "error initializing curl");
result = CURLE_FAILED_INIT;
}
@@ -192,10 +197,6 @@
{
Curl_safefree(config->trace_dump);
- if(config->errors_fopened && config->errors)
- fclose(config->errors);
- config->errors = NULL;
-
if(config->trace_fopened && config->trace_stream)
fclose(config->trace_stream);
config->trace_stream = NULL;
@@ -232,6 +233,11 @@
** curl tool main function.
*/
#ifdef _UNICODE
+#if defined(__GNUC__)
+/* GCC doesn't know about wmain() */
+#pragma GCC diagnostic ignored "-Wmissing-prototypes"
+#pragma GCC diagnostic ignored "-Wmissing-declarations"
+#endif
int wmain(int argc, wchar_t *argv[])
#else
int main(int argc, char *argv[])
@@ -241,6 +247,8 @@
struct GlobalConfig global;
memset(&global, 0, sizeof(global));
+ tool_init_stderr();
+
#ifdef WIN32
/* Undocumented diagnostic option to list the full paths of all loaded
modules. This is purposely pre-init. */
@@ -254,12 +262,15 @@
/* win32_init must be called before other init routines. */
result = win32_init();
if(result) {
- fprintf(stderr, "curl: (%d) Windows-specific init failed.\n", result);
+ errorf(&global, "(%d) Windows-specific init failed", result);
return result;
}
#endif
- main_checkfds();
+ if(main_checkfds()) {
+ errorf(&global, "out of file descriptors");
+ return CURLE_FAILED_INIT;
+ }
#if defined(HAVE_SIGNAL) && defined(SIGPIPE)
(void)signal(SIGPIPE, SIG_IGN);
@@ -284,11 +295,6 @@
fflush(NULL);
#endif
-#ifdef __NOVELL_LIBC__
- if(!getenv("_IN_NETWARE_BASH_"))
- tool_pressanykey();
-#endif
-
#ifdef __VMS
vms_special_exit(result, vms_show);
#else
diff --git a/src/tool_main.h b/src/tool_main.h
index a1fd107..cae520e 100644
--- a/src/tool_main.h
+++ b/src/tool_main.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_msgs.c b/src/tool_msgs.c
index 4900333..9754870 100644
--- a/src/tool_msgs.c
+++ b/src/tool_msgs.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,7 +42,8 @@
va_list ap)
{
size_t width = (79 - strlen(prefix));
- if(!config->mute) {
+ DEBUGASSERT(!strchr(fmt, '\n'));
+ if(!config->silent) {
size_t len;
char *ptr;
char *print_buffer;
@@ -54,12 +55,12 @@
ptr = print_buffer;
while(len > 0) {
- fputs(prefix, config->errors);
+ fputs(prefix, stderr);
if(len > width) {
size_t cut = width-1;
- while(!ISSPACE(ptr[cut]) && cut) {
+ while(!ISBLANK(ptr[cut]) && cut) {
cut--;
}
if(0 == cut)
@@ -67,13 +68,14 @@
max text width then! */
cut = width-1;
- (void)fwrite(ptr, cut + 1, 1, config->errors);
- fputs("\n", config->errors);
+ (void)fwrite(ptr, cut + 1, 1, stderr);
+ fputs("\n", stderr);
ptr += cut + 1; /* skip the space too */
len -= cut + 1;
}
else {
- fputs(ptr, config->errors);
+ fputs(ptr, stderr);
+ fputs("\n", stderr);
len = 0;
}
}
@@ -115,9 +117,11 @@
if(fmt) {
va_list ap;
va_start(ap, fmt);
+ DEBUGASSERT(!strchr(fmt, '\n'));
fputs("curl: ", errors); /* prefix it */
vfprintf(errors, fmt, ap);
va_end(ap);
+ fputs("\n", errors); /* newline it */
}
fprintf(errors, "curl: try 'curl --help' "
#ifdef USE_MANUAL
@@ -132,7 +136,7 @@
*/
void errorf(struct GlobalConfig *config, const char *fmt, ...)
{
- if(!config->mute) {
+ if(!config->silent || config->showerror) {
va_list ap;
va_start(ap, fmt);
voutf(config, ERROR_PREFIX, fmt, ap);
diff --git a/src/tool_msgs.h b/src/tool_msgs.h
index e35884e..9458991 100644
--- a/src/tool_msgs.h
+++ b/src/tool_msgs.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,6 +24,7 @@
*
***************************************************************************/
#include "tool_setup.h"
+#include "tool_cfgable.h"
void warnf(struct GlobalConfig *config, const char *fmt, ...);
void notef(struct GlobalConfig *config, const char *fmt, ...);
diff --git a/src/tool_operate.c b/src/tool_operate.c
index c317b3b..9cff7b3 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -205,6 +205,7 @@
struct per_transfer *transfers; /* first node */
static struct per_transfer *transfersl; /* last node */
+static curl_off_t all_pers;
/* add_per_transfer creates a new 'per_transfer' node in the linked
list of transfers */
@@ -227,6 +228,8 @@
}
*per = p;
all_xfers++; /* count total number of transfers added */
+ all_pers++;
+
return CURLE_OK;
}
@@ -254,6 +257,7 @@
transfersl = p;
free(per);
+ all_pers--;
return n;
}
@@ -269,11 +273,11 @@
/* VMS Note:
*
* Reading binary from files can be a problem... Only FIXED, VAR
- * etc WITHOUT implied CC will work Others need a \n appended to a
- * line
+ * etc WITHOUT implied CC will work. Others need a \n appended to
+ * a line
*
- * - Stat gives a size but this is UNRELIABLE in VMS As a f.e. a
- * fixed file with implied CC needs to have a byte added for every
+ * - Stat gives a size but this is UNRELIABLE in VMS. E.g.
+ * a fixed file with implied CC needs to have a byte added for every
* record processed, this can be derived from Filesize & recordsize
* for VARiable record files the records need to be counted! for
* every record add 1 for linefeed and subtract 2 for the record
@@ -302,7 +306,7 @@
if((per->infd == -1) || fstat(per->infd, &fileinfo))
#endif
{
- helpf(global->errors, "Can't open '%s'!\n", per->uploadfile);
+ helpf(stderr, "Can't open '%s'", per->uploadfile);
if(per->infd != -1) {
close(per->infd);
per->infd = STDIN_FILENO;
@@ -315,18 +319,70 @@
if(S_ISREG(fileinfo.st_mode))
uploadfilesize = fileinfo.st_size;
+#ifdef DEBUGBUILD
+ /* allow dedicated test cases to override */
+ {
+ char *ev = getenv("CURL_UPLOAD_SIZE");
+ if(ev) {
+ int sz = atoi(ev);
+ uploadfilesize = (curl_off_t)sz;
+ }
+ }
+#endif
+
if(uploadfilesize != -1) {
struct OperationConfig *config = per->config; /* for the macro below */
#ifdef CURL_DISABLE_LIBCURL_OPTION
(void)config;
+ (void)global;
#endif
my_setopt(per->curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
}
- per->input.fd = per->infd;
}
+ per->uploadfilesize = uploadfilesize;
+ per->start = tvnow();
return result;
}
+#ifdef __AMIGA__
+static void AmigaSetComment(struct per_transfer *per,
+ CURLcode result)
+{
+ struct OutStruct *outs = &per->outs;
+ if(!result && outs->s_isreg && outs->filename) {
+ /* Set the url (up to 80 chars) as comment for the file */
+ if(strlen(per->this_url) > 78)
+ per->this_url[79] = '\0';
+ SetComment(outs->filename, per->this_url);
+ }
+}
+#else
+#define AmigaSetComment(x,y) Curl_nop_stmt
+#endif
+
+/* When doing serial transfers, we use a single fixed error area */
+static char global_errorbuffer[CURL_ERROR_SIZE];
+
+void single_transfer_cleanup(struct OperationConfig *config)
+{
+ if(config) {
+ struct State *state = &config->state;
+ if(state->urls) {
+ /* Free list of remaining URLs */
+ glob_cleanup(state->urls);
+ state->urls = NULL;
+ }
+ Curl_safefree(state->outfiles);
+ Curl_safefree(state->httpgetfields);
+ Curl_safefree(state->uploadfile);
+ if(state->inglob) {
+ /* Free list of globbed upload files */
+ glob_cleanup(state->inglob);
+ state->inglob = NULL;
+ }
+ }
+}
+
/*
* Call this after a transfer has completed.
*/
@@ -339,6 +395,7 @@
struct OutStruct *outs = &per->outs;
CURL *curl = per->curl;
struct OperationConfig *config = per->config;
+ int rc;
if(!curl || !config)
return result;
@@ -352,25 +409,26 @@
#ifdef __VMS
if(is_vms_shell()) {
/* VMS DCL shell behavior */
- if(!global->showerror)
+ if(global->silent && !global->showerror)
vms_show = VMSSTS_HIDE;
}
else
#endif
- if(!config->synthetic_error && result && global->showerror) {
- fprintf(global->errors, "curl: (%d) %s\n", result,
- (per->errorbuffer[0]) ? per->errorbuffer :
- curl_easy_strerror(result));
+ if(!config->synthetic_error && result &&
+ (!global->silent || global->showerror)) {
+ const char *msg = per->errorbuffer;
+ fprintf(stderr, "curl: (%d) %s\n", result,
+ (msg && msg[0]) ? msg : curl_easy_strerror(result));
if(result == CURLE_PEER_FAILED_VERIFICATION)
- fputs(CURL_CA_CERT_ERRORMSG, global->errors);
+ fputs(CURL_CA_CERT_ERRORMSG, stderr);
}
else if(config->failwithbody) {
/* if HTTP response >= 400, return error */
long code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
if(code >= 400) {
- if(global->showerror)
- fprintf(global->errors,
+ if(!global->silent || global->showerror)
+ fprintf(stderr,
"curl: (%d) The requested URL returned error: %ld\n",
CURLE_HTTP_RETURNED_ERROR, code);
result = CURLE_HTTP_RETURNED_ERROR;
@@ -378,9 +436,9 @@
}
/* Set file extended attributes */
if(!result && config->xattr && outs->fopened && outs->stream) {
- int rc = fwrite_xattr(curl, fileno(outs->stream));
+ rc = fwrite_xattr(curl, per->this_url, fileno(outs->stream));
if(rc)
- warnf(config->global, "Error setting extended attributes on '%s': %s\n",
+ warnf(config->global, "Error setting extended attributes on '%s': %s",
outs->filename, strerror(errno));
}
@@ -398,12 +456,11 @@
if(!outs->s_isreg && outs->stream) {
/* Dump standard stream buffered data */
- int rc = fflush(outs->stream);
+ rc = fflush(outs->stream);
if(!result && rc) {
/* something went wrong in the writing process */
result = CURLE_WRITE_ERROR;
- if(global->showerror)
- fprintf(global->errors, "curl: (%d) Failed writing body\n", result);
+ errorf(global, "Failed writing body");
}
}
@@ -442,9 +499,10 @@
/* If it returned OK. _or_ failonerror was enabled and it
returned due to such an error, check for HTTP transient
errors to retry on. */
- long protocol = 0;
- curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
- if((protocol == CURLPROTO_HTTP) || (protocol == CURLPROTO_HTTPS)) {
+ const char *scheme;
+ curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme);
+ scheme = proto_token(scheme);
+ if(scheme == proto_http || scheme == proto_https) {
/* This was HTTP(S) */
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
@@ -471,13 +529,13 @@
}
} /* if CURLE_OK */
else if(result) {
- long protocol = 0;
+ const char *scheme;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
- curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+ curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme);
+ scheme = proto_token(scheme);
- if((protocol == CURLPROTO_FTP || protocol == CURLPROTO_FTPS) &&
- response / 100 == 4)
+ if((scheme == proto_ftp || scheme == proto_ftps) && response / 100 == 4)
/*
* This is typically when the FTP server only allows a certain
* amount of users and we are not one of them. All 4xx codes
@@ -529,7 +587,7 @@
}
warnf(config->global, "Problem %s. "
"Will retry in %ld seconds. "
- "%ld retries left.\n",
+ "%ld retries left.",
m[retry], sleeptime/1000L, per->retry_numretries);
per->retry_numretries--;
@@ -539,22 +597,18 @@
per->retry_sleep = RETRY_SLEEP_MAX;
}
if(outs->bytes && outs->filename && outs->stream) {
- int rc;
/* We have written data to an output file, we truncate file
*/
- if(!global->mute)
- fprintf(global->errors, "Throwing away %"
- CURL_FORMAT_CURL_OFF_T " bytes\n",
- outs->bytes);
+ notef(config->global,
+ "Throwing away %" CURL_FORMAT_CURL_OFF_T " bytes",
+ outs->bytes);
fflush(outs->stream);
/* truncate file at the position where we started appending */
#ifdef HAVE_FTRUNCATE
if(ftruncate(fileno(outs->stream), outs->init)) {
/* when truncate fails, we can't just append as then we'll
create something strange, bail out */
- if(global->showerror)
- fprintf(global->errors,
- "curl: (23) Failed to truncate file\n");
+ errorf(config->global, "Failed to truncate file");
return CURLE_WRITE_ERROR;
}
/* now seek to the end of the file, the position where we
@@ -568,9 +622,7 @@
rc = fseek(outs->stream, (long)outs->init, SEEK_SET);
#endif
if(rc) {
- if(global->showerror)
- fprintf(global->errors,
- "curl: (23) Failed seeking to end of file\n");
+ errorf(config->global, "Failed seeking to end of file");
return CURLE_WRITE_ERROR;
}
outs->bytes = 0; /* clear for next round */
@@ -580,7 +632,7 @@
return CURLE_OK;
}
} /* if retry_numretries */
- noretry:
+noretry:
if((global->progressmode == CURL_PROGRESS_BAR) &&
per->progressbar.calls)
@@ -590,19 +642,20 @@
/* Close the outs file */
if(outs->fopened && outs->stream) {
- int rc = fclose(outs->stream);
+ rc = fclose(outs->stream);
if(!result && rc) {
/* something went wrong in the writing process */
result = CURLE_WRITE_ERROR;
- if(global->showerror)
- fprintf(global->errors, "curl: (%d) Failed writing body\n", result);
+ errorf(config->global, "curl: (%d) Failed writing body", result);
}
if(result && config->rm_partial) {
- notef(global, "Removing output file: %s\n", outs->filename);
+ notef(global, "Removing output file: %s", outs->filename);
unlink(outs->filename);
}
}
+ AmigaSetComment(per, result);
+
/* File time can only be set _after_ the file has been closed */
if(!result && config->remote_time && outs->s_isreg && outs->filename) {
/* Ask libcurl if we got a remote file time */
@@ -613,7 +666,7 @@
/* Write the --write-out data before cleanup but after result is final */
if(config->writeout)
- ourWriteOut(config->writeout, per, result);
+ ourWriteOut(config, per, result);
/* Close function-local opened file descriptors */
if(per->heads.fopened && per->heads.stream)
@@ -634,37 +687,20 @@
free(per->this_url);
free(per->outfile);
free(per->uploadfile);
+ if(global->parallel)
+ free(per->errorbuffer);
return result;
}
-static void single_transfer_cleanup(struct OperationConfig *config)
-{
- if(config) {
- struct State *state = &config->state;
- if(state->urls) {
- /* Free list of remaining URLs */
- glob_cleanup(state->urls);
- state->urls = NULL;
- }
- Curl_safefree(state->outfiles);
- Curl_safefree(state->httpgetfields);
- Curl_safefree(state->uploadfile);
- if(state->inglob) {
- /* Free list of globbed upload files */
- glob_cleanup(state->inglob);
- state->inglob = NULL;
- }
- }
-}
-
/*
- * Return the proto bit for the scheme used in the given URL
+ * Return the protocol token for the scheme used in the given URL
*/
-static long url_proto(char *url)
+static const char *url_proto(char *url)
{
CURLU *uh = curl_url();
- long proto = 0;
+ const char *proto = NULL;
+
if(uh) {
if(url) {
if(!curl_url_set(uh, CURLUPART_URL, url,
@@ -673,18 +709,17 @@
if(!curl_url_get(uh, CURLUPART_SCHEME, &schemep,
CURLU_DEFAULT_SCHEME) &&
schemep) {
- proto = scheme2protocol(schemep);
+ proto = proto_token(schemep);
curl_free(schemep);
}
}
}
curl_url_cleanup(uh);
}
- return proto;
+ return proto? proto: "???"; /* Never match if not found. */
}
/* create the next (singular) transfer */
-
static CURLcode single_transfer(struct GlobalConfig *global,
struct OperationConfig *config,
CURLSH *share,
@@ -702,11 +737,11 @@
if(config->postfields) {
if(config->use_httpget) {
if(!httpgetfields) {
- /* Use the postfields data for a http get */
+ /* Use the postfields data for an HTTP get */
httpgetfields = state->httpgetfields = strdup(config->postfields);
Curl_safefree(config->postfields);
if(!httpgetfields) {
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
result = CURLE_OUT_OF_MEMORY;
}
else if(SetHTTPrequest(config,
@@ -749,7 +784,7 @@
state->up = 0;
if(!warn_more_options) {
/* only show this once */
- warnf(config->global, "Got more output options than URLs\n");
+ warnf(config->global, "Got more output options than URLs");
warn_more_options = TRUE;
}
continue; /* next URL please */
@@ -759,7 +794,7 @@
if(urlnode->outfile && !state->outfiles) {
state->outfiles = strdup(urlnode->outfile);
if(!state->outfiles) {
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
result = CURLE_OUT_OF_MEMORY;
break;
}
@@ -770,14 +805,15 @@
if(!config->globoff && infiles && !inglob) {
/* Unless explicitly shut off */
result = glob_url(&inglob, infiles, &state->infilenum,
- global->showerror?global->errors:NULL);
+ (!global->silent || global->showerror)?
+ stderr:NULL);
if(result)
break;
config->state.inglob = inglob;
}
{
- unsigned long urlnum;
+ curl_off_t urlnum;
if(!state->up && !infiles)
Curl_nop_stmt;
@@ -786,12 +822,12 @@
if(inglob) {
result = glob_next_url(&state->uploadfile, inglob);
if(result == CURLE_OUT_OF_MEMORY)
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
}
else if(!state->up) {
state->uploadfile = strdup(infiles);
if(!state->uploadfile) {
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
result = CURLE_OUT_OF_MEMORY;
}
}
@@ -805,7 +841,8 @@
/* Unless explicitly shut off, we expand '{...}' and '[...]'
expressions and return total number of URLs in pattern set */
result = glob_url(&state->urls, urlnode->url, &state->urlnum,
- global->showerror?global->errors:NULL);
+ (!global->silent || global->showerror)?
+ stderr:NULL);
if(result)
break;
urlnum = state->urlnum;
@@ -819,12 +856,11 @@
if(state->up < state->infilenum) {
struct per_transfer *per = NULL;
struct OutStruct *outs;
- struct InStruct *input;
struct OutStruct *heads;
struct OutStruct *etag_save;
struct HdrCbData *hdrcbdata = NULL;
struct OutStruct etag_first;
- long use_proto;
+ const char *use_proto;
CURL *curl;
/* --etag-save */
@@ -842,7 +878,7 @@
FILE *file = fopen(config->etag_compare_file, FOPEN_READTEXT);
if(!file && !config->etag_save_file) {
errorf(global,
- "Failed to open %s\n", config->etag_compare_file);
+ "Failed to open %s", config->etag_compare_file);
result = CURLE_READ_ERROR;
break;
}
@@ -859,7 +895,7 @@
if(file)
fclose(file);
errorf(global,
- "Failed to allocate memory for custom etag header\n");
+ "Failed to allocate memory for custom etag header");
result = CURLE_OUT_OF_MEMORY;
break;
}
@@ -882,7 +918,7 @@
FILE *newfile = fopen(config->etag_save_file, "wb");
if(!newfile) {
warnf(global, "Failed creating file for saving etags: \"%s\". "
- "Skip this transfer\n", config->etag_save_file);
+ "Skip this transfer", config->etag_save_file);
Curl_safefree(state->outfiles);
glob_cleanup(state->urls);
return CURLE_OK;
@@ -940,9 +976,25 @@
/* open file for output: */
if(strcmp(config->headerfile, "-")) {
FILE *newfile;
- newfile = fopen(config->headerfile, per->prev == NULL?"wb":"ab");
+
+ /*
+ * Since every transfer has its own file handle for dumping
+ * the headers, we need to open it in append mode, since transfers
+ * might finish in any order.
+ * The first transfer just clears the file.
+ * TODO: Consider placing the file handle inside the
+ * OperationConfig, so that it does not need to be opened/closed
+ * for every transfer.
+ */
+ if(!per->prev || per->prev->config != config) {
+ newfile = fopen(config->headerfile, "wb");
+ if(newfile)
+ fclose(newfile);
+ }
+ newfile = fopen(config->headerfile, "ab");
+
if(!newfile) {
- warnf(global, "Failed to open %s\n", config->headerfile);
+ errorf(global, "Failed to open %s", config->headerfile);
result = CURLE_WRITE_ERROR;
break;
}
@@ -962,7 +1014,6 @@
hdrcbdata = &per->hdrcbdata;
outs = &per->outs;
- input = &per->input;
per->outfile = NULL;
per->infdopen = FALSE;
@@ -1009,11 +1060,11 @@
result = get_url_file_name(&per->outfile, per->this_url);
if(result) {
errorf(global, "Failed to extract a sensible file name"
- " from the URL to use for storage!\n");
+ " from the URL to use for storage");
break;
}
if(!*per->outfile && !config->content_disposition) {
- errorf(global, "Remote file name has no length!\n");
+ errorf(global, "Remote file name has no length");
result = CURLE_WRITE_ERROR;
break;
}
@@ -1025,11 +1076,11 @@
Curl_safefree(storefile);
if(result) {
/* bad globbing */
- warnf(global, "bad output glob!\n");
+ warnf(global, "bad output glob");
break;
}
if(!*per->outfile) {
- warnf(global, "output glob produces empty string!\n");
+ warnf(global, "output glob produces empty string");
result = CURLE_WRITE_ERROR;
break;
}
@@ -1048,7 +1099,7 @@
file output call */
if(config->create_dirs) {
- result = create_dir_hierarchy(per->outfile, global->errors);
+ result = create_dir_hierarchy(per->outfile, global);
/* create_dir_hierarchy shows error upon CURLE_WRITE_ERROR */
if(result)
break;
@@ -1084,7 +1135,7 @@
FILE *file = fopen(per->outfile, "ab");
#endif
if(!file) {
- errorf(global, "Can't open '%s'!\n", per->outfile);
+ errorf(global, "Can't open '%s'", per->outfile);
result = CURLE_WRITE_ERROR;
break;
}
@@ -1103,12 +1154,10 @@
/*
* We have specified a file to upload and it isn't "-".
*/
- char *nurl = add_file_name_to_url(per->this_url, per->uploadfile);
- if(!nurl) {
- result = CURLE_OUT_OF_MEMORY;
+ result = add_file_name_to_url(per->curl, &per->this_url,
+ per->uploadfile);
+ if(result)
break;
- }
- per->this_url = nurl;
}
else if(per->uploadfile && stdin_upload(per->uploadfile)) {
/* count to see if there are more than one auth bit set
@@ -1127,13 +1176,13 @@
/*
* If the user has also selected --anyauth or --proxy-anyauth
- * we should warn him/her.
+ * we should warn them.
*/
if(config->proxyanyauth || (authbits>1)) {
warnf(global,
"Using --anyauth or --proxy-anyauth with upload from stdin"
" involves a big risk of it not working. Use a temporary"
- " file or a fixed auth type instead!\n");
+ " file or a fixed auth type instead");
}
DEBUGASSERT(per->infdopen == FALSE);
@@ -1143,7 +1192,7 @@
if(!strcmp(per->uploadfile, ".")) {
if(curlx_nonblock((curl_socket_t)per->infd, TRUE) < 0)
warnf(global,
- "fcntl failed on fd=%d: %s\n", per->infd, strerror(errno));
+ "fcntl failed on fd=%d: %s", per->infd, strerror(errno));
}
}
@@ -1162,49 +1211,38 @@
global->isatty = orig_isatty;
}
- if(httpgetfields) {
- char *urlbuffer;
- /* Find out whether the url contains a file name */
- const char *pc = strstr(per->this_url, "://");
- char sep = '?';
- if(pc)
- pc += 3;
- else
- pc = per->this_url;
-
- pc = strrchr(pc, '/'); /* check for a slash */
-
- if(pc) {
- /* there is a slash present in the URL */
-
- if(strchr(pc, '?'))
- /* Ouch, there's already a question mark in the URL string, we
- then append the data with an ampersand separator instead! */
- sep = '&';
+ if(httpgetfields || config->query) {
+ char *q = httpgetfields ? httpgetfields : config->query;
+ CURLU *uh = curl_url();
+ if(uh) {
+ CURLUcode uerr;
+ uerr = curl_url_set(uh, CURLUPART_URL, per->this_url,
+ CURLU_GUESS_SCHEME);
+ if(uerr) {
+ result = urlerr_cvt(uerr);
+ errorf(global, "(%d) Could not parse the URL, "
+ "failed to set query", result);
+ config->synthetic_error = TRUE;
+ }
+ else {
+ char *updated = NULL;
+ uerr = curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY);
+ if(!uerr)
+ uerr = curl_url_get(uh, CURLUPART_URL, &updated,
+ CURLU_GUESS_SCHEME);
+ if(uerr)
+ result = urlerr_cvt(uerr);
+ else {
+ Curl_safefree(per->this_url); /* free previous URL */
+ per->this_url = updated; /* use our new URL instead! */
+ }
+ }
+ curl_url_cleanup(uh);
+ if(result)
+ break;
}
- /*
- * Then append ? followed by the get fields to the url.
- */
- if(pc)
- urlbuffer = aprintf("%s%c%s", per->this_url, sep, httpgetfields);
- else
- /* Append / before the ? to create a well-formed url
- if the url contains a hostname only
- */
- urlbuffer = aprintf("%s/?%s", per->this_url, httpgetfields);
-
- if(!urlbuffer) {
- result = CURLE_OUT_OF_MEMORY;
- break;
- }
-
- Curl_safefree(per->this_url); /* free previous URL */
- per->this_url = urlbuffer; /* use our new URL instead! */
}
- if(!global->errors)
- global->errors = stderr;
-
if((!per->outfile || !strcmp(per->outfile, "-")) &&
!config->use_ascii) {
/* We get the output to stdout and we have not got the ASCII/text
@@ -1221,14 +1259,16 @@
if(result)
break;
- /* here */
use_proto = url_proto(per->this_url);
-#if 0
- if(!(use_proto & built_in_protos)) {
- warnf(global, "URL is '%s' but no support for the scheme\n",
- per->this_url);
- }
-#endif
+
+ /* On most modern OSes, exiting works thoroughly,
+ we'll clean everything up via exit(), so don't bother with
+ slow cleanups. Crappy ones might need to skip this.
+ Note: avoid having this setopt added to the --libcurl source
+ output. */
+ result = curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L);
+ if(result)
+ break;
if(!config->tcp_nodelay)
my_setopt(curl, CURLOPT_TCP_NODELAY, 0L);
@@ -1243,8 +1283,6 @@
/* what call to write */
my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
- /* for uploads */
- input->config = config;
/* Note that if CURLOPT_READFUNCTION is fread (the default), then
* lib/telnet.c will Curl_poll() on the input file descriptor
* rather than calling the READFUNCTION at regular intervals.
@@ -1252,24 +1290,36 @@
* behavior, by omitting to set the READFUNCTION & READDATA options,
* have not been determined.
*/
- my_setopt(curl, CURLOPT_READDATA, input);
+ my_setopt(curl, CURLOPT_READDATA, per);
/* what call to read */
my_setopt(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, input);
+ my_setopt(curl, CURLOPT_SEEKDATA, per);
my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
- if(config->recvpersecond &&
- (config->recvpersecond < BUFFER_SIZE))
- /* use a smaller sized buffer for better sleeps */
- my_setopt(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond);
- else
- my_setopt(curl, CURLOPT_BUFFERSIZE, (long)BUFFER_SIZE);
+ {
+#ifdef CURLDEBUG
+ char *env = getenv("CURL_BUFFERSIZE");
+ if(env) {
+ long size = strtol(env, NULL, 10);
+ if(size)
+ my_setopt(curl, CURLOPT_BUFFERSIZE, size);
+ }
+ else
+#endif
+ if(config->recvpersecond &&
+ (config->recvpersecond < BUFFER_SIZE))
+ /* use a smaller sized buffer for better sleeps */
+ my_setopt(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond);
+ else
+ my_setopt(curl, CURLOPT_BUFFERSIZE, (long)BUFFER_SIZE);
+ }
my_setopt_str(curl, CURLOPT_URL, per->this_url);
- my_setopt(curl, CURLOPT_NOPROGRESS, global->noprogress?1L:0L);
+ my_setopt(curl, CURLOPT_NOPROGRESS,
+ global->noprogress || global->silent?1L:0L);
if(config->no_body)
my_setopt(curl, CURLOPT_NOBODY, 1L);
@@ -1279,7 +1329,7 @@
my_setopt_str(curl, CURLOPT_PROXY, config->proxy);
if(config->proxy && result) {
- errorf(global, "proxy support is disabled in this libcurl\n");
+ errorf(global, "proxy support is disabled in this libcurl");
config->synthetic_error = TRUE;
result = CURLE_NOT_BUILT_IN;
break;
@@ -1342,24 +1392,38 @@
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(curl, CURLOPT_TIMEOUT_MS, (long)(config->timeout * 1000));
+ if(!global->parallel) {
+ per->errorbuffer = global_errorbuffer;
+ my_setopt(curl, CURLOPT_ERRORBUFFER, global_errorbuffer);
+ }
+ my_setopt(curl, CURLOPT_TIMEOUT_MS, config->timeout_ms);
switch(config->httpreq) {
case HTTPREQ_SIMPLEPOST:
- my_setopt_str(curl, CURLOPT_POSTFIELDS,
- config->postfields);
- my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
- config->postfieldsize);
+ if(config->resume_from) {
+ errorf(global, "cannot mix --continue-at with --data");
+ result = CURLE_FAILED_INIT;
+ }
+ else {
+ my_setopt_str(curl, CURLOPT_POSTFIELDS,
+ config->postfields);
+ my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
+ config->postfieldsize);
+ }
break;
case HTTPREQ_MIMEPOST:
/* free previous remainders */
curl_mime_free(config->mimepost);
config->mimepost = NULL;
- result = tool2curlmime(curl, config->mimeroot, &config->mimepost);
- if(result)
- break;
- my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
+ if(config->resume_from) {
+ errorf(global, "cannot mix --continue-at with --form");
+ result = CURLE_FAILED_INIT;
+ }
+ else {
+ result = tool2curlmime(curl, config->mimeroot, &config->mimepost);
+ if(!result)
+ my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
+ }
break;
default:
break;
@@ -1377,13 +1441,12 @@
my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
- if(built_in_protos & (CURLPROTO_HTTP | CURLPROTO_RTSP)) {
+ if(proto_http || proto_rtsp) {
my_setopt_str(curl, CURLOPT_REFERER, config->referer);
my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
}
- if(built_in_protos & CURLPROTO_HTTP) {
-
+ if(proto_http) {
long postRedir = 0;
my_setopt(curl, CURLOPT_FOLLOWLOCATION,
@@ -1396,7 +1459,7 @@
/* new in libcurl 7.36.0 */
if(config->proxyheaders) {
my_setopt_slist(curl, CURLOPT_PROXYHEADER, config->proxyheaders);
- my_setopt(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE);
+ my_setopt(curl, CURLOPT_HEADEROPT, (long)CURLHEADER_SEPARATE);
}
/* new in libcurl 7.5 */
@@ -1404,9 +1467,8 @@
if(config->httpversion)
my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion);
- else if(curlinfo->features & CURL_VERSION_HTTP2) {
+ else if(feature_http2)
my_setopt_enum(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
- }
/* curl 7.19.1 (the 301 version existed in 7.18.2),
303 was added in 7.26.0 */
@@ -1429,13 +1491,14 @@
my_setopt(curl, CURLOPT_HTTP09_ALLOWED,
config->http09_allowed ? 1L : 0L);
if(result) {
- errorf(global, "HTTP/0.9 is not supported in this build!\n");
+ errorf(global, "HTTP/0.9 is not supported in this build");
return result;
}
- } /* (built_in_protos & CURLPROTO_HTTP) */
+ } /* (proto_http) */
- my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport);
+ if(proto_ftp)
+ my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport);
my_setopt(curl, CURLOPT_LOW_SPEED_LIMIT,
config->low_speed_limit);
my_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
@@ -1452,7 +1515,7 @@
my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd);
- if(use_proto & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
+ if(use_proto == proto_scp || use_proto == proto_sftp) {
/* SSH and SSL private key uses same command-line option */
/* new in libcurl 7.16.1 */
@@ -1483,7 +1546,7 @@
if(config->capath) {
result = res_setopt_str(curl, CURLOPT_CAPATH, config->capath);
if(result == CURLE_NOT_BUILT_IN) {
- warnf(global, "ignoring %s, not supported by libcurl\n",
+ warnf(global, "ignoring %s, not supported by libcurl",
capath_from_env?
"SSL_CERT_DIR environment variable":"--capath");
}
@@ -1500,7 +1563,7 @@
if(result == CURLE_NOT_BUILT_IN) {
if(config->proxy_capath) {
warnf(global,
- "ignoring --proxy-capath, not supported by libcurl\n");
+ "ignoring --proxy-capath, not supported by libcurl");
}
}
else if(result)
@@ -1520,7 +1583,10 @@
if(config->ssl_ec_curves)
my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves);
- if(curlinfo->features & CURL_VERSION_SSL) {
+ if(config->writeout)
+ my_setopt_str(curl, CURLOPT_CERTINFO, 1L);
+
+ if(feature_ssl) {
/* Check if config->cert is a PKCS#11 URI and set the
* config->cert_type if necessary */
if(config->cert) {
@@ -1713,7 +1779,9 @@
(config->proxy_ssl_allow_beast ?
CURLSSLOPT_ALLOW_BEAST : 0) |
(config->proxy_ssl_auto_client_cert ?
- CURLSSLOPT_AUTO_CLIENT_CERT : 0);
+ CURLSSLOPT_AUTO_CLIENT_CERT : 0) |
+ (config->proxy_native_ca_store ?
+ CURLSSLOPT_NATIVE_CA : 0);
if(mask)
my_setopt_bitmask(curl, CURLOPT_PROXY_SSL_OPTIONS, mask);
@@ -1723,7 +1791,7 @@
if(config->path_as_is)
my_setopt(curl, CURLOPT_PATH_AS_IS, 1L);
- if((use_proto & (CURLPROTO_SCP|CURLPROTO_SFTP)) &&
+ if((use_proto == proto_scp || use_proto == proto_sftp) &&
!config->insecure_ok) {
char *known = findfile(".ssh/known_hosts", FALSE);
if(known) {
@@ -1737,7 +1805,7 @@
break;
}
else
- warnf(global, "Couldn't find a known_hosts file!");
+ warnf(global, "Couldn't find a known_hosts file");
}
if(config->no_body || config->remote_time) {
@@ -1755,15 +1823,20 @@
struct curl_slist *cl;
/* The maximum size needs to match MAX_NAME in cookie.h */
- curlx_dyn_init(&cookies, 4096);
+#define MAX_COOKIE_LINE 8200
+ curlx_dyn_init(&cookies, MAX_COOKIE_LINE);
for(cl = config->cookies; cl; cl = cl->next) {
if(cl == config->cookies)
result = curlx_dyn_addf(&cookies, "%s", cl->data);
else
result = curlx_dyn_addf(&cookies, ";%s", cl->data);
- if(result)
+ if(result) {
+ warnf(global,
+ "skipped provided cookie, the cookie header "
+ "would go over %u bytes", MAX_COOKIE_LINE);
break;
+ }
}
my_setopt_str(curl, CURLOPT_COOKIE, curlx_dyn_ptr(&cookies));
@@ -1788,7 +1861,7 @@
my_setopt(curl, CURLOPT_TIMEVALUE_LARGE, config->condtime);
my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
customrequest_helper(config, config->httpreq, config->customrequest);
- my_setopt(curl, CURLOPT_STDERR, global->errors);
+ my_setopt(curl, CURLOPT_STDERR, stderr);
/* three new ones in libcurl 7.3: */
my_setopt_str(curl, CURLOPT_INTERFACE, config->iface);
@@ -1796,7 +1869,7 @@
progressbarinit(&per->progressbar, config);
if((global->progressmode == CURL_PROGRESS_BAR) &&
- !global->noprogress && !global->mute) {
+ !global->noprogress && !global->silent) {
/* we want the alternative style, then we have to implement it
ourselves! */
my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb);
@@ -1820,14 +1893,13 @@
if(config->dns_ipv4_addr)
my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr);
if(config->dns_ipv6_addr)
- my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
+ my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
/* new in libcurl 7.6.2: */
my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
/* new in libcurl 7.7: */
- my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS,
- (long)(config->connecttimeout * 1000));
+ my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, config->connecttimeout_ms);
if(config->doh_url)
my_setopt_str(curl, CURLOPT_DOH_URL, config->doh_url);
@@ -1902,8 +1974,7 @@
/* new in curl 7.19.4 */
if(config->socks5_gssapi_nec)
- my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC,
- config->socks5_gssapi_nec);
+ my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC, 1L);
/* new in curl 7.55.0 */
if(config->socks5_auth)
@@ -1928,7 +1999,9 @@
my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip?1L:0L);
/* curl 7.15.1 */
- my_setopt(curl, CURLOPT_FTP_FILEMETHOD, (long)config->ftp_filemethod);
+ if(proto_ftp)
+ my_setopt(curl, CURLOPT_FTP_FILEMETHOD,
+ (long)config->ftp_filemethod);
/* curl 7.15.2 */
if(config->localport) {
@@ -1963,7 +2036,7 @@
my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 0L);
/* curl 7.20.0 */
- if(config->tftp_blksize)
+ if(config->tftp_blksize && proto_tftp)
my_setopt(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize);
if(config->mail_from)
@@ -1973,8 +2046,8 @@
my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
/* curl 7.69.x */
- my_setopt(curl, CURLOPT_MAIL_RCPT_ALLLOWFAILS,
- config->mail_rcpt_allowfails ? 1L : 0L);
+ my_setopt(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS,
+ config->mail_rcpt_allowfails ? 1L : 0L);
/* curl 7.20.x */
if(config->ftp_pret)
@@ -1984,9 +2057,10 @@
my_setopt(curl, CURLOPT_NEW_FILE_PERMS, config->create_file_mode);
if(config->proto_present)
- my_setopt_flags(curl, CURLOPT_PROTOCOLS, config->proto);
+ my_setopt_str(curl, CURLOPT_PROTOCOLS_STR, config->proto_str);
if(config->proto_redir_present)
- my_setopt_flags(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir);
+ my_setopt_str(curl, CURLOPT_REDIR_PROTOCOLS_STR,
+ config->proto_redir_str);
if(config->content_disposition
&& (urlnode->flags & GETOUT_USEREMOTE))
@@ -2012,7 +2086,7 @@
my_setopt_slist(curl, CURLOPT_CONNECT_TO, config->connect_to);
/* new in 7.21.4 */
- if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
+ if(feature_tls_srp) {
if(config->tls_username)
my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME,
config->tls_username);
@@ -2049,10 +2123,6 @@
if(config->sasl_ir)
my_setopt(curl, CURLOPT_SASL_IR, 1L);
- if(config->nonpn) {
- my_setopt(curl, CURLOPT_SSL_ENABLE_NPN, 0L);
- }
-
if(config->noalpn) {
my_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
}
@@ -2074,12 +2144,12 @@
my_setopt_str(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default);
/* new in 7.47.0 */
- if(config->expect100timeout > 0)
+ if(config->expect100timeout_ms > 0)
my_setopt_str(curl, CURLOPT_EXPECT_100_TIMEOUT_MS,
- (long)(config->expect100timeout*1000));
+ config->expect100timeout_ms);
/* new in 7.48.0 */
- if(config->tftp_no_options)
+ if(config->tftp_no_options && proto_tftp)
my_setopt(curl, CURLOPT_TFTP_NO_OPTIONS, 1L);
/* new in 7.59.0 */
@@ -2091,6 +2161,11 @@
if(config->haproxy_protocol)
my_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L);
+ /* new in 8.2.0 */
+ if(config->haproxy_clientip)
+ my_setopt_str(curl, CURLOPT_HAPROXY_CLIENT_IP,
+ config->haproxy_clientip);
+
if(config->disallow_username_in_url)
my_setopt(curl, CURLOPT_DISALLOW_USERNAME_IN_URL, 1L);
@@ -2168,11 +2243,14 @@
CURLcode result = CURLE_OK;
CURLMcode mcode;
bool sleeping = FALSE;
+ char *errorbuf;
*addedp = FALSE;
*morep = FALSE;
- result = create_transfer(global, share, addedp);
- if(result)
- return result;
+ if(all_pers < (global->parallel_max*2)) {
+ result = create_transfer(global, share, addedp);
+ if(result)
+ return result;
+ }
for(per = transfers; per && (all_added < global->parallel_max);
per = per->next) {
bool getadded = FALSE;
@@ -2184,11 +2262,16 @@
sleeping = TRUE;
continue;
}
+ per->added = TRUE;
result = pre_transfer(global, per);
if(result)
return result;
+ errorbuf = malloc(CURL_ERROR_SIZE);
+ if(!errorbuf)
+ return CURLE_OUT_OF_MEMORY;
+
/* parallel connect means that we don't set PIPEWAIT since pipewait
will make libcurl prefer multiplexing */
(void)curl_easy_setopt(per->curl, CURLOPT_PIPEWAIT,
@@ -2199,12 +2282,20 @@
(void)curl_easy_setopt(per->curl, CURLOPT_NOPROGRESS, 0L);
mcode = curl_multi_add_handle(multi, per->curl);
- if(mcode)
- return CURLE_OUT_OF_MEMORY;
+ if(mcode) {
+ DEBUGASSERT(mcode == CURLM_OUT_OF_MEMORY);
+ result = CURLE_OUT_OF_MEMORY;
+ }
- result = create_transfer(global, share, &getadded);
- if(result)
+ if(!result)
+ result = create_transfer(global, share, &getadded);
+ if(result) {
+ free(errorbuf);
return result;
+ }
+ errorbuf[0] = 0;
+ (void)curl_easy_setopt(per->curl, CURLOPT_ERRORBUFFER, errorbuf);
+ per->errorbuffer = errorbuf;
per->added = TRUE;
all_added++;
*addedp = TRUE;
@@ -2277,9 +2368,11 @@
curl_easy_getinfo(easy, CURLINFO_PRIVATE, (void *)&ended);
curl_multi_remove_handle(multi, easy);
- if(ended->abort && tres == CURLE_ABORTED_BY_CALLBACK) {
- msnprintf(ended->errorbuffer, sizeof(ended->errorbuffer),
- "Transfer aborted due to critical error in another transfer");
+ if(ended->abort && (tres == CURLE_ABORTED_BY_CALLBACK) &&
+ ended->errorbuffer) {
+ msnprintf(ended->errorbuffer, CURL_ERROR_SIZE,
+ "Transfer aborted due to critical error "
+ "in another transfer");
}
tres = post_per_transfer(global, ended, tres, &retry, &delay);
progress_finalize(ended); /* before it goes away */
@@ -2357,7 +2450,7 @@
if(result)
return result;
if(!added) {
- errorf(global, "no transfer performed\n");
+ errorf(global, "no transfer performed");
return CURLE_READ_ERROR;
}
for(per = transfers; per;) {
@@ -2369,13 +2462,11 @@
if(result)
break;
-#ifndef CURL_DISABLE_LIBCURL_OPTION
if(global->libcurl) {
result = easysrc_perform();
if(result)
break;
}
-#endif
start = tvnow();
#ifdef CURLDEBUG
if(global->test_event_based)
@@ -2396,8 +2487,10 @@
else {
/* setup the next one just before we delete this */
result = create_transfer(global, share, &added);
- if(result)
+ if(result) {
+ returncode = result;
bailout = TRUE;
+ }
}
per = del_per_transfer(per);
@@ -2410,7 +2503,7 @@
milliseconds */
long milli = tvdiff(tvnow(), start);
if(milli < global->ms_per_transfer) {
- notef(global, "Transfer took %ld ms, waits %ldms as set by --rate\n",
+ notef(global, "Transfer took %ld ms, waits %ldms as set by --rate",
milli, global->ms_per_transfer - milli);
/* The transfer took less time than wanted. Wait a little. */
tool_go_sleep(global->ms_per_transfer - milli);
@@ -2439,7 +2532,7 @@
/* Check we have a url */
if(!config->url_list || !config->url_list->url) {
- helpf(global->errors, "no URL specified!\n");
+ helpf(stderr, "(%d) no URL specified", CURLE_FAILED_INIT);
return CURLE_FAILED_INIT;
}
@@ -2465,8 +2558,10 @@
*/
result = curl_easy_getinfo(curltls, CURLINFO_TLS_SSL_PTR,
&tls_backend_info);
- if(result)
+ if(result) {
+ curl_easy_cleanup(curltls);
return result;
+ }
/* Set the CA cert locations specified in the environment. For Windows if
* no environment-specified filename is found then check for CA bundle
@@ -2483,7 +2578,8 @@
config->cacert = strdup(env);
if(!config->cacert) {
curl_free(env);
- errorf(global, "out of memory\n");
+ curl_easy_cleanup(curltls);
+ errorf(global, "out of memory");
return CURLE_OUT_OF_MEMORY;
}
}
@@ -2493,7 +2589,8 @@
config->capath = strdup(env);
if(!config->capath) {
curl_free(env);
- helpf(global->errors, "out of memory\n");
+ curl_easy_cleanup(curltls);
+ errorf(global, "out of memory");
return CURLE_OUT_OF_MEMORY;
}
capath_from_env = true;
@@ -2504,7 +2601,8 @@
config->cacert = strdup(env);
if(!config->cacert) {
curl_free(env);
- errorf(global, "out of memory\n");
+ curl_easy_cleanup(curltls);
+ errorf(global, "out of memory");
return CURLE_OUT_OF_MEMORY;
}
}
@@ -2596,9 +2694,10 @@
CURLcode result = CURLE_OK;
char *first_arg = argc > 1 ? curlx_convert_tchar_to_UTF8(argv[1]) : NULL;
- /* Setup proper locale from environment */
#ifdef HAVE_SETLOCALE
+ /* Override locale for number parsing (only) */
setlocale(LC_ALL, "");
+ setlocale(LC_NUMERIC, "C");
#endif
/* Parse .curlrc if necessary */
@@ -2609,7 +2708,7 @@
/* If we had no arguments then make sure a url was specified in .curlrc */
if((argc < 2) && (!global->first->url_list)) {
- helpf(global->errors, NULL);
+ helpf(stderr, NULL);
result = CURLE_FAILED_INIT;
}
}
@@ -2642,12 +2741,10 @@
result = CURLE_FAILED_INIT;
}
else {
-#ifndef CURL_DISABLE_LIBCURL_OPTION
if(global->libcurl) {
/* Initialise the libcurl source output */
result = easysrc_init();
}
-#endif
/* Perform the main operations */
if(!result) {
@@ -2655,12 +2752,10 @@
struct OperationConfig *operation = global->first;
CURLSH *share = curl_share_init();
if(!share) {
-#ifndef CURL_DISABLE_LIBCURL_OPTION
if(global->libcurl) {
/* Cleanup the libcurl source output */
easysrc_cleanup();
}
-#endif
return CURLE_OUT_OF_MEMORY;
}
@@ -2669,6 +2764,7 @@
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL);
+ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS);
/* Get the required arguments for each operation */
do {
@@ -2684,7 +2780,6 @@
result = run_all_transfers(global, share, result);
curl_share_cleanup(share);
-#ifndef CURL_DISABLE_LIBCURL_OPTION
if(global->libcurl) {
/* Cleanup the libcurl source output */
easysrc_cleanup();
@@ -2692,10 +2787,9 @@
/* Dump the libcurl code if previously enabled */
dumpeasysrc(global);
}
-#endif
}
else
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
}
}
diff --git a/src/tool_operate.h b/src/tool_operate.h
index a779239..21a7f92 100644
--- a/src/tool_operate.h
+++ b/src/tool_operate.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,10 +33,12 @@
struct per_transfer *next;
struct per_transfer *prev;
struct OperationConfig *config; /* for this transfer */
+ struct curl_certinfo *certinfo;
CURL *curl;
long retry_numretries;
long retry_sleep_default;
long retry_sleep;
+ struct timeval start; /* start of this transfer */
struct timeval retrystart;
char *this_url;
unsigned int urlnum; /* the index of the given URL */
@@ -48,11 +50,9 @@
struct OutStruct outs;
struct OutStruct heads;
struct OutStruct etag_save;
- struct InStruct input;
struct HdrCbData hdrcbdata;
long num_headers;
bool was_last_header_empty;
- char errorbuffer[CURL_ERROR_SIZE];
bool added; /* set TRUE when added to the multi handle */
time_t startat; /* when doing parallel transfers, this is a retry transfer
@@ -67,14 +67,19 @@
curl_off_t dlnow;
curl_off_t ultotal;
curl_off_t ulnow;
+ curl_off_t uploadfilesize; /* expected total amount */
+ curl_off_t uploadedsofar; /* amount delivered from the callback */
bool dltotal_added; /* if the total has been added from this */
bool ultotal_added;
/* NULL or malloced */
char *uploadfile;
+ char *errorbuffer; /* alloced and assigned while this is used for a
+ transfer */
};
CURLcode operate(struct GlobalConfig *config, int argc, argv_item_t argv[]);
+void single_transfer_cleanup(struct OperationConfig *config);
extern struct per_transfer *transfers; /* first node */
diff --git a/src/tool_operhlp.c b/src/tool_operhlp.c
index 0144442..a964d79 100644
--- a/src/tool_operhlp.c
+++ b/src/tool_operhlp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,6 +22,7 @@
*
***************************************************************************/
#include "tool_setup.h"
+#include "tool_operate.h"
#include "strcase.h"
@@ -51,6 +52,7 @@
}
config->url_list = NULL;
}
+ single_transfer_cleanup(config);
}
bool output_expected(const char *url, const char *uploadfile)
@@ -69,65 +71,109 @@
!strcmp(uploadfile, ".")) ? TRUE : FALSE;
}
+/* Convert a CURLUcode into a CURLcode */
+CURLcode urlerr_cvt(CURLUcode ucode)
+{
+ if(ucode == CURLUE_OUT_OF_MEMORY)
+ return CURLE_OUT_OF_MEMORY;
+ else if(ucode == CURLUE_UNSUPPORTED_SCHEME)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ else if(ucode == CURLUE_LACKS_IDN)
+ return CURLE_NOT_BUILT_IN;
+ else if(ucode == CURLUE_BAD_HANDLE)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ return CURLE_URL_MALFORMAT;
+}
+
/*
* Adds the file name to the URL if it doesn't already have one.
* url will be freed before return if the returned pointer is different
*/
-char *add_file_name_to_url(char *url, const char *filename)
+CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename)
{
- /* If no file name part is given in the URL, we add this file name */
- char *ptr = strstr(url, "://");
- CURL *curl = curl_easy_init(); /* for url escaping */
- if(!curl)
- return NULL; /* error! */
- if(ptr)
- ptr += 3;
- else
- ptr = url;
- ptr = strrchr(ptr, '/');
- if(!ptr || !*++ptr) {
- /* The URL has no file name part, add the local file name. In order
- to be able to do so, we have to create a new URL in another
- buffer.*/
-
- /* We only want the part of the local path that is on the right
- side of the rightmost slash and backslash. */
- const char *filep = strrchr(filename, '/');
- char *file2 = strrchr(filep?filep:filename, '\\');
- char *encfile;
-
- if(file2)
- filep = file2 + 1;
- else if(filep)
- filep++;
- else
- filep = filename;
-
- /* URL encode the file name */
- encfile = curl_easy_escape(curl, filep, 0 /* use strlen */);
- if(encfile) {
- char *urlbuffer;
- if(ptr)
- /* there is a trailing slash on the URL */
- urlbuffer = aprintf("%s%s", url, encfile);
- else
- /* there is no trailing slash on the URL */
- urlbuffer = aprintf("%s/%s", url, encfile);
-
- curl_free(encfile);
-
- if(!urlbuffer) {
- url = NULL;
- goto end;
- }
-
- Curl_safefree(url);
- url = urlbuffer; /* use our new URL instead! */
+ CURLcode result = CURLE_URL_MALFORMAT;
+ CURLUcode uerr;
+ CURLU *uh = curl_url();
+ char *path = NULL;
+ char *query = NULL;
+ if(uh) {
+ char *ptr;
+ uerr = curl_url_set(uh, CURLUPART_URL, *inurlp,
+ CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME);
+ if(uerr) {
+ result = urlerr_cvt(uerr);
+ goto fail;
}
+ uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0);
+ if(uerr) {
+ result = urlerr_cvt(uerr);
+ goto fail;
+ }
+ uerr = curl_url_get(uh, CURLUPART_QUERY, &query, 0);
+ if(!uerr && query) {
+ curl_free(query);
+ curl_free(path);
+ curl_url_cleanup(uh);
+ return CURLE_OK;
+ }
+ ptr = strrchr(path, '/');
+ if(!ptr || !*++ptr) {
+ /* The URL path has no file name part, add the local file name. In order
+ to be able to do so, we have to create a new URL in another buffer.*/
+
+ /* We only want the part of the local path that is on the right
+ side of the rightmost slash and backslash. */
+ const char *filep = strrchr(filename, '/');
+ char *file2 = strrchr(filep?filep:filename, '\\');
+ char *encfile;
+
+ if(file2)
+ filep = file2 + 1;
+ else if(filep)
+ filep++;
+ else
+ filep = filename;
+
+ /* URL encode the file name */
+ encfile = curl_easy_escape(curl, filep, 0 /* use strlen */);
+ if(encfile) {
+ char *newpath;
+ char *newurl;
+ if(ptr)
+ /* there is a trailing slash on the path */
+ newpath = aprintf("%s%s", path, encfile);
+ else
+ /* there is no trailing slash on the path */
+ newpath = aprintf("%s/%s", path, encfile);
+
+ curl_free(encfile);
+
+ if(!newpath)
+ goto fail;
+ uerr = curl_url_set(uh, CURLUPART_PATH, newpath, 0);
+ free(newpath);
+ if(uerr) {
+ result = urlerr_cvt(uerr);
+ goto fail;
+ }
+ uerr = curl_url_get(uh, CURLUPART_URL, &newurl, CURLU_DEFAULT_SCHEME);
+ if(uerr) {
+ result = urlerr_cvt(uerr);
+ goto fail;
+ }
+ free(*inurlp);
+ *inurlp = newurl;
+ result = CURLE_OK;
+ }
+ }
+ else
+ /* nothing to do */
+ result = CURLE_OK;
}
- end:
- curl_easy_cleanup(curl);
- return url;
+fail:
+ curl_url_cleanup(uh);
+ curl_free(path);
+ return result;
}
/* Extracts the name portion of the URL.
@@ -137,61 +183,72 @@
CURLcode get_url_file_name(char **filename, const char *url)
{
const char *pc, *pc2;
+ CURLU *uh = curl_url();
+ char *path = NULL;
+ CURLUcode uerr;
+
+ if(!uh)
+ return CURLE_OUT_OF_MEMORY;
*filename = NULL;
- /* Find and get the remote file name */
- pc = strstr(url, "://");
- if(pc)
- pc += 3;
- else
- pc = url;
+ uerr = curl_url_set(uh, CURLUPART_URL, url, CURLU_GUESS_SCHEME);
+ if(!uerr) {
+ uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0);
+ if(!uerr) {
+ curl_url_cleanup(uh);
- pc2 = strrchr(pc, '\\');
- pc = strrchr(pc, '/');
- if(pc2 && (!pc || pc < pc2))
- pc = pc2;
+ pc = strrchr(path, '/');
+ pc2 = strrchr(pc ? pc + 1 : path, '\\');
+ if(pc2)
+ pc = pc2;
- if(pc)
- /* duplicate the string beyond the slash */
- pc++;
- else
- /* no slash => empty string */
- pc = "";
+ if(pc)
+ /* duplicate the string beyond the slash */
+ pc++;
+ else
+ /* no slash => empty string */
+ pc = "";
- *filename = strdup(pc);
- if(!*filename)
- return CURLE_OUT_OF_MEMORY;
-
-#if defined(MSDOS) || defined(WIN32)
- {
- char *sanitized;
- SANITIZEcode sc = sanitize_file_name(&sanitized, *filename, 0);
- Curl_safefree(*filename);
- if(sc)
- return CURLE_URL_MALFORMAT;
- *filename = sanitized;
- }
-#endif /* MSDOS || WIN32 */
-
- /* in case we built debug enabled, we allow an environment variable
- * named CURL_TESTDIR to prefix the given file name to put it into a
- * specific directory
- */
-#ifdef DEBUGBUILD
- {
- char *tdir = curlx_getenv("CURL_TESTDIR");
- if(tdir) {
- char buffer[512]; /* suitably large */
- msnprintf(buffer, sizeof(buffer), "%s/%s", tdir, *filename);
- Curl_safefree(*filename);
- *filename = strdup(buffer); /* clone the buffer */
- curl_free(tdir);
+ *filename = strdup(pc);
+ curl_free(path);
if(!*filename)
return CURLE_OUT_OF_MEMORY;
+
+#if defined(MSDOS) || defined(WIN32)
+ {
+ char *sanitized;
+ SANITIZEcode sc = sanitize_file_name(&sanitized, *filename, 0);
+ Curl_safefree(*filename);
+ if(sc) {
+ if(sc == SANITIZE_ERR_OUT_OF_MEMORY)
+ return CURLE_OUT_OF_MEMORY;
+ return CURLE_URL_MALFORMAT;
+ }
+ *filename = sanitized;
+ }
+#endif /* MSDOS || WIN32 */
+
+ /* in case we built debug enabled, we allow an environment variable
+ * named CURL_TESTDIR to prefix the given file name to put it into a
+ * specific directory
+ */
+#ifdef DEBUGBUILD
+ {
+ char *tdir = curlx_getenv("CURL_TESTDIR");
+ if(tdir) {
+ char *alt = aprintf("%s/%s", tdir, *filename);
+ Curl_safefree(*filename);
+ *filename = alt;
+ curl_free(tdir);
+ if(!*filename)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+#endif
+ return CURLE_OK;
}
}
-#endif
-
- return CURLE_OK;
+ curl_url_cleanup(uh);
+ return urlerr_cvt(uerr);
}
diff --git a/src/tool_operhlp.h b/src/tool_operhlp.h
index c48d7ec..1d56fa0 100644
--- a/src/tool_operhlp.h
+++ b/src/tool_operhlp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,8 +33,10 @@
bool stdin_upload(const char *uploadfile);
-char *add_file_name_to_url(char *url, const char *filename);
+CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename);
CURLcode get_url_file_name(char **filename, const char *url);
+CURLcode urlerr_cvt(CURLUcode ucode);
+
#endif /* HEADER_CURL_TOOL_OPERHLP_H */
diff --git a/src/tool_panykey.c b/src/tool_panykey.c
deleted file mode 100644
index 81feaba..0000000
--- a/src/tool_panykey.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-#include "tool_setup.h"
-
-#if defined(NETWARE)
-
-#ifdef NETWARE
-# ifdef __NOVELL_LIBC__
-# include <screen.h>
-# else
-# include <nwconio.h>
-# endif
-#endif
-
-#include "tool_panykey.h"
-
-#include "memdebug.h" /* keep this as LAST include */
-
-void tool_pressanykey(void)
-{
-#if defined(NETWARE)
- pressanykey();
-#endif
-}
-
-#endif /* NETWARE */
diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c
index 5f87c5e..d224844 100644
--- a/src/tool_paramhlp.c
+++ b/src/tool_paramhlp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,6 +34,8 @@
#include "tool_getpass.h"
#include "tool_msgs.h"
#include "tool_paramhlp.h"
+#include "tool_libinfo.h"
+#include "tool_util.h"
#include "tool_version.h"
#include "dynbuf.h"
@@ -66,6 +68,7 @@
ParameterError file2string(char **bufp, FILE *file)
{
struct curlx_dynbuf dyn;
+ DEBUGASSERT(MAX_FILE2STRING < INT_MAX); /* needs to fit in an int later */
curlx_dyn_init(&dyn, MAX_FILE2STRING);
if(file) {
char buffer[256];
@@ -92,6 +95,8 @@
if(file) {
size_t nread;
struct curlx_dynbuf dyn;
+ /* The size needs to fit in an int later */
+ DEBUGASSERT(MAX_FILE2MEMORY < INT_MAX);
curlx_dyn_init(&dyn, MAX_FILE2MEMORY);
do {
char buffer[4096];
@@ -116,21 +121,6 @@
return PARAM_OK;
}
-void cleanarg(char *str)
-{
-#ifdef HAVE_WRITABLE_ARGV
- /* now that GetStr has copied the contents of nextarg, wipe the next
- * argument out so that the username:password isn't displayed in the
- * system process list */
- if(str) {
- size_t len = strlen(str);
- memset(str, ' ', len);
- }
-#else
- (void)str;
-#endif
-}
-
/*
* Parse the string and write the long in the given address. Return PARAM_OK
* on success, otherwise a parameter specific error enum.
@@ -228,7 +218,7 @@
* data.
*/
-static ParameterError str2double(double *val, const char *str, long max)
+static ParameterError str2double(double *val, const char *str, double max)
{
if(str) {
char *endptr;
@@ -250,8 +240,9 @@
}
/*
- * Parse the string and write the double in the given address. Return PARAM_OK
- * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
+ * Parse the string as seconds with decimals, and write the number of
+ * milliseconds that corresponds in the given address. Return PARAM_OK on
+ * success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
*
* The 'max' argument is the maximum value allowed, as the numbers are often
* multiplied when later used.
@@ -261,22 +252,69 @@
* data.
*/
-ParameterError str2udouble(double *valp, const char *str, long max)
+ParameterError secs2ms(long *valp, const char *str)
{
double value;
- ParameterError result = str2double(&value, str, max);
+ ParameterError result = str2double(&value, str, (double)LONG_MAX/1000);
if(result != PARAM_OK)
return result;
if(value < 0)
return PARAM_NEGATIVE_NUMERIC;
- *valp = value;
+ *valp = (long)(value*1000);
return PARAM_OK;
}
/*
- * Parse the string and modify the long in the given address. Return
- * non-zero on failure, zero on success.
+ * Implement protocol sets in null-terminated array of protocol name pointers.
+ */
+
+/* Return index of prototype token in set, card(set) if not found.
+ Can be called with proto == NULL to get card(set). */
+static size_t protoset_index(const char * const *protoset, const char *proto)
+{
+ const char * const *p = protoset;
+
+ DEBUGASSERT(proto == proto_token(proto)); /* Ensure it is tokenized. */
+
+ for(; *p; p++)
+ if(proto == *p)
+ break;
+ return p - protoset;
+}
+
+/* Include protocol token in set. */
+static void protoset_set(const char **protoset, const char *proto)
+{
+ if(proto) {
+ size_t n = protoset_index(protoset, proto);
+
+ if(!protoset[n]) {
+ DEBUGASSERT(n < proto_count);
+ protoset[n] = proto;
+ protoset[n + 1] = NULL;
+ }
+ }
+}
+
+/* Exclude protocol token from set. */
+static void protoset_clear(const char **protoset, const char *proto)
+{
+ if(proto) {
+ size_t n = protoset_index(protoset, proto);
+
+ if(protoset[n]) {
+ size_t m = protoset_index(protoset, NULL) - 1;
+
+ protoset[n] = protoset[m];
+ protoset[m] = NULL;
+ }
+ }
+}
+
+/*
+ * Parse the string and provide an allocated libcurl compatible protocol
+ * string output. Return non-zero on failure, zero on success.
*
* The string is a list of protocols
*
@@ -285,48 +323,42 @@
* data.
*/
-long proto2num(struct OperationConfig *config, long *val, const char *str)
+#define MAX_PROTOSTRING (64*11) /* Enough room for 64 10-chars proto names. */
+
+ParameterError proto2num(struct OperationConfig *config,
+ const char * const *val, char **ostr, const char *str)
{
char *buffer;
const char *sep = ",";
char *token;
+ const char **protoset;
+ struct curlx_dynbuf obuf;
+ size_t proto;
+ CURLcode result;
- static struct sprotos {
- const char *name;
- long bit;
- } const protos[] = {
- { "all", CURLPROTO_ALL },
- { "http", CURLPROTO_HTTP },
- { "https", CURLPROTO_HTTPS },
- { "ftp", CURLPROTO_FTP },
- { "ftps", CURLPROTO_FTPS },
- { "scp", CURLPROTO_SCP },
- { "sftp", CURLPROTO_SFTP },
- { "telnet", CURLPROTO_TELNET },
- { "ldap", CURLPROTO_LDAP },
- { "ldaps", CURLPROTO_LDAPS },
- { "dict", CURLPROTO_DICT },
- { "file", CURLPROTO_FILE },
- { "tftp", CURLPROTO_TFTP },
- { "imap", CURLPROTO_IMAP },
- { "imaps", CURLPROTO_IMAPS },
- { "pop3", CURLPROTO_POP3 },
- { "pop3s", CURLPROTO_POP3S },
- { "smtp", CURLPROTO_SMTP },
- { "smtps", CURLPROTO_SMTPS },
- { "rtsp", CURLPROTO_RTSP },
- { "gopher", CURLPROTO_GOPHER },
- { "smb", CURLPROTO_SMB },
- { "smbs", CURLPROTO_SMBS },
- { NULL, 0 }
- };
+ curlx_dyn_init(&obuf, MAX_PROTOSTRING);
if(!str)
- return 1;
+ return PARAM_OPTION_AMBIGUOUS;
buffer = strdup(str); /* because strtok corrupts it */
if(!buffer)
- return 1;
+ return PARAM_NO_MEM;
+
+ protoset = malloc((proto_count + 1) * sizeof(*protoset));
+ if(!protoset) {
+ free(buffer);
+ return PARAM_NO_MEM;
+ }
+
+ /* Preset protocol set with default values. */
+ protoset[0] = NULL;
+ for(; *val; val++) {
+ const char *p = proto_token(*val);
+
+ if(p)
+ protoset_set(protoset, p);
+ }
/* Allow strtok() here since this isn't used threaded */
/* !checksrc! disable BANNEDFUNC 2 */
@@ -335,11 +367,9 @@
token = strtok(NULL, sep)) {
enum e_action { allow, deny, set } action = allow;
- struct sprotos const *pp;
-
/* Process token modifiers */
while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
- switch (*token++) {
+ switch(*token++) {
case '=':
action = set;
break;
@@ -350,38 +380,63 @@
action = allow;
break;
default: /* Includes case of terminating NULL */
- Curl_safefree(buffer);
- return 1;
+ free(buffer);
+ free((char *) protoset);
+ return PARAM_BAD_USE;
}
}
- for(pp = protos; pp->name; pp++) {
- if(curl_strequal(token, pp->name)) {
- switch(action) {
- case deny:
- *val &= ~(pp->bit);
- break;
- case allow:
- *val |= pp->bit;
- break;
- case set:
- *val = pp->bit;
- break;
- }
+ if(curl_strequal(token, "all")) {
+ switch(action) {
+ case deny:
+ protoset[0] = NULL;
+ break;
+ case allow:
+ case set:
+ memcpy((char *) protoset,
+ built_in_protos, (proto_count + 1) * sizeof(*protoset));
break;
}
}
+ else {
+ const char *p = proto_token(token);
- if(!(pp->name)) { /* unknown protocol */
- /* If they have specified only this protocol, we say treat it as
- if no protocols are allowed */
- if(action == set)
- *val = 0;
- warnf(config->global, "unrecognized protocol '%s'\n", token);
+ if(p)
+ switch(action) {
+ case deny:
+ protoset_clear(protoset, p);
+ break;
+ case set:
+ protoset[0] = NULL;
+ /* FALLTHROUGH */
+ case allow:
+ protoset_set(protoset, p);
+ break;
+ }
+ else { /* unknown protocol */
+ /* If they have specified only this protocol, we say treat it as
+ if no protocols are allowed */
+ if(action == set)
+ protoset[0] = NULL;
+ warnf(config->global, "unrecognized protocol '%s'", token);
+ }
}
}
- Curl_safefree(buffer);
- return 0;
+ free(buffer);
+
+ /* We need the protocols in alphabetic order for CI tests requirements. */
+ qsort((char *) protoset, protoset_index(protoset, NULL), sizeof(*protoset),
+ struplocompare4sort);
+
+ result = curlx_dyn_addn(&obuf, "", 0);
+ for(proto = 0; protoset[proto] && !result; proto++)
+ result = curlx_dyn_addf(&obuf, "%s,", protoset[proto]);
+ free((char *) protoset);
+ curlx_dyn_setlen(&obuf, curlx_dyn_len(&obuf) - 1);
+ free(*ostr);
+ *ostr = curlx_dyn_ptr(&obuf);
+
+ return *ostr ? PARAM_OK : PARAM_NO_MEM;
}
/**
@@ -392,16 +447,13 @@
* @return PARAM_LIBCURL_UNSUPPORTED_PROTOCOL protocol not supported
* @return PARAM_REQUIRES_PARAMETER missing parameter
*/
-int check_protocol(const char *str)
+ParameterError check_protocol(const char *str)
{
- const char * const *pp;
- const curl_version_info_data *curlinfo = curl_version_info(CURLVERSION_NOW);
if(!str)
return PARAM_REQUIRES_PARAMETER;
- for(pp = curlinfo->protocols; *pp; pp++) {
- if(curl_strequal(*pp, str))
- return PARAM_OK;
- }
+
+ if(proto_token(str))
+ return PARAM_OK;
return PARAM_LIBCURL_UNSUPPORTED_PROTOCOL;
}
@@ -422,7 +474,7 @@
#if(SIZEOF_CURL_OFF_T > SIZEOF_LONG)
{
- CURLofft offt = curlx_strtoofft(str, &endptr, 0, val);
+ CURLofft offt = curlx_strtoofft(str, &endptr, 10, val);
if(CURL_OFFT_FLOW == offt)
return PARAM_NUMBER_TOO_LARGE;
else if(CURL_OFFT_INVAL == offt)
@@ -514,7 +566,7 @@
if(curl_strequal("multicwd", str))
return CURLFTPMETHOD_MULTICWD;
- warnf(config->global, "unrecognized ftp file method '%s', using default\n",
+ warnf(config->global, "unrecognized ftp file method '%s', using default",
str);
return CURLFTPMETHOD_MULTICWD;
@@ -527,7 +579,7 @@
if(curl_strequal("active", str))
return CURLFTPSSL_CCC_ACTIVE;
- warnf(config->global, "unrecognized ftp CCC method '%s', using default\n",
+ warnf(config->global, "unrecognized ftp CCC method '%s', using default",
str);
return CURLFTPSSL_CCC_PASSIVE;
@@ -542,7 +594,7 @@
if(curl_strequal("always", str))
return CURLGSSAPI_DELEGATION_FLAG;
- warnf(config->global, "unrecognized delegation method '%s', using none\n",
+ warnf(config->global, "unrecognized delegation method '%s', using none",
str);
return CURLGSSAPI_DELEGATION_NONE;
@@ -613,7 +665,7 @@
if(!config->useragent) {
config->useragent = my_useragent();
if(!config->useragent) {
- errorf(config->global, "out of memory\n");
+ errorf(config->global, "out of memory");
result = CURLE_OUT_OF_MEMORY;
}
}
diff --git a/src/tool_paramhlp.h b/src/tool_paramhlp.h
index 9f8acf3..edb8781 100644
--- a/src/tool_paramhlp.h
+++ b/src/tool_paramhlp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,6 +24,7 @@
*
***************************************************************************/
#include "tool_setup.h"
+#include "tool_libinfo.h"
struct getout *new_getout(struct OperationConfig *config);
@@ -31,17 +32,17 @@
ParameterError file2memory(char **bufp, size_t *size, FILE *file);
-void cleanarg(char *str);
-
ParameterError str2num(long *val, const char *str);
ParameterError str2unum(long *val, const char *str);
ParameterError oct2nummax(long *val, const char *str, long max);
ParameterError str2unummax(long *val, const char *str, long max);
-ParameterError str2udouble(double *val, const char *str, long max);
+ParameterError secs2ms(long *val, const char *str);
-long proto2num(struct OperationConfig *config, long *val, const char *str);
+ParameterError proto2num(struct OperationConfig *config,
+ const char * const *val, char **obuf,
+ const char *str);
-int check_protocol(const char *str);
+ParameterError check_protocol(const char *str);
ParameterError str2offset(curl_off_t *val, const char *str);
diff --git a/src/tool_parsecfg.c b/src/tool_parsecfg.c
index a166757..0bc6964 100644
--- a/src/tool_parsecfg.c
+++ b/src/tool_parsecfg.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -43,7 +43,7 @@
static const char *unslashquote(const char *line, char *param);
-#define MAX_CONFIG_LINE_LENGTH (100*1024)
+#define MAX_CONFIG_LINE_LENGTH (10*1024*1024)
static bool my_get_line(FILE *fp, struct curlx_dynbuf *, bool *error);
#ifdef WIN32
@@ -210,7 +210,7 @@
break;
default:
warnf(operation->global, "%s:%d: warning: '%s' uses unquoted "
- "whitespace in the line that may cause side-effects!\n",
+ "whitespace in the line that may cause side-effects",
filename, lineno, option);
}
}
@@ -223,7 +223,7 @@
#ifdef DEBUG_CONFIG
fprintf(stderr, "PARAM: \"%s\"\n",(param ? param : "(null)"));
#endif
- res = getparameter(option, param, &usedarg, global, operation);
+ res = getparameter(option, param, NULL, &usedarg, global, operation);
operation = global->last;
if(!res && param && *param && !usedarg)
@@ -263,7 +263,7 @@
res != PARAM_VERSION_INFO_REQUESTED &&
res != PARAM_ENGINES_REQUESTED) {
const char *reason = param2text(res);
- warnf(operation->global, "%s:%d: warning: '%s' %s\n",
+ warnf(operation->global, "%s:%d: warning: '%s' %s",
filename, lineno, option, reason);
}
}
diff --git a/src/tool_parsecfg.h b/src/tool_parsecfg.h
index 90af619..75f9127 100644
--- a/src/tool_parsecfg.h
+++ b/src/tool_parsecfg.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_progress.c b/src/tool_progress.c
index da5317b..782ad3b 100644
--- a/src/tool_progress.c
+++ b/src/tool_progress.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -53,8 +53,6 @@
CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE,
(bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) );
-#if (SIZEOF_CURL_OFF_T > 4)
-
else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE)
/* 'XXXXM' is good until we're at 10000MB or above */
msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
@@ -77,16 +75,8 @@
/* up to 10000PB, display without decimal: XXXXP */
msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE);
- /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number
- can hold, but our data type is signed so 8192PB will be the maximum. */
-
-#else
-
- else
- msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
-
-#endif
-
+ /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number can
+ hold, but our data type is signed so 8192PB will be the maximum. */
return max5;
}
@@ -161,8 +151,8 @@
static struct speedcount speedstore[SPEEDCNT];
/*
- |DL% UL% Dled Uled Xfers Live Qd Total Current Left Speed
- | 6 -- 9.9G 0 2 2 0 0:00:40 0:00:02 0:00:37 4087M
+ |DL% UL% Dled Uled Xfers Live Total Current Left Speed
+ | 6 -- 9.9G 0 2 2 0:00:40 0:00:02 0:00:37 4087M
*/
bool progress_meter(struct GlobalConfig *global,
struct timeval *start,
@@ -173,7 +163,7 @@
struct timeval now;
long diff;
- if(global->noprogress)
+ if(global->noprogress || global->silent)
return FALSE;
now = tvnow();
@@ -181,9 +171,9 @@
if(!header) {
header = TRUE;
- fputs("DL% UL% Dled Uled Xfers Live Qd "
+ fputs("DL% UL% Dled Uled Xfers Live "
"Total Current Left Speed\n",
- global->errors);
+ stderr);
}
if(final || (diff > 500)) {
char time_left[10];
@@ -199,7 +189,6 @@
bool dlknown = TRUE;
bool ulknown = TRUE;
curl_off_t all_running = 0; /* in progress */
- curl_off_t all_queued = 0; /* pending */
curl_off_t speed = 0;
unsigned int i;
stamp = now;
@@ -225,9 +214,7 @@
all_ultotal += per->ultotal;
per->ultotal_added = TRUE;
}
- if(!per->added)
- all_queued++;
- else
+ if(per->added)
all_running++;
}
if(dlknown && all_dltotal)
@@ -268,6 +255,8 @@
dl = all_dlnow;
ul = all_ulnow;
}
+ if(!deltams) /* no division by zero please */
+ deltams++;
dls = (curl_off_t)((double)dl / ((double)deltams/1000.0));
uls = (curl_off_t)((double)ul / ((double)deltams/1000.0));
speed = dls > uls ? dls : uls;
@@ -286,7 +275,7 @@
}
time2str(time_spent, spent);
- fprintf(global->errors,
+ fprintf(stderr,
"\r"
"%-3s " /* percent downloaded */
"%-3s " /* percent uploaded */
@@ -294,8 +283,7 @@
"%s " /* Uled */
"%5" CURL_FORMAT_CURL_OFF_T " " /* Xfers */
"%5" CURL_FORMAT_CURL_OFF_T " " /* Live */
- "%5" CURL_FORMAT_CURL_OFF_T " " /* Queued */
- "%s " /* Total time */
+ " %s " /* Total time */
"%s " /* Current time */
"%s " /* Time left */
"%s " /* Speed */
@@ -307,7 +295,6 @@
max5data(all_ulnow, buffer[1]),
all_xfers,
all_running,
- all_queued,
time_total,
time_spent,
time_left,
diff --git a/src/tool_progress.h b/src/tool_progress.h
index 5f68474..4c869a0 100644
--- a/src/tool_progress.h
+++ b/src/tool_progress.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_sdecls.h b/src/tool_sdecls.h
index 70e44d4..7c03a04 100644
--- a/src/tool_sdecls.h
+++ b/src/tool_sdecls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -70,23 +70,6 @@
curl_off_t init;
};
-
-/*
- * InStruct variables keep track of information relative to curl's
- * input reading, which may take place from stdin or from some file.
- *
- * 'fd' member is either 'stdin' file descriptor number STDIN_FILENO
- * or a file descriptor as returned from an 'open' call for some file.
- *
- * 'config' member is a pointer to associated 'OperationConfig' struct.
- */
-
-struct InStruct {
- int fd;
- struct OperationConfig *config;
-};
-
-
/*
* A linked list of these 'getout' nodes contain URL's to fetch,
* as well as information relative to where URL contents should
diff --git a/src/tool_setopt.c b/src/tool_setopt.c
index 5ff86c7..08e8c23 100644
--- a/src/tool_setopt.c
+++ b/src/tool_setopt.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,6 +33,7 @@
#include "tool_easysrc.h"
#include "tool_setopt.h"
#include "tool_msgs.h"
+#include "dynbuf.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -90,6 +91,7 @@
NV(CURL_HTTP_VERSION_2_0),
NV(CURL_HTTP_VERSION_2TLS),
NV(CURL_HTTP_VERSION_3),
+ NV(CURL_HTTP_VERSION_3ONLY),
NVEND,
};
@@ -145,35 +147,6 @@
NVEND,
};
-/* These mappings essentially triplicated - see
- * tool_libinfo.c and tool_paramhlp.c */
-const struct NameValue setopt_nv_CURLPROTO[] = {
- NV(CURLPROTO_ALL), /* combination */
- NV(CURLPROTO_DICT),
- NV(CURLPROTO_FILE),
- NV(CURLPROTO_FTP),
- NV(CURLPROTO_FTPS),
- NV(CURLPROTO_GOPHER),
- NV(CURLPROTO_HTTP),
- NV(CURLPROTO_HTTPS),
- NV(CURLPROTO_IMAP),
- NV(CURLPROTO_IMAPS),
- NV(CURLPROTO_LDAP),
- NV(CURLPROTO_LDAPS),
- NV(CURLPROTO_POP3),
- NV(CURLPROTO_POP3S),
- NV(CURLPROTO_RTSP),
- NV(CURLPROTO_SCP),
- NV(CURLPROTO_SFTP),
- NV(CURLPROTO_SMB),
- NV(CURLPROTO_SMBS),
- NV(CURLPROTO_SMTP),
- NV(CURLPROTO_SMTPS),
- NV(CURLPROTO_TELNET),
- NV(CURLPROTO_TFTP),
- NVEND,
-};
-
/* These options have non-zero default values. */
static const struct NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
NV1(CURLOPT_SSL_VERIFYPEER, 1),
@@ -223,7 +196,7 @@
#define REM0(s) ADD((&easysrc_toohard, s))
#define REM1(f,a) ADDF((&easysrc_toohard, f,a))
-#define REM2(f,a,b) ADDF((&easysrc_toohard, f,a,b))
+#define REM3(f,a,b,c) ADDF((&easysrc_toohard, f,a,b,c))
/* Escape string to C string syntax. Return NULL if out of memory.
* Is this correct for those wacky EBCDIC guys? */
@@ -234,9 +207,11 @@
static char *c_escape(const char *str, curl_off_t len)
{
const char *s;
- unsigned char c;
- char *escaped, *e;
unsigned int cutoff = 0;
+ CURLcode result;
+ struct curlx_dynbuf escaped;
+
+ curlx_dyn_init(&escaped, 4 * MAX_STRING_LENGTH_OUTPUT + 3);
if(len == ZERO_TERMINATED)
len = strlen(str);
@@ -247,51 +222,44 @@
cutoff = 3;
}
- /* Allocate space based on worst-case */
- escaped = malloc(4 * (size_t)len + 1 + cutoff);
- if(!escaped)
- return NULL;
+ result = curlx_dyn_addn(&escaped, STRCONST(""));
+ for(s = str; !result && len; s++, len--) {
+ /* escape question marks as well, to prevent generating accidental
+ trigraphs */
+ static const char from[] = "\t\r\n?\"\\";
+ static const char to[] = "\\t\\r\\n\\?\\\"\\\\";
+ const char *p = strchr(from, *s);
- e = escaped;
- for(s = str; len; s++, len--) {
- c = *s;
- if(c == '\n') {
- strcpy(e, "\\n");
- e += 2;
+ if(!p && ISPRINT(*s))
+ continue;
+
+ result = curlx_dyn_addn(&escaped, str, s - str);
+ str = s + 1;
+
+ if(!result) {
+ if(p && *p)
+ result = curlx_dyn_addn(&escaped, to + 2 * (p - from), 2);
+ else {
+ const char *format = "\\x%02x";
+
+ if(len > 1 && ISXDIGIT(s[1])) {
+ /* Octal escape to avoid >2 digit hex. */
+ format = "\\%03o";
+ }
+
+ result = curlx_dyn_addf(&escaped, format,
+ (unsigned int) *(unsigned char *) s);
+ }
}
- else if(c == '\r') {
- strcpy(e, "\\r");
- e += 2;
- }
- else if(c == '\t') {
- strcpy(e, "\\t");
- e += 2;
- }
- else if(c == '\\') {
- strcpy(e, "\\\\");
- e += 2;
- }
- else if(c == '"') {
- strcpy(e, "\\\"");
- e += 2;
- }
- else if(c == '?') {
- /* escape question marks as well, to prevent generating accidental
- trigraphs */
- strcpy(e, "\\?");
- e += 2;
- }
- else if(!isprint(c)) {
- msnprintf(e, 5, "\\x%02x", (unsigned)c);
- e += 4;
- }
- else
- *e++ = c;
}
- while(cutoff--)
- *e++ = '.';
- *e = '\0';
- return escaped;
+
+ if(!result)
+ result = curlx_dyn_addn(&escaped, str, s - str);
+
+ if(!result)
+ (void) !curlx_dyn_addn(&escaped, "...", cutoff);
+
+ return curlx_dyn_ptr(&escaped);
}
/* setopt wrapper for enum types */
@@ -326,9 +294,9 @@
#ifdef DEBUGBUILD
if(ret)
- warnf(config, "option %s returned error (%d)\n", name, (int)ret);
+ warnf(config, "option %s returned error (%d)", name, (int)ret);
#endif
- nomem:
+nomem:
return ret;
}
@@ -370,7 +338,7 @@
CODE2("%s%ldL);", preamble, rest);
}
- nomem:
+nomem:
return ret;
}
@@ -413,7 +381,7 @@
CODE2("%s%luUL);", preamble, rest);
}
- nomem:
+nomem:
return ret;
}
@@ -439,7 +407,7 @@
*slistno, *slistno, escaped);
}
- nomem:
+nomem:
Curl_safefree(escaped);
return ret;
}
@@ -622,7 +590,7 @@
CODE2("curl_easy_setopt(hnd, %s, slist%d);", name, i);
}
- nomem:
+nomem:
return ret;
}
@@ -668,7 +636,7 @@
/* function pointers are never printable */
if(tag >= CURLOPTTYPE_FUNCTIONPOINT) {
if(pval) {
- value = "functionpointer";
+ value = "function pointer";
remark = TRUE;
}
else
@@ -680,7 +648,7 @@
escape = TRUE;
}
else if(pval) {
- value = "objectpointer";
+ value = "object pointer";
remark = TRUE;
}
else
@@ -706,7 +674,7 @@
/* blobs are never printable */
if(pblob) {
- value = "blobpointer";
+ value = "blob pointer";
remark = TRUE;
}
else
@@ -721,7 +689,7 @@
/* we only use this for real if --libcurl was used */
if(remark)
- REM2("%s set to a %s", name, value);
+ REM3("%s was set to a%s %s", name, (*value == 'o' ? "n" : ""), value);
else {
if(escape) {
curl_off_t len = ZERO_TERMINATED;
@@ -736,14 +704,11 @@
}
}
- nomem:
+nomem:
Curl_safefree(escaped);
return ret;
}
#else /* CURL_DISABLE_LIBCURL_OPTION */
-#include "tool_cfgable.h"
-#include "tool_setopt.h"
-
#endif /* CURL_DISABLE_LIBCURL_OPTION */
diff --git a/src/tool_setopt.h b/src/tool_setopt.h
index 2646edb..4396c00 100644
--- a/src/tool_setopt.h
+++ b/src/tool_setopt.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -57,7 +57,6 @@
extern const struct NameValue setopt_nv_CURLUSESSL[];
extern const struct NameValueUnsigned setopt_nv_CURLSSLOPT[];
extern const struct NameValue setopt_nv_CURL_NETRC[];
-extern const struct NameValue setopt_nv_CURLPROTO[];
extern const struct NameValueUnsigned setopt_nv_CURLAUTH[];
extern const struct NameValueUnsigned setopt_nv_CURLHSTS[];
@@ -73,8 +72,6 @@
#define setopt_nv_CURLOPT_SSL_OPTIONS setopt_nv_CURLSSLOPT
#define setopt_nv_CURLOPT_PROXY_SSL_OPTIONS setopt_nv_CURLSSLOPT
#define setopt_nv_CURLOPT_NETRC setopt_nv_CURL_NETRC
-#define setopt_nv_CURLOPT_PROTOCOLS setopt_nv_CURLPROTO
-#define setopt_nv_CURLOPT_REDIR_PROTOCOLS setopt_nv_CURLPROTO
#define setopt_nv_CURLOPT_PROXYTYPE setopt_nv_CURLPROXY
#define setopt_nv_CURLOPT_PROXYAUTH setopt_nv_CURLAUTH
#define setopt_nv_CURLOPT_SOCKS5_AUTH setopt_nv_CURLAUTH
diff --git a/src/tool_setup.h b/src/tool_setup.h
index 16fa00e..1a723f8 100644
--- a/src/tool_setup.h
+++ b/src/tool_setup.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,6 +37,15 @@
#include "curl_setup.h" /* from the lib directory */
+extern FILE *tool_stderr;
+
+#if !defined(CURL_DO_NOT_OVERRIDE_STDERR) && !defined(UNITTESTS)
+#ifdef stderr
+#undef stderr
+#endif
+#define stderr tool_stderr
+#endif
+
/*
* curl tool certainly uses libcurl's external interface.
*/
@@ -47,7 +56,7 @@
* Platform specific stuff.
*/
-#if defined(macintosh) && defined(__MRC__)
+#ifdef macintosh
# define main(x,y) curl_main(x,y)
#endif
@@ -64,4 +73,10 @@
# include "tool_strdup.h"
#endif
+#if defined(WIN32) && !defined(MSDOS)
+/* set in win32_init() */
+extern LARGE_INTEGER tool_freq;
+extern bool tool_isVistaOrGreater;
+#endif
+
#endif /* HEADER_CURL_TOOL_SETUP_H */
diff --git a/src/tool_sleep.c b/src/tool_sleep.c
index c52425f..08d6f90 100644
--- a/src/tool_sleep.c
+++ b/src/tool_sleep.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_sleep.h b/src/tool_sleep.h
index d84b467..de1d7e2 100644
--- a/src/tool_sleep.h
+++ b/src/tool_sleep.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_stderr.c b/src/tool_stderr.c
new file mode 100644
index 0000000..23643df
--- /dev/null
+++ b/src/tool_stderr.c
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+/* In this file, stdio.h's stderr macro is not overridden. */
+#define CURL_DO_NOT_OVERRIDE_STDERR
+
+#include "tool_setup.h"
+#include "tool_stderr.h"
+#include "tool_msgs.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* In other tool files stderr is defined as tool_stderr by tool_setup.h */
+FILE *tool_stderr;
+
+void tool_init_stderr(void)
+{
+ tool_stderr = stderr;
+}
+
+void tool_set_stderr_file(struct GlobalConfig *global, char *filename)
+{
+ FILE *fp;
+
+ if(!filename)
+ return;
+
+ if(!strcmp(filename, "-")) {
+ tool_stderr = stdout;
+ return;
+ }
+
+ /* precheck that filename is accessible to lessen the chance that the
+ subsequent freopen will fail. */
+ fp = fopen(filename, FOPEN_WRITETEXT);
+ if(!fp) {
+ warnf(global, "Warning: Failed to open %s", filename);
+ return;
+ }
+ fclose(fp);
+
+ /* freopen the actual stderr (stdio.h stderr) instead of tool_stderr since
+ the latter may be set to stdout. */
+ fp = freopen(filename, FOPEN_WRITETEXT, stderr);
+ if(!fp) {
+ /* stderr may have been closed by freopen. there is nothing to be done. */
+ DEBUGASSERT(0);
+ return;
+ }
+ tool_stderr = stderr;
+}
diff --git a/src/tool_panykey.h b/src/tool_stderr.h
similarity index 77%
rename from src/tool_panykey.h
rename to src/tool_stderr.h
index c5cc322..c887275 100644
--- a/src/tool_panykey.h
+++ b/src/tool_stderr.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_TOOL_PANYKEY_H
-#define HEADER_CURL_TOOL_PANYKEY_H
+#ifndef HEADER_CURL_TOOL_STDERR_H
+#define HEADER_CURL_TOOL_STDERR_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,11 +24,9 @@
*
***************************************************************************/
#include "tool_setup.h"
+#include "tool_cfgable.h"
-#if defined(NETWARE)
-void tool_pressanykey(void);
-#else
-#define tool_pressanykey() Curl_nop_stmt
-#endif
+void tool_init_stderr(void);
+void tool_set_stderr_file(struct GlobalConfig *global, char *filename);
-#endif /* HEADER_CURL_TOOL_PANYKEY_H */
+#endif /* HEADER_CURL_TOOL_STDERR_H */
diff --git a/src/tool_strdup.c b/src/tool_strdup.c
index 402f1c9..a5725d6 100644
--- a/src/tool_strdup.c
+++ b/src/tool_strdup.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_strdup.h b/src/tool_strdup.h
index c31c046..9b21618 100644
--- a/src/tool_strdup.h
+++ b/src/tool_strdup.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index fae8b13..2cccef2 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -64,9 +64,9 @@
*
* Multiplies and checks for overflow.
*/
-static int multiply(unsigned long *amount, long with)
+static int multiply(curl_off_t *amount, curl_off_t with)
{
- unsigned long sum = *amount * with;
+ curl_off_t sum = *amount * with;
if(!with) {
*amount = 0;
return 0;
@@ -78,7 +78,7 @@
}
static CURLcode glob_set(struct URLGlob *glob, char **patternp,
- size_t *posp, unsigned long *amount,
+ size_t *posp, curl_off_t *amount,
int globindex)
{
/* processes a set expression with the point behind the opening '{'
@@ -100,7 +100,7 @@
pat->globindex = globindex;
while(!done) {
- switch (*pattern) {
+ switch(*pattern) {
case '\0': /* URL ended while set was still open */
return GLOBERROR("unmatched brace", opos, CURLE_URL_MALFORMAT);
@@ -123,7 +123,8 @@
*buf = '\0';
if(pat->content.Set.elements) {
char **new_arr = realloc(pat->content.Set.elements,
- (pat->content.Set.size + 1) * sizeof(char *));
+ (size_t)(pat->content.Set.size + 1) *
+ sizeof(char *));
if(!new_arr)
return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
@@ -172,7 +173,7 @@
}
static CURLcode glob_range(struct URLGlob *glob, char **patternp,
- size_t *posp, unsigned long *amount,
+ size_t *posp, curl_off_t *amount,
int globindex)
{
/* processes a range expression with the point behind the opening '['
@@ -295,7 +296,7 @@
}
}
- fail:
+fail:
*posp += (pattern - *patternp);
if(!endp || !step_n ||
@@ -350,7 +351,7 @@
memcpy(hostname, str, hlen);
hostname[hlen] = 0;
- /* ask to "guess scheme" as then it works without a https:// prefix */
+ /* ask to "guess scheme" as then it works without an https:// prefix */
rc = curl_url_set(u, CURLUPART_URL, hostname, CURLU_GUESS_SCHEME);
curl_url_cleanup(u);
@@ -360,7 +361,7 @@
}
static CURLcode glob_parse(struct URLGlob *glob, char *pattern,
- size_t pos, unsigned long *amount)
+ size_t pos, curl_off_t *amount)
{
/* processes a literal string component of a URL
special characters '{' and '[' branch to set/range processing functions
@@ -411,7 +412,7 @@
res = glob_fixed(glob, glob->glob_buffer, sublen);
}
else {
- switch (*pattern) {
+ switch(*pattern) {
case '\0': /* done */
break;
@@ -437,7 +438,7 @@
return res;
}
-CURLcode glob_url(struct URLGlob **glob, char *url, unsigned long *urlnum,
+CURLcode glob_url(struct URLGlob **glob, char *url, curl_off_t *urlnum,
FILE *error)
{
/*
@@ -445,7 +446,7 @@
* as the specified URL!
*/
struct URLGlob *glob_expand;
- unsigned long amount = 0;
+ curl_off_t amount = 0;
char *glob_buffer;
CURLcode res;
@@ -496,7 +497,7 @@
void glob_cleanup(struct URLGlob *glob)
{
size_t i;
- int elem;
+ curl_off_t elem;
if(!glob)
return;
diff --git a/src/tool_urlglob.h b/src/tool_urlglob.h
index 80c1537..c38f9d9 100644
--- a/src/tool_urlglob.h
+++ b/src/tool_urlglob.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -38,7 +38,7 @@
union {
struct {
char **elements;
- int size;
+ curl_off_t size;
int ptr_s;
} Set;
struct {
@@ -48,11 +48,11 @@
int step;
} CharRange;
struct {
- unsigned long min_n;
- unsigned long max_n;
+ curl_off_t min_n;
+ curl_off_t max_n;
int padlength;
- unsigned long ptr_n;
- unsigned long step;
+ curl_off_t ptr_n;
+ curl_off_t step;
} NumRange;
} content;
};
@@ -70,7 +70,7 @@
size_t pos; /* column position of error or 0 */
};
-CURLcode glob_url(struct URLGlob**, char *, unsigned long *, FILE *);
+CURLcode glob_url(struct URLGlob**, char *, curl_off_t *, FILE *);
CURLcode glob_next_url(char **, struct URLGlob *);
CURLcode glob_match_url(char **, char *, struct URLGlob *);
void glob_cleanup(struct URLGlob *glob);
diff --git a/src/tool_util.c b/src/tool_util.c
index 8d32343..7a1c03b 100644
--- a/src/tool_util.c
+++ b/src/tool_util.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,16 +23,16 @@
***************************************************************************/
#include "tool_setup.h"
+#if defined(HAVE_STRCASECMP) && defined(HAVE_STRINGS_H)
+#include <strings.h>
+#endif
+
#include "tool_util.h"
#include "memdebug.h" /* keep this as LAST include */
#if defined(WIN32) && !defined(MSDOS)
-/* set in win32_init() */
-extern LARGE_INTEGER tool_freq;
-extern bool tool_isVistaOrGreater;
-
/* In case of bug fix this function has a counterpart in timeval.c */
struct timeval tvnow(void)
{
@@ -135,3 +135,27 @@
return (long)(newer.tv_sec-older.tv_sec)*1000+
(long)(newer.tv_usec-older.tv_usec)/1000;
}
+
+/* Case insensitive compare. Accept NULL pointers. */
+int struplocompare(const char *p1, const char *p2)
+{
+ if(!p1)
+ return p2? -1: 0;
+ if(!p2)
+ return 1;
+#ifdef HAVE_STRCASECMP
+ return strcasecmp(p1, p2);
+#elif defined(HAVE_STRCMPI)
+ return strcmpi(p1, p2);
+#elif defined(HAVE_STRICMP)
+ return stricmp(p1, p2);
+#else
+ return strcmp(p1, p2);
+#endif
+}
+
+/* Indirect version to use as qsort callback. */
+int struplocompare4sort(const void *p1, const void *p2)
+{
+ return struplocompare(* (char * const *) p1, * (char * const *) p2);
+}
diff --git a/src/tool_util.h b/src/tool_util.h
index 366afe4..d688672 100644
--- a/src/tool_util.h
+++ b/src/tool_util.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,4 +35,8 @@
*/
long tvdiff(struct timeval t1, struct timeval t2);
+/* Case insensitive comparison support. */
+int struplocompare(const char *p1, const char *p2);
+int struplocompare4sort(const void *p1, const void *p2);
+
#endif /* HEADER_CURL_TOOL_UTIL_H */
diff --git a/src/tool_version.h b/src/tool_version.h
index 62f082b..7ca5061 100644
--- a/src/tool_version.h
+++ b/src/tool_version.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_vms.c b/src/tool_vms.c
index 7d45d5f..9402574 100644
--- a/src/tool_vms.c
+++ b/src/tool_vms.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_vms.h b/src/tool_vms.h
index 949206d..cc2d31d 100644
--- a/src/tool_vms.h
+++ b/src/tool_vms.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_writeout.c b/src/tool_writeout.c
index 616a958..2509d18 100644
--- a/src/tool_writeout.c
+++ b/src/tool_writeout.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,6 +28,7 @@
#include "tool_cfgable.h"
#include "tool_writeout.h"
#include "tool_writeout_json.h"
+#include "dynbuf.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -72,23 +73,26 @@
Variable names should be in alphabetical order.
*/
static const struct writeoutvar variables[] = {
+ {"certs", VAR_CERT, CURLINFO_NONE, writeString},
{"content_type", VAR_CONTENT_TYPE, CURLINFO_CONTENT_TYPE, writeString},
- {"errormsg", VAR_ERRORMSG, 0, writeString},
- {"exitcode", VAR_EXITCODE, 0, writeLong},
- {"filename_effective", VAR_EFFECTIVE_FILENAME, 0, writeString},
+ {"conn_id", VAR_CONN_ID, CURLINFO_CONN_ID, writeOffset},
+ {"errormsg", VAR_ERRORMSG, CURLINFO_NONE, writeString},
+ {"exitcode", VAR_EXITCODE, CURLINFO_NONE, writeLong},
+ {"filename_effective", VAR_EFFECTIVE_FILENAME, CURLINFO_NONE, writeString},
{"ftp_entry_path", VAR_FTP_ENTRY_PATH, CURLINFO_FTP_ENTRY_PATH, writeString},
- {"header_json", VAR_HEADER_JSON, 0, NULL},
+ {"header_json", VAR_HEADER_JSON, CURLINFO_NONE, NULL},
{"http_code", VAR_HTTP_CODE, CURLINFO_RESPONSE_CODE, writeLong},
{"http_connect", VAR_HTTP_CODE_PROXY, CURLINFO_HTTP_CONNECTCODE, writeLong},
{"http_version", VAR_HTTP_VERSION, CURLINFO_HTTP_VERSION, writeString},
- {"json", VAR_JSON, 0, NULL},
+ {"json", VAR_JSON, CURLINFO_NONE, NULL},
{"local_ip", VAR_LOCAL_IP, CURLINFO_LOCAL_IP, writeString},
{"local_port", VAR_LOCAL_PORT, CURLINFO_LOCAL_PORT, writeLong},
{"method", VAR_EFFECTIVE_METHOD, CURLINFO_EFFECTIVE_METHOD, writeString},
+ {"num_certs", VAR_NUM_CERTS, CURLINFO_NONE, writeLong},
{"num_connects", VAR_NUM_CONNECTS, CURLINFO_NUM_CONNECTS, writeLong},
- {"num_headers", VAR_NUM_HEADERS, 0, writeLong},
+ {"num_headers", VAR_NUM_HEADERS, CURLINFO_NONE, writeLong},
{"num_redirects", VAR_REDIRECT_COUNT, CURLINFO_REDIRECT_COUNT, writeLong},
- {"onerror", VAR_ONERROR, 0, NULL},
+ {"onerror", VAR_ONERROR, CURLINFO_NONE, NULL},
{"proxy_ssl_verify_result", VAR_PROXY_SSL_VERIFY_RESULT,
CURLINFO_PROXY_SSL_VERIFYRESULT, writeLong},
{"redirect_url", VAR_REDIRECT_URL, CURLINFO_REDIRECT_URL, writeString},
@@ -106,8 +110,8 @@
{"speed_upload", VAR_SPEED_UPLOAD, CURLINFO_SPEED_UPLOAD_T, writeOffset},
{"ssl_verify_result", VAR_SSL_VERIFY_RESULT, CURLINFO_SSL_VERIFYRESULT,
writeLong},
- {"stderr", VAR_STDERR, 0, NULL},
- {"stdout", VAR_STDOUT, 0, NULL},
+ {"stderr", VAR_STDERR, CURLINFO_NONE, NULL},
+ {"stdout", VAR_STDOUT, CURLINFO_NONE, NULL},
{"time_appconnect", VAR_APPCONNECT_TIME, CURLINFO_APPCONNECT_TIME_T,
writeTime},
{"time_connect", VAR_CONNECT_TIME, CURLINFO_CONNECT_TIME_T, writeTime},
@@ -119,10 +123,31 @@
{"time_starttransfer", VAR_STARTTRANSFER_TIME, CURLINFO_STARTTRANSFER_TIME_T,
writeTime},
{"time_total", VAR_TOTAL_TIME, CURLINFO_TOTAL_TIME_T, writeTime},
- {"url", VAR_INPUT_URL, 0, writeString},
+ {"url", VAR_INPUT_URL, CURLINFO_NONE, writeString},
+ {"url.scheme", VAR_INPUT_URLSCHEME, CURLINFO_NONE, writeString},
+ {"url.user", VAR_INPUT_URLUSER, CURLINFO_NONE, writeString},
+ {"url.password", VAR_INPUT_URLPASSWORD, CURLINFO_NONE, writeString},
+ {"url.options", VAR_INPUT_URLOPTIONS, CURLINFO_NONE, writeString},
+ {"url.host", VAR_INPUT_URLHOST, CURLINFO_NONE, writeString},
+ {"url.port", VAR_INPUT_URLPORT, CURLINFO_NONE, writeString},
+ {"url.path", VAR_INPUT_URLPATH, CURLINFO_NONE, writeString},
+ {"url.query", VAR_INPUT_URLQUERY, CURLINFO_NONE, writeString},
+ {"url.fragment", VAR_INPUT_URLFRAGMENT, CURLINFO_NONE, writeString},
+ {"url.zoneid", VAR_INPUT_URLZONEID, CURLINFO_NONE, writeString},
+ {"urle.scheme", VAR_INPUT_URLESCHEME, CURLINFO_NONE, writeString},
+ {"urle.user", VAR_INPUT_URLEUSER, CURLINFO_NONE, writeString},
+ {"urle.password", VAR_INPUT_URLEPASSWORD, CURLINFO_NONE, writeString},
+ {"urle.options", VAR_INPUT_URLEOPTIONS, CURLINFO_NONE, writeString},
+ {"urle.host", VAR_INPUT_URLEHOST, CURLINFO_NONE, writeString},
+ {"urle.port", VAR_INPUT_URLEPORT, CURLINFO_NONE, writeString},
+ {"urle.path", VAR_INPUT_URLEPATH, CURLINFO_NONE, writeString},
+ {"urle.query", VAR_INPUT_URLEQUERY, CURLINFO_NONE, writeString},
+ {"urle.fragment", VAR_INPUT_URLEFRAGMENT, CURLINFO_NONE, writeString},
+ {"urle.zoneid", VAR_INPUT_URLEZONEID, CURLINFO_NONE, writeString},
{"url_effective", VAR_EFFECTIVE_URL, CURLINFO_EFFECTIVE_URL, writeString},
- {"urlnum", VAR_URLNUM, 0, writeLong},
- {NULL, VAR_NONE, 0, NULL}
+ {"urlnum", VAR_URLNUM, CURLINFO_NONE, writeLong},
+ {"xfer_id", VAR_EASY_ID, CURLINFO_XFER_ID, writeOffset},
+ {NULL, VAR_NONE, CURLINFO_NONE, NULL}
};
static int writeTime(FILE *stream, const struct writeoutvar *wovar,
@@ -162,12 +187,96 @@
return 1; /* return 1 if anything was written */
}
+static int urlpart(struct per_transfer *per, writeoutid vid,
+ const char **contentp)
+{
+ CURLU *uh = curl_url();
+ int rc = 0;
+ if(uh) {
+ CURLUPart cpart = CURLUPART_HOST;
+ char *part = NULL;
+ const char *url = NULL;
+
+ if(vid >= VAR_INPUT_URLEHOST) {
+ if(curl_easy_getinfo(per->curl, CURLINFO_EFFECTIVE_URL, &url))
+ rc = 5;
+ }
+ else
+ url = per->this_url;
+
+ if(!rc) {
+ switch(vid) {
+ case VAR_INPUT_URLSCHEME:
+ case VAR_INPUT_URLESCHEME:
+ cpart = CURLUPART_SCHEME;
+ break;
+ case VAR_INPUT_URLUSER:
+ case VAR_INPUT_URLEUSER:
+ cpart = CURLUPART_USER;
+ break;
+ case VAR_INPUT_URLPASSWORD:
+ case VAR_INPUT_URLEPASSWORD:
+ cpart = CURLUPART_PASSWORD;
+ break;
+ case VAR_INPUT_URLOPTIONS:
+ case VAR_INPUT_URLEOPTIONS:
+ cpart = CURLUPART_OPTIONS;
+ break;
+ case VAR_INPUT_URLHOST:
+ case VAR_INPUT_URLEHOST:
+ cpart = CURLUPART_HOST;
+ break;
+ case VAR_INPUT_URLPORT:
+ case VAR_INPUT_URLEPORT:
+ cpart = CURLUPART_PORT;
+ break;
+ case VAR_INPUT_URLPATH:
+ case VAR_INPUT_URLEPATH:
+ cpart = CURLUPART_PATH;
+ break;
+ case VAR_INPUT_URLQUERY:
+ case VAR_INPUT_URLEQUERY:
+ cpart = CURLUPART_QUERY;
+ break;
+ case VAR_INPUT_URLFRAGMENT:
+ case VAR_INPUT_URLEFRAGMENT:
+ cpart = CURLUPART_FRAGMENT;
+ break;
+ case VAR_INPUT_URLZONEID:
+ case VAR_INPUT_URLEZONEID:
+ cpart = CURLUPART_ZONEID;
+ break;
+ default:
+ /* not implemented */
+ rc = 4;
+ break;
+ }
+ }
+ if(!rc && curl_url_set(uh, CURLUPART_URL, url,
+ CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME))
+ rc = 2;
+
+ if(!rc && curl_url_get(uh, cpart, &part, CURLU_DEFAULT_PORT))
+ rc = 3;
+
+ if(!rc && part)
+ *contentp = part;
+ curl_url_cleanup(uh);
+ }
+ else
+ return 1;
+ return rc;
+}
+
static int writeString(FILE *stream, const struct writeoutvar *wovar,
struct per_transfer *per, CURLcode per_result,
bool use_json)
{
bool valid = false;
const char *strinfo = NULL;
+ const char *freestr = NULL;
+ struct dynbuf buf;
+ curlx_dyn_init(&buf, 256*1024);
DEBUGASSERT(wovar->writefunc == writeString);
@@ -193,10 +302,55 @@
}
else {
switch(wovar->id) {
+ case VAR_CERT:
+ if(per->certinfo) {
+ int i;
+ bool error = FALSE;
+ for(i = 0; (i < per->certinfo->num_of_certs) && !error; i++) {
+ struct curl_slist *slist;
+
+ for(slist = per->certinfo->certinfo[i]; slist; slist = slist->next) {
+ size_t len;
+ if(curl_strnequal(slist->data, "cert:", 5)) {
+ if(curlx_dyn_add(&buf, &slist->data[5])) {
+ error = TRUE;
+ break;
+ }
+ }
+ else {
+ if(curlx_dyn_add(&buf, slist->data)) {
+ error = TRUE;
+ break;
+ }
+ }
+ len = curlx_dyn_len(&buf);
+ if(len) {
+ char *ptr = curlx_dyn_ptr(&buf);
+ if(ptr[len -1] != '\n') {
+ /* add a newline to make things look better */
+ if(curlx_dyn_addn(&buf, "\n", 1)) {
+ error = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if(!error) {
+ strinfo = curlx_dyn_ptr(&buf);
+ if(!strinfo)
+ /* maybe not a TLS protocol */
+ strinfo = "";
+ valid = true;
+ }
+ }
+ else
+ strinfo = ""; /* no cert info */
+ break;
case VAR_ERRORMSG:
if(per_result) {
- strinfo = per->errorbuffer[0] ? per->errorbuffer :
- curl_easy_strerror(per_result);
+ strinfo = (per->errorbuffer && per->errorbuffer[0]) ?
+ per->errorbuffer : curl_easy_strerror(per_result);
valid = true;
}
break;
@@ -212,6 +366,33 @@
valid = true;
}
break;
+ case VAR_INPUT_URLSCHEME:
+ case VAR_INPUT_URLUSER:
+ case VAR_INPUT_URLPASSWORD:
+ case VAR_INPUT_URLOPTIONS:
+ case VAR_INPUT_URLHOST:
+ case VAR_INPUT_URLPORT:
+ case VAR_INPUT_URLPATH:
+ case VAR_INPUT_URLQUERY:
+ case VAR_INPUT_URLFRAGMENT:
+ case VAR_INPUT_URLZONEID:
+ case VAR_INPUT_URLESCHEME:
+ case VAR_INPUT_URLEUSER:
+ case VAR_INPUT_URLEPASSWORD:
+ case VAR_INPUT_URLEOPTIONS:
+ case VAR_INPUT_URLEHOST:
+ case VAR_INPUT_URLEPORT:
+ case VAR_INPUT_URLEPATH:
+ case VAR_INPUT_URLEQUERY:
+ case VAR_INPUT_URLEFRAGMENT:
+ case VAR_INPUT_URLEZONEID:
+ if(per->this_url) {
+ if(!urlpart(per, wovar->id, &strinfo)) {
+ freestr = strinfo;
+ valid = true;
+ }
+ }
+ break;
default:
DEBUGASSERT(0);
break;
@@ -231,7 +412,9 @@
if(use_json)
fprintf(stream, "\"%s\":null", wovar->name);
}
+ curl_free((char *)freestr);
+ curlx_dyn_free(&buf);
return 1; /* return 1 if anything was written */
}
@@ -250,6 +433,10 @@
}
else {
switch(wovar->id) {
+ case VAR_NUM_CERTS:
+ longinfo = per->certinfo ? per->certinfo->num_of_certs : 0;
+ valid = true;
+ break;
case VAR_NUM_HEADERS:
longinfo = per->num_headers;
valid = true;
@@ -321,12 +508,21 @@
return 1; /* return 1 if anything was written */
}
-void ourWriteOut(const char *writeinfo, struct per_transfer *per,
+void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,
CURLcode per_result)
{
FILE *stream = stdout;
+ const char *writeinfo = config->writeout;
const char *ptr = writeinfo;
bool done = FALSE;
+ struct curl_certinfo *certinfo;
+ CURLcode res = curl_easy_getinfo(per->curl, CURLINFO_CERTINFO, &certinfo);
+
+ if(!writeinfo)
+ return;
+
+ if(!res && certinfo)
+ per->certinfo = certinfo;
while(ptr && *ptr && !done) {
if('%' == *ptr && ptr[1]) {
@@ -338,8 +534,8 @@
else {
/* this is meant as a variable to output */
char *end;
+ size_t vlen;
if('{' == ptr[1]) {
- char keepit;
int i;
bool match = FALSE;
end = strchr(ptr, '}');
@@ -348,10 +544,10 @@
fputs("%{", stream);
continue;
}
- keepit = *end;
- *end = 0; /* null-terminate */
+ vlen = end - ptr;
for(i = 0; variables[i].name; i++) {
- if(curl_strequal(ptr, variables[i].name)) {
+ if((strlen(variables[i].name) == vlen) &&
+ curl_strnequal(ptr, variables[i].name, vlen)) {
match = TRUE;
switch(variables[i].id) {
case VAR_ONERROR:
@@ -380,21 +576,26 @@
}
}
if(!match) {
- fprintf(stderr, "curl: unknown --write-out variable: '%s'\n", ptr);
+ fprintf(stderr, "curl: unknown --write-out variable: '%.*s'\n",
+ (int)vlen, ptr);
}
ptr = end + 1; /* pass the end */
- *end = keepit;
}
else if(!strncmp("header{", &ptr[1], 7)) {
ptr += 8;
end = strchr(ptr, '}');
if(end) {
+ char hname[256]; /* holds the longest header field name */
struct curl_header *header;
- *end = 0;
- if(CURLHE_OK == curl_easy_header(per->curl, ptr, 0, CURLH_HEADER,
- -1, &header))
- fputs(header->value, stream);
- ptr = end + 1; /* pass the end */
+ vlen = end - ptr;
+ if(vlen < sizeof(hname)) {
+ memcpy(hname, ptr, vlen);
+ hname[vlen] = 0;
+ if(CURLHE_OK == curl_easy_header(per->curl, hname, 0,
+ CURLH_HEADER, -1, &header))
+ fputs(header->value, stream);
+ }
+ ptr = end + 1;
}
else
fputs("%header{", stream);
diff --git a/src/tool_writeout.h b/src/tool_writeout.h
index c7cdb97..4e690a6 100644
--- a/src/tool_writeout.h
+++ b/src/tool_writeout.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,8 +29,11 @@
typedef enum {
VAR_NONE, /* must be the first */
VAR_APPCONNECT_TIME,
+ VAR_CERT,
VAR_CONNECT_TIME,
VAR_CONTENT_TYPE,
+ VAR_CONN_ID,
+ VAR_EASY_ID,
VAR_EFFECTIVE_FILENAME,
VAR_EFFECTIVE_METHOD,
VAR_EFFECTIVE_URL,
@@ -43,10 +46,32 @@
VAR_HTTP_CODE_PROXY,
VAR_HTTP_VERSION,
VAR_INPUT_URL,
+ VAR_INPUT_URLSCHEME,
+ VAR_INPUT_URLUSER,
+ VAR_INPUT_URLPASSWORD,
+ VAR_INPUT_URLOPTIONS,
+ VAR_INPUT_URLHOST,
+ VAR_INPUT_URLPORT,
+ VAR_INPUT_URLPATH,
+ VAR_INPUT_URLQUERY,
+ VAR_INPUT_URLFRAGMENT,
+ VAR_INPUT_URLZONEID,
+ /* the same ones again for url *effective* */
+ VAR_INPUT_URLESCHEME,
+ VAR_INPUT_URLEUSER,
+ VAR_INPUT_URLEPASSWORD,
+ VAR_INPUT_URLEOPTIONS,
+ VAR_INPUT_URLEHOST,
+ VAR_INPUT_URLEPORT,
+ VAR_INPUT_URLEPATH,
+ VAR_INPUT_URLEQUERY,
+ VAR_INPUT_URLEFRAGMENT,
+ VAR_INPUT_URLEZONEID,
VAR_JSON,
VAR_LOCAL_IP,
VAR_LOCAL_PORT,
VAR_NAMELOOKUP_TIME,
+ VAR_NUM_CERTS,
VAR_NUM_CONNECTS,
VAR_NUM_HEADERS,
VAR_ONERROR,
@@ -82,7 +107,7 @@
bool use_json);
};
-void ourWriteOut(const char *writeinfo, struct per_transfer *per,
+void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,
CURLcode per_result);
#endif /* HEADER_CURL_TOOL_WRITEOUT_H */
diff --git a/src/tool_writeout_json.c b/src/tool_writeout_json.c
index a36d60c..0e4623f 100644
--- a/src/tool_writeout_json.c
+++ b/src/tool_writeout_json.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -61,8 +61,8 @@
fputs("\\t", stream);
break;
default:
- if (*i < 32) {
- fprintf(stream, "u%04x", *i);
+ if(*i < 32) {
+ fprintf(stream, "\\u%04x", *i);
}
else {
char out = *i;
@@ -110,11 +110,6 @@
fputc('{', stream);
while((header = curl_easy_nextheader(per->curl, CURLH_HEADER, -1,
prev))) {
- if(prev)
- fputs(",\n", stream);
- jsonWriteString(stream, header->name, TRUE);
- fputc(':', stream);
- prev = header;
if(header->amount > 1) {
if(!header->index) {
/* act on the 0-index entry and pull the others in, then output in a
@@ -122,6 +117,11 @@
size_t a = header->amount;
size_t i = 0;
char *name = header->name;
+ if(prev)
+ fputs(",\n", stream);
+ jsonWriteString(stream, header->name, TRUE);
+ fputc(':', stream);
+ prev = header;
fputc('[', stream);
do {
jsonWriteString(stream, header->value, FALSE);
@@ -132,13 +132,18 @@
-1, &header))
break;
} while(1);
+ fputc(']', stream);
}
- fputc(']', stream);
}
else {
+ if(prev)
+ fputs(",\n", stream);
+ jsonWriteString(stream, header->name, TRUE);
+ fputc(':', stream);
fputc('[', stream);
jsonWriteString(stream, header->value, FALSE);
fputc(']', stream);
+ prev = header;
}
}
fputs("\n}", stream);
diff --git a/src/tool_writeout_json.h b/src/tool_writeout_json.h
index d846605..6d8f8d0 100644
--- a/src/tool_writeout_json.h
+++ b/src/tool_writeout_json.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/src/tool_xattr.c b/src/tool_xattr.c
index b2a509d..968cf2f 100644
--- a/src/tool_xattr.c
+++ b/src/tool_xattr.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,17 +22,6 @@
*
***************************************************************************/
#include "tool_setup.h"
-
-#ifdef HAVE_FSETXATTR
-# include <sys/xattr.h> /* header from libc, not from libattr */
-# define USE_XATTR
-#elif (defined(__FreeBSD_version) && (__FreeBSD_version > 500000)) || \
- defined(__MidnightBSD_version)
-# include <sys/types.h>
-# include <sys/extattr.h>
-# define USE_XATTR
-#endif
-
#include "tool_xattr.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -48,26 +37,25 @@
* https://freedesktop.org/wiki/CommonExtendedAttributes/
*/
{ "user.xdg.referrer.url", CURLINFO_REFERER },
- { "user.xdg.origin.url", CURLINFO_EFFECTIVE_URL },
{ "user.mime_type", CURLINFO_CONTENT_TYPE },
{ NULL, CURLINFO_NONE } /* last element, abort here */
};
-/* returns TRUE if a new URL is returned, that then needs to be freed */
+/* returns a new URL that needs to be freed */
/* @unittest: 1621 */
#ifdef UNITTESTS
-bool stripcredentials(char **url);
+char *stripcredentials(const char *url);
#else
static
#endif
-bool stripcredentials(char **url)
+char *stripcredentials(const char *url)
{
CURLU *u;
CURLUcode uc;
char *nurl;
u = curl_url();
if(u) {
- uc = curl_url_set(u, CURLUPART_URL, *url, 0);
+ uc = curl_url_set(u, CURLUPART_URL, url, 0);
if(uc)
goto error;
@@ -85,59 +73,64 @@
curl_url_cleanup(u);
- *url = nurl;
- return TRUE;
+ return nurl;
}
- error:
+error:
curl_url_cleanup(u);
- return FALSE;
+ return NULL;
}
+static int xattr(int fd,
+ const char *attr, /* name of the xattr */
+ const char *value)
+{
+ int err = 0;
+ if(value) {
+#ifdef DEBUGBUILD
+ if(getenv("CURL_FAKE_XATTR")) {
+ printf("%s => %s\n", attr, value);
+ }
+ return 0;
+#endif
+#ifdef HAVE_FSETXATTR_6
+ err = fsetxattr(fd, attr, value, strlen(value), 0, 0);
+#elif defined(HAVE_FSETXATTR_5)
+ err = fsetxattr(fd, attr, value, strlen(value), 0);
+#elif defined(__FreeBSD_version) || defined(__MidnightBSD_version)
+ {
+ ssize_t rc = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER,
+ attr, value, strlen(value));
+ /* FreeBSD's extattr_set_fd returns the length of the extended
+ attribute */
+ err = (rc < 0 ? -1 : 0);
+ }
+#endif
+ }
+ return err;
+}
/* store metadata from the curl request alongside the downloaded
* file using extended attributes
*/
-int fwrite_xattr(CURL *curl, int fd)
+int fwrite_xattr(CURL *curl, const char *url, int fd)
{
int i = 0;
int err = 0;
/* loop through all xattr-curlinfo pairs and abort on a set error */
- while(err == 0 && mappings[i].attr) {
+ while(!err && mappings[i].attr) {
char *value = NULL;
CURLcode result = curl_easy_getinfo(curl, mappings[i].info, &value);
- if(!result && value) {
- bool freeptr = FALSE;
- if(CURLINFO_EFFECTIVE_URL == mappings[i].info)
- freeptr = stripcredentials(&value);
- if(value) {
-#ifdef HAVE_FSETXATTR_6
- err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0, 0);
-#elif defined(HAVE_FSETXATTR_5)
- err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0);
-#elif defined(__FreeBSD_version) || defined(__MidnightBSD_version)
- {
- ssize_t rc = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER,
- mappings[i].attr, value, strlen(value));
- /* FreeBSD's extattr_set_fd returns the length of the extended
- attribute */
- err = (rc < 0 ? -1 : 0);
- }
-#endif
- if(freeptr)
- curl_free(value);
- }
- }
+ if(!result && value)
+ err = xattr(fd, mappings[i].attr, value);
i++;
}
-
+ if(!err) {
+ char *nurl = stripcredentials(url);
+ if(!nurl)
+ return 1;
+ err = xattr(fd, "user.xdg.origin.url", nurl);
+ curl_free(nurl);
+ }
return err;
}
-#else
-int fwrite_xattr(CURL *curl, int fd)
-{
- (void)curl;
- (void)fd;
-
- return 0;
-}
#endif
diff --git a/src/tool_xattr.h b/src/tool_xattr.h
index 8cc0204..2ffffd2 100644
--- a/src/tool_xattr.h
+++ b/src/tool_xattr.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,6 +25,21 @@
***************************************************************************/
#include "tool_setup.h"
-int fwrite_xattr(CURL *curl, int fd);
+#ifdef HAVE_FSETXATTR
+# include <sys/xattr.h> /* header from libc, not from libattr */
+# define USE_XATTR
+#elif (defined(__FreeBSD_version) && (__FreeBSD_version > 500000)) || \
+ defined(__MidnightBSD_version)
+# include <sys/types.h>
+# include <sys/extattr.h>
+# define USE_XATTR
+#endif
+
+#ifdef USE_XATTR
+int fwrite_xattr(CURL *curl, const char *url, int fd);
+
+#else
+#define fwrite_xattr(a,b,c) 0
+#endif
#endif /* HEADER_CURL_TOOL_XATTR_H */
diff --git a/tests/.gitignore b/tests/.gitignore
index 07590a3..eae0490 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
@@ -19,8 +19,10 @@
ftps_stunnel.conf
https_stunnel.conf
log
+log*
runtests.html
runtests.pdf
testcurl.html
testcurl.pdf
*.port
+config
diff --git a/tests/CI.md b/tests/CI.md
index febd1f8..0d3d110 100644
--- a/tests/CI.md
+++ b/tests/CI.md
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 1998 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
@@ -39,28 +39,28 @@
| LGTM analysis: Python | stable | new findings |
| LGTM analysis: C/C++ | stable | new findings |
| buildbot/curl_winssl_ ... | stable | all errors and failures |
- | continuous-integration/appveyor/pr | stable | all errors and failures |
+ | AppVeyor | flaky | all errors and failures |
| curl.curl (linux ...) | stable | all errors and failures |
| curl.curl (windows ...) | flaky | repetitive errors/failures |
- | deepcode-ci-bot | stable | new findings |
- | musedev | stable | new findings |
+ | CodeQL | stable | new findings |
Sometimes the tests fail due to a dependency service temporarily being offline
-or otherwise unavailable, eg. package downloads. In this case you can just
-try to update your pull requests to rerun the tests later as described below.
+or otherwise unavailable, for example package downloads. In this case you can
+just try to update your pull requests to rerun the tests later as described
+below.
## CI servers
Here are the different CI environments that are currently in use, and how they
are configured:
-### Github Actions
+### GitHub Actions
-Github Actions runs the following tests:
+GitHub Actions runs the following tests:
- Mac OS tests with a variety of different compilation options
-- Fuzz tests ([see tests/fuzz/README for
- more info](https://github.com/curl/curl/blob/master/tests/fuzz/README)).
+- Fuzz tests ([see the curl-fuzzer repo for more
+ info](https://github.com/curl/curl-fuzzer)).
- Curl compiled using the Rust TLS backend with Hyper
- CodeQL static analysis
@@ -75,51 +75,35 @@
These are all configured in `.azure-pipelines.yml`.
-As of November 2021 @bagder and @mback2k are the only people with administrator
-access to the Azure CI environment. Additional admins/group members can be added
-on request.
+As of November 2021 `@bagder` and `@mback2k` are the only people with
+administrator access to the Azure CI environment. Additional admins/group
+members can be added on request.
-### Appveyor
+### AppVeyor
-Appveyor runs a variety of different Windows builds, with different compilation
+AppVeyor runs a variety of different Windows builds, with different compilation
options.
-As of November 2021 @bagder, @mback2k, @jay, @vszakats, @dfandrich and
-@danielgustafsson have administrator access to the Appveyor CI environment.
-Additional admins/group members can be added on request.
+As of November 2021 `@bagder`, `@mback2k`, `@jay`, `@vszakats`, `@dfandrich`
+and `@danielgustafsson` have administrator access to the AppVeyor CI
+environment. Additional admins/group members can be added on request.
-The tests are configured in appveyor.yml.
+The tests are configured in `appveyor.yml`.
### Zuul
-[Zuul](https://zuul-ci.org/) is an open source CI tool. A number of Curl tests
-are run at [curl.zuul.vexxhost.dev](https://curl.zuul.vexxhost.dev/builds):
+Not used anymore.
-- Source code is formatted according to expectations (`make checksrc`).
-- Curl compiled with a number of different TLS configurations (WolfSSL, rustls,
-BoringSSL, etc).
-- Curl compiled with different C compilers.
+### Circle CI
-As of November 2021, the tests run (sometimes) but do not run consistently and
-do not report results to the Github checks runner - you need to manually check
-for failures. See [#7522](https://github.com/curl/curl/issues/7522) for more
-information.
-
-As of November 2021 Daniel Stenberg is the only person with administrator access
-to the Zuul CI environment.
-
-These are configured in `zuul.d` and have test runners in `scripts/zuul`.
-
-### CircleCI
-
-CircleCI runs a basic Linux test suite on Ubuntu for both x86 and ARM
+Circle CI runs a basic Linux test suite on Ubuntu for both x86 and ARM
processors. This is configured in `.circleci/config.yml`.
-You can [view the full list of CI jobs on CircleCI's
+You can [view the full list of CI jobs on Circle CI's
website](https://app.circleci.com/pipelines/github/curl/curl).
-@bagder has access to edit the "Project Settings" on that page.
-Additional admins/group members can be added on request.
+`@bagder` has access to edit the "Project Settings" on that page. Additional
+admins/group members can be added on request.
### Cirrus CI
@@ -129,5 +113,5 @@
You can [view the full list of CI jobs on Cirrus CI's
website](https://cirrus-ci.com/github/curl/curl).
-@bagder has access to edit the "Project Settings" on that page.
-Additional admins/group members can be added on request.
+`@bagder` has access to edit the "Project Settings" on that page. Additional
+admins/group members can be added on request.
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 8ce7610..20bb533 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -21,6 +21,8 @@
# SPDX-License-Identifier: curl
#
###########################################################################
+set(CMAKE_UNITY_BUILD OFF)
+
add_custom_target(testdeps)
add_subdirectory(data)
add_subdirectory(libtest)
diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md
index dc1092b..cf0ab99 100644
--- a/tests/FILEFORMAT.md
+++ b/tests/FILEFORMAT.md
@@ -1,31 +1,31 @@
<!--
-Copyright (C) 1998 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
# curl test suite file format
-The curl test suite's file format is very simple and extensible, closely
-resembling 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
-`<!--` and `-->`) 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
+The curl test suite's file format is simple and extendable, closely resembling
+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 `<!--` and
+`-->`) 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).
Each test case source exists as a file matching the format
-`tests/data/testNUM`, where NUM is the unique test number, and must begin with
-a 'testcase' tag, which encompasses the remainder of the file.
+`tests/data/testNUM`, where `NUM` is the unique test number, and must begin
+with a `testcase` tag, which encompasses the remainder of the file.
# Preprocessing
When a test is to be executed, the source file is first preprocessed and
-variables are substituted by the their respective contents and the output
-version of the test file is stored as `log/testNUM`. That version is what will
-be read and used by the test servers.
+variables are substituted by their respective contents and the output
+version of the test file is stored as `%LOGDIR/testNUM`. That version is what
+will be read and used by the test servers.
## Base64 Encoding
@@ -70,7 +70,7 @@
%repeat[<number> x <string>]%
-For example, to insert the word hello a 100 times:
+For example, to insert the word hello 100 times:
%repeat[100 x hello]%
@@ -79,7 +79,7 @@
Lines in the test file can be made to appear conditionally on a specific
feature (see the "features" section below) being set or not set. If the
specific feature is present, the following lines will be output, otherwise it
-outputs nothing, until a following else or endif clause. Like this:
+outputs nothing, until a following else or `endif` clause. Like this:
%if brotli
Accept-Encoding
@@ -114,13 +114,13 @@
- `%CLIENT6IP` - IPv6 address of the client running curl
- `%CLIENTIP` - IPv4 address of the client running curl
- `%CURL` - Path to the curl executable
-- `%FILE_PWD` - Current directory, on windows prefixed with a slash
+- `%FILE_PWD` - Current directory, on Windows prefixed with a slash
- `%FTP6PORT` - IPv6 port number of the FTP server
- `%FTPPORT` - Port number of the FTP server
- `%FTPSPORT` - Port number of the FTPS server
- `%FTPTIME2` - Timeout in seconds that should be just sufficient to receive a
response from the test FTP server
-- `%FTPTIME3` - Even longer than %FTPTIME2
+- `%FTPTIME3` - Even longer than `%FTPTIME2`
- `%GOPHER6PORT` - IPv6 port number of the Gopher server
- `%GOPHERPORT` - Port number of the Gopher server
- `%GOPHERSPORT` - Port number of the Gophers server
@@ -134,9 +134,10 @@
- `%HTTPTLS6PORT` - IPv6 port number of the HTTP TLS server
- `%HTTPTLSPORT` - Port number of the HTTP TLS server
- `%HTTPUNIXPATH` - Path to the Unix socket of the HTTP server
-- `%SOCKSUNIXPATH` - Absolute Path to the Unix socket of the SOCKS server
+- `%SOCKSUNIXPATH` - Path to the Unix socket of the SOCKS server
- `%IMAP6PORT` - IPv6 port number of the IMAP server
- `%IMAPPORT` - Port number of the IMAP server
+- `%LOGDIR` - Log directory relative to %PWD
- `%MQTTPORT` - Port number of the MQTT server
- `%TELNETPORT` - Port number of the telnet server
- `%NOLISTENPORT` - Port number where no service is listening
@@ -165,8 +166,9 @@
# `<testcase>`
-Each test is always specified entirely within the testcase tag. Each test case
-is split up in four main sections: `info`, `reply`, `client` and `verify`.
+Each test is always specified entirely within the `testcase` tag. Each test
+case is split up in four main sections: `info`, `reply`, `client` and
+`verify`.
- **info** provides information about the test case
@@ -176,7 +178,7 @@
- **client** defines how the client should behave
- **verify** defines how to verify that the data stored after a command has
-been run ended up correctly
+been run ended up correct
Each main section has a number of available subsections that can be specified,
that will be checked/used if specified.
@@ -185,24 +187,29 @@
### `<keywords>`
A newline-separated list of keywords describing what this test case uses and
-tests. Try to use already used keywords. These keywords will be used for
+tests. Try to use already used keywords. These keywords will be used for
statistical/informational purposes and for choosing or skipping classes of
-tests. "Keywords" must begin with an alphabetic character, "-", "[" or "{"
-and may actually consist of multiple words separated by spaces which are
-treated together as a single identifier.
+tests. Keywords must begin with an alphabetic character, `-`, `[` or `{` and
+may actually consist of multiple words separated by spaces which are treated
+together as a single identifier.
-When using curl built with Hyper, the keywords must include HTTP or HTTPS for
-'hyper mode' to kick in and make line ending checks work for tests.
+When using curl built with Hyper, the keywords must include `HTTP` or `HTTPS`
+for 'hyper mode' to kick in and make line ending checks work for tests.
+
+When running a unit test and the keywords include `unittest`, the `<tool>`
+section can be left empty to use the standard unit test tool name `unitN` where
+`N` is the test number.
+
## `<reply>`
-### `<data [nocheck="yes"] [sendzero="yes"] [base64="yes"] [hex="yes"] [nonewline="yes"]>`
+### `<data [nocheck="yes"] [sendzero="yes"] [base64="yes"] [hex="yes"] [nonewline="yes"] [crlf="yes"]>`
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
the arrival of this data.
If the data contains `swsclose` anywhere within the start and end tag, and
-this is a HTTP test, then the connection will be closed by the server after
+this is an HTTP test, then the connection will be closed by the server after
this response is sent. If not, the connection will be kept persistent.
If the data contains `swsbounce` anywhere within the start and end tag, the
@@ -224,29 +231,33 @@
`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.
+
For FTP file listings, the `<data>` section will 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 can't know from
+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 can't know from
which test file to load the list content.
-### `<dataNUM>`
+### `<dataNUM [crlf="yes"]>`
-Send back this contents instead of the <data> one. The num is set by:
+Send back this contents instead of the <data> one. The `NUM` is set by:
- The test number in the request line is >10000 and this is the remainder
of [test case number]%10000.
- - The request was HTTP and included digest details, which adds 1000 to NUM
- - If a HTTP request is NTLM type-1, it adds 1001 to num
- - If a HTTP request is NTLM type-3, it adds 1002 to num
- - If a HTTP request is Basic and num is already >=1000, it adds 1 to num
- - If a HTTP request is Negotiate, num gets incremented by one for each
+ - The request was HTTP and included digest details, which adds 1000 to `NUM`
+ - If an HTTP request is NTLM type-1, it adds 1001 to `NUM`
+ - If an HTTP request is NTLM type-3, it adds 1002 to `NUM`
+ - If an HTTP request is Basic and `NUM` is already >=1000, it adds 1 to `NUM`
+ - If an HTTP request is Negotiate, `NUM` gets incremented by one for each
request with Negotiate authorization header on the same test case.
-Dynamically changing num in this way allows the test harness to be used to
+Dynamically changing `NUM` in this way allows the test harness to be used to
test authentication negotiation where several different requests must be sent
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.
+section. Validating the entire negotiation sequence can be done by specifying
+a `datacheck` section.
### `<connect>`
The connect section is used instead of the 'data' for all CONNECT
@@ -256,7 +267,7 @@
### `<socks>`
Address type and address details as logged by the SOCKS proxy.
-### `<datacheck [mode="text"] [nonewline="yes"]>`
+### `<datacheck [mode="text"] [nonewline="yes"] [crlf="yes"]>`
if the data is sent but this is what should be checked afterwards. If
`nonewline=yes` is set, runtests will cut off the trailing newline from the
data before comparing with the one actually received by the client.
@@ -264,15 +275,15 @@
Use the `mode="text"` attribute if the output is in text mode on platforms
that have a text/binary difference.
-### `<datacheckNUM [nonewline="yes"] [mode="text"]>`
-The contents of numbered datacheck sections are appended to the non-numbered
+### `<datacheckNUM [nonewline="yes"] [mode="text"] [crlf="yes"]>`
+The contents of numbered `datacheck` sections are appended to the non-numbered
one.
### `<size>`
number to return on a ftp SIZE command (set to -1 to make this command fail)
### `<mdtm>`
-what to send back if the client sends a (FTP) MDTM command, set to -1 to
+what to send back if the client sends a (FTP) `MDTM` command, set to -1 to
have it return that the file doesn't exist
### `<postcmd>`
@@ -306,6 +317,7 @@
appear at once when a file is transferred
- `RETRNOSIZE` - Make sure the RETR response doesn't contain the size of the
file
+- `RETRSIZE [size]` - Force RETR response to contain the specified size
- `NOSAVE` - Don't actually save what is received
- `SLOWDOWN` - Send FTP responses with 0.01 sec delay between each byte
- `PASVBADIP` - makes PASV send back an illegal IP in its 227 response
@@ -343,33 +355,43 @@
### `<server>`
What server(s) this test case requires/uses. Available servers:
+- `dict`
- `file`
-- `ftp-ipv6`
- `ftp`
+- `ftp-ipv6`
- `ftps`
- `gopher`
+- `gopher-ipv6`
- `gophers`
+- `http`
+- `http/2`
- `http-ipv6`
- `http-proxy`
-- `http-unix`
-- `http/2`
-- `http`
- `https`
-- `httptls+srp-ipv6`
+- `https-proxy`
- `httptls+srp`
+- `httptls+srp-ipv6`
+- `http-unix`
- `imap`
- `mqtt`
- `none`
- `pop3`
-- `rtsp-ipv6`
- `rtsp`
+- `rtsp-ipv6`
- `scp`
- `sftp`
+- `smb`
- `smtp`
- `socks4`
- `socks5`
+- `socks5unix`
+- `telnet`
+- `tftp`
-Give only one per line. This subsection is mandatory.
+Give only one per line. This subsection is mandatory (use `none` if no servers
+are required). Servers that require a special server certificate can have the
+PEM certificate file name (found in the `certs` directory) appended to the
+server name separated by a space.
### `<features>`
A list of features that MUST be present in the client/library for this test to
@@ -384,7 +406,9 @@
- `alt-svc`
- `bearssl`
+- `brotli`
- `c-ares`
+- `CharConv`
- `cookies`
- `crypto`
- `debug`
@@ -393,9 +417,12 @@
- `GnuTLS`
- `GSS-API`
- `h2c`
+- `headers-api`
- `HSTS`
- `HTTP-auth`
- `http/2`
+- `http/3`
+- `https-proxy`
- `hyper`
- `idn`
- `ipv6`
@@ -407,10 +434,14 @@
- `oldlibssh` (versions before 0.9.4)
- `libz`
- `manual`
+- `mbedtls`
- `Mime`
- `netrc`
+- `nghttpx`
+- `nghttpx-h3`
- `NSS`
- `NTLM`
+- `NTLM_WB`
- `OpenSSL`
- `parsedate`
- `proxy`
@@ -428,6 +459,7 @@
- `TLS-SRP`
- `TrackMemory`
- `typecheck`
+- `threadsafe`
- `Unicode`
- `unittest`
- `unix-sockets`
@@ -436,10 +468,12 @@
- `win32`
- `wolfssh`
- `wolfssl`
+- `xattr`
+- `zstd`
-as well as each protocol that curl supports. A protocol only needs to be
-specified if it is different from the server (useful when the server
-is `none`).
+as well as each protocol that curl supports. A protocol only needs to be
+specified if it is different from the server (useful when the server is
+`none`).
### `<killserver>`
Using the same syntax as in `<server>` but when mentioned here these servers
@@ -460,8 +494,8 @@
### `<tool>`
Name of tool to invoke instead of "curl". This tool must be built and exist
-either in the libtest/ directory (if the tool name starts with 'lib') or in
-the unit/ directory (if the tool name starts with 'unit').
+either in the `libtest/` directory (if the tool name starts with `lib`) or in
+the `unit/` directory (if the tool name starts with `unit`).
### `<name>`
Brief test case description, shown when the test runs.
@@ -505,33 +539,33 @@
`--include` argument.
Set `option="binary-trace"` to use `--trace` instead of `--trace-ascii` for
-tracing. Suitable for binary-oriented protocols such as MQTT.
+tracing. Suitable for binary-oriented protocols such as MQTT.
Set `timeout="secs"` to override default server logs advisor read lock
-timeout. This timeout is used by the test harness, once that the command has
+timeout. This timeout is used by the test harness, once that the command has
completed execution, to wait for the test server to write out server side log
files and remove the lock that advised not to read them. The "secs" parameter
is the not negative integer number of seconds for the timeout. This `timeout`
attribute is documented for completeness sake, but is deep test harness stuff
-and only needed for very singular and specific test cases. Avoid using it.
+and only needed for singular and specific test cases. Avoid using it.
Set `delay="secs"` to introduce a time delay once that the command has
completed execution and before the `<postcheck>` section runs. The "secs"
parameter is the not negative integer number of seconds for the delay. This
-'delay' attribute is intended for very specific test cases, and normally not
+'delay' attribute is intended for specific test cases, and normally not
needed.
-### `<file name="log/filename" [nonewline="yes"]>`
+### `<file name="%LOGDIR/filename" [nonewline="yes"]>`
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 will have the final newline
+If `nonewline="yes"` is used, the created file will have the final newline
stripped off.
### `<stdin [nonewline="yes"]>`
Pass this given data on stdin to the tool.
-If 'nonewline' is set, we will cut off the trailing newline of this given data
+If `nonewline` is set, we will cut off the trailing newline of this given data
before comparing with the one actually received by the client
## `<verify>`
@@ -542,24 +576,27 @@
### `<strip>`
One regex per line that is removed from the protocol dumps before the
-comparison is made. This is very useful to remove dependencies on dynamically
+comparison is made. This is useful to remove dependencies on dynamically
changing protocol data such as port numbers or user-agent strings.
### `<strippart>`
One perl op per line that operates on the protocol dump. This is pretty
advanced. Example: `s/^EPRT .*/EPRT stripped/`.
-### `<protocol [nonewline="yes"]>`
+### `<protocol [nonewline="yes"][crlf="yes"]>`
-the protocol dump curl should transmit, if 'nonewline' is set, we will cut off
+the protocol dump curl should transmit, if `nonewline` is set, we will cut off
the trailing newline of this given data before comparing with the one actually
sent by the client The `<strip>` and `<strippart>` rules are applied before
comparisons are made.
-### `<proxy [nonewline="yes"]>`
+`crlf=yes` forces the newlines to become CRLF even if not written so in the
+test.
-The protocol dump curl should transmit to a HTTP proxy (when the http-proxy
-server is used), if 'nonewline' is set, we will cut off the trailing newline
+### `<proxy [nonewline="yes"][crlf="yes"]>`
+
+The protocol dump curl should transmit to an HTTP proxy (when the http-proxy
+server is used), if `nonewline` is set, we will cut off the trailing newline
of this given data before comparing with the one actually sent by the client
The `<strip>` and `<strippart>` rules are applied before comparisons are made.
@@ -569,20 +606,23 @@
Use the mode="text" attribute if the output is in text mode on platforms that
have a text/binary difference.
-If 'nonewline' is set, we will cut off the trailing newline of this given data
+If `nonewline` is set, we will cut off the trailing newline of this given data
before comparing with the one actually received by the client
-### `<stdout [mode="text"] [nonewline="yes"]>`
+### `<stdout [mode="text"] [nonewline="yes"] [crlf="yes"]>`
This verifies that this data was passed to stdout.
Use the mode="text" attribute if the output is in text mode on platforms that
have a text/binary difference.
-If 'nonewline' is set, we will cut off the trailing newline of this given data
+If `nonewline` is set, we will cut off the trailing newline of this given data
before comparing with the one actually received by the client
-### `<file name="log/filename" [mode="text"]>`
-The file's contents must be identical to this after the test is complete. Use
+`crlf=yes` forces the newlines to become CRLF even if not written so in the
+test.
+
+### `<file name="%LOGDIR/filename" [mode="text"]>`
+The file's contents must be identical to this after the test is complete. Use
the mode="text" attribute if the output is in text mode on platforms that have
a text/binary difference.
@@ -601,7 +641,7 @@
advanced. Example: "s/^EPRT .*/EPRT stripped/"
### `<stripfile1>`
-1 to 4 can be appended to 'stripfile' to strip the corresponding <fileN>
+1 to 4 can be appended to `stripfile` to strip the corresponding <fileN>
content
### `<stripfile2>`
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 62d1ba3..7708132 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -26,15 +26,15 @@
PDFPAGES = testcurl.pdf runtests.pdf
MANDISTPAGES = runtests.1.dist testcurl.1.dist
-EXTRA_DIST = ftpserver.pl httpserver.pl secureserver.pl runtests.pl \
- getpart.pm FILEFORMAT.md README.md stunnel.pem memanalyze.pl testcurl.pl \
- valgrind.pm ftp.pm sshserver.pl sshhelp.pm pathhelp.pm testcurl.1 runtests.1 \
- serverhelp.pm tftpserver.pl rtspserver.pl directories.pm symbol-scan.pl \
- CMakeLists.txt mem-include-scan.pl valgrind.supp extern-scan.pl \
- manpage-scan.pl nroff-scan.pl http2-server.pl dictserver.py \
- negtelnetserver.py smbserver.py util.py \
- disable-scan.pl manpage-syntax.pl error-codes.pl badsymbols.pl \
- azure.pm appveyor.pm version-scan.pl options-scan.pl
+EXTRA_DIST = appveyor.pm azure.pm badsymbols.pl check-deprecated.pl CMakeLists.txt \
+ devtest.pl dictserver.py directories.pm disable-scan.pl error-codes.pl extern-scan.pl FILEFORMAT.md \
+ processhelp.pm ftpserver.pl getpart.pm globalconfig.pm http-server.pl http2-server.pl \
+ http3-server.pl manpage-scan.pl manpage-syntax.pl markdown-uppercase.pl mem-include-scan.pl \
+ memanalyze.pl negtelnetserver.py nroff-scan.pl option-check.pl options-scan.pl \
+ pathhelp.pm README.md rtspserver.pl runner.pm runtests.1 runtests.pl secureserver.pl \
+ serverhelp.pm servers.pm smbserver.py sshhelp.pm sshserver.pl stunnel.pem symbol-scan.pl \
+ testcurl.1 testcurl.pl testutil.pm tftpserver.pl util.py valgrind.pm \
+ valgrind.supp version-scan.pl
DISTCLEANFILES = configurehelp.pm
@@ -49,7 +49,7 @@
DIST_UNIT = unit
endif
-SUBDIRS = certs data server libtest $(BUILD_UNIT)
+SUBDIRS = certs data server libtest http $(BUILD_UNIT)
DIST_SUBDIRS = $(SUBDIRS) $(DIST_UNIT)
PERLFLAGS = -I$(srcdir)
@@ -75,7 +75,7 @@
TEST_NF = -a -p !flaky
# special CI target derived from nonflaky with CI-specific flags
-TEST_CI = $(TEST_NF) -r -rm
+TEST_CI = $(TEST_NF) -rm
endif
# make sure that PERL is pointing to an executable
@@ -120,6 +120,7 @@
cd libtest && $(MAKE) checksrc
cd unit && $(MAKE) checksrc
cd server && $(MAKE) checksrc
+ cd http && $(MAKE) checksrc
if CURLDEBUG
# for debug builds, we scan the sources on all regular make invokes
diff --git a/tests/README.md b/tests/README.md
index 2aa9f2b..86597d8 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 1998 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
@@ -16,7 +16,7 @@
- diff (when a test fails, a diff is shown)
- stunnel (for HTTPS and FTPS tests)
- OpenSSH or SunSSH (for SCP, SFTP and SOCKS4/5 tests)
- - nghttpx (for HTTP/2 tests)
+ - nghttpx (for HTTP/2 and HTTP/3 tests)
- nroff (for --manual tests)
- An available `en_US.UTF-8` locale
@@ -53,7 +53,7 @@
continue to work independent on what port numbers the test servers actually
use.
- See [FILEFORMAT](FILEFORMAT.md) for the port number variables.
+ See [`FILEFORMAT`](FILEFORMAT.md) for the port number variables.
### Test servers
@@ -69,6 +69,11 @@
The HTTP server supports listening on a Unix domain socket, the default
location is 'http.sock'.
+
+ For HTTP/2 and HTTP/3 testing an installed `nghttpx` is used. HTTP/3
+ tests check if nghttpx supports the protocol. To override the nghttpx
+ used, set the environment variable `NGHTTPX`. The default can also be
+ changed by specifying `--with-test-nghttpx=<path>` as argument to `configure`.
### Run
@@ -113,15 +118,15 @@
Tests which use the ssh test server, SCP/SFTP/SOCKS tests, might be badly
influenced by the output of system wide or user specific shell startup
scripts, .bashrc, .profile, /etc/csh.cshrc, .login, /etc/bashrc, etc. which
- output text messages or escape sequences on user login. When these shell
+ output text messages or escape sequences on user login. When these shell
startup messages or escape sequences are output they might corrupt the
expected stream of data which flows to the sftp-server or from the ssh
- client which can result in bad test behavior or even prevent the test
- server from running.
+ client which can result in bad test behavior or even prevent the test server
+ from running.
If the test suite ssh or sftp server fails to start up and logs the message
'Received message too long' then you are certainly suffering the unwanted
- output of a shell startup script. Locate, cleanup or adjust the shell
+ output of a shell startup script. Locate, cleanup or adjust the shell
script.
### Memory test
@@ -129,15 +134,15 @@
The test script will check that all allocated memory is freed properly IF
curl has been built with the `CURLDEBUG` define set. The script will
automatically detect if that is the case, and it will use the
- 'memanalyze.pl' script to analyze the memory debugging output.
+ `memanalyze.pl` script to analyze the memory debugging output.
Also, if you run tests on a machine where valgrind is found, the script will
use valgrind to run the test with (unless you use `-n`) to further verify
correctness.
- runtests.pl's `-t` option will enable torture testing mode, which runs each
+ The `runtests.pl` `-t` option enables torture testing mode. It runs each
test many times and makes each different memory allocation fail on each
- successive run. This tests the out of memory error handling code to ensure
+ successive run. This tests the out of memory error handling code to ensure
that memory leaks do not occur even in those situations. It can help to
compile curl with `CPPFLAGS=-DMEMDEBUG_LOG_SYNC` when using this option, to
ensure that the memory log file is properly written even if curl crashes.
@@ -145,48 +150,76 @@
### Debug
If a test case fails, you can conveniently get the script to invoke the
- debugger (gdb) for you with the server running and the exact same command
- line parameters that failed. Just invoke `runtests.pl <test number> -g` and
- then just type 'run' in the debugger to perform the command through the
- debugger.
+ debugger (gdb) for you with the server running and the same command line
+ parameters that failed. Just invoke `runtests.pl <test number> -g` and then
+ just type 'run' in the debugger to perform the command through the debugger.
### Logs
All logs are generated in the log/ subdirectory (it is emptied first in the
runtests.pl script). They remain in there after a test run.
+
+### Log Verbosity
+ A curl build with `--enable-debug` offers more verbose output in the logs.
+ This applies not only for test cases, but also when running it standalone
+ with `curl -v`. While a curl debug built is
+ ***not suitable for production***, it is often helpful in tracking down
+ problems.
+
+ Sometimes, one needs detailed logging of operations, but does not want
+ 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
+
+ will make 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
+
+ The order of filter type names is not relevant. Names used here are
+ case insensitive. Note that these names are implementation internals and
+ subject to change.
+
+ Some, likely stable names are `tcp`, `ssl`, `http/2`. For a current list,
+ one may search the sources for `struct Curl_cftype` definitions and find
+ the names there. Also, some filters are only available with certain build
+ options, of course.
+
### Test input files
All test cases are put in the `data/` subdirectory. Each test is stored in
the file named according to the test number.
- See [FILEFORMAT.md](FILEFORMAT.md) for a description of the test case file
+ See [`FILEFORMAT`](FILEFORMAT.md) for a description of the test case file
format.
### Code coverage
gcc provides a tool that can determine the code coverage figures for the
- test suite. To use it, configure curl with `CFLAGS='-fprofile-arcs
- -ftest-coverage -g -O0'`. Make sure you run the normal and torture tests to
+ test suite. To use it, configure curl with `CFLAGS='-fprofile-arcs
+ -ftest-coverage -g -O0'`. Make sure you run the normal and torture tests to
get more full coverage, i.e. do:
make test
make test-torture
- The graphical tool ggcov can be used to browse the source and create
+ The graphical tool `ggcov` can be used to browse the source and create
coverage reports on \*nix hosts:
ggcov -r lib src
- The text mode tool gcov may also be used, but it doesn't handle object files
- in more than one directory very well.
+ The text mode tool `gcov` may also be used, but it doesn't handle object
+ files in more than one directory correctly.
### Remote testing
The runtests.pl script provides some hooks to allow curl to be tested on a
- machine where perl can not be run. The test framework in this case runs on
+ machine where perl can not be run. The test framework in this case runs on
a workstation where perl is available, while curl itself is run on a remote
- system using ssh or some other remote execution method. See the comments at
+ system using ssh or some other remote execution method. See the comments at
the beginning of runtests.pl for details.
## Test case numbering
@@ -212,7 +245,7 @@
These files are `tests/data/test[num]` where `[num]` is just a unique
identifier described above, and the XML-like file format of them is
- described in the separate [FILEFORMAT.md](FILEFORMAT.md) document.
+ described in the separate [`FILEFORMAT`](FILEFORMAT.md) document.
### curl tests
diff --git a/tests/appveyor.pm b/tests/appveyor.pm
index 1821534..2a6a5d5 100644
--- a/tests/appveyor.pm
+++ b/tests/appveyor.pm
@@ -5,8 +5,8 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2020-2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-# Copyright (C) 2020-2022, Marc Hoersken, <info@marc-hoersken.de>
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Marc Hoersken, <info@marc-hoersken.de>
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,10 +23,23 @@
#
###########################################################################
+package appveyor;
+
use strict;
use warnings;
-my %APPVEYOR_TEST_NAMES;
+BEGIN {
+ use base qw(Exporter);
+
+ our @EXPORT = qw(
+ appveyor_check_environment
+ appveyor_create_test_result
+ appveyor_update_test_result
+ );
+}
+
+
+my %APPVEYOR_TEST_NAMES; # JSON and shell-quoted test names by test number
sub appveyor_check_environment {
if(defined $ENV{'APPVEYOR_API_URL'} && $ENV{'APPVEYOR_API_URL'}) {
@@ -38,20 +51,20 @@
sub appveyor_create_test_result {
my ($curl, $testnum, $testname)=@_;
$testname =~ s/\\/\\\\/g;
- $testname =~ s/\'/\\\'/g;
$testname =~ s/\"/\\\"/g;
+ $testname =~ s/\'/'"'"'/g;
my $appveyor_baseurl="$ENV{'APPVEYOR_API_URL'}";
- my $appveyor_result=`$curl --silent --noproxy "*" \\
- --header "Content-Type: application/json" \\
- --data "
+ my $appveyor_result=`$curl --silent --noproxy '*' \\
+ --header 'Content-Type: application/json' \\
+ --data '
{
- 'testName': '$testname',
- 'testFramework': 'runtests.pl',
- 'fileName': 'tests/data/test$testnum',
- 'outcome': 'Running'
+ "testName": "$testname",
+ "testFramework": "runtests.pl",
+ "fileName": "tests/data/test$testnum",
+ "outcome": "Running"
}
- " \\
- "$appveyor_baseurl/api/tests"`;
+ ' \\
+ '$appveyor_baseurl/api/tests'`;
print "AppVeyor API result: $appveyor_result\n" if ($appveyor_result);
$APPVEYOR_TEST_NAMES{$testnum}=$testname;
}
@@ -85,31 +98,31 @@
$appveyor_category = 'Error';
}
my $appveyor_baseurl="$ENV{'APPVEYOR_API_URL'}";
- my $appveyor_result=`$curl --silent --noproxy "*" --request PUT \\
- --header "Content-Type: application/json" \\
- --data "
+ my $appveyor_result=`$curl --silent --noproxy '*' --request PUT \\
+ --header 'Content-Type: application/json' \\
+ --data '
{
- 'testName': '$testname',
- 'testFramework': 'runtests.pl',
- 'fileName': 'tests/data/test$testnum',
- 'outcome': '$appveyor_outcome',
- 'durationMilliseconds': $appveyor_duration,
- 'ErrorMessage': 'Test $testnum $appveyor_outcome'
+ "testName": "$testname",
+ "testFramework": "runtests.pl",
+ "fileName": "tests/data/test$testnum",
+ "outcome": "$appveyor_outcome",
+ "durationMilliseconds": $appveyor_duration,
+ "ErrorMessage": "Test $testnum $appveyor_outcome"
}
- " \\
- "$appveyor_baseurl/api/tests"`;
+ ' \\
+ '$appveyor_baseurl/api/tests'`;
print "AppVeyor API result: $appveyor_result\n" if ($appveyor_result);
if($appveyor_category eq 'Error') {
- $appveyor_result=`$curl --silent --noproxy "*" \\
- --header "Content-Type: application/json" \\
- --data "
+ $appveyor_result=`$curl --silent --noproxy '*' \\
+ --header 'Content-Type: application/json' \\
+ --data '
{
- 'message': '$appveyor_outcome: $testname',
- 'category': '$appveyor_category',
- 'details': 'Test $testnum $appveyor_outcome'
+ "message": "$appveyor_outcome: $testname",
+ "category": "$appveyor_category",
+ "details": "Test $testnum $appveyor_outcome"
}
- " \\
- "$appveyor_baseurl/api/build/messages"`;
+ ' \\
+ '$appveyor_baseurl/api/build/messages'`;
print "AppVeyor API result: $appveyor_result\n" if ($appveyor_result);
}
}
diff --git a/tests/azure.pm b/tests/azure.pm
index e6d3bf8..2810f48 100644
--- a/tests/azure.pm
+++ b/tests/azure.pm
@@ -5,8 +5,8 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2020-2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-# Copyright (C) 2020-2022, Marc Hoersken, <info@marc-hoersken.de>
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Marc Hoersken, <info@marc-hoersken.de>
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,9 +23,23 @@
#
###########################################################################
+package azure;
+
use strict;
use warnings;
+BEGIN {
+ use base qw(Exporter);
+
+ our @EXPORT = qw(
+ azure_check_environment
+ azure_create_test_run
+ azure_create_test_result
+ azure_update_test_result
+ azure_update_test_run
+ );
+}
+
use POSIX qw(strftime);
sub azure_check_environment {
@@ -61,26 +75,26 @@
sub azure_create_test_result {
my ($curl, $azure_run_id, $testnum, $testname)=@_;
$testname =~ s/\\/\\\\/g;
- $testname =~ s/\'/\\\'/g;
$testname =~ s/\"/\\\"/g;
+ $testname =~ s/\'/'"'"'/g;
my $title_testnum=sprintf("%04d", $testnum);
my $azure_baseurl="$ENV{'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI'}$ENV{'SYSTEM_TEAMPROJECTID'}";
- my $azure_result=`$curl --silent --noproxy "*" \\
+ my $azure_result=`$curl --silent --noproxy '*' \\
--header "Authorization: Bearer $ENV{'AZURE_ACCESS_TOKEN'}" \\
- --header "Content-Type: application/json" \\
- --data "
+ --header 'Content-Type: application/json' \\
+ --data '
[
{
- 'build': {'id': '$ENV{'BUILD_BUILDID'}'},
- 'testCase': {'id': $testnum},
- 'testCaseTitle': '$title_testnum: $testname',
- 'testCaseRevision': 2,
- 'automatedTestName': 'curl.tests.$testnum',
- 'outcome': 'InProgress'
+ "build": {"id": "$ENV{'BUILD_BUILDID'}"},
+ "testCase": {"id": $testnum},
+ "testCaseTitle": "$title_testnum: $testname",
+ "testCaseRevision": 2,
+ "automatedTestName": "curl.tests.$testnum",
+ "outcome": "InProgress"
}
]
- " \\
- "$azure_baseurl/_apis/test/runs/$azure_run_id/results?api-version=5.1"`;
+ ' \\
+ '$azure_baseurl/_apis/test/runs/$azure_run_id/results?api-version=5.1'`;
if($azure_result =~ /\[\{"id":(\d+)/) {
return $1;
}
@@ -109,21 +123,21 @@
$azure_outcome = 'Failed';
}
my $azure_baseurl="$ENV{'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI'}$ENV{'SYSTEM_TEAMPROJECTID'}";
- my $azure_result=`$curl --silent --noproxy "*" --request PATCH \\
+ my $azure_result=`$curl --silent --noproxy '*' --request PATCH \\
--header "Authorization: Bearer $ENV{'AZURE_ACCESS_TOKEN'}" \\
--header "Content-Type: application/json" \\
- --data "
+ --data '
[
{
- 'id': $azure_result_id,
- 'outcome': '$azure_outcome',
- 'startedDate': '$azure_start',
- 'completedDate': '$azure_complete',
- 'durationInMs': $azure_duration
+ "id": $azure_result_id,
+ "outcome": "$azure_outcome",
+ "startedDate": "$azure_start",
+ "completedDate": "$azure_complete",
+ "durationInMs": $azure_duration
}
]
- " \\
- "$azure_baseurl/_apis/test/runs/$azure_run_id/results?api-version=5.1"`;
+ ' \\
+ '$azure_baseurl/_apis/test/runs/$azure_run_id/results?api-version=5.1'`;
if($azure_result =~ /\[\{"id":(\d+)/) {
return $1;
}
@@ -133,15 +147,15 @@
sub azure_update_test_run {
my ($curl, $azure_run_id)=@_;
my $azure_baseurl="$ENV{'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI'}$ENV{'SYSTEM_TEAMPROJECTID'}";
- my $azure_run=`$curl --silent --noproxy "*" --request PATCH \\
+ my $azure_run=`$curl --silent --noproxy '*' --request PATCH \\
--header "Authorization: Bearer $ENV{'AZURE_ACCESS_TOKEN'}" \\
- --header "Content-Type: application/json" \\
- --data "
+ --header 'Content-Type: application/json' \\
+ --data '
{
- 'state': 'Completed'
+ "state": "Completed"
}
- " \\
- "$azure_baseurl/_apis/test/runs/$azure_run_id?api-version=5.1"`;
+ ' \\
+ '$azure_baseurl/_apis/test/runs/$azure_run_id?api-version=5.1'`;
if($azure_run =~ /"id":(\d+)/) {
return $1;
}
diff --git a/tests/badsymbols.pl b/tests/badsymbols.pl
index 392b190..a3a39d4 100755
--- a/tests/badsymbols.pl
+++ b/tests/badsymbols.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2010-2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -74,7 +74,8 @@
my ($file)=@_;
my $skipit = 0;
- open H_IN, "-|", "$Cpreprocessor $i$file" || die "Cannot preprocess $file";
+ open H_IN, "-|", "$Cpreprocessor -DCURL_DISABLE_DEPRECATION $i$file" ||
+ die "Cannot preprocess $file";
while ( <H_IN> ) {
my ($line, $linenum) = ($_, $.);
if( /^#(line|) (\d+) \"(.*)\"/) {
@@ -102,6 +103,7 @@
if(($_ !~ /\}(;|)/) &&
($_ ne "typedef") &&
($_ ne "enum") &&
+ ($_ ne "=") &&
($_ !~ /^[ \t]*$/)) {
if($verbose) {
print "Source: $Cpreprocessor $i$file\n";
diff --git a/tests/certs/.gitignore b/tests/certs/.gitignore
new file mode 100644
index 0000000..f549fdf
--- /dev/null
+++ b/tests/certs/.gitignore
@@ -0,0 +1,10 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+EdelCurlRoot-*-ca.cacert
+EdelCurlRoot-ca.cnt
+EdelCurlRoot-ca.cnt.old
+EdelCurlRoot-ca.db
+EdelCurlRoot-ca.db.attr
+EdelCurlRoot-ca.db.attr.old
+EdelCurlRoot-ca.db.old
diff --git a/tests/certs/EdelCurlRoot-ca.cacert b/tests/certs/EdelCurlRoot-ca.cacert
index ac46717..4e191f5 100644
--- a/tests/certs/EdelCurlRoot-ca.cacert
+++ b/tests/certs/EdelCurlRoot-ca.cacert
@@ -1,41 +1,41 @@
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15373408817751 (0xdfb66925257)
+ Serial Number: 16717980969522 (0xf3475512a32)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = Northern Nowhere Trust Anchor
Validity
- Not Before: Sep 19 07:08:01 2018 GMT
- Not After : Feb 22 07:08:01 2035 GMT
+ Not Before: Dec 23 12:21:36 2022 GMT
+ Not After : May 28 12:21:36 2039 GMT
Subject:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = Northern Nowhere Trust Anchor
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:e1:4c:d9:74:1a:a4:a3:42:57:a4:7a:2e:74:02:
- 08:49:6a:6a:1d:db:de:c3:43:d6:48:60:12:30:ed:
- d6:6e:74:16:81:16:4e:50:b9:6c:b9:36:0d:19:a4:
- f7:85:99:40:46:26:46:33:86:ce:0c:27:71:e4:8f:
- 0f:b4:3a:99:6d:af:78:48:b7:cb:c4:d3:60:7d:d0:
- 17:6f:23:bc:89:c0:bc:16:b8:94:f0:b2:10:8d:c8:
- e0:35:97:ed:8f:c6:db:9b:cd:aa:f6:8c:45:dc:0f:
- ee:a0:78:12:be:f6:7d:f4:f7:b6:8c:4e:e5:7d:32:
- e8:f7:f7:1e:04:46:9e:08:cd:cb:ec:e2:9a:c3:35:
- 3f:ce:a1:01:e3:10:0a:ec:d9:ab:13:09:eb:e6:39:
- 6b:92:30:c7:08:bd:8a:32:ef:0b:b2:61:6f:11:43:
- 95:cf:31:ea:19:01:cc:1a:6d:d2:d5:57:35:da:c0:
- ae:46:39:d3:33:ed:f8:c0:1e:ad:3d:68:6f:a8:53:
- 24:ac:d6:f9:dd:2b:51:50:77:e4:b7:5d:ad:48:80:
- 5d:65:57:e5:eb:07:82:7d:cb:72:4f:06:6a:34:d4:
- 38:c8:6b:ed:8a:3a:68:5e:35:e3:78:14:da:5d:86:
- 9f:e5:d4:1c:dd:90:c2:7c:a2:00:d4:95:65:04:85:
- ff:83
+ 00:a1:d8:60:15:d1:5b:09:3b:d1:4e:79:40:0a:03:
+ 81:07:60:ba:6b:03:f4:87:4e:1e:e9:77:b1:ea:83:
+ 66:56:c4:6c:19:5e:cf:64:23:44:03:f5:d0:27:e1:
+ 1d:a5:05:dd:a5:f2:c1:9a:28:e2:31:66:a2:7b:e0:
+ 3b:bb:f3:b4:06:b4:43:97:7b:80:3c:96:1b:ed:85:
+ 7c:8b:2e:0f:62:b9:53:69:3d:2b:19:af:16:d3:e2:
+ a9:d3:2d:f2:ec:b1:31:76:2d:d9:78:67:91:ce:16:
+ 52:e3:68:34:f1:bc:f0:5e:99:bf:28:cf:91:88:31:
+ a6:48:cc:fb:84:a1:87:85:8b:08:18:eb:39:e9:34:
+ ee:1b:3a:a3:bd:2a:77:63:50:c8:88:6b:f1:d3:c4:
+ b7:25:db:7f:eb:b9:84:73:a8:86:8a:69:7d:40:5a:
+ c3:24:81:10:8d:97:ae:ce:45:eb:5d:fb:14:31:5b:
+ a1:c2:d1:aa:2f:44:a0:42:28:38:16:c7:42:1e:dd:
+ db:0f:a9:d9:70:25:cc:da:be:e9:8c:8c:84:48:a3:
+ ab:af:20:7a:7e:b3:09:a9:05:0d:ce:f8:9b:c2:77:
+ e8:82:f8:6a:56:21:db:92:a7:0a:3c:f1:0c:a0:d4:
+ 9c:8c:c0:62:2b:62:bc:5e:c4:ba:5e:3a:fc:1a:05:
+ 49:ef
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
@@ -43,42 +43,53 @@
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Subject Key Identifier:
- 12:CA:BA:4B:46:04:A7:75:8A:2C:E8:0E:54:94:BC:12:65:A6:7B:CE
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
+ X509v3 Authority Key Identifier:
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
Signature Algorithm: sha256WithRSAEncryption
- 2c:82:a4:ff:21:f3:fc:ba:6a:7a:11:b1:56:d4:9a:8f:4d:bf:
- 23:cf:d0:0b:d4:e2:6f:7a:a7:40:1a:c6:39:fa:db:ae:32:ab:
- 3d:bb:9f:45:d1:46:a5:95:27:3c:d4:89:d2:43:84:4c:43:70:
- ff:16:3c:a8:8c:e6:5c:0a:fb:20:1d:a7:c3:90:66:41:ef:be:
- 91:de:9d:9b:5d:1b:f1:59:44:d3:77:32:a3:6c:6e:24:a4:2d:
- a8:50:5f:86:81:47:fa:d7:80:a7:e7:fd:f2:00:bd:b8:cc:b5:
- 2f:cc:50:c7:46:74:3a:05:12:cc:e2:c4:d0:e6:b0:59:a1:16:
- 73:ff:3d:12:f5:89:be:95:cd:cc:43:22:3b:28:63:0d:9b:69:
- da:d3:28:75:55:97:3a:5d:be:2c:7d:30:67:77:4f:51:a0:b9:
- 07:18:9f:47:23:d6:73:dc:12:7f:0d:fa:2d:5a:d0:2a:89:0b:
- 29:dd:a6:ba:a0:a1:f5:13:e2:dd:48:e4:16:c7:d6:c3:68:2f:
- 4f:40:e5:da:cf:04:13:86:b5:10:83:fe:45:59:4d:92:3f:20:
- be:45:ca:b6:f7:cc:91:12:92:df:00:11:13:14:0b:61:9a:64:
- 92:50:f4:3f:74:5f:9e:24:ba:ff:cf:d7:16:51:c9:75:95:e9:
- 65:e9:8d:b4
+ Signature Value:
+ 86:19:bd:3d:12:4f:6b:8c:8e:1b:72:db:8f:9b:67:68:96:f8:
+ f4:ad:d9:a0:b5:48:0e:19:f6:34:09:92:a5:b8:ab:70:c6:6b:
+ 44:be:f7:fd:a4:75:ad:16:c4:ad:54:aa:c4:36:e6:86:87:84:
+ 0d:d9:1f:ea:b5:95:3a:69:60:02:2f:5c:a2:a3:1d:c9:28:f6:
+ 78:22:cd:e3:1d:47:37:a0:a0:a4:8a:3b:da:50:a9:12:e0:e4:
+ e7:1f:b6:bc:7e:e8:b6:a1:b7:99:9f:98:2c:c1:70:db:32:ea:
+ 82:45:ff:71:ea:36:34:65:bd:ad:cd:c5:2b:a2:a1:6b:2e:a3:
+ 30:b2:95:ea:77:a9:17:cf:bf:e4:df:4f:ef:6d:72:d0:a1:95:
+ c6:ef:e5:b8:70:0f:d2:82:b3:a7:54:4b:f7:2d:b9:2f:dc:37:
+ ff:f7:4d:26:b4:4b:6a:46:a3:f9:2c:ad:58:8c:96:e8:e6:a4:
+ aa:d0:c1:2d:35:db:b5:2f:ac:34:40:e3:7f:da:f7:34:f8:a2:
+ fd:6f:61:46:69:f0:24:20:32:f3:ad:e2:72:27:1a:58:a3:aa:
+ 77:4e:fa:06:5e:34:40:d3:50:39:66:29:f6:a6:f5:40:3a:af:
+ 97:23:19:cf:58:27:c9:8f:c4:b3:58:9e:87:78:2f:a7:24:9e:
+ 3e:5d:d1:52
-----BEGIN CERTIFICATE-----
-MIIDkjCCAnqgAwIBAgIGDftmklJXMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+MIIENDCCAxygAwIBAgIGDzR1USoyMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
-Fw0xODA5MTkwNzA4MDFaFw0zNTAyMjIwNzA4MDFaMGgxCzAJBgNVBAYTAk5OMTEw
+Fw0yMjEyMjMxMjIxMzZaFw0zOTA1MjgxMjIxMzZaMGgxCzAJBgNVBAYTAk5OMTEw
LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
MSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjCCASIwDQYJ
-KoZIhvcNAQEBBQADggEPADCCAQoCggEBAOFM2XQapKNCV6R6LnQCCElqah3b3sND
-1khgEjDt1m50FoEWTlC5bLk2DRmk94WZQEYmRjOGzgwnceSPD7Q6mW2veEi3y8TT
-YH3QF28jvInAvBa4lPCyEI3I4DWX7Y/G25vNqvaMRdwP7qB4Er72ffT3toxO5X0y
-6Pf3HgRGngjNy+zimsM1P86hAeMQCuzZqxMJ6+Y5a5Iwxwi9ijLvC7JhbxFDlc8x
-6hkBzBpt0tVXNdrArkY50zPt+MAerT1ob6hTJKzW+d0rUVB35LddrUiAXWVX5esH
-gn3Lck8GajTUOMhr7Yo6aF4143gU2l2Gn+XUHN2QwnyiANSVZQSF/4MCAwEAAaNC
-MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLK
-uktGBKd1iizoDlSUvBJlpnvOMA0GCSqGSIb3DQEBCwUAA4IBAQAsgqT/IfP8ump6
-EbFW1JqPTb8jz9AL1OJveqdAGsY5+tuuMqs9u59F0UallSc81InSQ4RMQ3D/Fjyo
-jOZcCvsgHafDkGZB776R3p2bXRvxWUTTdzKjbG4kpC2oUF+GgUf614Cn5/3yAL24
-zLUvzFDHRnQ6BRLM4sTQ5rBZoRZz/z0S9Ym+lc3MQyI7KGMNm2na0yh1VZc6Xb4s
-fTBnd09RoLkHGJ9HI9Zz3BJ/DfotWtAqiQsp3aa6oKH1E+LdSOQWx9bDaC9PQOXa
-zwQThrUQg/5FWU2SPyC+Rcq298yREpLfABETFAthmmSSUPQ/dF+eJLr/z9cWUcl1
-lell6Y20
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKHYYBXRWwk70U55QAoDgQdgumsD9IdO
+Hul3seqDZlbEbBlez2QjRAP10CfhHaUF3aXywZoo4jFmonvgO7vztAa0Q5d7gDyW
+G+2FfIsuD2K5U2k9KxmvFtPiqdMt8uyxMXYt2Xhnkc4WUuNoNPG88F6ZvyjPkYgx
+pkjM+4Shh4WLCBjrOek07hs6o70qd2NQyIhr8dPEtyXbf+u5hHOohoppfUBawySB
+EI2Xrs5F6137FDFbocLRqi9EoEIoOBbHQh7d2w+p2XAlzNq+6YyMhEijq68gen6z
+CakFDc74m8J36IL4alYh25KnCjzxDKDUnIzAYitivF7Eul46/BoFSe8CAwEAAaOB
+4zCB4DAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
+h8uxMy7BZ35x4+UrTE2ks27SW6kwHwYDVR0jBBgwFoAUh8uxMy7BZ35x4+UrTE2k
+s27SW6kwQwYIKwYBBQUHAQEENzA1MDMGCCsGAQUFBzAChidodHRwOi8vdGVzdC5j
+dXJsLnNlL2NhL0VkZWxDdXJsUm9vdC5jZXIwOAYDVR0fBDEwLzAtoCugKYYnaHR0
+cDovL3Rlc3QuY3VybC5zZS9jYS9FZGVsQ3VybFJvb3QuY3JsMA0GCSqGSIb3DQEB
+CwUAA4IBAQCGGb09Ek9rjI4bctuPm2dolvj0rdmgtUgOGfY0CZKluKtwxmtEvvf9
+pHWtFsStVKrENuaGh4QN2R/qtZU6aWACL1yiox3JKPZ4Is3jHUc3oKCkijvaUKkS
+4OTnH7a8fui2obeZn5gswXDbMuqCRf9x6jY0Zb2tzcUroqFrLqMwspXqd6kXz7/k
+30/vbXLQoZXG7+W4cA/SgrOnVEv3Lbkv3Df/900mtEtqRqP5LK1YjJbo5qSq0MEt
+Ndu1L6w0QON/2vc0+KL9b2FGafAkIDLzreJyJxpYo6p3TvoGXjRA01A5Zin2pvVA
+Oq+XIxnPWCfJj8SzWJ6HeC+nJJ4+XdFS
-----END CERTIFICATE-----
diff --git a/tests/certs/EdelCurlRoot-ca.cnf b/tests/certs/EdelCurlRoot-ca.cnf
index ba99881..b8c630b 100644
--- a/tests/certs/EdelCurlRoot-ca.cnf
+++ b/tests/certs/EdelCurlRoot-ca.cnf
@@ -6,6 +6,6 @@
certificate = EdelCurlRoot-ca.crt
private_key = EdelCurlRoot-ca.key
crlnumber = EdelCurlRoot-ca.cnt
-default_md = sha1
+default_md = sha256
default_days = 365
default_crl_days = 30
diff --git a/tests/certs/EdelCurlRoot-ca.crt b/tests/certs/EdelCurlRoot-ca.crt
index ac46717..4e191f5 100644
--- a/tests/certs/EdelCurlRoot-ca.crt
+++ b/tests/certs/EdelCurlRoot-ca.crt
@@ -1,41 +1,41 @@
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15373408817751 (0xdfb66925257)
+ Serial Number: 16717980969522 (0xf3475512a32)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = Northern Nowhere Trust Anchor
Validity
- Not Before: Sep 19 07:08:01 2018 GMT
- Not After : Feb 22 07:08:01 2035 GMT
+ Not Before: Dec 23 12:21:36 2022 GMT
+ Not After : May 28 12:21:36 2039 GMT
Subject:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = Northern Nowhere Trust Anchor
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:e1:4c:d9:74:1a:a4:a3:42:57:a4:7a:2e:74:02:
- 08:49:6a:6a:1d:db:de:c3:43:d6:48:60:12:30:ed:
- d6:6e:74:16:81:16:4e:50:b9:6c:b9:36:0d:19:a4:
- f7:85:99:40:46:26:46:33:86:ce:0c:27:71:e4:8f:
- 0f:b4:3a:99:6d:af:78:48:b7:cb:c4:d3:60:7d:d0:
- 17:6f:23:bc:89:c0:bc:16:b8:94:f0:b2:10:8d:c8:
- e0:35:97:ed:8f:c6:db:9b:cd:aa:f6:8c:45:dc:0f:
- ee:a0:78:12:be:f6:7d:f4:f7:b6:8c:4e:e5:7d:32:
- e8:f7:f7:1e:04:46:9e:08:cd:cb:ec:e2:9a:c3:35:
- 3f:ce:a1:01:e3:10:0a:ec:d9:ab:13:09:eb:e6:39:
- 6b:92:30:c7:08:bd:8a:32:ef:0b:b2:61:6f:11:43:
- 95:cf:31:ea:19:01:cc:1a:6d:d2:d5:57:35:da:c0:
- ae:46:39:d3:33:ed:f8:c0:1e:ad:3d:68:6f:a8:53:
- 24:ac:d6:f9:dd:2b:51:50:77:e4:b7:5d:ad:48:80:
- 5d:65:57:e5:eb:07:82:7d:cb:72:4f:06:6a:34:d4:
- 38:c8:6b:ed:8a:3a:68:5e:35:e3:78:14:da:5d:86:
- 9f:e5:d4:1c:dd:90:c2:7c:a2:00:d4:95:65:04:85:
- ff:83
+ 00:a1:d8:60:15:d1:5b:09:3b:d1:4e:79:40:0a:03:
+ 81:07:60:ba:6b:03:f4:87:4e:1e:e9:77:b1:ea:83:
+ 66:56:c4:6c:19:5e:cf:64:23:44:03:f5:d0:27:e1:
+ 1d:a5:05:dd:a5:f2:c1:9a:28:e2:31:66:a2:7b:e0:
+ 3b:bb:f3:b4:06:b4:43:97:7b:80:3c:96:1b:ed:85:
+ 7c:8b:2e:0f:62:b9:53:69:3d:2b:19:af:16:d3:e2:
+ a9:d3:2d:f2:ec:b1:31:76:2d:d9:78:67:91:ce:16:
+ 52:e3:68:34:f1:bc:f0:5e:99:bf:28:cf:91:88:31:
+ a6:48:cc:fb:84:a1:87:85:8b:08:18:eb:39:e9:34:
+ ee:1b:3a:a3:bd:2a:77:63:50:c8:88:6b:f1:d3:c4:
+ b7:25:db:7f:eb:b9:84:73:a8:86:8a:69:7d:40:5a:
+ c3:24:81:10:8d:97:ae:ce:45:eb:5d:fb:14:31:5b:
+ a1:c2:d1:aa:2f:44:a0:42:28:38:16:c7:42:1e:dd:
+ db:0f:a9:d9:70:25:cc:da:be:e9:8c:8c:84:48:a3:
+ ab:af:20:7a:7e:b3:09:a9:05:0d:ce:f8:9b:c2:77:
+ e8:82:f8:6a:56:21:db:92:a7:0a:3c:f1:0c:a0:d4:
+ 9c:8c:c0:62:2b:62:bc:5e:c4:ba:5e:3a:fc:1a:05:
+ 49:ef
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
@@ -43,42 +43,53 @@
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Subject Key Identifier:
- 12:CA:BA:4B:46:04:A7:75:8A:2C:E8:0E:54:94:BC:12:65:A6:7B:CE
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
+ X509v3 Authority Key Identifier:
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
Signature Algorithm: sha256WithRSAEncryption
- 2c:82:a4:ff:21:f3:fc:ba:6a:7a:11:b1:56:d4:9a:8f:4d:bf:
- 23:cf:d0:0b:d4:e2:6f:7a:a7:40:1a:c6:39:fa:db:ae:32:ab:
- 3d:bb:9f:45:d1:46:a5:95:27:3c:d4:89:d2:43:84:4c:43:70:
- ff:16:3c:a8:8c:e6:5c:0a:fb:20:1d:a7:c3:90:66:41:ef:be:
- 91:de:9d:9b:5d:1b:f1:59:44:d3:77:32:a3:6c:6e:24:a4:2d:
- a8:50:5f:86:81:47:fa:d7:80:a7:e7:fd:f2:00:bd:b8:cc:b5:
- 2f:cc:50:c7:46:74:3a:05:12:cc:e2:c4:d0:e6:b0:59:a1:16:
- 73:ff:3d:12:f5:89:be:95:cd:cc:43:22:3b:28:63:0d:9b:69:
- da:d3:28:75:55:97:3a:5d:be:2c:7d:30:67:77:4f:51:a0:b9:
- 07:18:9f:47:23:d6:73:dc:12:7f:0d:fa:2d:5a:d0:2a:89:0b:
- 29:dd:a6:ba:a0:a1:f5:13:e2:dd:48:e4:16:c7:d6:c3:68:2f:
- 4f:40:e5:da:cf:04:13:86:b5:10:83:fe:45:59:4d:92:3f:20:
- be:45:ca:b6:f7:cc:91:12:92:df:00:11:13:14:0b:61:9a:64:
- 92:50:f4:3f:74:5f:9e:24:ba:ff:cf:d7:16:51:c9:75:95:e9:
- 65:e9:8d:b4
+ Signature Value:
+ 86:19:bd:3d:12:4f:6b:8c:8e:1b:72:db:8f:9b:67:68:96:f8:
+ f4:ad:d9:a0:b5:48:0e:19:f6:34:09:92:a5:b8:ab:70:c6:6b:
+ 44:be:f7:fd:a4:75:ad:16:c4:ad:54:aa:c4:36:e6:86:87:84:
+ 0d:d9:1f:ea:b5:95:3a:69:60:02:2f:5c:a2:a3:1d:c9:28:f6:
+ 78:22:cd:e3:1d:47:37:a0:a0:a4:8a:3b:da:50:a9:12:e0:e4:
+ e7:1f:b6:bc:7e:e8:b6:a1:b7:99:9f:98:2c:c1:70:db:32:ea:
+ 82:45:ff:71:ea:36:34:65:bd:ad:cd:c5:2b:a2:a1:6b:2e:a3:
+ 30:b2:95:ea:77:a9:17:cf:bf:e4:df:4f:ef:6d:72:d0:a1:95:
+ c6:ef:e5:b8:70:0f:d2:82:b3:a7:54:4b:f7:2d:b9:2f:dc:37:
+ ff:f7:4d:26:b4:4b:6a:46:a3:f9:2c:ad:58:8c:96:e8:e6:a4:
+ aa:d0:c1:2d:35:db:b5:2f:ac:34:40:e3:7f:da:f7:34:f8:a2:
+ fd:6f:61:46:69:f0:24:20:32:f3:ad:e2:72:27:1a:58:a3:aa:
+ 77:4e:fa:06:5e:34:40:d3:50:39:66:29:f6:a6:f5:40:3a:af:
+ 97:23:19:cf:58:27:c9:8f:c4:b3:58:9e:87:78:2f:a7:24:9e:
+ 3e:5d:d1:52
-----BEGIN CERTIFICATE-----
-MIIDkjCCAnqgAwIBAgIGDftmklJXMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+MIIENDCCAxygAwIBAgIGDzR1USoyMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
-Fw0xODA5MTkwNzA4MDFaFw0zNTAyMjIwNzA4MDFaMGgxCzAJBgNVBAYTAk5OMTEw
+Fw0yMjEyMjMxMjIxMzZaFw0zOTA1MjgxMjIxMzZaMGgxCzAJBgNVBAYTAk5OMTEw
LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
MSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjCCASIwDQYJ
-KoZIhvcNAQEBBQADggEPADCCAQoCggEBAOFM2XQapKNCV6R6LnQCCElqah3b3sND
-1khgEjDt1m50FoEWTlC5bLk2DRmk94WZQEYmRjOGzgwnceSPD7Q6mW2veEi3y8TT
-YH3QF28jvInAvBa4lPCyEI3I4DWX7Y/G25vNqvaMRdwP7qB4Er72ffT3toxO5X0y
-6Pf3HgRGngjNy+zimsM1P86hAeMQCuzZqxMJ6+Y5a5Iwxwi9ijLvC7JhbxFDlc8x
-6hkBzBpt0tVXNdrArkY50zPt+MAerT1ob6hTJKzW+d0rUVB35LddrUiAXWVX5esH
-gn3Lck8GajTUOMhr7Yo6aF4143gU2l2Gn+XUHN2QwnyiANSVZQSF/4MCAwEAAaNC
-MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLK
-uktGBKd1iizoDlSUvBJlpnvOMA0GCSqGSIb3DQEBCwUAA4IBAQAsgqT/IfP8ump6
-EbFW1JqPTb8jz9AL1OJveqdAGsY5+tuuMqs9u59F0UallSc81InSQ4RMQ3D/Fjyo
-jOZcCvsgHafDkGZB776R3p2bXRvxWUTTdzKjbG4kpC2oUF+GgUf614Cn5/3yAL24
-zLUvzFDHRnQ6BRLM4sTQ5rBZoRZz/z0S9Ym+lc3MQyI7KGMNm2na0yh1VZc6Xb4s
-fTBnd09RoLkHGJ9HI9Zz3BJ/DfotWtAqiQsp3aa6oKH1E+LdSOQWx9bDaC9PQOXa
-zwQThrUQg/5FWU2SPyC+Rcq298yREpLfABETFAthmmSSUPQ/dF+eJLr/z9cWUcl1
-lell6Y20
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKHYYBXRWwk70U55QAoDgQdgumsD9IdO
+Hul3seqDZlbEbBlez2QjRAP10CfhHaUF3aXywZoo4jFmonvgO7vztAa0Q5d7gDyW
+G+2FfIsuD2K5U2k9KxmvFtPiqdMt8uyxMXYt2Xhnkc4WUuNoNPG88F6ZvyjPkYgx
+pkjM+4Shh4WLCBjrOek07hs6o70qd2NQyIhr8dPEtyXbf+u5hHOohoppfUBawySB
+EI2Xrs5F6137FDFbocLRqi9EoEIoOBbHQh7d2w+p2XAlzNq+6YyMhEijq68gen6z
+CakFDc74m8J36IL4alYh25KnCjzxDKDUnIzAYitivF7Eul46/BoFSe8CAwEAAaOB
+4zCB4DAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
+h8uxMy7BZ35x4+UrTE2ks27SW6kwHwYDVR0jBBgwFoAUh8uxMy7BZ35x4+UrTE2k
+s27SW6kwQwYIKwYBBQUHAQEENzA1MDMGCCsGAQUFBzAChidodHRwOi8vdGVzdC5j
+dXJsLnNlL2NhL0VkZWxDdXJsUm9vdC5jZXIwOAYDVR0fBDEwLzAtoCugKYYnaHR0
+cDovL3Rlc3QuY3VybC5zZS9jYS9FZGVsQ3VybFJvb3QuY3JsMA0GCSqGSIb3DQEB
+CwUAA4IBAQCGGb09Ek9rjI4bctuPm2dolvj0rdmgtUgOGfY0CZKluKtwxmtEvvf9
+pHWtFsStVKrENuaGh4QN2R/qtZU6aWACL1yiox3JKPZ4Is3jHUc3oKCkijvaUKkS
+4OTnH7a8fui2obeZn5gswXDbMuqCRf9x6jY0Zb2tzcUroqFrLqMwspXqd6kXz7/k
+30/vbXLQoZXG7+W4cA/SgrOnVEv3Lbkv3Df/900mtEtqRqP5LK1YjJbo5qSq0MEt
+Ndu1L6w0QON/2vc0+KL9b2FGafAkIDLzreJyJxpYo6p3TvoGXjRA01A5Zin2pvVA
+Oq+XIxnPWCfJj8SzWJ6HeC+nJJ4+XdFS
-----END CERTIFICATE-----
diff --git a/tests/certs/EdelCurlRoot-ca.csr b/tests/certs/EdelCurlRoot-ca.csr
index 7d5e300..2eeb6f0 100644
--- a/tests/certs/EdelCurlRoot-ca.csr
+++ b/tests/certs/EdelCurlRoot-ca.csr
@@ -2,16 +2,16 @@
MIICrTCCAZUCAQAwaDELMAkGA1UEBhMCTk4xMTAvBgNVBAoMKEVkZWwgQ3VybCBB
cmN0aWMgSWxsdWRpdW0gUmVzZWFyY2ggQ2xvdWQxJjAkBgNVBAMMHU5vcnRoZXJu
IE5vd2hlcmUgVHJ1c3QgQW5jaG9yMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEA4UzZdBqko0JXpHoudAIISWpqHdvew0PWSGASMO3WbnQWgRZOULlsuTYN
-GaT3hZlARiZGM4bODCdx5I8PtDqZba94SLfLxNNgfdAXbyO8icC8FriU8LIQjcjg
-NZftj8bbm82q9oxF3A/uoHgSvvZ99Pe2jE7lfTLo9/ceBEaeCM3L7OKawzU/zqEB
-4xAK7NmrEwnr5jlrkjDHCL2KMu8LsmFvEUOVzzHqGQHMGm3S1Vc12sCuRjnTM+34
-wB6tPWhvqFMkrNb53StRUHfkt12tSIBdZVfl6weCfctyTwZqNNQ4yGvtijpoXjXj
-eBTaXYaf5dQc3ZDCfKIA1JVlBIX/gwIDAQABoAAwDQYJKoZIhvcNAQELBQADggEB
-ANpolqnyNQ2zhqURf1ImBOTKLqN77neGe01rdkMrQfNP+ZSr5pxcoOZgMjUGrhyQ
-C6RWexcjwMFvr+16bsEyiBgw/PxTziw6ozvJZkDVQanKZet9+6o8P6AzfjOfwIiU
-8OkLYDaNJ0M807fTNFWdt/yDY1WNfNAxIX3gMMJ1dRvvLvgIJVE4RRAaW/pEMHky
-sQTfExs99Xooqh3E6CWyR1bVHWuid0a02LcD2Q0bKTBmi3xyBjEaq3vXxS6j1fDs
-aWpwznwuuX+J7K+MHYJH9DQIg/QY6rQzxokZ92wJGFdzL3m+kou6++OAPu1plpTL
-im5n/e87gdjerEJgCqoP4S8=
+CgKCAQEAodhgFdFbCTvRTnlACgOBB2C6awP0h04e6Xex6oNmVsRsGV7PZCNEA/XQ
+J+EdpQXdpfLBmijiMWaie+A7u/O0BrRDl3uAPJYb7YV8iy4PYrlTaT0rGa8W0+Kp
+0y3y7LExdi3ZeGeRzhZS42g08bzwXpm/KM+RiDGmSMz7hKGHhYsIGOs56TTuGzqj
+vSp3Y1DIiGvx08S3Jdt/67mEc6iGiml9QFrDJIEQjZeuzkXrXfsUMVuhwtGqL0Sg
+Qig4FsdCHt3bD6nZcCXM2r7pjIyESKOrryB6frMJqQUNzvibwnfogvhqViHbkqcK
+PPEMoNScjMBiK2K8XsS6Xjr8GgVJ7wIDAQABoAAwDQYJKoZIhvcNAQELBQADggEB
+AGRzOAmRFC2HX9tV94v7PxAPLY8LC5IsCdk2E07gQ76kWU8B0qd3Okx970O6d9Iw
+jy27At8CIFmCwdiNpOfLv1uqtbBgitxRX6FfciN5Lu0D1wxICc2gX7tDgqLhrT8E
+fp8q7/F//UPT04l5B6b+2h210Rkzjs/EmjQt2cFGjQpGSy8nb1ey3/W91NAej7Aq
+Hrp3/64hC+0QZMpgYQpYx65LYOST+U8lnDbrlcRUQqkUmGidwbYqGQMv+Tk5TKjL
+zMOjuu/I6stoGSJGJvhrfToZazG0u9tT+sXQdbi3emXVP1tMVpkhOYvKaaCno9QR
+RREL1l6yq15NUoT030u7pvs=
-----END CERTIFICATE REQUEST-----
diff --git a/tests/certs/EdelCurlRoot-ca.der b/tests/certs/EdelCurlRoot-ca.der
index f95f7e8..9a4e2ef 100644
--- a/tests/certs/EdelCurlRoot-ca.der
+++ b/tests/certs/EdelCurlRoot-ca.der
Binary files differ
diff --git a/tests/certs/EdelCurlRoot-ca.key b/tests/certs/EdelCurlRoot-ca.key
index bf46d1e..624ab3f 100644
--- a/tests/certs/EdelCurlRoot-ca.key
+++ b/tests/certs/EdelCurlRoot-ca.key
@@ -1,27 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEA4UzZdBqko0JXpHoudAIISWpqHdvew0PWSGASMO3WbnQWgRZO
-ULlsuTYNGaT3hZlARiZGM4bODCdx5I8PtDqZba94SLfLxNNgfdAXbyO8icC8FriU
-8LIQjcjgNZftj8bbm82q9oxF3A/uoHgSvvZ99Pe2jE7lfTLo9/ceBEaeCM3L7OKa
-wzU/zqEB4xAK7NmrEwnr5jlrkjDHCL2KMu8LsmFvEUOVzzHqGQHMGm3S1Vc12sCu
-RjnTM+34wB6tPWhvqFMkrNb53StRUHfkt12tSIBdZVfl6weCfctyTwZqNNQ4yGvt
-ijpoXjXjeBTaXYaf5dQc3ZDCfKIA1JVlBIX/gwIDAQABAoIBAQDGGcWGgjrLVnUr
-qUcZOARDUW9XK9IWjZpn7xlvrmECo8552Lwp3LDNtcoVB2mhLhxG0jad7eVU6IYL
-ewNK7M+lk0lHX1yrh1Trq0I/tgN8eFyp+cj0Tw2hLcR/O0RmTGsi9tdhi/uNQPEI
-ZivNf31HHVyEyIae7FnOVpotFk6022EElQd8F8GeeKpo9pQs8sHAVOUVC8Mf2sr+
-bFyo9nzU0XkSay72ozU9O5Iw2d5aVrN5f3NS+JG9OpzvouNwkaAMOUsLVvZlUTqY
-0ve5CY2rB3D72h4GJfM2aHi8hwj56yBOsyIhBSXNYJM8nXKEbJaK5ulVv/a7KKTk
-KzSdk/mJAoGBAPXPLLJgx0mZKXNXqSvSsvgVzcpLrJh8figoF4rMzq8+5bN9Y6KU
-Lvb2ODIm/oGCIiGDdFTYqBJ0/EpauaAJgdzIwYnMZXmVB97pmwni9KrDPDwWTOqS
-3Yzh0t4C8DAgwZE4X6Ad/fmn7V06dfJZZJynL9exPp8RF7ptJ2yOnlbdAoGBAOqk
-AfRWuPGeZL9rFkd45+j03MDHglE2xKhsbRobHANItHo7r26D/Ov7QkM+lGlqdrNg
-tTPPtHs50Ek+Sb0X31/Fj45IqQroxctpbZAaJchVl88tvKXA8fkk14a9GLiow3Bk
-UGA5DFRmsIMXEengzRJoxcHAbbciGWdeSneH49nfAoGAVMypHcyXU8Ob8ieuu+iP
-R1i2SvC6VUy1dQMHxCGNuBVZxwcd5Ut7vEUK8/pR2LndLnScIF0x9lQXaUtNOHGv
-NEypv/EcnMoWEgfDLbD3OSXrVMtYs6ABAIYzadXXqLLUNFYfXyyZnpQZJg1x/S5r
-sENZFO8XrGaIKg9YB3JYG50CgYBUQweMpmQOKNKHRz6d9hZaOyzXcg4jeiaPUTiw
-6lFaAI8HYk2yw2VdnUKDgYKshJYR/sWz0IBAzFc3Jk42wM7vxrOx5fgGuebmEHtP
-B4TP96TnusYHRE3hKdDYSyoIjlp5Dx0qIPKDkMkMmolNUvRyCvwRgzgjTvSOgXb+
-i+dQQwKBgQCKn04xYbhkMOiHxNP/DUf6+XmV1V7KbpjIySychbxcTKCV98c9q491
-YjF8FJgi2JdV5XOHWaKti2Qg/tYz7CBtqkQdeNjtfKkOUA8ZyZeiNZdPIza9tzmr
-t6mCthH1oT3jyiddhSYxyfUBW3olPhBPj8YBblmq1QHE8y2j3CNjvw==
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCh2GAV0VsJO9FO
+eUAKA4EHYLprA/SHTh7pd7Hqg2ZWxGwZXs9kI0QD9dAn4R2lBd2l8sGaKOIxZqJ7
+4Du787QGtEOXe4A8lhvthXyLLg9iuVNpPSsZrxbT4qnTLfLssTF2Ldl4Z5HOFlLj
+aDTxvPBemb8oz5GIMaZIzPuEoYeFiwgY6znpNO4bOqO9KndjUMiIa/HTxLcl23/r
+uYRzqIaKaX1AWsMkgRCNl67ORetd+xQxW6HC0aovRKBCKDgWx0Ie3dsPqdlwJcza
+vumMjIRIo6uvIHp+swmpBQ3O+JvCd+iC+GpWIduSpwo88Qyg1JyMwGIrYrxexLpe
+OvwaBUnvAgMBAAECggEADFrjQucfhv3tBYuWCu2njPOiZ4b+xNF+5J3BlECBsIAA
+LJOjS2axy4eZY2H5DF79Q6zbgLQ8SD8oikJc7QU2qgha3JaN/JINAb3d+xYCEKxL
+JM6JmsVV/cjg5AEu+UixmO75Ggr2A4CKxVdwK0AcLWyZPjlSR85aflY/oSlfmh8a
+txULdID0fH+/tIVQE/xlS9M8xfHxqQQyoBsWkwPPcxhgPRgPpTxo/a12iZk2z+lV
+F/1TZxyb0MWRktVgHQwhmXSnEguosspjk6fqDXwM14WJLQA1XdFdblI3aiHmlc5h
+qanreSsaUgYsV1WvVxh1qfoljm6pUzoYvOChdz62SQKBgQDiavOlubV+kgFU4he+
+LzdaZJUlq6JO4dbbcgE4lZBnoJp2Ga5V1OvBnBcrdtiHO46V2Durq66YHa/tZfTN
+6RlA6GyPVLb6qlwbCYUnpSfuwIVJx7Zty7FrnOn9oRlwLpQQMG4AOsS3E+JY1vQZ
+9+8htuT9OprjY2Mx6wLm2EuZ3QKBgQC2/aZll+nRMerAsZLsTm1idkvxztvDPyoQ
+yQwGlDy79OvezjzXEAczGk/XDSRnGIptZQacxw5z/Lw8IHaaTp7GPFBrD7Lr84dc
+QopdLqqeQJ2n7WGjmJ3gLJCp7NHHP+xDkipc2Xq+nFGlS+PxVzB0hOq3wQdPV54e
+h+x9CNDkOwKBgA3TfiFmn8Ck5dPrIowIkhbBAaKVQooSnG42HgD4kSLi2cvQcabo
+I6VlBL0wurQ3XNOlqq8nArhjR7T1fud8DoC6MLbn82yHLqyv/iOXoEKiGwGQYoF9
+6M2rfVZxmf4RuhTrACyfahfL7QyDw9A6Ja4nXwBfrcmo7gvEUB8MokE5AoGBAKbY
+sZ5SG/wE4oGdp1PU0oGDUQ2CSfhFIGq7lT5ubM4HrASz0N9amuXqaL+xGO7zfkvu
+YFAUY0Y4O70q8FkTtEsVdVGYt8/RdSsW9KevxBuU2OrjUzJiFhjvKVv2NPPSge6+
+V+fe177yMrNfdc94axLimky/MJYUUnSOBH+gyS4/AoGBALJt7WqFnb3iazOgVUDd
+ZGOJUuBnlgS6MK/YxP+8csq+MPnGVVGruXx72hzWe3bJ8QM16QvHUPC9RNgnclXB
+Ekx45SNSG1g//rxHwCJAgcTlnhiTZQ21Fn3V2EckjOa/Z4udk/7PxFRto1beNznK
+nW2eB0xvsK+qq5yc3TQClWgc
+-----END PRIVATE KEY-----
diff --git a/tests/certs/EdelCurlRoot-ca.prm b/tests/certs/EdelCurlRoot-ca.prm
index 2e81047..c8e248b 100644
--- a/tests/certs/EdelCurlRoot-ca.prm
+++ b/tests/certs/EdelCurlRoot-ca.prm
@@ -15,3 +15,16 @@
basicConstraints = critical,CA:true
keyUsage = critical,keyCertSign,cRLSign
subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
\ No newline at end of file
diff --git a/tests/certs/Makefile.am b/tests/certs/Makefile.am
index 0563e07..e21cdd5 100644
--- a/tests/certs/Makefile.am
+++ b/tests/certs/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -30,7 +30,10 @@
EdelCurlRoot-ca.cnf \
Server-localhost-sv.prm \
Server-localhost.nn-sv.prm \
- Server-localhost0h-sv.prm
+ Server-localhost0h-sv.prm \
+ Server-localhost-firstSAN-sv.prm \
+ Server-localhost-lastSAN-sv.prm \
+ stunnel-sv.prm
GENERATEDCERTS = \
EdelCurlRoot-ca.cacert \
@@ -82,7 +85,16 @@
Server-localhost-lastSAN-sv.key \
Server-localhost-lastSAN-sv.pem \
Server-localhost-lastSAN-sv.pub.der \
- Server-localhost-lastSAN-sv.pub.pem
+ Server-localhost-lastSAN-sv.pub.pem \
+ stunnel-sv.crl \
+ stunnel-sv.crt \
+ stunnel-sv.csr \
+ stunnel-sv.der \
+ stunnel-sv.dhp \
+ stunnel-sv.key \
+ stunnel-sv.pem \
+ stunnel-sv.der \
+ stunnel-sv.pub.pem
SRPFILES = \
srp-verifier-conf \
@@ -97,7 +109,8 @@
build-certs: $(srcdir)/EdelCurlRoot-ca.cacert $(srcdir)/Server-localhost-sv.pem \
$(srcdir)/Server-localhost.nn-sv.pem $(srcdir)/Server-localhost0h-sv.pem \
- $(srcdir)/Server-localhost-firstSAN-sv.pem $(srcdir)/Server-localhost-lastSAN-sv.pem
+ $(srcdir)/Server-localhost-firstSAN-sv.pem $(srcdir)/Server-localhost-lastSAN-sv.pem \
+ $(srcdir)/stunnel-sv.pem ../stunnel.pem
$(srcdir)/EdelCurlRoot-ca.cacert:
cd $(srcdir); scripts/genroot.sh EdelCurlRoot
@@ -115,4 +128,10 @@
cd $(srcdir); scripts/genserv.sh Server-localhost-firstSAN EdelCurlRoot
$(srcdir)/Server-localhost-lastSAN-sv.pem: $(srcdir)/EdelCurlRoot-ca.cacert
- cd $(srcdir); scripts/genserv.sh Server-localhost-firstSAN EdelCurlRoot
+ cd $(srcdir); scripts/genserv.sh Server-localhost-lastSAN EdelCurlRoot
+
+$(srcdir)/stunnel-sv.pem: $(srcdir)/EdelCurlRoot-ca.cacert
+ cd $(srcdir); scripts/genserv.sh stunnel EdelCurlRoot
+
+../stunnel.pem: $(srcdir)/stunnel-sv.pem
+ cp $< $@
diff --git a/tests/certs/Server-localhost-firstSAN-sv.crl b/tests/certs/Server-localhost-firstSAN-sv.crl
index 66b2ad4..1944a4a 100644
--- a/tests/certs/Server-localhost-firstSAN-sv.crl
+++ b/tests/certs/Server-localhost-firstSAN-sv.crl
@@ -1,15 +1,14 @@
-----BEGIN X509 CRL-----
-MIICQTCCASkCAQEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCTk4xMTAvBgNV
+MIICKDCCARACAQEwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UEBhMCTk4xMTAvBgNV
BAoMKEVkZWwgQ3VybCBBcmN0aWMgSWxsdWRpdW0gUmVzZWFyY2ggQ2xvdWQxJjAk
-BgNVBAMMHU5vcnRoZXJuIE5vd2hlcmUgVHJ1c3QgQW5jaG9yFw0xODA5MTkwNzE0
-NDhaFw0xODEwMTkwNzE0NDhaMH0wFwIGDftmwfBTFw0xODA5MTkwNzEzMTRaMBcC
-Bg37ZsrxnhcNMTgwOTE5MDcxNDEyWjAXAgYN+2bMn24XDTE4MDkxOTA3MTQyM1ow
-FwIGDftmzumEFw0xODA5MTkwNzE0MzhaMBcCBg37ZtBwRBcNMTgwOTE5MDcxNDQ4
-WqAOMAwwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADggEBAA0CKirTrPR1TyFP
-60Z0iW6b7zZFRIiRt+HBOntYdWLFUin1TpbDAGh3ddUPgQ0eGNuvnDA2FZLP787S
-JhXr65bonMEe7p17Cbh2swycdAuQsMYP6lFg1aIdjXB9/g+unG7KsB16BGYzalOs
-4crSfP6Z11JnFFmVp9jOOwL65to/3GQwVxfWamEKDFOMrPba6dkTAU9+OCV1CZYd
-anEjWrewmTj8nD7nb5fZ3fRQPVvwLbtkoGFmSHg8Qy9uDBGdRrw0V2w+ntkQMIJ9
-ILhQZDcaIN4MsnBTn/esrfvFVKomf9i78SCEhRvmTWmpYasI4oJzfmlLb1Dh6JPG
-59JdagI=
+BgNVBAMMHU5vcnRoZXJuIE5vd2hlcmUgVHJ1c3QgQW5jaG9yFw0yMjEyMjMxMjIx
+MzhaFw0yMzAxMjIxMjIxMzhaMGQwFwIGDzR1USo8Fw0yMjEyMjMxMjIxMzZaMBcC
+Bg80dVFRYRcNMjIxMjIzMTIyMTM3WjAXAgYPNHVRUXUXDTIyMTIyMzEyMjEzN1ow
+FwIGDzR1UVGJFw0yMjEyMjMxMjIxMzhaoA4wDDAKBgNVHRQEAwIBATANBgkqhkiG
+9w0BAQsFAAOCAQEANTZwNcoHukPV2Wf9ykTUELJtpH3OCzinsOBm/h0LRWp06NAm
+0YJcStMclU7syd6izwPZPI9HT5tPQKHaxJDa8rZH4XRE8bSIAHQacj+22mcLV1EB
+5TdRRRHA6UvhebO8f6cf32SQIJ821LDW1FeFj3VvJqRfM6P9E0BNiCGvxJCFAE4K
++/uN5v/x12kKDl3+7wqh1q36qM99QRbNbWh+3ndxG5Gm8Zl2MWLstMLVDI0SjipZ
+mnMpQ0py5IdiStCY8iYiTk48QUqQ9Jki+bmjNwG05HQUVdUiwwtJhlYhyTpNIBE8
+MB+39cFiwpJ7YbFC8Quhppg/isJ2ZaBmTg7zpA==
-----END X509 CRL-----
diff --git a/tests/certs/Server-localhost-firstSAN-sv.crt b/tests/certs/Server-localhost-firstSAN-sv.crt
index ba53c28..6eadce2 100644
--- a/tests/certs/Server-localhost-firstSAN-sv.crt
+++ b/tests/certs/Server-localhost-firstSAN-sv.crt
@@ -1,41 +1,41 @@
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15373412888644 (0xdfb66d07044)
+ Serial Number: 16717980979593 (0xf3475515189)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = Northern Nowhere Trust Anchor
Validity
- Not Before: Sep 19 07:14:48 2018 GMT
- Not After : Dec 6 07:14:48 2026 GMT
+ Not Before: Dec 23 12:21:38 2022 GMT
+ Not After : Mar 11 12:21:38 2031 GMT
Subject:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = localhost.nn
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:b5:a0:56:65:ff:1a:1d:9a:4d:f1:17:be:14:c7:
- 32:fe:51:a0:a3:22:26:59:6c:d5:0c:74:a9:6c:26:
- 1c:a6:92:66:1d:96:0e:59:cb:7d:05:01:b0:31:13:
- dc:db:e6:81:f1:79:43:80:08:37:74:2e:51:82:b6:
- 87:7c:fd:87:2d:fd:d0:d3:42:32:c9:a8:d1:cc:e0:
- 37:7f:e2:3e:65:92:d2:4d:fd:79:ed:ef:23:d5:31:
- 2f:fb:ef:5f:03:68:49:6a:7c:aa:e9:70:23:6b:43:
- 95:bd:5e:d1:f8:16:a7:d5:e0:bd:7f:63:44:a4:2c:
- 4d:34:16:32:11:12:ce:df:16:a4:d8:06:a5:cb:d4:
- 4c:cf:29:ac:67:c1:82:26:c1:0b:ff:44:af:f3:b2:
- 89:31:a2:10:fd:a5:32:f8:04:4e:6b:32:1d:24:5e:
- 83:89:3d:49:9c:34:24:5a:13:dd:2c:0b:2c:5c:b3:
- 5f:be:fc:6d:db:be:c3:c4:40:6d:e8:51:bf:e1:fe:
- 3b:f0:28:42:24:f5:68:c4:2e:00:fa:21:34:f0:d1:
- 94:3f:65:50:19:8d:be:cf:07:2a:08:4f:68:70:77:
- f6:14:78:45:2f:70:da:47:26:51:73:1d:bb:b2:93:
- e1:23:77:6d:a0:47:4e:34:c7:af:fd:a9:53:41:ea:
- e7:73
+ 00:aa:14:6e:3d:82:1c:28:cd:8f:80:af:50:ed:17:
+ 97:6d:e6:a8:61:3e:ac:a8:ac:13:ce:99:eb:29:2c:
+ 49:73:f9:12:40:35:c4:79:84:0d:9e:b0:28:c4:9f:
+ 64:e3:c1:6d:2d:71:11:5d:4b:14:61:20:4b:18:a1:
+ cb:21:6d:9e:78:1b:11:d2:83:1c:89:75:d5:77:3d:
+ ca:c8:83:17:74:5c:44:b2:1f:ac:f3:8b:c5:6a:34:
+ 7a:86:ab:08:f5:3d:79:72:ab:36:48:23:de:2b:ba:
+ 4c:e0:ef:18:91:64:97:c6:09:92:ed:26:d2:a7:0d:
+ a2:21:1f:34:06:c7:99:17:b2:50:96:b6:0f:9b:ed:
+ 45:ff:be:81:47:29:e5:f3:49:db:21:65:44:de:8d:
+ 2b:12:07:12:0d:59:cc:bb:4d:1a:33:c0:7a:7e:e5:
+ 5b:06:50:62:b2:7f:8f:5c:6d:91:cb:6a:5c:e3:e4:
+ ae:b9:ab:0d:36:ef:0a:d5:6d:07:5b:25:58:20:0d:
+ d2:4b:25:0f:e8:11:f5:ce:19:b1:29:c6:d3:49:d7:
+ f2:4a:78:52:d2:c5:fc:4f:11:63:f1:4e:77:ae:0a:
+ 87:65:45:49:b6:ac:21:1b:c8:94:c1:0c:e7:13:e6:
+ be:f3:ff:a2:bd:68:4c:c6:34:04:2b:fc:ff:c3:e8:
+ 23:57
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
@@ -45,48 +45,56 @@
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Key Identifier:
- 70:FA:B9:27:7B:97:78:48:80:FC:D7:D7:31:90:12:ED:E5:4F:90:35
+ DB:7A:18:5E:83:AC:D3:48:C9:00:99:3C:EB:BF:A6:21:F0:39:80:CC
X509v3 Authority Key Identifier:
- keyid:12:CA:BA:4B:46:04:A7:75:8A:2C:E8:0E:54:94:BC:12:65:A6:7B:CE
-
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
X509v3 Basic Constraints:
CA:FALSE
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
Signature Algorithm: sha256WithRSAEncryption
- 8f:e0:79:cb:0a:9d:dd:a3:9b:56:6f:74:75:01:31:ec:01:94:
- c1:6b:76:69:34:da:db:a6:1f:50:07:2f:2a:eb:44:83:23:f4:
- 01:81:f1:aa:f9:65:fe:8c:08:4a:ef:75:36:17:d2:ce:81:f1:
- 2a:ca:cc:5b:2c:c5:fc:30:c2:cf:bc:29:1f:82:17:d4:9f:2a:
- e9:a6:23:9c:19:36:86:e9:46:a2:10:86:65:9a:b5:60:d5:8b:
- ec:05:d3:73:6d:50:a1:38:43:0f:0f:ea:1b:0d:ba:c0:36:2e:
- d4:bd:f7:4e:1d:df:fc:24:8e:50:f2:40:a5:c7:3c:7e:5a:8a:
- 88:1d:f9:28:49:57:42:07:55:1e:ca:94:7c:d9:56:b1:3b:38:
- 62:56:58:6a:ea:fd:30:47:1e:e9:2a:35:e2:d3:57:85:29:6e:
- 06:b3:ad:e9:6a:6e:d1:06:9c:c5:d4:1f:62:fb:fa:1c:e9:f5:
- a7:18:c0:67:29:e0:25:fc:c6:ff:82:76:e3:2f:d6:b2:5f:54:
- a0:8a:93:e4:b2:13:60:f7:96:45:f5:db:b8:95:99:34:62:14:
- cd:e6:58:a3:5c:d6:92:21:f4:ce:dd:da:02:67:12:e7:f6:50:
- 51:e1:8e:9b:84:2f:e6:57:21:81:6a:00:bb:14:bb:29:37:c9:
- 80:c3:74:a2
+ Signature Value:
+ 75:0d:9b:eb:8a:df:ca:a7:7c:9d:9e:6a:eb:30:10:24:12:1b:
+ 81:f6:cd:b0:a0:f8:de:10:f1:6e:b8:57:3a:3a:b0:a4:8c:1d:
+ c1:8f:95:22:e3:1f:8b:3a:21:89:e5:96:08:3d:83:33:37:66:
+ 48:03:f7:98:dd:2f:6d:09:7a:82:26:c1:eb:16:b9:5e:5b:f5:
+ 67:4c:a0:e7:93:e7:2e:d4:53:b8:77:5f:5e:6a:3a:d9:06:19:
+ ca:85:ca:7c:09:61:0d:08:8b:6a:b3:e2:03:8c:ea:b1:55:b2:
+ 30:9b:aa:66:0e:6e:d7:0a:0a:22:ca:6d:8d:d8:53:a8:bc:df:
+ 13:29:d3:b6:1e:9f:3e:a1:8d:f3:8c:48:bf:71:e9:4e:f4:76:
+ ed:77:97:3f:59:27:ca:bb:5b:7c:58:23:82:e7:b5:2d:39:02:
+ 9f:52:07:2f:7b:17:6d:c8:af:90:f5:ed:81:99:a9:cf:80:fb:
+ eb:ba:9c:bc:9a:df:c5:04:78:2c:73:73:bf:95:23:cf:fb:c9:
+ 3e:fa:5b:ee:02:39:8e:09:78:ca:89:08:fd:83:77:37:72:01:
+ 6c:dd:fb:eb:70:20:df:87:28:b3:0f:a0:c5:b3:70:fb:5d:38:
+ 72:23:46:7f:f5:d8:fc:b6:67:72:82:e5:ce:29:f5:b5:34:db:
+ a3:d5:fe:20
-----BEGIN CERTIFICATE-----
-MIID3jCCAsagAwIBAgIGDftm0HBEMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+MIIEXzCCA0egAwIBAgIGDzR1UVGJMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
-Fw0xODA5MTkwNzE0NDhaFw0yNjEyMDYwNzE0NDhaMFcxCzAJBgNVBAYTAk5OMTEw
+Fw0yMjEyMjMxMjIxMzhaFw0zMTAzMTExMjIxMzhaMFcxCzAJBgNVBAYTAk5OMTEw
LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
MRUwEwYDVQQDDAxsb2NhbGhvc3Qubm4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQC1oFZl/xodmk3xF74UxzL+UaCjIiZZbNUMdKlsJhymkmYdlg5Zy30F
-AbAxE9zb5oHxeUOACDd0LlGCtod8/Yct/dDTQjLJqNHM4Dd/4j5lktJN/Xnt7yPV
-MS/7718DaElqfKrpcCNrQ5W9XtH4FqfV4L1/Y0SkLE00FjIREs7fFqTYBqXL1EzP
-KaxnwYImwQv/RK/zsokxohD9pTL4BE5rMh0kXoOJPUmcNCRaE90sCyxcs1++/G3b
-vsPEQG3oUb/h/jvwKEIk9WjELgD6ITTw0ZQ/ZVAZjb7PByoIT2hwd/YUeEUvcNpH
-JlFzHbuyk+Ejd22gR040x6/9qVNB6udzAgMBAAGjgZ4wgZswLAYDVR0RBCUwI4IJ
-bG9jYWxob3N0ggpsb2NhbGhvc3Qxggpsb2NhbGhvc3QyMAsGA1UdDwQEAwIDqDAT
-BgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUcPq5J3uXeEiA/NfXMZAS7eVP
-kDUwHwYDVR0jBBgwFoAUEsq6S0YEp3WKLOgOVJS8EmWme84wCQYDVR0TBAIwADAN
-BgkqhkiG9w0BAQsFAAOCAQEAj+B5ywqd3aObVm90dQEx7AGUwWt2aTTa26YfUAcv
-KutEgyP0AYHxqvll/owISu91NhfSzoHxKsrMWyzF/DDCz7wpH4IX1J8q6aYjnBk2
-hulGohCGZZq1YNWL7AXTc21QoThDDw/qGw26wDYu1L33Th3f/CSOUPJApcc8flqK
-iB35KElXQgdVHsqUfNlWsTs4YlZYaur9MEce6So14tNXhSluBrOt6Wpu0QacxdQf
-Yvv6HOn1pxjAZyngJfzG/4J24y/Wsl9UoIqT5LITYPeWRfXbuJWZNGIUzeZYo1zW
-kiH0zt3aAmcS5/ZQUeGOm4Qv5lchgWoAuxS7KTfJgMN0og==
+ggEKAoIBAQCqFG49ghwozY+Ar1DtF5dt5qhhPqyorBPOmespLElz+RJANcR5hA2e
+sCjEn2TjwW0tcRFdSxRhIEsYocshbZ54GxHSgxyJddV3PcrIgxd0XESyH6zzi8Vq
+NHqGqwj1PXlyqzZII94rukzg7xiRZJfGCZLtJtKnDaIhHzQGx5kXslCWtg+b7UX/
+voFHKeXzSdshZUTejSsSBxINWcy7TRozwHp+5VsGUGKyf49cbZHLalzj5K65qw02
+7wrVbQdbJVggDdJLJQ/oEfXOGbEpxtNJ1/JKeFLSxfxPEWPxTneuCodlRUm2rCEb
+yJTBDOcT5r7z/6K9aEzGNAQr/P/D6CNXAgMBAAGjggEeMIIBGjAsBgNVHREEJTAj
+gglsb2NhbGhvc3SCCmxvY2FsaG9zdDGCCmxvY2FsaG9zdDIwCwYDVR0PBAQDAgOo
+MBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1UdDgQWBBTbehheg6zTSMkAmTzrv6Yh
+8DmAzDAfBgNVHSMEGDAWgBSHy7EzLsFnfnHj5StMTaSzbtJbqTAJBgNVHRMEAjAA
+MEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcwAoYnaHR0cDovL3Rlc3QuY3VybC5z
+ZS9jYS9FZGVsQ3VybFJvb3QuY2VyMDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly90
+ZXN0LmN1cmwuc2UvY2EvRWRlbEN1cmxSb290LmNybDANBgkqhkiG9w0BAQsFAAOC
+AQEAdQ2b64rfyqd8nZ5q6zAQJBIbgfbNsKD43hDxbrhXOjqwpIwdwY+VIuMfizoh
+ieWWCD2DMzdmSAP3mN0vbQl6gibB6xa5Xlv1Z0yg55PnLtRTuHdfXmo62QYZyoXK
+fAlhDQiLarPiA4zqsVWyMJuqZg5u1woKIsptjdhTqLzfEynTth6fPqGN84xIv3Hp
+TvR27XeXP1knyrtbfFgjgue1LTkCn1IHL3sXbcivkPXtgZmpz4D767qcvJrfxQR4
+LHNzv5Ujz/vJPvpb7gI5jgl4yokI/YN3N3IBbN3763Ag34cosw+gxbNw+104ciNG
+f/XY/LZncoLlzin1tTTbo9X+IA==
-----END CERTIFICATE-----
diff --git a/tests/certs/Server-localhost-firstSAN-sv.csr b/tests/certs/Server-localhost-firstSAN-sv.csr
index d8aa70b..031639c 100644
--- a/tests/certs/Server-localhost-firstSAN-sv.csr
+++ b/tests/certs/Server-localhost-firstSAN-sv.csr
@@ -1,16 +1,16 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICnDCCAYQCAQAwVzELMAkGA1UEBhMCTk4xMTAvBgNVBAoMKEVkZWwgQ3VybCBB
cmN0aWMgSWxsdWRpdW0gUmVzZWFyY2ggQ2xvdWQxFTATBgNVBAMMDGxvY2FsaG9z
-dC5ubjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALWgVmX/Gh2aTfEX
-vhTHMv5RoKMiJlls1Qx0qWwmHKaSZh2WDlnLfQUBsDET3NvmgfF5Q4AIN3QuUYK2
-h3z9hy390NNCMsmo0czgN3/iPmWS0k39ee3vI9UxL/vvXwNoSWp8qulwI2tDlb1e
-0fgWp9XgvX9jRKQsTTQWMhESzt8WpNgGpcvUTM8prGfBgibBC/9Er/OyiTGiEP2l
-MvgETmsyHSReg4k9SZw0JFoT3SwLLFyzX778bdu+w8RAbehRv+H+O/AoQiT1aMQu
-APohNPDRlD9lUBmNvs8HKghPaHB39hR4RS9w2kcmUXMdu7KT4SN3baBHTjTHr/2p
-U0Hq53MCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBt9eE5YhGU2bhKrDvnOlCW
-2/5QFLzKYgZQHf3v+bK4DzhPFZSLHkls5oV+MbAms/CdU1t4uA9J63DIlfDEe302
-k5m4NJ/v4NvpQtHVheMi6BkK+BQWnV/BVTv85N550wi2BtkxRqtEPyJu6XDbIgPp
-nUP9TCVPjgM1/njekHLD2fm8NBFwFaKBLsw2GSSm7mpdwyhOxTdwOHbwpei5xR/9
-U0OtS2NJv0KIiZS0GyGoBK2VN6iwUTPBEuxTUNfpRoboknwtY0f0RfRXeYZzAelx
-OL7UNvFt1njk4pY8YOAVKqHszWGV46c5XalMQDJpwP7xzc52W+q9x4psx3br4J3u
+dC5ubjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKoUbj2CHCjNj4Cv
+UO0Xl23mqGE+rKisE86Z6yksSXP5EkA1xHmEDZ6wKMSfZOPBbS1xEV1LFGEgSxih
+yyFtnngbEdKDHIl11Xc9ysiDF3RcRLIfrPOLxWo0eoarCPU9eXKrNkgj3iu6TODv
+GJFkl8YJku0m0qcNoiEfNAbHmReyUJa2D5vtRf++gUcp5fNJ2yFlRN6NKxIHEg1Z
+zLtNGjPAen7lWwZQYrJ/j1xtkctqXOPkrrmrDTbvCtVtB1slWCAN0kslD+gR9c4Z
+sSnG00nX8kp4UtLF/E8RY/FOd64Kh2VFSbasIRvIlMEM5xPmvvP/or1oTMY0BCv8
+/8PoI1cCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBRfTSEtMHj/52TYk5kUHlY
+gTBoePcTVfRCBRfqlGGDAokBrvXq/dFU+5Z/CyulXWnqPji+qw6GDG8KPX0oA6wj
+4Yi2z0Dy4BYaRO4PWTGPZ6zsSXAtv0CVtf995O8Ko8axhYQhjDb54G8oMOr5XOHz
+GV4LolrlsgxNM0m/KJ2FPVnnfN78qbRO8DpqjFwDOS+ZCIHh+59X34Jyi1HCse+Y
+XJ4/YIV5Aw5rGabRproxESwV01Eq4HsXEKP9TtdNDFMkrObWisb7g2M40i4QTR9/
+BNCt3d5vcnAxi2rf+CEvHQDGROZ0tTOZ20HowBA4ahMbYsfC9U+pFkq08auaoe6n
-----END CERTIFICATE REQUEST-----
diff --git a/tests/certs/Server-localhost-firstSAN-sv.der b/tests/certs/Server-localhost-firstSAN-sv.der
index 3294af0..2c17c0f 100644
--- a/tests/certs/Server-localhost-firstSAN-sv.der
+++ b/tests/certs/Server-localhost-firstSAN-sv.der
Binary files differ
diff --git a/tests/certs/Server-localhost-firstSAN-sv.key b/tests/certs/Server-localhost-firstSAN-sv.key
index dd9e714..0b6bbaa 100644
--- a/tests/certs/Server-localhost-firstSAN-sv.key
+++ b/tests/certs/Server-localhost-firstSAN-sv.key
@@ -1,27 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEAtaBWZf8aHZpN8Re+FMcy/lGgoyImWWzVDHSpbCYcppJmHZYO
-Wct9BQGwMRPc2+aB8XlDgAg3dC5RgraHfP2HLf3Q00IyyajRzOA3f+I+ZZLSTf15
-7e8j1TEv++9fA2hJanyq6XAja0OVvV7R+Ban1eC9f2NEpCxNNBYyERLO3xak2Aal
-y9RMzymsZ8GCJsEL/0Sv87KJMaIQ/aUy+AROazIdJF6DiT1JnDQkWhPdLAssXLNf
-vvxt277DxEBt6FG/4f478ChCJPVoxC4A+iE08NGUP2VQGY2+zwcqCE9ocHf2FHhF
-L3DaRyZRcx27spPhI3dtoEdONMev/alTQerncwIDAQABAoIBAD6smIPT1tg2QgUb
-E02qO4+E7XC9vQwIwS/uJfSa5jIYvMIi4MrdrEOJBJq65vC/B0IjfUZ2D2S5Awmf
-IPvhpL8bIe90nX/3EIapLJ2lnbCBTK769BNF/VB5C7zdKiVL3GGxqWyqdJ50EPzq
-9nusnbfxOJL311zrqKx7qEU5/0b9vYtCW+o7P90pHK7VAMJfzXT28lJepn3RW2OW
-vSMqfF5VjlSzjq+0Xlbu3tOk+I3zBhv1dcZCYCCdUNj18XOmhIKgsqjfgMGAeA77
-e6h/9pn8O/rxM4PwU4vJbtfsiEQa5ekNWR+jyoeOu5XfyYFHSDtKEiRkD2zq6K1V
-+O5gBYECgYEA2b/xjuT8cJM/OAt9jP/6yC2YyIX/2EmzbsyH1XfRY7Xhy63qidza
-wBVCxdlguEGte05x6k2z3S7QUFU/LQKs0aOm2j9WHpnw9LlZ1mE1PtFPJPEaKzfP
-dlUibC/mQ6Qh8dWli8aMXUOj9/o4QxKFC64Q1D/xk/h+h0ExNusJw7MCgYEA1Yfy
-aiFjUhTCsH4R/wHAgUcLDlfCpHLiymO2mylVhu+/frScqn+3RC2JJjyljtwKLC7C
-k6iXRKaqoMcwf4jmhxsoGzqjmHSCxvpucDcN0XJ2uBRg9rTOFIoAg3bocgbbrpl1
-dRsAScO1BvRY4oLSLQjLRguOxUizL6N6kGjvbUECgYACEDSMwxS1SF/n+wvkgyRw
-MyZoeASVmxUtLpj259y/EiEimfJH/iTAfzMTxtyIwm6PZY3kx3m11dS5fiVMGuNi
-VSeml8UMIy9KUltMkb08bCVQ10wFLtEzcNkTp1yKNYrwzLJ14ZrA43wxRFi2If3K
-v4p/SF/UpB0m0PJTb+S2ywKBgF1onA37TxRwCn7kl4DDRnAHIPoEQBxqOXWpyw7z
-NPvTUyTdY49eUVBczxtP+miVL0oGpo2reYjJk+jDWh7gR2Ag7BmFPF2L0k2y7a7f
-FodiGDcMiyJBE8l+WR0pXiPLhjxJ200AI88g8sb5Cw0Dh2e16h5ZHfqFhAU58XrM
-vLhBAoGBAIwabHuf+Q058c6KdInkgwQ97xOuL6iqgXztl77zo3v9v8Uyvbed57Y5
-hohvGXHwdvBP0J4w5SYcH3C7ZXF8k9MK+AownCeq7wruvcliCmWmo9dvhcD0nBPL
-XZP1GEqNHpVQ+KzObbzQpZmZkIo6Ttg50jbLdoAn24kTdR2PVb2Q
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqFG49ghwozY+A
+r1DtF5dt5qhhPqyorBPOmespLElz+RJANcR5hA2esCjEn2TjwW0tcRFdSxRhIEsY
+ocshbZ54GxHSgxyJddV3PcrIgxd0XESyH6zzi8VqNHqGqwj1PXlyqzZII94rukzg
+7xiRZJfGCZLtJtKnDaIhHzQGx5kXslCWtg+b7UX/voFHKeXzSdshZUTejSsSBxIN
+Wcy7TRozwHp+5VsGUGKyf49cbZHLalzj5K65qw027wrVbQdbJVggDdJLJQ/oEfXO
+GbEpxtNJ1/JKeFLSxfxPEWPxTneuCodlRUm2rCEbyJTBDOcT5r7z/6K9aEzGNAQr
+/P/D6CNXAgMBAAECggEABTfYrgT/xHXbOkOmuvieLp5ODH7joPLldvX3+FpqxxSL
+EhdB7qNaaVYftYLrkaVNvKS/3BDBfk+nwr+Qmy4X8wH5m0sdpSqWfDDLAPAss53y
+zi8ZLcBJ6v3TMa5AQolfBPPFzrfzAA8GNao3IuSLoK5BqMFMmhjr+8kGS8CrGn0c
+PaMd+zNUaCo0ml7dsO+14qjeLSSzKaYl7mOHeEq02B3UDa5twvkyVQiCHV7CThF0
+0oxJ+DOFzBefPB8pIurh6X0WwaDumEQVnEaaaOWEa1IayscTSrkLcNwkZC55/23M
+k9qaR/qGnfUSpu34NTlyy7ifbJOeHp+rZDEFKgBoWQKBgQDalQKzRAjpXn9sSBQS
+aTvP293zxP5ueJnv0TmViUfadDDPZ/VX6W0n7mGuOmNKaWnjM1rvMGpqo6e65eir
+obuUe7GfJAqexUK6VDFOIzFSBqWpquyjjHWa6C4zgL+BVDGItIhQI/6wYsQ0HgLV
+R/n3nqCcYAc/a131GDGdfshbwwKBgQDHMePvhNBZo3p1vUG5l3HiTQRmeDmhlOmT
+qU5XRBPDnh5Hdkq3G34QVwaLEDapyQOnbrylVlE0a+uaB+llzw4GrFOVcRi0K8M5
+wcwI8sSgfoOyv6WKH5780I9T1EiNBDmS5XFr+dkI16+GO1LJdI5JuMoio+0WBKHk
+m3He1rik3QKBgQC1ds/vE6RyWclfk9dWEZdeUSJKpli0Tds+hWxRAM9uRNfg2GWO
+vnOomvbtNfwIYstNm+z6di9iqMsvFn+7PWIFO0uS2tEWTp2/IvZr8DuZ5XrTCNu8
+S3e3StpQV6qlK8iTvY0NO1TOCrDos6GWf1K+iCq+p9pchD5Uo+lM31xnEQKBgHSL
++0pkEiewX/FNp4v4UTjQSTfPNiEVaMjtsZmbiljVRfAYBUU3f739vSVWejVDGLE5
+OIUgiOi8ECCSanwX9qPu5gS1JHgedt5vRnsh1+vzugi22xuCvto7CPFKbpybkTgi
+qQc9K0BiOh+2zAx09t+pkBNOiGRul26TiL+SMHy9AoGABbo9jk6Je4fcLmB9YtHT
+O8L+e2S88r/KuXGrqECD5c/FZL33oTrP9pzvL4Be2W8489DM2UMMD4w0uiUIq/Iu
+5Hp/Lsj8ha2OHoU2TbFaNFoS3fvaOz9zQ0GySjpMngZOKIoYtR9R4ZNI/hlmhAqq
+usJ3GDPcvFSsedJr8gP52QU=
+-----END PRIVATE KEY-----
diff --git a/tests/certs/Server-localhost-firstSAN-sv.pem b/tests/certs/Server-localhost-firstSAN-sv.pem
index 8294d91..3751e7b 100644
--- a/tests/certs/Server-localhost-firstSAN-sv.pem
+++ b/tests/certs/Server-localhost-firstSAN-sv.pem
@@ -6,11 +6,25 @@
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
basicConstraints = CA:false
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
+
[ req ]
default_bits = 1024
distinguished_name = req_DN
default_md = sha256
string_mask = utf8only
+
[ req_DN ]
countryName = "Country Name is Northern Nowhere"
countryName_value = NN
@@ -23,71 +37,72 @@
# The key
# the certificate
# some dhparam
------BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEAtaBWZf8aHZpN8Re+FMcy/lGgoyImWWzVDHSpbCYcppJmHZYO
-Wct9BQGwMRPc2+aB8XlDgAg3dC5RgraHfP2HLf3Q00IyyajRzOA3f+I+ZZLSTf15
-7e8j1TEv++9fA2hJanyq6XAja0OVvV7R+Ban1eC9f2NEpCxNNBYyERLO3xak2Aal
-y9RMzymsZ8GCJsEL/0Sv87KJMaIQ/aUy+AROazIdJF6DiT1JnDQkWhPdLAssXLNf
-vvxt277DxEBt6FG/4f478ChCJPVoxC4A+iE08NGUP2VQGY2+zwcqCE9ocHf2FHhF
-L3DaRyZRcx27spPhI3dtoEdONMev/alTQerncwIDAQABAoIBAD6smIPT1tg2QgUb
-E02qO4+E7XC9vQwIwS/uJfSa5jIYvMIi4MrdrEOJBJq65vC/B0IjfUZ2D2S5Awmf
-IPvhpL8bIe90nX/3EIapLJ2lnbCBTK769BNF/VB5C7zdKiVL3GGxqWyqdJ50EPzq
-9nusnbfxOJL311zrqKx7qEU5/0b9vYtCW+o7P90pHK7VAMJfzXT28lJepn3RW2OW
-vSMqfF5VjlSzjq+0Xlbu3tOk+I3zBhv1dcZCYCCdUNj18XOmhIKgsqjfgMGAeA77
-e6h/9pn8O/rxM4PwU4vJbtfsiEQa5ekNWR+jyoeOu5XfyYFHSDtKEiRkD2zq6K1V
-+O5gBYECgYEA2b/xjuT8cJM/OAt9jP/6yC2YyIX/2EmzbsyH1XfRY7Xhy63qidza
-wBVCxdlguEGte05x6k2z3S7QUFU/LQKs0aOm2j9WHpnw9LlZ1mE1PtFPJPEaKzfP
-dlUibC/mQ6Qh8dWli8aMXUOj9/o4QxKFC64Q1D/xk/h+h0ExNusJw7MCgYEA1Yfy
-aiFjUhTCsH4R/wHAgUcLDlfCpHLiymO2mylVhu+/frScqn+3RC2JJjyljtwKLC7C
-k6iXRKaqoMcwf4jmhxsoGzqjmHSCxvpucDcN0XJ2uBRg9rTOFIoAg3bocgbbrpl1
-dRsAScO1BvRY4oLSLQjLRguOxUizL6N6kGjvbUECgYACEDSMwxS1SF/n+wvkgyRw
-MyZoeASVmxUtLpj259y/EiEimfJH/iTAfzMTxtyIwm6PZY3kx3m11dS5fiVMGuNi
-VSeml8UMIy9KUltMkb08bCVQ10wFLtEzcNkTp1yKNYrwzLJ14ZrA43wxRFi2If3K
-v4p/SF/UpB0m0PJTb+S2ywKBgF1onA37TxRwCn7kl4DDRnAHIPoEQBxqOXWpyw7z
-NPvTUyTdY49eUVBczxtP+miVL0oGpo2reYjJk+jDWh7gR2Ag7BmFPF2L0k2y7a7f
-FodiGDcMiyJBE8l+WR0pXiPLhjxJ200AI88g8sb5Cw0Dh2e16h5ZHfqFhAU58XrM
-vLhBAoGBAIwabHuf+Q058c6KdInkgwQ97xOuL6iqgXztl77zo3v9v8Uyvbed57Y5
-hohvGXHwdvBP0J4w5SYcH3C7ZXF8k9MK+AownCeq7wruvcliCmWmo9dvhcD0nBPL
-XZP1GEqNHpVQ+KzObbzQpZmZkIo6Ttg50jbLdoAn24kTdR2PVb2Q
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqFG49ghwozY+A
+r1DtF5dt5qhhPqyorBPOmespLElz+RJANcR5hA2esCjEn2TjwW0tcRFdSxRhIEsY
+ocshbZ54GxHSgxyJddV3PcrIgxd0XESyH6zzi8VqNHqGqwj1PXlyqzZII94rukzg
+7xiRZJfGCZLtJtKnDaIhHzQGx5kXslCWtg+b7UX/voFHKeXzSdshZUTejSsSBxIN
+Wcy7TRozwHp+5VsGUGKyf49cbZHLalzj5K65qw027wrVbQdbJVggDdJLJQ/oEfXO
+GbEpxtNJ1/JKeFLSxfxPEWPxTneuCodlRUm2rCEbyJTBDOcT5r7z/6K9aEzGNAQr
+/P/D6CNXAgMBAAECggEABTfYrgT/xHXbOkOmuvieLp5ODH7joPLldvX3+FpqxxSL
+EhdB7qNaaVYftYLrkaVNvKS/3BDBfk+nwr+Qmy4X8wH5m0sdpSqWfDDLAPAss53y
+zi8ZLcBJ6v3TMa5AQolfBPPFzrfzAA8GNao3IuSLoK5BqMFMmhjr+8kGS8CrGn0c
+PaMd+zNUaCo0ml7dsO+14qjeLSSzKaYl7mOHeEq02B3UDa5twvkyVQiCHV7CThF0
+0oxJ+DOFzBefPB8pIurh6X0WwaDumEQVnEaaaOWEa1IayscTSrkLcNwkZC55/23M
+k9qaR/qGnfUSpu34NTlyy7ifbJOeHp+rZDEFKgBoWQKBgQDalQKzRAjpXn9sSBQS
+aTvP293zxP5ueJnv0TmViUfadDDPZ/VX6W0n7mGuOmNKaWnjM1rvMGpqo6e65eir
+obuUe7GfJAqexUK6VDFOIzFSBqWpquyjjHWa6C4zgL+BVDGItIhQI/6wYsQ0HgLV
+R/n3nqCcYAc/a131GDGdfshbwwKBgQDHMePvhNBZo3p1vUG5l3HiTQRmeDmhlOmT
+qU5XRBPDnh5Hdkq3G34QVwaLEDapyQOnbrylVlE0a+uaB+llzw4GrFOVcRi0K8M5
+wcwI8sSgfoOyv6WKH5780I9T1EiNBDmS5XFr+dkI16+GO1LJdI5JuMoio+0WBKHk
+m3He1rik3QKBgQC1ds/vE6RyWclfk9dWEZdeUSJKpli0Tds+hWxRAM9uRNfg2GWO
+vnOomvbtNfwIYstNm+z6di9iqMsvFn+7PWIFO0uS2tEWTp2/IvZr8DuZ5XrTCNu8
+S3e3StpQV6qlK8iTvY0NO1TOCrDos6GWf1K+iCq+p9pchD5Uo+lM31xnEQKBgHSL
++0pkEiewX/FNp4v4UTjQSTfPNiEVaMjtsZmbiljVRfAYBUU3f739vSVWejVDGLE5
+OIUgiOi8ECCSanwX9qPu5gS1JHgedt5vRnsh1+vzugi22xuCvto7CPFKbpybkTgi
+qQc9K0BiOh+2zAx09t+pkBNOiGRul26TiL+SMHy9AoGABbo9jk6Je4fcLmB9YtHT
+O8L+e2S88r/KuXGrqECD5c/FZL33oTrP9pzvL4Be2W8489DM2UMMD4w0uiUIq/Iu
+5Hp/Lsj8ha2OHoU2TbFaNFoS3fvaOz9zQ0GySjpMngZOKIoYtR9R4ZNI/hlmhAqq
+usJ3GDPcvFSsedJr8gP52QU=
+-----END PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15373412888644 (0xdfb66d07044)
+ Serial Number: 16717980979593 (0xf3475515189)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = Northern Nowhere Trust Anchor
Validity
- Not Before: Sep 19 07:14:48 2018 GMT
- Not After : Dec 6 07:14:48 2026 GMT
+ Not Before: Dec 23 12:21:38 2022 GMT
+ Not After : Mar 11 12:21:38 2031 GMT
Subject:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = localhost.nn
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:b5:a0:56:65:ff:1a:1d:9a:4d:f1:17:be:14:c7:
- 32:fe:51:a0:a3:22:26:59:6c:d5:0c:74:a9:6c:26:
- 1c:a6:92:66:1d:96:0e:59:cb:7d:05:01:b0:31:13:
- dc:db:e6:81:f1:79:43:80:08:37:74:2e:51:82:b6:
- 87:7c:fd:87:2d:fd:d0:d3:42:32:c9:a8:d1:cc:e0:
- 37:7f:e2:3e:65:92:d2:4d:fd:79:ed:ef:23:d5:31:
- 2f:fb:ef:5f:03:68:49:6a:7c:aa:e9:70:23:6b:43:
- 95:bd:5e:d1:f8:16:a7:d5:e0:bd:7f:63:44:a4:2c:
- 4d:34:16:32:11:12:ce:df:16:a4:d8:06:a5:cb:d4:
- 4c:cf:29:ac:67:c1:82:26:c1:0b:ff:44:af:f3:b2:
- 89:31:a2:10:fd:a5:32:f8:04:4e:6b:32:1d:24:5e:
- 83:89:3d:49:9c:34:24:5a:13:dd:2c:0b:2c:5c:b3:
- 5f:be:fc:6d:db:be:c3:c4:40:6d:e8:51:bf:e1:fe:
- 3b:f0:28:42:24:f5:68:c4:2e:00:fa:21:34:f0:d1:
- 94:3f:65:50:19:8d:be:cf:07:2a:08:4f:68:70:77:
- f6:14:78:45:2f:70:da:47:26:51:73:1d:bb:b2:93:
- e1:23:77:6d:a0:47:4e:34:c7:af:fd:a9:53:41:ea:
- e7:73
+ 00:aa:14:6e:3d:82:1c:28:cd:8f:80:af:50:ed:17:
+ 97:6d:e6:a8:61:3e:ac:a8:ac:13:ce:99:eb:29:2c:
+ 49:73:f9:12:40:35:c4:79:84:0d:9e:b0:28:c4:9f:
+ 64:e3:c1:6d:2d:71:11:5d:4b:14:61:20:4b:18:a1:
+ cb:21:6d:9e:78:1b:11:d2:83:1c:89:75:d5:77:3d:
+ ca:c8:83:17:74:5c:44:b2:1f:ac:f3:8b:c5:6a:34:
+ 7a:86:ab:08:f5:3d:79:72:ab:36:48:23:de:2b:ba:
+ 4c:e0:ef:18:91:64:97:c6:09:92:ed:26:d2:a7:0d:
+ a2:21:1f:34:06:c7:99:17:b2:50:96:b6:0f:9b:ed:
+ 45:ff:be:81:47:29:e5:f3:49:db:21:65:44:de:8d:
+ 2b:12:07:12:0d:59:cc:bb:4d:1a:33:c0:7a:7e:e5:
+ 5b:06:50:62:b2:7f:8f:5c:6d:91:cb:6a:5c:e3:e4:
+ ae:b9:ab:0d:36:ef:0a:d5:6d:07:5b:25:58:20:0d:
+ d2:4b:25:0f:e8:11:f5:ce:19:b1:29:c6:d3:49:d7:
+ f2:4a:78:52:d2:c5:fc:4f:11:63:f1:4e:77:ae:0a:
+ 87:65:45:49:b6:ac:21:1b:c8:94:c1:0c:e7:13:e6:
+ be:f3:ff:a2:bd:68:4c:c6:34:04:2b:fc:ff:c3:e8:
+ 23:57
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
@@ -97,48 +112,56 @@
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Key Identifier:
- 70:FA:B9:27:7B:97:78:48:80:FC:D7:D7:31:90:12:ED:E5:4F:90:35
+ DB:7A:18:5E:83:AC:D3:48:C9:00:99:3C:EB:BF:A6:21:F0:39:80:CC
X509v3 Authority Key Identifier:
- keyid:12:CA:BA:4B:46:04:A7:75:8A:2C:E8:0E:54:94:BC:12:65:A6:7B:CE
-
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
X509v3 Basic Constraints:
CA:FALSE
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
Signature Algorithm: sha256WithRSAEncryption
- 8f:e0:79:cb:0a:9d:dd:a3:9b:56:6f:74:75:01:31:ec:01:94:
- c1:6b:76:69:34:da:db:a6:1f:50:07:2f:2a:eb:44:83:23:f4:
- 01:81:f1:aa:f9:65:fe:8c:08:4a:ef:75:36:17:d2:ce:81:f1:
- 2a:ca:cc:5b:2c:c5:fc:30:c2:cf:bc:29:1f:82:17:d4:9f:2a:
- e9:a6:23:9c:19:36:86:e9:46:a2:10:86:65:9a:b5:60:d5:8b:
- ec:05:d3:73:6d:50:a1:38:43:0f:0f:ea:1b:0d:ba:c0:36:2e:
- d4:bd:f7:4e:1d:df:fc:24:8e:50:f2:40:a5:c7:3c:7e:5a:8a:
- 88:1d:f9:28:49:57:42:07:55:1e:ca:94:7c:d9:56:b1:3b:38:
- 62:56:58:6a:ea:fd:30:47:1e:e9:2a:35:e2:d3:57:85:29:6e:
- 06:b3:ad:e9:6a:6e:d1:06:9c:c5:d4:1f:62:fb:fa:1c:e9:f5:
- a7:18:c0:67:29:e0:25:fc:c6:ff:82:76:e3:2f:d6:b2:5f:54:
- a0:8a:93:e4:b2:13:60:f7:96:45:f5:db:b8:95:99:34:62:14:
- cd:e6:58:a3:5c:d6:92:21:f4:ce:dd:da:02:67:12:e7:f6:50:
- 51:e1:8e:9b:84:2f:e6:57:21:81:6a:00:bb:14:bb:29:37:c9:
- 80:c3:74:a2
+ Signature Value:
+ 75:0d:9b:eb:8a:df:ca:a7:7c:9d:9e:6a:eb:30:10:24:12:1b:
+ 81:f6:cd:b0:a0:f8:de:10:f1:6e:b8:57:3a:3a:b0:a4:8c:1d:
+ c1:8f:95:22:e3:1f:8b:3a:21:89:e5:96:08:3d:83:33:37:66:
+ 48:03:f7:98:dd:2f:6d:09:7a:82:26:c1:eb:16:b9:5e:5b:f5:
+ 67:4c:a0:e7:93:e7:2e:d4:53:b8:77:5f:5e:6a:3a:d9:06:19:
+ ca:85:ca:7c:09:61:0d:08:8b:6a:b3:e2:03:8c:ea:b1:55:b2:
+ 30:9b:aa:66:0e:6e:d7:0a:0a:22:ca:6d:8d:d8:53:a8:bc:df:
+ 13:29:d3:b6:1e:9f:3e:a1:8d:f3:8c:48:bf:71:e9:4e:f4:76:
+ ed:77:97:3f:59:27:ca:bb:5b:7c:58:23:82:e7:b5:2d:39:02:
+ 9f:52:07:2f:7b:17:6d:c8:af:90:f5:ed:81:99:a9:cf:80:fb:
+ eb:ba:9c:bc:9a:df:c5:04:78:2c:73:73:bf:95:23:cf:fb:c9:
+ 3e:fa:5b:ee:02:39:8e:09:78:ca:89:08:fd:83:77:37:72:01:
+ 6c:dd:fb:eb:70:20:df:87:28:b3:0f:a0:c5:b3:70:fb:5d:38:
+ 72:23:46:7f:f5:d8:fc:b6:67:72:82:e5:ce:29:f5:b5:34:db:
+ a3:d5:fe:20
-----BEGIN CERTIFICATE-----
-MIID3jCCAsagAwIBAgIGDftm0HBEMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+MIIEXzCCA0egAwIBAgIGDzR1UVGJMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
-Fw0xODA5MTkwNzE0NDhaFw0yNjEyMDYwNzE0NDhaMFcxCzAJBgNVBAYTAk5OMTEw
+Fw0yMjEyMjMxMjIxMzhaFw0zMTAzMTExMjIxMzhaMFcxCzAJBgNVBAYTAk5OMTEw
LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
MRUwEwYDVQQDDAxsb2NhbGhvc3Qubm4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQC1oFZl/xodmk3xF74UxzL+UaCjIiZZbNUMdKlsJhymkmYdlg5Zy30F
-AbAxE9zb5oHxeUOACDd0LlGCtod8/Yct/dDTQjLJqNHM4Dd/4j5lktJN/Xnt7yPV
-MS/7718DaElqfKrpcCNrQ5W9XtH4FqfV4L1/Y0SkLE00FjIREs7fFqTYBqXL1EzP
-KaxnwYImwQv/RK/zsokxohD9pTL4BE5rMh0kXoOJPUmcNCRaE90sCyxcs1++/G3b
-vsPEQG3oUb/h/jvwKEIk9WjELgD6ITTw0ZQ/ZVAZjb7PByoIT2hwd/YUeEUvcNpH
-JlFzHbuyk+Ejd22gR040x6/9qVNB6udzAgMBAAGjgZ4wgZswLAYDVR0RBCUwI4IJ
-bG9jYWxob3N0ggpsb2NhbGhvc3Qxggpsb2NhbGhvc3QyMAsGA1UdDwQEAwIDqDAT
-BgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUcPq5J3uXeEiA/NfXMZAS7eVP
-kDUwHwYDVR0jBBgwFoAUEsq6S0YEp3WKLOgOVJS8EmWme84wCQYDVR0TBAIwADAN
-BgkqhkiG9w0BAQsFAAOCAQEAj+B5ywqd3aObVm90dQEx7AGUwWt2aTTa26YfUAcv
-KutEgyP0AYHxqvll/owISu91NhfSzoHxKsrMWyzF/DDCz7wpH4IX1J8q6aYjnBk2
-hulGohCGZZq1YNWL7AXTc21QoThDDw/qGw26wDYu1L33Th3f/CSOUPJApcc8flqK
-iB35KElXQgdVHsqUfNlWsTs4YlZYaur9MEce6So14tNXhSluBrOt6Wpu0QacxdQf
-Yvv6HOn1pxjAZyngJfzG/4J24y/Wsl9UoIqT5LITYPeWRfXbuJWZNGIUzeZYo1zW
-kiH0zt3aAmcS5/ZQUeGOm4Qv5lchgWoAuxS7KTfJgMN0og==
+ggEKAoIBAQCqFG49ghwozY+Ar1DtF5dt5qhhPqyorBPOmespLElz+RJANcR5hA2e
+sCjEn2TjwW0tcRFdSxRhIEsYocshbZ54GxHSgxyJddV3PcrIgxd0XESyH6zzi8Vq
+NHqGqwj1PXlyqzZII94rukzg7xiRZJfGCZLtJtKnDaIhHzQGx5kXslCWtg+b7UX/
+voFHKeXzSdshZUTejSsSBxINWcy7TRozwHp+5VsGUGKyf49cbZHLalzj5K65qw02
+7wrVbQdbJVggDdJLJQ/oEfXOGbEpxtNJ1/JKeFLSxfxPEWPxTneuCodlRUm2rCEb
+yJTBDOcT5r7z/6K9aEzGNAQr/P/D6CNXAgMBAAGjggEeMIIBGjAsBgNVHREEJTAj
+gglsb2NhbGhvc3SCCmxvY2FsaG9zdDGCCmxvY2FsaG9zdDIwCwYDVR0PBAQDAgOo
+MBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1UdDgQWBBTbehheg6zTSMkAmTzrv6Yh
+8DmAzDAfBgNVHSMEGDAWgBSHy7EzLsFnfnHj5StMTaSzbtJbqTAJBgNVHRMEAjAA
+MEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcwAoYnaHR0cDovL3Rlc3QuY3VybC5z
+ZS9jYS9FZGVsQ3VybFJvb3QuY2VyMDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly90
+ZXN0LmN1cmwuc2UvY2EvRWRlbEN1cmxSb290LmNybDANBgkqhkiG9w0BAQsFAAOC
+AQEAdQ2b64rfyqd8nZ5q6zAQJBIbgfbNsKD43hDxbrhXOjqwpIwdwY+VIuMfizoh
+ieWWCD2DMzdmSAP3mN0vbQl6gibB6xa5Xlv1Z0yg55PnLtRTuHdfXmo62QYZyoXK
+fAlhDQiLarPiA4zqsVWyMJuqZg5u1woKIsptjdhTqLzfEynTth6fPqGN84xIv3Hp
+TvR27XeXP1knyrtbfFgjgue1LTkCn1IHL3sXbcivkPXtgZmpz4D767qcvJrfxQR4
+LHNzv5Ujz/vJPvpb7gI5jgl4yokI/YN3N3IBbN3763Ag34cosw+gxbNw+104ciNG
+f/XY/LZncoLlzin1tTTbo9X+IA==
-----END CERTIFICATE-----
diff --git a/tests/certs/Server-localhost-firstSAN-sv.prm b/tests/certs/Server-localhost-firstSAN-sv.prm
index f299a3c..911f4ce 100644
--- a/tests/certs/Server-localhost-firstSAN-sv.prm
+++ b/tests/certs/Server-localhost-firstSAN-sv.prm
@@ -6,11 +6,25 @@
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
basicConstraints = CA:false
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
+
[ req ]
default_bits = 1024
distinguished_name = req_DN
default_md = sha256
string_mask = utf8only
+
[ req_DN ]
countryName = "Country Name is Northern Nowhere"
countryName_value = NN
diff --git a/tests/certs/Server-localhost-firstSAN-sv.pub.der b/tests/certs/Server-localhost-firstSAN-sv.pub.der
index 24f0794..0bb7877 100644
--- a/tests/certs/Server-localhost-firstSAN-sv.pub.der
+++ b/tests/certs/Server-localhost-firstSAN-sv.pub.der
Binary files differ
diff --git a/tests/certs/Server-localhost-firstSAN-sv.pub.pem b/tests/certs/Server-localhost-firstSAN-sv.pub.pem
index fa65135..4bc6c69 100644
--- a/tests/certs/Server-localhost-firstSAN-sv.pub.pem
+++ b/tests/certs/Server-localhost-firstSAN-sv.pub.pem
@@ -1,9 +1,9 @@
-----BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtaBWZf8aHZpN8Re+FMcy
-/lGgoyImWWzVDHSpbCYcppJmHZYOWct9BQGwMRPc2+aB8XlDgAg3dC5RgraHfP2H
-Lf3Q00IyyajRzOA3f+I+ZZLSTf157e8j1TEv++9fA2hJanyq6XAja0OVvV7R+Ban
-1eC9f2NEpCxNNBYyERLO3xak2Aaly9RMzymsZ8GCJsEL/0Sv87KJMaIQ/aUy+ARO
-azIdJF6DiT1JnDQkWhPdLAssXLNfvvxt277DxEBt6FG/4f478ChCJPVoxC4A+iE0
-8NGUP2VQGY2+zwcqCE9ocHf2FHhFL3DaRyZRcx27spPhI3dtoEdONMev/alTQern
-cwIDAQAB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqhRuPYIcKM2PgK9Q7ReX
+beaoYT6sqKwTzpnrKSxJc/kSQDXEeYQNnrAoxJ9k48FtLXERXUsUYSBLGKHLIW2e
+eBsR0oMciXXVdz3KyIMXdFxEsh+s84vFajR6hqsI9T15cqs2SCPeK7pM4O8YkWSX
+xgmS7SbSpw2iIR80BseZF7JQlrYPm+1F/76BRynl80nbIWVE3o0rEgcSDVnMu00a
+M8B6fuVbBlBisn+PXG2Ry2pc4+SuuasNNu8K1W0HWyVYIA3SSyUP6BH1zhmxKcbT
+SdfySnhS0sX8TxFj8U53rgqHZUVJtqwhG8iUwQznE+a+8/+ivWhMxjQEK/z/w+gj
+VwIDAQAB
-----END PUBLIC KEY-----
diff --git a/tests/certs/Server-localhost-firstSAN-sv.pubkey-pinned b/tests/certs/Server-localhost-firstSAN-sv.pubkey-pinned
new file mode 100644
index 0000000..892077d
--- /dev/null
+++ b/tests/certs/Server-localhost-firstSAN-sv.pubkey-pinned
@@ -0,0 +1 @@
++V1rGPoCoOLZjthRz6LwtLV9Z/6Gds5LH3j8KUrCIwc=
diff --git a/tests/certs/Server-localhost-lastSAN-sv.crl b/tests/certs/Server-localhost-lastSAN-sv.crl
index f876774..e47a90c 100644
--- a/tests/certs/Server-localhost-lastSAN-sv.crl
+++ b/tests/certs/Server-localhost-lastSAN-sv.crl
@@ -1,12 +1,15 @@
-----BEGIN X509 CRL-----
-MIIB3DCBxQIBATANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJOTjExMC8GA1UE
-CgwoRWRlbCBDdXJsIEFyY3RpYyBJbGx1ZGl1bSBSZXNlYXJjaCBDbG91ZDEmMCQG
-A1UEAwwdTm9ydGhlcm4gTm93aGVyZSBUcnVzdCBBbmNob3IXDTE5MTEwMjEyNTMy
-N1oXDTE5MTIwMjEyNTMyN1owGTAXAgYOTbnGJLAXDTE5MTEwMjEyNTMyNlqgDjAM
-MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4IBAQClxELmQvUD2S0UcNFbjMe/
-vv80HtpnwhTK356DUggVBh+EjvIXT4EakBbxxgDZMkaxJYH70RQ0UPLtB41pfmg3
-BS6Gl/0Vn+cAk8w/+dG4DHibdeqSPjIHCaAlkKqHV89Lp7IS6qrD0Bn/L7De6O7c
-4xLvRiDvx/cO5uAkX8vOtzKsOU/0U06QSSGK09dRL2mHbaH4FQj2PFMgcDd1GxAQ
-saii0bWZ6qLiYkQRtJGAplD+uqOaSSsioqVFy/NjaIip0axNtCG9sBhvp6lTpeiR
-Phl04I+WyKoP5f/NTU+fKbWarWka4evPSpRM2o9QYrYb/vj0TMK8lJ3JqgwlLrJ+
+MIICQTCCASkCAQEwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UEBhMCTk4xMTAvBgNV
+BAoMKEVkZWwgQ3VybCBBcmN0aWMgSWxsdWRpdW0gUmVzZWFyY2ggQ2xvdWQxJjAk
+BgNVBAMMHU5vcnRoZXJuIE5vd2hlcmUgVHJ1c3QgQW5jaG9yFw0yMjEyMjMxMjIx
+MzhaFw0yMzAxMjIxMjIxMzhaMH0wFwIGDzR1USo8Fw0yMjEyMjMxMjIxMzZaMBcC
+Bg80dVFRYRcNMjIxMjIzMTIyMTM3WjAXAgYPNHVRUXUXDTIyMTIyMzEyMjEzN1ow
+FwIGDzR1UVGJFw0yMjEyMjMxMjIxMzhaMBcCBg80dVF4rhcNMjIxMjIzMTIyMTM4
+WqAOMAwwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBADZeuue7woDyqDdc
+DCxuNE94pNl78cTedT+V9svX0gbMExAI0WRovb9FudimX+CRofFTwZ4RSDF7AdHw
+PqbVSMjZtGTlQrKrMAZ5kBMs9ZI1tWGpGVJNxv4hKMt2VITLPJ22CP8j3yZahNpw
+/kgJQx+7aIRKTC1n6UEAsOsLyDsrFDvdXU2euU0NIx6KudeRUagdgyOntwrLaeeW
++g18IZTewQWefx4iA6eW6y3E9CM0n3d4n7VAxLb95TysLAUoxOeVxtUSa+wm8jWt
+gjm/2UkFxX79dDhDMc5LsL9mBDL3dasunhcUCtI5CTL1aX2Fg2YkztsyQiO0lNx/
+meUHDNM=
-----END X509 CRL-----
diff --git a/tests/certs/Server-localhost-lastSAN-sv.crt b/tests/certs/Server-localhost-lastSAN-sv.crt
index 578fff7..ec37cf1 100644
--- a/tests/certs/Server-localhost-lastSAN-sv.crt
+++ b/tests/certs/Server-localhost-lastSAN-sv.crt
@@ -1,42 +1,41 @@
Certificate:
Data:
Version: 3 (0x2)
- Serial Number:
- 0e:4d:b9:c6:24:b0
+ Serial Number: 16717980989614 (0xf34755178ae)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = Northern Nowhere Trust Anchor
Validity
- Not Before: Nov 2 12:53:25 2019 GMT
- Not After : Jan 19 12:53:25 2028 GMT
+ Not Before: Dec 23 12:21:38 2022 GMT
+ Not After : Mar 11 12:21:38 2031 GMT
Subject:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = localhost.nn
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:bd:97:0e:a7:6d:b6:73:8c:d0:21:6b:f3:36:74:
- 5d:0a:aa:3a:f0:fa:6e:b1:5c:1c:13:74:ca:67:2b:
- 22:03:d1:a6:3c:25:ef:87:4f:e8:38:9f:21:1d:2e:
- 88:12:36:66:82:03:02:4c:f8:17:35:02:95:31:b1:
- 53:40:21:24:2f:00:f0:bf:80:58:16:b1:92:b3:d3:
- 78:bf:78:cb:0a:91:0c:d2:6d:5d:b2:1f:41:73:16:
- 02:7c:1a:cd:16:25:c9:e1:1b:81:bd:84:93:4c:63:
- ce:38:f4:3e:ad:98:6b:00:89:a8:ba:f5:7e:08:83:
- f3:9a:f5:98:b8:9f:d6:d8:c7:d4:f3:07:1c:8f:ef:
- bc:29:10:60:8c:85:8b:4c:7a:73:c7:9f:a8:23:2f:
- c4:47:f5:18:85:98:fb:27:de:58:93:4b:08:a5:66:
- c9:df:db:f0:22:f8:64:9f:a1:56:89:97:ab:02:2c:
- 5a:99:f2:6f:bf:72:31:90:22:32:ae:86:25:6b:13:
- c6:72:ec:df:2e:c8:12:00:c1:e3:38:b4:a0:40:ba:
- 01:61:c2:d7:b1:ef:7d:4b:29:18:e2:fe:28:d0:98:
- e4:65:3f:4c:34:39:e4:82:a9:ca:b2:3d:c4:91:8f:
- a0:94:bf:e3:f8:b3:73:48:b7:fe:fa:04:43:e7:b5:
- bc:bd
+ 00:c8:84:fe:69:64:33:c3:dc:b5:74:8a:c7:b2:bb:
+ d9:69:e2:a9:95:6d:5f:b7:25:e6:82:00:2b:f5:53:
+ 21:e7:28:ae:66:b6:38:fd:15:b1:91:88:52:31:29:
+ bb:73:e2:e0:99:62:95:44:35:51:d7:54:c8:d2:6d:
+ 25:3c:f0:2e:03:1b:a8:a1:25:e1:83:9a:5c:bd:65:
+ 57:93:44:7e:a3:cc:dd:ac:59:69:60:01:e0:80:b9:
+ d0:c4:70:63:cf:17:a0:c6:13:0f:21:3b:c8:c1:46:
+ 4e:18:fd:6a:36:76:24:4a:57:d8:73:2f:13:42:a0:
+ 2e:90:1f:bf:84:9d:81:e7:bd:f8:75:53:f3:fa:52:
+ e1:f0:aa:f6:23:d7:0d:61:17:0c:e5:9a:ab:e2:d5:
+ e8:c3:c9:6b:2a:a6:da:f9:cb:f6:4d:1d:40:53:7e:
+ 68:2f:51:9f:d3:17:95:34:21:32:0d:47:d6:a9:4d:
+ 28:bb:e0:50:13:2f:5b:76:a1:90:5a:51:48:2f:ce:
+ db:d9:da:2e:d1:3a:0f:fb:80:61:24:0b:0b:79:b2:
+ 45:cd:1d:2d:66:ee:4a:96:5d:08:b7:c4:80:95:2d:
+ 4e:8e:ac:0e:15:fa:2c:06:0c:49:74:49:81:77:17:
+ a5:b2:01:de:aa:88:2b:9a:66:13:bb:06:b4:89:fb:
+ e4:91
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
@@ -46,48 +45,56 @@
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Key Identifier:
- 4E:54:63:95:A1:58:0C:FA:BD:3E:58:26:AF:AF:A4:F3:66:1A:CB:25
+ B3:77:93:C4:CA:9A:B3:62:CF:51:0D:17:1D:8E:87:F6:C2:3E:17:75
X509v3 Authority Key Identifier:
- keyid:12:CA:BA:4B:46:04:A7:75:8A:2C:E8:0E:54:94:BC:12:65:A6:7B:CE
-
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
X509v3 Basic Constraints:
CA:FALSE
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
Signature Algorithm: sha256WithRSAEncryption
- 2c:f9:48:33:7c:93:ca:3c:9c:58:92:8c:2b:87:61:9f:0d:9c:
- 9d:e8:43:43:12:d6:a3:40:71:ec:cb:31:76:80:68:b1:54:d1:
- 86:f4:b3:9e:c8:50:62:b4:87:12:be:9b:d6:3c:2b:cf:22:0e:
- 66:26:c2:31:dd:1f:c6:97:1e:61:a4:51:ea:68:75:81:66:b9:
- 3b:a6:1f:f6:80:ec:6b:aa:65:66:0c:02:ab:c9:57:bd:6a:4e:
- 6d:24:30:13:7b:65:17:60:9a:14:37:57:f7:22:66:55:7d:1a:
- 1a:5b:27:43:3b:d4:88:bc:2f:d3:d7:bb:d5:3f:9b:25:26:5d:
- 39:a0:4c:8a:84:2c:db:04:87:8a:df:49:7d:4b:d2:85:7a:09:
- 5e:df:6b:1b:b5:6e:9c:bb:2b:f6:c5:01:19:5a:87:d0:cf:16:
- 67:8b:54:41:87:c1:33:c3:21:f6:e5:84:d2:84:5d:da:82:cd:
- 39:4d:50:97:f3:83:37:9e:e5:04:0e:dc:c6:20:d1:b3:f6:c7:
- 3d:dd:95:be:8c:b9:72:72:7a:71:66:aa:4a:8e:cf:37:38:e8:
- c8:06:69:68:8d:d8:d6:8b:4c:23:50:27:fa:e9:bb:2a:a6:89:
- 56:ad:be:4d:bd:be:0c:d7:55:b4:f4:b9:f7:6a:b5:2c:7f:5f:
- 9f:df:f6:61
+ Signature Value:
+ 10:22:60:56:f6:14:b7:03:18:c4:01:ba:06:c7:65:49:98:d7:
+ 64:64:d4:2a:2b:19:16:d1:0e:e9:b0:04:86:01:fb:ae:37:e4:
+ c9:19:37:d5:02:27:63:da:6f:de:a2:d0:23:36:7f:2f:3e:55:
+ d2:b5:ef:23:5d:f7:ac:71:3f:95:77:bc:74:d3:1e:51:d9:7d:
+ 7e:0d:8e:03:f3:82:95:3e:88:dd:3c:ed:3a:aa:b4:e1:85:fb:
+ d8:ea:3f:6a:7d:34:b7:b3:df:b1:fe:2b:ec:af:e0:1c:9c:ec:
+ 43:63:80:17:3a:32:ca:13:35:2d:c7:3d:3e:ac:aa:55:d6:1a:
+ 6d:3f:f0:ff:23:4f:e0:88:a1:42:d9:91:1c:a5:6b:87:14:1b:
+ 0b:4d:24:a8:33:36:7a:21:f7:e2:86:9c:65:36:f3:7c:0c:4d:
+ be:f1:98:45:c3:27:e4:11:4a:7d:8a:e3:70:ae:fb:ac:9f:a6:
+ f4:0d:dc:a7:83:39:50:c3:1e:1a:95:68:0d:b0:56:8f:64:d2:
+ db:a1:a7:97:d1:2c:ea:7a:f9:9b:2f:5f:4d:ed:7c:f9:df:74:
+ 1a:81:73:79:f8:00:2a:78:18:23:72:7a:4b:66:6b:61:da:95:
+ 29:85:7c:4d:42:76:2e:43:70:6d:ac:0c:dc:98:d5:47:da:e1:
+ 54:0c:71:bf
-----BEGIN CERTIFICATE-----
-MIID3jCCAsagAwIBAgIGDk25xiSwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+MIIEXzCCA0egAwIBAgIGDzR1UXiuMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
-Fw0xOTExMDIxMjUzMjVaFw0yODAxMTkxMjUzMjVaMFcxCzAJBgNVBAYTAk5OMTEw
+Fw0yMjEyMjMxMjIxMzhaFw0zMTAzMTExMjIxMzhaMFcxCzAJBgNVBAYTAk5OMTEw
LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
MRUwEwYDVQQDDAxsb2NhbGhvc3Qubm4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQC9lw6nbbZzjNAha/M2dF0Kqjrw+m6xXBwTdMpnKyID0aY8Je+HT+g4
-nyEdLogSNmaCAwJM+Bc1ApUxsVNAISQvAPC/gFgWsZKz03i/eMsKkQzSbV2yH0Fz
-FgJ8Gs0WJcnhG4G9hJNMY8449D6tmGsAiai69X4Ig/Oa9Zi4n9bYx9TzBxyP77wp
-EGCMhYtMenPHn6gjL8RH9RiFmPsn3liTSwilZsnf2/Ai+GSfoVaJl6sCLFqZ8m+/
-cjGQIjKuhiVrE8Zy7N8uyBIAweM4tKBAugFhwtex731LKRji/ijQmORlP0w0OeSC
-qcqyPcSRj6CUv+P4s3NIt/76BEPntby9AgMBAAGjgZ4wgZswLAYDVR0RBCUwI4IK
-bG9jYWxob3N0MYIKbG9jYWxob3N0MoIJbG9jYWxob3N0MAsGA1UdDwQEAwIDqDAT
-BgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUTlRjlaFYDPq9Plgmr6+k82Ya
-yyUwHwYDVR0jBBgwFoAUEsq6S0YEp3WKLOgOVJS8EmWme84wCQYDVR0TBAIwADAN
-BgkqhkiG9w0BAQsFAAOCAQEALPlIM3yTyjycWJKMK4dhnw2cnehDQxLWo0Bx7Msx
-doBosVTRhvSznshQYrSHEr6b1jwrzyIOZibCMd0fxpceYaRR6mh1gWa5O6Yf9oDs
-a6plZgwCq8lXvWpObSQwE3tlF2CaFDdX9yJmVX0aGlsnQzvUiLwv09e71T+bJSZd
-OaBMioQs2wSHit9JfUvShXoJXt9rG7VunLsr9sUBGVqH0M8WZ4tUQYfBM8Mh9uWE
-0oRd2oLNOU1Ql/ODN57lBA7cxiDRs/bHPd2Vvoy5cnJ6cWaqSo7PNzjoyAZpaI3Y
-1otMI1An+um7KqaJVq2+Tb2+DNdVtPS592q1LH9fn9/2YQ==
+ggEKAoIBAQDIhP5pZDPD3LV0iseyu9lp4qmVbV+3JeaCACv1UyHnKK5mtjj9FbGR
+iFIxKbtz4uCZYpVENVHXVMjSbSU88C4DG6ihJeGDmly9ZVeTRH6jzN2sWWlgAeCA
+udDEcGPPF6DGEw8hO8jBRk4Y/Wo2diRKV9hzLxNCoC6QH7+EnYHnvfh1U/P6UuHw
+qvYj1w1hFwzlmqvi1ejDyWsqptr5y/ZNHUBTfmgvUZ/TF5U0ITINR9apTSi74FAT
+L1t2oZBaUUgvztvZ2i7ROg/7gGEkCwt5skXNHS1m7kqWXQi3xICVLU6OrA4V+iwG
+DEl0SYF3F6WyAd6qiCuaZhO7BrSJ++SRAgMBAAGjggEeMIIBGjAsBgNVHREEJTAj
+ggpsb2NhbGhvc3Qxggpsb2NhbGhvc3Qygglsb2NhbGhvc3QwCwYDVR0PBAQDAgOo
+MBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1UdDgQWBBSzd5PEypqzYs9RDRcdjof2
+wj4XdTAfBgNVHSMEGDAWgBSHy7EzLsFnfnHj5StMTaSzbtJbqTAJBgNVHRMEAjAA
+MEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcwAoYnaHR0cDovL3Rlc3QuY3VybC5z
+ZS9jYS9FZGVsQ3VybFJvb3QuY2VyMDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly90
+ZXN0LmN1cmwuc2UvY2EvRWRlbEN1cmxSb290LmNybDANBgkqhkiG9w0BAQsFAAOC
+AQEAECJgVvYUtwMYxAG6BsdlSZjXZGTUKisZFtEO6bAEhgH7rjfkyRk31QInY9pv
+3qLQIzZ/Lz5V0rXvI133rHE/lXe8dNMeUdl9fg2OA/OClT6I3TztOqq04YX72Oo/
+an00t7Pfsf4r7K/gHJzsQ2OAFzoyyhM1Lcc9PqyqVdYabT/w/yNP4IihQtmRHKVr
+hxQbC00kqDM2eiH34oacZTbzfAxNvvGYRcMn5BFKfYrjcK77rJ+m9A3cp4M5UMMe
+GpVoDbBWj2TS26Gnl9Es6nr5my9fTe18+d90GoFzefgAKngYI3J6S2ZrYdqVKYV8
+TUJ2LkNwbawM3JjVR9rhVAxxvw==
-----END CERTIFICATE-----
diff --git a/tests/certs/Server-localhost-lastSAN-sv.csr b/tests/certs/Server-localhost-lastSAN-sv.csr
index a113db6..ec93078 100644
--- a/tests/certs/Server-localhost-lastSAN-sv.csr
+++ b/tests/certs/Server-localhost-lastSAN-sv.csr
@@ -1,16 +1,16 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICnDCCAYQCAQAwVzELMAkGA1UEBhMCTk4xMTAvBgNVBAoMKEVkZWwgQ3VybCBB
cmN0aWMgSWxsdWRpdW0gUmVzZWFyY2ggQ2xvdWQxFTATBgNVBAMMDGxvY2FsaG9z
-dC5ubjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2XDqdttnOM0CFr
-8zZ0XQqqOvD6brFcHBN0ymcrIgPRpjwl74dP6DifIR0uiBI2ZoIDAkz4FzUClTGx
-U0AhJC8A8L+AWBaxkrPTeL94ywqRDNJtXbIfQXMWAnwazRYlyeEbgb2Ek0xjzjj0
-Pq2YawCJqLr1fgiD85r1mLif1tjH1PMHHI/vvCkQYIyFi0x6c8efqCMvxEf1GIWY
-+yfeWJNLCKVmyd/b8CL4ZJ+hVomXqwIsWpnyb79yMZAiMq6GJWsTxnLs3y7IEgDB
-4zi0oEC6AWHC17HvfUspGOL+KNCY5GU/TDQ55IKpyrI9xJGPoJS/4/izc0i3/voE
-Q+e1vL0CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCpqiSx7VjqeQ2g8lpHF0Nb
-/10H1DqaK7Z3y49xFK3xxKWdxKUdq3Nf7JYlhKpWDYokrkw5W+nhGQILYt6ZD8tN
-tBZphyp3rvmTcewEFtbBne5N7OsAaanlBxeCLhnCICGhd+QCqYJKWe+zw8Oc5dCp
-SRmWEL5FTu9AavBc0LDx1gNBupDiXGhF+BptOzgfDbijd0aRgy9cYwAQ9kXo4H+y
-TH1ZYcSfB0gs7sShiY5FvuGr54Vv0czn+HqrdyWKDGLp7ilPYCT4WXBWfTon9j1H
-9NDomhrVme9IGKItYHg+p59WpevklW900X4NZCVspePgNeBOvXYbGqDEN01o1xIG
+dC5ubjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMiE/mlkM8PctXSK
+x7K72WniqZVtX7cl5oIAK/VTIecorma2OP0VsZGIUjEpu3Pi4JlilUQ1UddUyNJt
+JTzwLgMbqKEl4YOaXL1lV5NEfqPM3axZaWAB4IC50MRwY88XoMYTDyE7yMFGThj9
+ajZ2JEpX2HMvE0KgLpAfv4Sdgee9+HVT8/pS4fCq9iPXDWEXDOWaq+LV6MPJayqm
+2vnL9k0dQFN+aC9Rn9MXlTQhMg1H1qlNKLvgUBMvW3ahkFpRSC/O29naLtE6D/uA
+YSQLC3myRc0dLWbuSpZdCLfEgJUtTo6sDhX6LAYMSXRJgXcXpbIB3qqIK5pmE7sG
+tIn75JECAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCeDxLX9uy0Fv7yaY/gqL/G
+x+TFx7xoKOJwqu3NqrGiTfs6SeXvmxIj5oOE2gBi9cjc184TUa/zHSW+iYug2RVO
+f18zO3sOUXeFLN10f1OEgkOEm6k9I4MuWhEJuCY0FePAl6i71b4iy2O6n0CxLNKB
+D+IM8MBOjx18Ev+BETXmf2R6zyQaVY+VP541XRtcCwcMU9IV92CilhfHjPJy3g4V
+7mQIcvgdpQMuQLsBvMY+yFRUwRpWiPjOOot5q6bQKgA5pcRU7UtraqLzT7gG9cF2
+SDN2y9A05EWYZB7/hlg+URdJKjrCLn20i5BR52VVepLDWUOCBafkdCOp1O6JTRK2
-----END CERTIFICATE REQUEST-----
diff --git a/tests/certs/Server-localhost-lastSAN-sv.der b/tests/certs/Server-localhost-lastSAN-sv.der
index c72bcb9..c4706a5 100644
--- a/tests/certs/Server-localhost-lastSAN-sv.der
+++ b/tests/certs/Server-localhost-lastSAN-sv.der
Binary files differ
diff --git a/tests/certs/Server-localhost-lastSAN-sv.key b/tests/certs/Server-localhost-lastSAN-sv.key
index dae4828..7a5d854 100644
--- a/tests/certs/Server-localhost-lastSAN-sv.key
+++ b/tests/certs/Server-localhost-lastSAN-sv.key
@@ -1,27 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEAvZcOp222c4zQIWvzNnRdCqo68PpusVwcE3TKZysiA9GmPCXv
-h0/oOJ8hHS6IEjZmggMCTPgXNQKVMbFTQCEkLwDwv4BYFrGSs9N4v3jLCpEM0m1d
-sh9BcxYCfBrNFiXJ4RuBvYSTTGPOOPQ+rZhrAImouvV+CIPzmvWYuJ/W2MfU8wcc
-j++8KRBgjIWLTHpzx5+oIy/ER/UYhZj7J95Yk0sIpWbJ39vwIvhkn6FWiZerAixa
-mfJvv3IxkCIyroYlaxPGcuzfLsgSAMHjOLSgQLoBYcLXse99SykY4v4o0JjkZT9M
-NDnkgqnKsj3EkY+glL/j+LNzSLf++gRD57W8vQIDAQABAoIBAQCC0wTKpdtbmtRX
-66y1a9B0NolblgPiISRCjLnKPSpIpldmc+r4XTxqLexkvaIppx5PIpJo2FzzOGgJ
-FUrUGspkIOr/yil+52PK8OcGgOziyrqlTdB0xDqelpZ6WuggG01WJ2v8gco+0TQR
-ewDxOxbDFTq4YARrDdqAmG6dH7baeMDvh6IVe/dkJOVlyh0MA2QP+VR6fDv73jUe
-3yW6G+hql9mjZK6Cgz2lWoeW7YXAvWtTXT68/bcZLO64oLyCjBmsbSrBRQN5m9M9
-dWJV5B0h02P+uMF5H+EAD3qN5I670iSY3d+FWBpd3cA2arRGWlUXNmCGG3CjLYUS
-wGw1lbFhAoGBAPG6JhdXAaH3DN9khp54plbFSIanvjWK8RAEaQgkurwDUL3o1LmC
-ObqiCmMTU25HRlwWkwlCxejHfzOEqFdwiX5QuNmYBE6TYHtmnWSJ5ebMG7SOtlIS
-9Z4dLNZz8j95OGKb3XI9qR0ItxsmuLgWvrJUayd0UXcU7BTzHCXGx99JAoGBAMjI
-0z5+DeTwBhDY1mIUY081FmhrT9PhFHGtRy2OIENW0ZhJ5yE+ygVQssnR+Lr/yl1p
-zGC+CM//5wmJ774Xx0reMsh/rgK4Z0Wq47JJFGo0RMfYVmlod0OndtdobDc7ds7t
-Q3wIGt2ZXW6BtzMo8KVUuuHL8QwZoZqJNe/7QE3VAoGAGGrRRjJHu/CUoEwrPP66
-7rDm7pMrJ4VtbEzFv0jWg/9hvI00T7jT1AJiQjfFibIxbUPqflj8XNMqCi4wQwTf
-Hp9QzMoKRVWlvVFUPL+hNXsQoWB5EjlQDjSsPs1ffwHjrDJKYCvSVVh4BooWxqGl
-iaX1XPrm77xxTHxyL26w6eECgYA176S3g9stpcCrY+RrInju/R7Q3Arsquj4BIk7
-VpOaI0dYdnnNN3XDacMtbec4LKBq6ZHKZyIs5dxldpVdZjvWA8x2ib3v4yNy1o4m
-BXWjdfkICjhkRnjLRsAo61cumx22Row7VF4LKzirB9NzvcqvTwyIvWU6T+RWhAdm
-OQM0JQKBgC+gmBGfnQShTRYlfpb4RVnDijPpC34AdEO7wdeMcdQK9KfWsLZT5y0w
-qoZhW9IPlu1dNRhwHqGHWu2CmQVwFpy5/ccpukCJfyZw7edbb9dIqzKlUWw8Jmmg
-C7WKz4z3mKkZrwptFxDu0dpQ644yOP/gnRaLLyP0zn/brmnYz09X
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDIhP5pZDPD3LV0
+iseyu9lp4qmVbV+3JeaCACv1UyHnKK5mtjj9FbGRiFIxKbtz4uCZYpVENVHXVMjS
+bSU88C4DG6ihJeGDmly9ZVeTRH6jzN2sWWlgAeCAudDEcGPPF6DGEw8hO8jBRk4Y
+/Wo2diRKV9hzLxNCoC6QH7+EnYHnvfh1U/P6UuHwqvYj1w1hFwzlmqvi1ejDyWsq
+ptr5y/ZNHUBTfmgvUZ/TF5U0ITINR9apTSi74FATL1t2oZBaUUgvztvZ2i7ROg/7
+gGEkCwt5skXNHS1m7kqWXQi3xICVLU6OrA4V+iwGDEl0SYF3F6WyAd6qiCuaZhO7
+BrSJ++SRAgMBAAECggEAApUDLABsPI6EGqj/1dDJRa2zcSxm92DfpUG9zytVIYN6
+rXFqw0g10LyF5xf/uogLzDCCtg25YlG3QqMWVUDNguDmt2kutycJddnkemMUfg+m
+X3CzpJbEQ+bApgrsH2+micPB5d5odnlX35wByQuVP4zT3sssJGc+JOvNEkwvRE3o
+0x+B7qnW5YWDA9X67Sb9Kgcg9xExC7lbUqQoDetpa6x36LVx2OCqmomIKf8CQqHr
+FOOTKNkTs6mal3jxxxwvLmj7Bkz+InSIRK0VE9d5G2VWliwcRMVjB9c5oh/P6Le3
+/jCyi18omkMgQK0Hm6CJBjsT+PdJu09hbo1TXD8cbQKBgQD8CwQNzHSolSUoKMpd
+SfsAIB5gjILns7xAAtemkHEn15ga6p7510wtvkWAzOqBtt3RrTqb/AoWKUkHwfRd
+AYFE1RrGVUA0Yohuf4eJFjAXuEQXNKx2uuHIpwEf0UpfiyAFLzDyUmTjMHLw15ZP
+OrhIHJBRfWiU9nWIScNZC4/A7QKBgQDLquZxndjls3h/LotU62CcjZSqU59Wbhfs
+VoGDgvj5jxxdcy4u7BntYYBKsaIL7k/Q6vyrNWnQoUgazhIqJ3RJ2p3OzaCLjKY8
+7+vf8F1bSZL+VbHTJZfuPKKShGlIfZ0ixjuP0vEUh+xblEwsmgNN4XOc/M/mVyid
+qek2xFPRtQKBgA8SXZCxrDw0hv9KyScg+Gh+gzKE1IMkhVpSkTC9rHaUdt0NMKqC
+DGUj3qYgGtnc5JDYSgvv226N03cqSwGQyHkkQTChAnDff4cUCzfQYtnYRAIbPUDw
+VfYYvoF3k3n5KNYGh2fGM5A+YnEygyODwGdXhe3JkQpvXoHi31Kg1VzVAoGBAKGa
+JCmopq50PjskElg6P7lYucqAeaCZ0I+tgCx6otVZ0ZbwyodevZ/WSnZ6BetTl69c
+lUnAIwrwvgbO1ijuj13+glLSY/32hv05Hb7duSWy9liqZGP2o1vcbt61A9kKGsG5
+6w7OwI2a4Fc2D08gkVideB/rlYbeR5L6e9sB4sQ1AoGAcLMiz2/cF40/pMhqq/C/
+SyFDa1OAquW00PujVrTbgIHY+2HdjaIlzwNVFWIY/K7LCJtLvK6mVCVbo1n7/Agp
+qYZZzPEUwJ84ZY1ZNxC0Z89dBFmJeFvyNSan9zGujye7Kx8QctCvn5DzjoWtA52k
+MvALyxOMqzvGI5bC4r1o3Hw=
+-----END PRIVATE KEY-----
diff --git a/tests/certs/Server-localhost-lastSAN-sv.pem b/tests/certs/Server-localhost-lastSAN-sv.pem
index 42e4a11..b1cbd4b 100644
--- a/tests/certs/Server-localhost-lastSAN-sv.pem
+++ b/tests/certs/Server-localhost-lastSAN-sv.pem
@@ -6,6 +6,19 @@
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
basicConstraints = CA:false
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
+
[ req ]
default_bits = 1024
distinguished_name = req_DN
@@ -23,72 +36,72 @@
# The key
# the certificate
# some dhparam
------BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEAvZcOp222c4zQIWvzNnRdCqo68PpusVwcE3TKZysiA9GmPCXv
-h0/oOJ8hHS6IEjZmggMCTPgXNQKVMbFTQCEkLwDwv4BYFrGSs9N4v3jLCpEM0m1d
-sh9BcxYCfBrNFiXJ4RuBvYSTTGPOOPQ+rZhrAImouvV+CIPzmvWYuJ/W2MfU8wcc
-j++8KRBgjIWLTHpzx5+oIy/ER/UYhZj7J95Yk0sIpWbJ39vwIvhkn6FWiZerAixa
-mfJvv3IxkCIyroYlaxPGcuzfLsgSAMHjOLSgQLoBYcLXse99SykY4v4o0JjkZT9M
-NDnkgqnKsj3EkY+glL/j+LNzSLf++gRD57W8vQIDAQABAoIBAQCC0wTKpdtbmtRX
-66y1a9B0NolblgPiISRCjLnKPSpIpldmc+r4XTxqLexkvaIppx5PIpJo2FzzOGgJ
-FUrUGspkIOr/yil+52PK8OcGgOziyrqlTdB0xDqelpZ6WuggG01WJ2v8gco+0TQR
-ewDxOxbDFTq4YARrDdqAmG6dH7baeMDvh6IVe/dkJOVlyh0MA2QP+VR6fDv73jUe
-3yW6G+hql9mjZK6Cgz2lWoeW7YXAvWtTXT68/bcZLO64oLyCjBmsbSrBRQN5m9M9
-dWJV5B0h02P+uMF5H+EAD3qN5I670iSY3d+FWBpd3cA2arRGWlUXNmCGG3CjLYUS
-wGw1lbFhAoGBAPG6JhdXAaH3DN9khp54plbFSIanvjWK8RAEaQgkurwDUL3o1LmC
-ObqiCmMTU25HRlwWkwlCxejHfzOEqFdwiX5QuNmYBE6TYHtmnWSJ5ebMG7SOtlIS
-9Z4dLNZz8j95OGKb3XI9qR0ItxsmuLgWvrJUayd0UXcU7BTzHCXGx99JAoGBAMjI
-0z5+DeTwBhDY1mIUY081FmhrT9PhFHGtRy2OIENW0ZhJ5yE+ygVQssnR+Lr/yl1p
-zGC+CM//5wmJ774Xx0reMsh/rgK4Z0Wq47JJFGo0RMfYVmlod0OndtdobDc7ds7t
-Q3wIGt2ZXW6BtzMo8KVUuuHL8QwZoZqJNe/7QE3VAoGAGGrRRjJHu/CUoEwrPP66
-7rDm7pMrJ4VtbEzFv0jWg/9hvI00T7jT1AJiQjfFibIxbUPqflj8XNMqCi4wQwTf
-Hp9QzMoKRVWlvVFUPL+hNXsQoWB5EjlQDjSsPs1ffwHjrDJKYCvSVVh4BooWxqGl
-iaX1XPrm77xxTHxyL26w6eECgYA176S3g9stpcCrY+RrInju/R7Q3Arsquj4BIk7
-VpOaI0dYdnnNN3XDacMtbec4LKBq6ZHKZyIs5dxldpVdZjvWA8x2ib3v4yNy1o4m
-BXWjdfkICjhkRnjLRsAo61cumx22Row7VF4LKzirB9NzvcqvTwyIvWU6T+RWhAdm
-OQM0JQKBgC+gmBGfnQShTRYlfpb4RVnDijPpC34AdEO7wdeMcdQK9KfWsLZT5y0w
-qoZhW9IPlu1dNRhwHqGHWu2CmQVwFpy5/ccpukCJfyZw7edbb9dIqzKlUWw8Jmmg
-C7WKz4z3mKkZrwptFxDu0dpQ644yOP/gnRaLLyP0zn/brmnYz09X
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDIhP5pZDPD3LV0
+iseyu9lp4qmVbV+3JeaCACv1UyHnKK5mtjj9FbGRiFIxKbtz4uCZYpVENVHXVMjS
+bSU88C4DG6ihJeGDmly9ZVeTRH6jzN2sWWlgAeCAudDEcGPPF6DGEw8hO8jBRk4Y
+/Wo2diRKV9hzLxNCoC6QH7+EnYHnvfh1U/P6UuHwqvYj1w1hFwzlmqvi1ejDyWsq
+ptr5y/ZNHUBTfmgvUZ/TF5U0ITINR9apTSi74FATL1t2oZBaUUgvztvZ2i7ROg/7
+gGEkCwt5skXNHS1m7kqWXQi3xICVLU6OrA4V+iwGDEl0SYF3F6WyAd6qiCuaZhO7
+BrSJ++SRAgMBAAECggEAApUDLABsPI6EGqj/1dDJRa2zcSxm92DfpUG9zytVIYN6
+rXFqw0g10LyF5xf/uogLzDCCtg25YlG3QqMWVUDNguDmt2kutycJddnkemMUfg+m
+X3CzpJbEQ+bApgrsH2+micPB5d5odnlX35wByQuVP4zT3sssJGc+JOvNEkwvRE3o
+0x+B7qnW5YWDA9X67Sb9Kgcg9xExC7lbUqQoDetpa6x36LVx2OCqmomIKf8CQqHr
+FOOTKNkTs6mal3jxxxwvLmj7Bkz+InSIRK0VE9d5G2VWliwcRMVjB9c5oh/P6Le3
+/jCyi18omkMgQK0Hm6CJBjsT+PdJu09hbo1TXD8cbQKBgQD8CwQNzHSolSUoKMpd
+SfsAIB5gjILns7xAAtemkHEn15ga6p7510wtvkWAzOqBtt3RrTqb/AoWKUkHwfRd
+AYFE1RrGVUA0Yohuf4eJFjAXuEQXNKx2uuHIpwEf0UpfiyAFLzDyUmTjMHLw15ZP
+OrhIHJBRfWiU9nWIScNZC4/A7QKBgQDLquZxndjls3h/LotU62CcjZSqU59Wbhfs
+VoGDgvj5jxxdcy4u7BntYYBKsaIL7k/Q6vyrNWnQoUgazhIqJ3RJ2p3OzaCLjKY8
+7+vf8F1bSZL+VbHTJZfuPKKShGlIfZ0ixjuP0vEUh+xblEwsmgNN4XOc/M/mVyid
+qek2xFPRtQKBgA8SXZCxrDw0hv9KyScg+Gh+gzKE1IMkhVpSkTC9rHaUdt0NMKqC
+DGUj3qYgGtnc5JDYSgvv226N03cqSwGQyHkkQTChAnDff4cUCzfQYtnYRAIbPUDw
+VfYYvoF3k3n5KNYGh2fGM5A+YnEygyODwGdXhe3JkQpvXoHi31Kg1VzVAoGBAKGa
+JCmopq50PjskElg6P7lYucqAeaCZ0I+tgCx6otVZ0ZbwyodevZ/WSnZ6BetTl69c
+lUnAIwrwvgbO1ijuj13+glLSY/32hv05Hb7duSWy9liqZGP2o1vcbt61A9kKGsG5
+6w7OwI2a4Fc2D08gkVideB/rlYbeR5L6e9sB4sQ1AoGAcLMiz2/cF40/pMhqq/C/
+SyFDa1OAquW00PujVrTbgIHY+2HdjaIlzwNVFWIY/K7LCJtLvK6mVCVbo1n7/Agp
+qYZZzPEUwJ84ZY1ZNxC0Z89dBFmJeFvyNSan9zGujye7Kx8QctCvn5DzjoWtA52k
+MvALyxOMqzvGI5bC4r1o3Hw=
+-----END PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number:
- 0e:4d:b9:c6:24:b0
+ Serial Number: 16717980989614 (0xf34755178ae)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = Northern Nowhere Trust Anchor
Validity
- Not Before: Nov 2 12:53:25 2019 GMT
- Not After : Jan 19 12:53:25 2028 GMT
+ Not Before: Dec 23 12:21:38 2022 GMT
+ Not After : Mar 11 12:21:38 2031 GMT
Subject:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = localhost.nn
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:bd:97:0e:a7:6d:b6:73:8c:d0:21:6b:f3:36:74:
- 5d:0a:aa:3a:f0:fa:6e:b1:5c:1c:13:74:ca:67:2b:
- 22:03:d1:a6:3c:25:ef:87:4f:e8:38:9f:21:1d:2e:
- 88:12:36:66:82:03:02:4c:f8:17:35:02:95:31:b1:
- 53:40:21:24:2f:00:f0:bf:80:58:16:b1:92:b3:d3:
- 78:bf:78:cb:0a:91:0c:d2:6d:5d:b2:1f:41:73:16:
- 02:7c:1a:cd:16:25:c9:e1:1b:81:bd:84:93:4c:63:
- ce:38:f4:3e:ad:98:6b:00:89:a8:ba:f5:7e:08:83:
- f3:9a:f5:98:b8:9f:d6:d8:c7:d4:f3:07:1c:8f:ef:
- bc:29:10:60:8c:85:8b:4c:7a:73:c7:9f:a8:23:2f:
- c4:47:f5:18:85:98:fb:27:de:58:93:4b:08:a5:66:
- c9:df:db:f0:22:f8:64:9f:a1:56:89:97:ab:02:2c:
- 5a:99:f2:6f:bf:72:31:90:22:32:ae:86:25:6b:13:
- c6:72:ec:df:2e:c8:12:00:c1:e3:38:b4:a0:40:ba:
- 01:61:c2:d7:b1:ef:7d:4b:29:18:e2:fe:28:d0:98:
- e4:65:3f:4c:34:39:e4:82:a9:ca:b2:3d:c4:91:8f:
- a0:94:bf:e3:f8:b3:73:48:b7:fe:fa:04:43:e7:b5:
- bc:bd
+ 00:c8:84:fe:69:64:33:c3:dc:b5:74:8a:c7:b2:bb:
+ d9:69:e2:a9:95:6d:5f:b7:25:e6:82:00:2b:f5:53:
+ 21:e7:28:ae:66:b6:38:fd:15:b1:91:88:52:31:29:
+ bb:73:e2:e0:99:62:95:44:35:51:d7:54:c8:d2:6d:
+ 25:3c:f0:2e:03:1b:a8:a1:25:e1:83:9a:5c:bd:65:
+ 57:93:44:7e:a3:cc:dd:ac:59:69:60:01:e0:80:b9:
+ d0:c4:70:63:cf:17:a0:c6:13:0f:21:3b:c8:c1:46:
+ 4e:18:fd:6a:36:76:24:4a:57:d8:73:2f:13:42:a0:
+ 2e:90:1f:bf:84:9d:81:e7:bd:f8:75:53:f3:fa:52:
+ e1:f0:aa:f6:23:d7:0d:61:17:0c:e5:9a:ab:e2:d5:
+ e8:c3:c9:6b:2a:a6:da:f9:cb:f6:4d:1d:40:53:7e:
+ 68:2f:51:9f:d3:17:95:34:21:32:0d:47:d6:a9:4d:
+ 28:bb:e0:50:13:2f:5b:76:a1:90:5a:51:48:2f:ce:
+ db:d9:da:2e:d1:3a:0f:fb:80:61:24:0b:0b:79:b2:
+ 45:cd:1d:2d:66:ee:4a:96:5d:08:b7:c4:80:95:2d:
+ 4e:8e:ac:0e:15:fa:2c:06:0c:49:74:49:81:77:17:
+ a5:b2:01:de:aa:88:2b:9a:66:13:bb:06:b4:89:fb:
+ e4:91
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
@@ -98,48 +111,56 @@
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Key Identifier:
- 4E:54:63:95:A1:58:0C:FA:BD:3E:58:26:AF:AF:A4:F3:66:1A:CB:25
+ B3:77:93:C4:CA:9A:B3:62:CF:51:0D:17:1D:8E:87:F6:C2:3E:17:75
X509v3 Authority Key Identifier:
- keyid:12:CA:BA:4B:46:04:A7:75:8A:2C:E8:0E:54:94:BC:12:65:A6:7B:CE
-
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
X509v3 Basic Constraints:
CA:FALSE
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
Signature Algorithm: sha256WithRSAEncryption
- 2c:f9:48:33:7c:93:ca:3c:9c:58:92:8c:2b:87:61:9f:0d:9c:
- 9d:e8:43:43:12:d6:a3:40:71:ec:cb:31:76:80:68:b1:54:d1:
- 86:f4:b3:9e:c8:50:62:b4:87:12:be:9b:d6:3c:2b:cf:22:0e:
- 66:26:c2:31:dd:1f:c6:97:1e:61:a4:51:ea:68:75:81:66:b9:
- 3b:a6:1f:f6:80:ec:6b:aa:65:66:0c:02:ab:c9:57:bd:6a:4e:
- 6d:24:30:13:7b:65:17:60:9a:14:37:57:f7:22:66:55:7d:1a:
- 1a:5b:27:43:3b:d4:88:bc:2f:d3:d7:bb:d5:3f:9b:25:26:5d:
- 39:a0:4c:8a:84:2c:db:04:87:8a:df:49:7d:4b:d2:85:7a:09:
- 5e:df:6b:1b:b5:6e:9c:bb:2b:f6:c5:01:19:5a:87:d0:cf:16:
- 67:8b:54:41:87:c1:33:c3:21:f6:e5:84:d2:84:5d:da:82:cd:
- 39:4d:50:97:f3:83:37:9e:e5:04:0e:dc:c6:20:d1:b3:f6:c7:
- 3d:dd:95:be:8c:b9:72:72:7a:71:66:aa:4a:8e:cf:37:38:e8:
- c8:06:69:68:8d:d8:d6:8b:4c:23:50:27:fa:e9:bb:2a:a6:89:
- 56:ad:be:4d:bd:be:0c:d7:55:b4:f4:b9:f7:6a:b5:2c:7f:5f:
- 9f:df:f6:61
+ Signature Value:
+ 10:22:60:56:f6:14:b7:03:18:c4:01:ba:06:c7:65:49:98:d7:
+ 64:64:d4:2a:2b:19:16:d1:0e:e9:b0:04:86:01:fb:ae:37:e4:
+ c9:19:37:d5:02:27:63:da:6f:de:a2:d0:23:36:7f:2f:3e:55:
+ d2:b5:ef:23:5d:f7:ac:71:3f:95:77:bc:74:d3:1e:51:d9:7d:
+ 7e:0d:8e:03:f3:82:95:3e:88:dd:3c:ed:3a:aa:b4:e1:85:fb:
+ d8:ea:3f:6a:7d:34:b7:b3:df:b1:fe:2b:ec:af:e0:1c:9c:ec:
+ 43:63:80:17:3a:32:ca:13:35:2d:c7:3d:3e:ac:aa:55:d6:1a:
+ 6d:3f:f0:ff:23:4f:e0:88:a1:42:d9:91:1c:a5:6b:87:14:1b:
+ 0b:4d:24:a8:33:36:7a:21:f7:e2:86:9c:65:36:f3:7c:0c:4d:
+ be:f1:98:45:c3:27:e4:11:4a:7d:8a:e3:70:ae:fb:ac:9f:a6:
+ f4:0d:dc:a7:83:39:50:c3:1e:1a:95:68:0d:b0:56:8f:64:d2:
+ db:a1:a7:97:d1:2c:ea:7a:f9:9b:2f:5f:4d:ed:7c:f9:df:74:
+ 1a:81:73:79:f8:00:2a:78:18:23:72:7a:4b:66:6b:61:da:95:
+ 29:85:7c:4d:42:76:2e:43:70:6d:ac:0c:dc:98:d5:47:da:e1:
+ 54:0c:71:bf
-----BEGIN CERTIFICATE-----
-MIID3jCCAsagAwIBAgIGDk25xiSwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+MIIEXzCCA0egAwIBAgIGDzR1UXiuMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
-Fw0xOTExMDIxMjUzMjVaFw0yODAxMTkxMjUzMjVaMFcxCzAJBgNVBAYTAk5OMTEw
+Fw0yMjEyMjMxMjIxMzhaFw0zMTAzMTExMjIxMzhaMFcxCzAJBgNVBAYTAk5OMTEw
LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
MRUwEwYDVQQDDAxsb2NhbGhvc3Qubm4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQC9lw6nbbZzjNAha/M2dF0Kqjrw+m6xXBwTdMpnKyID0aY8Je+HT+g4
-nyEdLogSNmaCAwJM+Bc1ApUxsVNAISQvAPC/gFgWsZKz03i/eMsKkQzSbV2yH0Fz
-FgJ8Gs0WJcnhG4G9hJNMY8449D6tmGsAiai69X4Ig/Oa9Zi4n9bYx9TzBxyP77wp
-EGCMhYtMenPHn6gjL8RH9RiFmPsn3liTSwilZsnf2/Ai+GSfoVaJl6sCLFqZ8m+/
-cjGQIjKuhiVrE8Zy7N8uyBIAweM4tKBAugFhwtex731LKRji/ijQmORlP0w0OeSC
-qcqyPcSRj6CUv+P4s3NIt/76BEPntby9AgMBAAGjgZ4wgZswLAYDVR0RBCUwI4IK
-bG9jYWxob3N0MYIKbG9jYWxob3N0MoIJbG9jYWxob3N0MAsGA1UdDwQEAwIDqDAT
-BgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUTlRjlaFYDPq9Plgmr6+k82Ya
-yyUwHwYDVR0jBBgwFoAUEsq6S0YEp3WKLOgOVJS8EmWme84wCQYDVR0TBAIwADAN
-BgkqhkiG9w0BAQsFAAOCAQEALPlIM3yTyjycWJKMK4dhnw2cnehDQxLWo0Bx7Msx
-doBosVTRhvSznshQYrSHEr6b1jwrzyIOZibCMd0fxpceYaRR6mh1gWa5O6Yf9oDs
-a6plZgwCq8lXvWpObSQwE3tlF2CaFDdX9yJmVX0aGlsnQzvUiLwv09e71T+bJSZd
-OaBMioQs2wSHit9JfUvShXoJXt9rG7VunLsr9sUBGVqH0M8WZ4tUQYfBM8Mh9uWE
-0oRd2oLNOU1Ql/ODN57lBA7cxiDRs/bHPd2Vvoy5cnJ6cWaqSo7PNzjoyAZpaI3Y
-1otMI1An+um7KqaJVq2+Tb2+DNdVtPS592q1LH9fn9/2YQ==
+ggEKAoIBAQDIhP5pZDPD3LV0iseyu9lp4qmVbV+3JeaCACv1UyHnKK5mtjj9FbGR
+iFIxKbtz4uCZYpVENVHXVMjSbSU88C4DG6ihJeGDmly9ZVeTRH6jzN2sWWlgAeCA
+udDEcGPPF6DGEw8hO8jBRk4Y/Wo2diRKV9hzLxNCoC6QH7+EnYHnvfh1U/P6UuHw
+qvYj1w1hFwzlmqvi1ejDyWsqptr5y/ZNHUBTfmgvUZ/TF5U0ITINR9apTSi74FAT
+L1t2oZBaUUgvztvZ2i7ROg/7gGEkCwt5skXNHS1m7kqWXQi3xICVLU6OrA4V+iwG
+DEl0SYF3F6WyAd6qiCuaZhO7BrSJ++SRAgMBAAGjggEeMIIBGjAsBgNVHREEJTAj
+ggpsb2NhbGhvc3Qxggpsb2NhbGhvc3Qygglsb2NhbGhvc3QwCwYDVR0PBAQDAgOo
+MBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1UdDgQWBBSzd5PEypqzYs9RDRcdjof2
+wj4XdTAfBgNVHSMEGDAWgBSHy7EzLsFnfnHj5StMTaSzbtJbqTAJBgNVHRMEAjAA
+MEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcwAoYnaHR0cDovL3Rlc3QuY3VybC5z
+ZS9jYS9FZGVsQ3VybFJvb3QuY2VyMDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly90
+ZXN0LmN1cmwuc2UvY2EvRWRlbEN1cmxSb290LmNybDANBgkqhkiG9w0BAQsFAAOC
+AQEAECJgVvYUtwMYxAG6BsdlSZjXZGTUKisZFtEO6bAEhgH7rjfkyRk31QInY9pv
+3qLQIzZ/Lz5V0rXvI133rHE/lXe8dNMeUdl9fg2OA/OClT6I3TztOqq04YX72Oo/
+an00t7Pfsf4r7K/gHJzsQ2OAFzoyyhM1Lcc9PqyqVdYabT/w/yNP4IihQtmRHKVr
+hxQbC00kqDM2eiH34oacZTbzfAxNvvGYRcMn5BFKfYrjcK77rJ+m9A3cp4M5UMMe
+GpVoDbBWj2TS26Gnl9Es6nr5my9fTe18+d90GoFzefgAKngYI3J6S2ZrYdqVKYV8
+TUJ2LkNwbawM3JjVR9rhVAxxvw==
-----END CERTIFICATE-----
diff --git a/tests/certs/Server-localhost-lastSAN-sv.prm b/tests/certs/Server-localhost-lastSAN-sv.prm
index faefe68..c5e72f4 100644
--- a/tests/certs/Server-localhost-lastSAN-sv.prm
+++ b/tests/certs/Server-localhost-lastSAN-sv.prm
@@ -6,6 +6,19 @@
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
basicConstraints = CA:false
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
+
[ req ]
default_bits = 1024
distinguished_name = req_DN
diff --git a/tests/certs/Server-localhost-lastSAN-sv.pub.der b/tests/certs/Server-localhost-lastSAN-sv.pub.der
index 480ee31..fc61b6d 100644
--- a/tests/certs/Server-localhost-lastSAN-sv.pub.der
+++ b/tests/certs/Server-localhost-lastSAN-sv.pub.der
Binary files differ
diff --git a/tests/certs/Server-localhost-lastSAN-sv.pub.pem b/tests/certs/Server-localhost-lastSAN-sv.pub.pem
index 5c1d333..3644fd9 100644
--- a/tests/certs/Server-localhost-lastSAN-sv.pub.pem
+++ b/tests/certs/Server-localhost-lastSAN-sv.pub.pem
@@ -1,9 +1,9 @@
-----BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvZcOp222c4zQIWvzNnRd
-Cqo68PpusVwcE3TKZysiA9GmPCXvh0/oOJ8hHS6IEjZmggMCTPgXNQKVMbFTQCEk
-LwDwv4BYFrGSs9N4v3jLCpEM0m1dsh9BcxYCfBrNFiXJ4RuBvYSTTGPOOPQ+rZhr
-AImouvV+CIPzmvWYuJ/W2MfU8wccj++8KRBgjIWLTHpzx5+oIy/ER/UYhZj7J95Y
-k0sIpWbJ39vwIvhkn6FWiZerAixamfJvv3IxkCIyroYlaxPGcuzfLsgSAMHjOLSg
-QLoBYcLXse99SykY4v4o0JjkZT9MNDnkgqnKsj3EkY+glL/j+LNzSLf++gRD57W8
-vQIDAQAB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyIT+aWQzw9y1dIrHsrvZ
+aeKplW1ftyXmggAr9VMh5yiuZrY4/RWxkYhSMSm7c+LgmWKVRDVR11TI0m0lPPAu
+AxuooSXhg5pcvWVXk0R+o8zdrFlpYAHggLnQxHBjzxegxhMPITvIwUZOGP1qNnYk
+SlfYcy8TQqAukB+/hJ2B5734dVPz+lLh8Kr2I9cNYRcM5Zqr4tXow8lrKqba+cv2
+TR1AU35oL1Gf0xeVNCEyDUfWqU0ou+BQEy9bdqGQWlFIL87b2dou0ToP+4BhJAsL
+ebJFzR0tZu5Kll0It8SAlS1OjqwOFfosBgxJdEmBdxelsgHeqogrmmYTuwa0ifvk
+kQIDAQAB
-----END PUBLIC KEY-----
diff --git a/tests/certs/Server-localhost-lastSAN-sv.pubkey-pinned b/tests/certs/Server-localhost-lastSAN-sv.pubkey-pinned
new file mode 100644
index 0000000..bcb4d42
--- /dev/null
+++ b/tests/certs/Server-localhost-lastSAN-sv.pubkey-pinned
@@ -0,0 +1 @@
+1iO+QG+cArKLLyo3az2OBu0lM1t8v5bLLI3pNXoJJQ0=
diff --git a/tests/certs/Server-localhost-sv.crl b/tests/certs/Server-localhost-sv.crl
index 5b52c60..d10b90c 100644
--- a/tests/certs/Server-localhost-sv.crl
+++ b/tests/certs/Server-localhost-sv.crl
@@ -1,12 +1,12 @@
-----BEGIN X509 CRL-----
-MIIB3DCBxQIBATANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJOTjExMC8GA1UE
+MIIB3DCBxQIBATANBgkqhkiG9w0BAQsFADBoMQswCQYDVQQGEwJOTjExMC8GA1UE
CgwoRWRlbCBDdXJsIEFyY3RpYyBJbGx1ZGl1bSBSZXNlYXJjaCBDbG91ZDEmMCQG
-A1UEAwwdTm9ydGhlcm4gTm93aGVyZSBUcnVzdCBBbmNob3IXDTE4MDkxOTA3MTMx
-NFoXDTE4MTAxOTA3MTMxNFowGTAXAgYN+2bB8FMXDTE4MDkxOTA3MTMxNFqgDjAM
-MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBBQUAA4IBAQCllmWJK8FzgV2ebqeiXzxv
-OHnz3E4pgz40qB66ry6PAlbXpYWwjAdpRaG/G4tN8q3q6iloHdkPK6Ed5coB3UXU
-kRy/rojSTxzRYqt15sndz9943URJW4EGZNKf64DKq7yQL4B19ik2x7CcWNqdfsx9
-w7R/ypqTxK3+L5bcLgXMTVZEAWwez9aTAnNl3bL2pN16fC15SU9vS8HOl0R5GQeO
-dl9dZRVwKg119PUAngLeEmQcTZcHr5aOMDBJTgTKybOHJCgkC/1mICISU5JAxvc7
-03ohKy5ZzzTzi7wJyfT3QOgC8EDc/6+wa3AjJMAccEth4USC4ABlX1ja2aZLa1L5
+A1UEAwwdTm9ydGhlcm4gTm93aGVyZSBUcnVzdCBBbmNob3IXDTIyMTIyMzEyMjEz
+NloXDTIzMDEyMjEyMjEzNlowGTAXAgYPNHVRKjwXDTIyMTIyMzEyMjEzNlqgDjAM
+MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBU6nAPnIyD/G6eK21pfHeh
+myCoBy+B9b8R1Ed1Y3YDoWS6KFXAoPJxWmy0gdo0sbhzVvC4iSb1iZzWjki/rAVL
+lkYdJr+r/D5y7A80+Kngf18j77oLvtRkNiVT4Kac1kHg7h9oznO42T+DI90PPd33
+puX+J/aH9V51NUyZcQWQjY7ZiOMbMUnCjozwhidVPL65pK/ggrTFy08WorHpx4Ew
+i1oT5qD478+/4alUxs+EFJMvVTBPrKbpBYq2fr1n1L1/XdRGLi4U3M9B4jsXdmXd
+JyHPVlMNNBPTM8S95vNko4Q94UuZrCQv0TlPJtQI1B0KDDWCJxuyA/3+hYRFglBe
-----END X509 CRL-----
diff --git a/tests/certs/Server-localhost-sv.crt b/tests/certs/Server-localhost-sv.crt
index e3fc42a..06355e3 100644
--- a/tests/certs/Server-localhost-sv.crt
+++ b/tests/certs/Server-localhost-sv.crt
@@ -1,41 +1,41 @@
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15373411938387 (0xdfb66c1f053)
+ Serial Number: 16717980969532 (0xf3475512a3c)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = Northern Nowhere Trust Anchor
Validity
- Not Before: Sep 19 07:13:14 2018 GMT
- Not After : Dec 6 07:13:14 2026 GMT
+ Not Before: Dec 23 12:21:36 2022 GMT
+ Not After : Mar 11 12:21:36 2031 GMT
Subject:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:9f:a9:30:50:f9:70:bc:33:7f:1f:aa:c6:5e:5a:
- 0a:f6:cf:99:22:cd:bc:3a:41:e7:76:bc:05:01:85:
- 24:cd:22:79:47:26:4d:6a:9d:41:cf:31:80:20:1f:
- 5f:3a:87:2f:4f:ff:5c:23:ac:67:0b:f4:14:58:a7:
- 47:d7:76:03:53:fe:b3:0d:23:08:19:ff:b4:ac:47:
- bd:60:90:c8:04:94:05:cb:cf:1b:10:aa:bb:08:46:
- 54:42:a8:2b:cc:35:f9:6a:b9:46:9e:82:47:18:77:
- cf:c0:48:1f:5c:d2:9b:ed:fd:8d:3d:29:0b:20:b7:
- dd:02:60:27:62:18:73:1c:0c:b1:82:2d:3c:9c:1e:
- b6:3e:86:f4:0e:d3:02:50:f1:f8:01:87:32:8a:2d:
- c5:61:0b:aa:94:f0:b3:29:3f:49:a7:f6:4a:dd:75:
- 30:c0:62:97:14:6b:de:4d:71:44:40:39:8e:08:f5:
- b9:73:41:d5:eb:12:d8:ce:5d:be:29:76:ea:6b:94:
- 18:d7:2c:43:5e:89:12:f1:50:f2:2d:c0:6d:19:07:
- 99:96:f3:a8:46:f3:3b:e8:c8:1d:0d:fa:54:96:a0:
- 26:2c:4f:c0:60:84:a9:21:39:0f:44:28:e4:e3:11:
- 79:e4:a3:44:e2:20:e1:9d:65:54:a2:27:56:67:94:
- 02:27
+ 00:c6:b8:04:3d:d6:fa:31:a0:d7:f7:e9:88:4b:5a:
+ 5e:6f:6f:db:f4:c9:4b:7e:6c:2a:cf:34:7b:2a:ba:
+ 1a:71:ad:7f:78:6c:f7:1e:ca:07:d0:29:03:49:e4:
+ 63:86:4c:f6:67:3f:bd:32:69:cb:b8:15:e7:0e:cf:
+ 28:3d:9e:96:91:8e:4f:73:a9:27:77:4c:26:61:cd:
+ d6:e7:4e:3c:64:c3:13:ba:8e:ec:03:0f:bc:d4:83:
+ b3:94:f2:be:d0:18:30:c5:52:49:cb:9a:60:cf:f3:
+ b9:ca:2f:63:9d:34:ee:87:3a:58:e7:a1:99:dd:dc:
+ 56:87:e1:a0:d7:6b:37:ae:bb:13:db:7d:fa:2a:3d:
+ 9c:39:79:f6:01:a6:e3:3a:e7:18:14:cb:c7:57:b9:
+ 83:d1:ba:b8:2c:5a:c4:97:2f:ee:8d:68:48:37:f8:
+ 17:db:32:b9:ea:25:4f:28:57:01:39:13:dc:c0:f7:
+ d0:cc:65:f9:2b:b8:4c:a1:5b:11:ce:44:e2:28:b9:
+ 63:62:fd:08:fa:b6:cd:49:d5:b9:fe:9e:68:9c:9a:
+ b5:1a:3e:cc:bf:0e:74:db:52:3f:25:30:cd:7d:02:
+ 41:c7:c9:8a:58:12:35:25:21:95:c4:6b:c3:f5:79:
+ c2:00:cb:ef:7f:d7:9f:89:c9:ff:c0:b9:72:59:4c:
+ 33:47
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
@@ -45,48 +45,55 @@
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Key Identifier:
- D2:36:0A:53:12:B2:99:64:47:05:53:D2:17:69:12:FC:8E:DB:D7:07
+ 4A:F1:79:1B:13:71:A4:0F:F9:06:CC:B6:2C:CD:24:46:DF:E6:08:2D
X509v3 Authority Key Identifier:
- keyid:12:CA:BA:4B:46:04:A7:75:8A:2C:E8:0E:54:94:BC:12:65:A6:7B:CE
-
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
X509v3 Basic Constraints:
CA:FALSE
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
Signature Algorithm: sha256WithRSAEncryption
- 2a:cc:91:d3:be:49:63:2f:84:f2:cf:e8:43:e7:fa:fc:c5:b9:
- d7:6b:d7:40:2b:ee:89:58:98:24:57:cd:eb:51:a0:8b:22:18:
- 7d:57:81:f5:0c:06:14:d1:81:90:78:59:34:23:d6:68:19:c7:
- 8b:13:1c:b2:76:65:a1:9b:24:c8:b6:43:04:a5:2b:2e:c4:4b:
- c9:69:03:1f:ca:86:54:53:e5:25:a1:5d:a3:22:11:d9:2e:c8:
- 1a:e0:dd:04:3b:6f:3c:ea:a6:73:5f:80:bd:6c:3b:41:be:3b:
- 1e:fa:68:be:91:9f:85:c0:81:28:cb:38:23:eb:b4:16:bf:81:
- 1c:eb:67:9e:b3:03:84:b0:a1:2d:76:ba:7a:55:77:31:49:2d:
- 40:7a:bf:3f:e3:d2:50:11:ad:3a:06:fd:b5:75:36:50:29:5c:
- 26:e4:45:43:1d:25:78:f1:de:81:f1:d9:39:70:70:46:77:48:
- ca:64:7a:19:57:5f:4d:9b:0b:0d:57:bb:c1:b5:1f:d9:ab:26:
- fb:4b:54:2d:01:2a:f3:e4:6f:e7:b3:4a:05:4c:f3:0b:a6:d1:
- 10:5a:27:e4:15:6c:80:55:2c:63:50:f1:36:0d:eb:ff:e1:eb:
- 68:20:7e:a5:98:7c:0e:d0:1e:f5:68:7f:4f:3e:b9:b8:e0:0f:
- ea:34:a6:b1
+ Signature Value:
+ 67:ef:ad:8f:fa:ee:f1:fd:33:67:62:06:5f:09:55:7c:cf:82:
+ 1a:e8:fc:f5:97:ba:63:bd:d0:a0:8b:85:2c:fc:f0:34:4a:97:
+ b2:18:d7:63:34:63:f4:1f:50:c7:0e:13:d9:bc:3b:73:3d:41:
+ 93:16:b3:30:95:88:cd:75:c8:8c:58:4b:ab:96:e6:78:68:15:
+ 0f:84:e7:8e:17:94:1a:b3:f3:12:ab:26:fd:fa:73:31:33:36:
+ 85:83:2d:e3:3a:f2:a6:29:c6:37:30:3d:17:d2:39:31:d1:56:
+ 1b:8d:df:fb:07:ad:81:0b:91:e5:bd:7b:37:a0:a0:5a:2c:33:
+ 2b:8d:69:8b:d7:c1:45:61:85:ef:32:45:dd:00:a2:81:98:44:
+ 0d:eb:01:95:fc:ac:0f:b5:34:a4:5f:35:5c:68:63:50:5a:69:
+ 56:f3:99:c4:67:70:89:13:30:c0:64:ff:f1:a6:77:68:69:63:
+ 9e:6f:f8:3c:6f:cd:af:7f:de:0d:87:55:ae:39:b3:b2:f5:4f:
+ 47:79:1f:32:ee:ae:8f:32:dc:88:30:cd:38:6c:4b:28:55:c3:
+ 7d:74:6b:de:d0:49:c9:05:ea:62:71:a6:f8:1e:76:da:3c:a7:
+ 17:cd:1a:92:a3:c4:e8:85:d1:ad:34:0c:71:37:3f:6c:d3:7f:
+ 9a:d6:ca:de
-----BEGIN CERTIFICATE-----
-MIIDwzCCAqugAwIBAgIGDftmwfBTMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+MIIERDCCAyygAwIBAgIGDzR1USo8MA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
-Fw0xODA5MTkwNzEzMTRaFw0yNjEyMDYwNzEzMTRaMFQxCzAJBgNVBAYTAk5OMTEw
+Fw0yMjEyMjMxMjIxMzZaFw0zMTAzMTExMjIxMzZaMFQxCzAJBgNVBAYTAk5OMTEw
LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
-AoIBAQCfqTBQ+XC8M38fqsZeWgr2z5kizbw6Qed2vAUBhSTNInlHJk1qnUHPMYAg
-H186hy9P/1wjrGcL9BRYp0fXdgNT/rMNIwgZ/7SsR71gkMgElAXLzxsQqrsIRlRC
-qCvMNflquUaegkcYd8/ASB9c0pvt/Y09KQsgt90CYCdiGHMcDLGCLTycHrY+hvQO
-0wJQ8fgBhzKKLcVhC6qU8LMpP0mn9krddTDAYpcUa95NcURAOY4I9blzQdXrEtjO
-Xb4pduprlBjXLENeiRLxUPItwG0ZB5mW86hG8zvoyB0N+lSWoCYsT8BghKkhOQ9E
-KOTjEXnko0TiIOGdZVSiJ1ZnlAInAgMBAAGjgYYwgYMwFAYDVR0RBA0wC4IJbG9j
-YWxob3N0MAsGA1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4E
-FgQU0jYKUxKymWRHBVPSF2kS/I7b1wcwHwYDVR0jBBgwFoAUEsq6S0YEp3WKLOgO
-VJS8EmWme84wCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAKsyR075JYy+E
-8s/oQ+f6/MW512vXQCvuiViYJFfN61GgiyIYfVeB9QwGFNGBkHhZNCPWaBnHixMc
-snZloZskyLZDBKUrLsRLyWkDH8qGVFPlJaFdoyIR2S7IGuDdBDtvPOqmc1+AvWw7
-Qb47HvpovpGfhcCBKMs4I+u0Fr+BHOtnnrMDhLChLXa6elV3MUktQHq/P+PSUBGt
-Ogb9tXU2UClcJuRFQx0lePHegfHZOXBwRndIymR6GVdfTZsLDVe7wbUf2asm+0tU
-LQEq8+Rv57NKBUzzC6bREFon5BVsgFUsY1DxNg3r/+HraCB+pZh8DtAe9Wh/Tz65
-uOAP6jSmsQ==
+AoIBAQDGuAQ91voxoNf36YhLWl5vb9v0yUt+bCrPNHsquhpxrX94bPceygfQKQNJ
+5GOGTPZnP70yacu4FecOzyg9npaRjk9zqSd3TCZhzdbnTjxkwxO6juwDD7zUg7OU
+8r7QGDDFUknLmmDP87nKL2OdNO6HOljnoZnd3FaH4aDXazeuuxPbffoqPZw5efYB
+puM65xgUy8dXuYPRurgsWsSXL+6NaEg3+BfbMrnqJU8oVwE5E9zA99DMZfkruEyh
+WxHOROIouWNi/Qj6ts1J1bn+nmicmrUaPsy/DnTbUj8lMM19AkHHyYpYEjUlIZXE
+a8P1ecIAy+9/15+Jyf/AuXJZTDNHAgMBAAGjggEGMIIBAjAUBgNVHREEDTALggls
+b2NhbGhvc3QwCwYDVR0PBAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1Ud
+DgQWBBRK8XkbE3GkD/kGzLYszSRG3+YILTAfBgNVHSMEGDAWgBSHy7EzLsFnfnHj
+5StMTaSzbtJbqTAJBgNVHRMEAjAAMEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcw
+AoYnaHR0cDovL3Rlc3QuY3VybC5zZS9jYS9FZGVsQ3VybFJvb3QuY2VyMDgGA1Ud
+HwQxMC8wLaAroCmGJ2h0dHA6Ly90ZXN0LmN1cmwuc2UvY2EvRWRlbEN1cmxSb290
+LmNybDANBgkqhkiG9w0BAQsFAAOCAQEAZ++tj/ru8f0zZ2IGXwlVfM+CGuj89Ze6
+Y73QoIuFLPzwNEqXshjXYzRj9B9Qxw4T2bw7cz1BkxazMJWIzXXIjFhLq5bmeGgV
+D4TnjheUGrPzEqsm/fpzMTM2hYMt4zrypinGNzA9F9I5MdFWG43f+wetgQuR5b17
+N6CgWiwzK41pi9fBRWGF7zJF3QCigZhEDesBlfysD7U0pF81XGhjUFppVvOZxGdw
+iRMwwGT/8aZ3aGljnm/4PG/Nr3/eDYdVrjmzsvVPR3kfMu6ujzLciDDNOGxLKFXD
+fXRr3tBJyQXqYnGm+B522jynF80akqPE6IXRrTQMcTc/bNN/mtbK3g==
-----END CERTIFICATE-----
diff --git a/tests/certs/Server-localhost-sv.csr b/tests/certs/Server-localhost-sv.csr
index d75cafa..aa3dc8c 100644
--- a/tests/certs/Server-localhost-sv.csr
+++ b/tests/certs/Server-localhost-sv.csr
@@ -1,16 +1,16 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICmTCCAYECAQAwVDELMAkGA1UEBhMCTk4xMTAvBgNVBAoMKEVkZWwgQ3VybCBB
cmN0aWMgSWxsdWRpdW0gUmVzZWFyY2ggQ2xvdWQxEjAQBgNVBAMMCWxvY2FsaG9z
-dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ+pMFD5cLwzfx+qxl5a
-CvbPmSLNvDpB53a8BQGFJM0ieUcmTWqdQc8xgCAfXzqHL0//XCOsZwv0FFinR9d2
-A1P+sw0jCBn/tKxHvWCQyASUBcvPGxCquwhGVEKoK8w1+Wq5Rp6CRxh3z8BIH1zS
-m+39jT0pCyC33QJgJ2IYcxwMsYItPJwetj6G9A7TAlDx+AGHMootxWELqpTwsyk/
-Saf2St11MMBilxRr3k1xREA5jgj1uXNB1esS2M5dvil26muUGNcsQ16JEvFQ8i3A
-bRkHmZbzqEbzO+jIHQ36VJagJixPwGCEqSE5D0Qo5OMReeSjROIg4Z1lVKInVmeU
-AicCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQAH9pAANaXZsKkkYwwsQx7tJHeL
-dP9WFMg4Cs6EV5QoAju3E4SocylEA213VbBlEmCjXZXgD9c7uR1NPpO5MIMN3ohA
-+5OQ8pGN9N0MIBWlMhJnaqCYIRga4Ajh8gL9qo6Su4FmlPWFLNMnAdwf5zm5ji3V
-4QpDkOWqB/GyFVqYpsPma9VJgDp9ktc09reVzHRkhlLtWei4OOpfiDcDFuG+1IPj
-nlE13kcRBJ+TyVaVTcRc/3eBs1QUHvwFoAwLtG1Bbkzf6VhtjDSV5gyqDHedG/N5
-PNlNt3eF5Cq5i4rnC+jHuYZslWmwzXT8fM7VdHpXE9Awq6Wp6nqJ8K7+6/oX
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMa4BD3W+jGg1/fpiEta
+Xm9v2/TJS35sKs80eyq6GnGtf3hs9x7KB9ApA0nkY4ZM9mc/vTJpy7gV5w7PKD2e
+lpGOT3OpJ3dMJmHN1udOPGTDE7qO7AMPvNSDs5TyvtAYMMVSScuaYM/zucovY500
+7oc6WOehmd3cVofhoNdrN667E9t9+io9nDl59gGm4zrnGBTLx1e5g9G6uCxaxJcv
+7o1oSDf4F9syueolTyhXATkT3MD30Mxl+Su4TKFbEc5E4ii5Y2L9CPq2zUnVuf6e
+aJyatRo+zL8OdNtSPyUwzX0CQcfJilgSNSUhlcRrw/V5wgDL73/Xn4nJ/8C5cllM
+M0cCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBtz8OLB7+70UnIZ1s3VNIoYetH
+yqnBkNQusZrWmv4kHrIUP4K8zq0HCTGTWdxOAp23aU+yZyceu75aD8WosZoT0Q71
+zTLMMjo+ZRkeWuTo+xyLYoSdlkmyQN9xaj0owQ6UycL07aainnf2+n/ybaMFtUYB
+g1LVOwSvtyLQTxByZZ7mJvl+fczSN+E4AuNA8feECXh3oZ/MmWKFGIhkJ36Q4DYD
+PZ9J2RAV11KeHXLAKjnxsetQRiEdlvKetRknMCptgjVO23qIV62EbyL5mKrlz9Kx
+lTzM788YjSx+u2PTWJi4gduTcsirVel3yFJyHjvSEhMPTPuSDfD1fXSvp22G
-----END CERTIFICATE REQUEST-----
diff --git a/tests/certs/Server-localhost-sv.der b/tests/certs/Server-localhost-sv.der
index 255d293..2e56bd9 100644
--- a/tests/certs/Server-localhost-sv.der
+++ b/tests/certs/Server-localhost-sv.der
Binary files differ
diff --git a/tests/certs/Server-localhost-sv.key b/tests/certs/Server-localhost-sv.key
index cda47c1..a2c95ee 100644
--- a/tests/certs/Server-localhost-sv.key
+++ b/tests/certs/Server-localhost-sv.key
@@ -1,27 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEAn6kwUPlwvDN/H6rGXloK9s+ZIs28OkHndrwFAYUkzSJ5RyZN
-ap1BzzGAIB9fOocvT/9cI6xnC/QUWKdH13YDU/6zDSMIGf+0rEe9YJDIBJQFy88b
-EKq7CEZUQqgrzDX5arlGnoJHGHfPwEgfXNKb7f2NPSkLILfdAmAnYhhzHAyxgi08
-nB62Pob0DtMCUPH4AYcyii3FYQuqlPCzKT9Jp/ZK3XUwwGKXFGveTXFEQDmOCPW5
-c0HV6xLYzl2+KXbqa5QY1yxDXokS8VDyLcBtGQeZlvOoRvM76MgdDfpUlqAmLE/A
-YISpITkPRCjk4xF55KNE4iDhnWVUoidWZ5QCJwIDAQABAoIBAQCHqDWJV6fWANtO
-iMere049jv5KeAwqY7zLQc3vELXIJjZtobm9kIhOB30Zzg4XqK0mh44+MUoM+gIf
-oWKFS5xgTdTMoKtNi9pzVzEtT1bjrPGPzhTtAGOSEE+fo0wzYtjdOTcrjv3haEt4
-0M71C225tOnAwZLW5eI/Fnvf+W40sayHnWb4S04i6hd89kqHAjtr2xDbGdd8XDJD
-3auwEqXiycpBKntrZUVBQqCPWXKCkQSrb2yftVdPwed0dnOhaLqKnnLFkdiQq6Db
-SyKcb960SGhZj+jlIraJnYvBWRZpHejBBZf/yTJrav9kAx38K/UJrLTUpRQEi0p8
-XRTOTAehAoGBANGzRhZBi0PSZ2KCKErwNUu0inBGqy9SNeTm5SbgG5vtT2gSmb2Q
-ev0DVz2qfYii0Jd9sC3BANwBGrvSJY7Rsk09JWa2skLaZa/lFDFQmlSvyEUMfKCj
-ZuCK3rO20YjzSJQamKAROAeS+u61LJgv/RngvVUUQ7o4HfJFeAV48io7AoGBAMLp
-k8KQjplvRFFuAN+W9s82d5jqCGm19ctqxtQbZNw/dlU3cZjunm1U9Opn8ws9xLrn
-pEBSYWIMbO1Fo9FyYD6SCy8VVGdy7L6mmUMZo4iyVM5mIEsyb7UkjfkBEwX/Ax4S
-wLPS6Em0zIW99YqexMeh6TeJCqoxS4IHw6GSqZ0FAoGBALkqMNAELkHD7zBHt+Z7
-9sOTds6vSAcv85Dc5SkPqLFlucEu83w0sLTrF0THX7Of+Mpb3I56JxUdEIsag7l5
-ppSXUohA+GUZzcKkZ9En2C7BTPjTjtSVlIjfdsh/vMPN9p94YJ6utafSfCr95ZO4
-hCguj2Ap1agAV0kPWGyUoFjzAoGABU8JWD5JtAIk0Tb2zSA2frRUE5UkP4TWOgEh
-gztvxtPvrCiDbo/pPr8WoJ/OLdsz1YdjoODdiCcgfGHuMVE1L98YcOLa1qp5qkOt
-Xvd+zcVVq/16GbI4+q0RNNwDoaEte481MnCnJQLIo0fmPS1P3MQbLwkLglEvZk5B
-1M/C0OUCgYEAnevGxuXS49nIwcCZQpSrAQj2DoFj0ffd3ZWeqzlFvEV0ac48YjmF
-irDzOf5uuboHom++On4MqXNAWnZVQcY6thkR/KiJp+bqfgtu01jWn9dbRCd62lAt
-09hB+Da3Z3TZ0GnXerPwYT27enP/w6hh/G4Mn73Auf6Tz1cFdwzvSNg=
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDGuAQ91voxoNf3
+6YhLWl5vb9v0yUt+bCrPNHsquhpxrX94bPceygfQKQNJ5GOGTPZnP70yacu4FecO
+zyg9npaRjk9zqSd3TCZhzdbnTjxkwxO6juwDD7zUg7OU8r7QGDDFUknLmmDP87nK
+L2OdNO6HOljnoZnd3FaH4aDXazeuuxPbffoqPZw5efYBpuM65xgUy8dXuYPRurgs
+WsSXL+6NaEg3+BfbMrnqJU8oVwE5E9zA99DMZfkruEyhWxHOROIouWNi/Qj6ts1J
+1bn+nmicmrUaPsy/DnTbUj8lMM19AkHHyYpYEjUlIZXEa8P1ecIAy+9/15+Jyf/A
+uXJZTDNHAgMBAAECggEAH48J3WhOw6LvqYeFBbKMXNY+8FknjCRRiCaliNuVZ4hO
+PinP9SvQodZhl1KWG7YNS8hrm54BpHKWB1wO3/pXnzYimBO9GM0XK2EtR/68yKPS
+dkZMZRASxQ1Fb9o9Q38T/8JZxeP2jBAA6YMtJsJJP2Cczex0Ky/a7il/CbcVWMJF
+VCqHEWCBge59xZifsKiAiK/Yw5W6uyi9OZ9a2D7bzJh0sojPIY90d7EhW4u/QCzk
+aXn78RbgxDkQyz5AQrIQzEMcOYr+AxiVT5S1v15FoaoWlm1IrNpEmf63PvwRKPZM
+ZW1cqR8onTQBndzAdwn9qHjtuRvhoHMe5RWs4rzDAQKBgQDTq2NGbkNdK14oSu7/
+t+z4Z3nGhHmY9pI1jF5/s3ialO/7YD4ul5MXaJt6dbklkPqsN0vmhPeeavAy6tsG
+iU4SdTuptKg5aZMZnDa9zu9lM4raJpDf9AuncffjVFqy9EDII5Wi1UIRDTD8D1gp
+LBYuFUTpo7R+JD3yqLXvbOw8UQKBgQDwVkgTqbAwbx35sKhpFo0VOAj3GVZkC6zt
+nFS03MmHPjge69u3B3I6oavYtwROq+6S9rj3MLuj4DhVbO5Yxi+XqY5wXhFUPPSp
+1ejXF8aAwWtZEeMTTsaN8jl3nfzdNul8G5mVfpY/VmZMhuAXclsAR9ke/x+FcmrQ
+Furd0lxIFwKBgQDSXVobzEf817YLW3WuBbBorAY1ysFCyYND3s6oIcjx8KWU8fC6
+w3+3WwpyqX8pm63V7Frtriaede9k2050b498/rAeGGK8NHWylTM+buQzcwdDieKg
+AN54Ouc/Mj217tRXVC5KF6JCahbN274lpSAiCpdjkIQ4fXJnsU6ntlwOEQKBgQDr
+rCAHsAkGpZ+mPlYWnreADC+2ZtExT8WmRvtFU5AHH7sWj0An7ZRU7D5AR89gefZ7
+hJaCRvZpTzDOi//5a3Y16V200Hl7uj5M4GbvrO/JSGHEuOaMA15uyQ0TQAg6wGMa
+gVIMp1IcD9RGzKeoNkoIL2w4mgJF8JnPLfnnxSUaxwKBgQCXP6btCbX7fryeIfUB
+PC1TOtyNvNWeoPJNT9eeNHxPC5VW2AC78XKxbHsVec16KJsOgj4Elc3h8/+X0wAU
+7Zo9CD7M2i1Tm5sKh90yBsZsU6jBWOBorLQnatDKVPXHLblVAEgK0qTJTAW8hLDn
+myYsFbt36qBXf1dVvo+5yhCxAw==
+-----END PRIVATE KEY-----
diff --git a/tests/certs/Server-localhost-sv.pem b/tests/certs/Server-localhost-sv.pem
index 55cf4a3..583831f 100644
--- a/tests/certs/Server-localhost-sv.pem
+++ b/tests/certs/Server-localhost-sv.pem
@@ -6,6 +6,19 @@
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
basicConstraints = CA:false
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
+
[ req ]
default_bits = 1024
distinguished_name = req_DN
@@ -23,71 +36,72 @@
# The key
# the certificate
# some dhparam
------BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEAn6kwUPlwvDN/H6rGXloK9s+ZIs28OkHndrwFAYUkzSJ5RyZN
-ap1BzzGAIB9fOocvT/9cI6xnC/QUWKdH13YDU/6zDSMIGf+0rEe9YJDIBJQFy88b
-EKq7CEZUQqgrzDX5arlGnoJHGHfPwEgfXNKb7f2NPSkLILfdAmAnYhhzHAyxgi08
-nB62Pob0DtMCUPH4AYcyii3FYQuqlPCzKT9Jp/ZK3XUwwGKXFGveTXFEQDmOCPW5
-c0HV6xLYzl2+KXbqa5QY1yxDXokS8VDyLcBtGQeZlvOoRvM76MgdDfpUlqAmLE/A
-YISpITkPRCjk4xF55KNE4iDhnWVUoidWZ5QCJwIDAQABAoIBAQCHqDWJV6fWANtO
-iMere049jv5KeAwqY7zLQc3vELXIJjZtobm9kIhOB30Zzg4XqK0mh44+MUoM+gIf
-oWKFS5xgTdTMoKtNi9pzVzEtT1bjrPGPzhTtAGOSEE+fo0wzYtjdOTcrjv3haEt4
-0M71C225tOnAwZLW5eI/Fnvf+W40sayHnWb4S04i6hd89kqHAjtr2xDbGdd8XDJD
-3auwEqXiycpBKntrZUVBQqCPWXKCkQSrb2yftVdPwed0dnOhaLqKnnLFkdiQq6Db
-SyKcb960SGhZj+jlIraJnYvBWRZpHejBBZf/yTJrav9kAx38K/UJrLTUpRQEi0p8
-XRTOTAehAoGBANGzRhZBi0PSZ2KCKErwNUu0inBGqy9SNeTm5SbgG5vtT2gSmb2Q
-ev0DVz2qfYii0Jd9sC3BANwBGrvSJY7Rsk09JWa2skLaZa/lFDFQmlSvyEUMfKCj
-ZuCK3rO20YjzSJQamKAROAeS+u61LJgv/RngvVUUQ7o4HfJFeAV48io7AoGBAMLp
-k8KQjplvRFFuAN+W9s82d5jqCGm19ctqxtQbZNw/dlU3cZjunm1U9Opn8ws9xLrn
-pEBSYWIMbO1Fo9FyYD6SCy8VVGdy7L6mmUMZo4iyVM5mIEsyb7UkjfkBEwX/Ax4S
-wLPS6Em0zIW99YqexMeh6TeJCqoxS4IHw6GSqZ0FAoGBALkqMNAELkHD7zBHt+Z7
-9sOTds6vSAcv85Dc5SkPqLFlucEu83w0sLTrF0THX7Of+Mpb3I56JxUdEIsag7l5
-ppSXUohA+GUZzcKkZ9En2C7BTPjTjtSVlIjfdsh/vMPN9p94YJ6utafSfCr95ZO4
-hCguj2Ap1agAV0kPWGyUoFjzAoGABU8JWD5JtAIk0Tb2zSA2frRUE5UkP4TWOgEh
-gztvxtPvrCiDbo/pPr8WoJ/OLdsz1YdjoODdiCcgfGHuMVE1L98YcOLa1qp5qkOt
-Xvd+zcVVq/16GbI4+q0RNNwDoaEte481MnCnJQLIo0fmPS1P3MQbLwkLglEvZk5B
-1M/C0OUCgYEAnevGxuXS49nIwcCZQpSrAQj2DoFj0ffd3ZWeqzlFvEV0ac48YjmF
-irDzOf5uuboHom++On4MqXNAWnZVQcY6thkR/KiJp+bqfgtu01jWn9dbRCd62lAt
-09hB+Da3Z3TZ0GnXerPwYT27enP/w6hh/G4Mn73Auf6Tz1cFdwzvSNg=
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDGuAQ91voxoNf3
+6YhLWl5vb9v0yUt+bCrPNHsquhpxrX94bPceygfQKQNJ5GOGTPZnP70yacu4FecO
+zyg9npaRjk9zqSd3TCZhzdbnTjxkwxO6juwDD7zUg7OU8r7QGDDFUknLmmDP87nK
+L2OdNO6HOljnoZnd3FaH4aDXazeuuxPbffoqPZw5efYBpuM65xgUy8dXuYPRurgs
+WsSXL+6NaEg3+BfbMrnqJU8oVwE5E9zA99DMZfkruEyhWxHOROIouWNi/Qj6ts1J
+1bn+nmicmrUaPsy/DnTbUj8lMM19AkHHyYpYEjUlIZXEa8P1ecIAy+9/15+Jyf/A
+uXJZTDNHAgMBAAECggEAH48J3WhOw6LvqYeFBbKMXNY+8FknjCRRiCaliNuVZ4hO
+PinP9SvQodZhl1KWG7YNS8hrm54BpHKWB1wO3/pXnzYimBO9GM0XK2EtR/68yKPS
+dkZMZRASxQ1Fb9o9Q38T/8JZxeP2jBAA6YMtJsJJP2Cczex0Ky/a7il/CbcVWMJF
+VCqHEWCBge59xZifsKiAiK/Yw5W6uyi9OZ9a2D7bzJh0sojPIY90d7EhW4u/QCzk
+aXn78RbgxDkQyz5AQrIQzEMcOYr+AxiVT5S1v15FoaoWlm1IrNpEmf63PvwRKPZM
+ZW1cqR8onTQBndzAdwn9qHjtuRvhoHMe5RWs4rzDAQKBgQDTq2NGbkNdK14oSu7/
+t+z4Z3nGhHmY9pI1jF5/s3ialO/7YD4ul5MXaJt6dbklkPqsN0vmhPeeavAy6tsG
+iU4SdTuptKg5aZMZnDa9zu9lM4raJpDf9AuncffjVFqy9EDII5Wi1UIRDTD8D1gp
+LBYuFUTpo7R+JD3yqLXvbOw8UQKBgQDwVkgTqbAwbx35sKhpFo0VOAj3GVZkC6zt
+nFS03MmHPjge69u3B3I6oavYtwROq+6S9rj3MLuj4DhVbO5Yxi+XqY5wXhFUPPSp
+1ejXF8aAwWtZEeMTTsaN8jl3nfzdNul8G5mVfpY/VmZMhuAXclsAR9ke/x+FcmrQ
+Furd0lxIFwKBgQDSXVobzEf817YLW3WuBbBorAY1ysFCyYND3s6oIcjx8KWU8fC6
+w3+3WwpyqX8pm63V7Frtriaede9k2050b498/rAeGGK8NHWylTM+buQzcwdDieKg
+AN54Ouc/Mj217tRXVC5KF6JCahbN274lpSAiCpdjkIQ4fXJnsU6ntlwOEQKBgQDr
+rCAHsAkGpZ+mPlYWnreADC+2ZtExT8WmRvtFU5AHH7sWj0An7ZRU7D5AR89gefZ7
+hJaCRvZpTzDOi//5a3Y16V200Hl7uj5M4GbvrO/JSGHEuOaMA15uyQ0TQAg6wGMa
+gVIMp1IcD9RGzKeoNkoIL2w4mgJF8JnPLfnnxSUaxwKBgQCXP6btCbX7fryeIfUB
+PC1TOtyNvNWeoPJNT9eeNHxPC5VW2AC78XKxbHsVec16KJsOgj4Elc3h8/+X0wAU
+7Zo9CD7M2i1Tm5sKh90yBsZsU6jBWOBorLQnatDKVPXHLblVAEgK0qTJTAW8hLDn
+myYsFbt36qBXf1dVvo+5yhCxAw==
+-----END PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15373411938387 (0xdfb66c1f053)
+ Serial Number: 16717980969532 (0xf3475512a3c)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = Northern Nowhere Trust Anchor
Validity
- Not Before: Sep 19 07:13:14 2018 GMT
- Not After : Dec 6 07:13:14 2026 GMT
+ Not Before: Dec 23 12:21:36 2022 GMT
+ Not After : Mar 11 12:21:36 2031 GMT
Subject:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:9f:a9:30:50:f9:70:bc:33:7f:1f:aa:c6:5e:5a:
- 0a:f6:cf:99:22:cd:bc:3a:41:e7:76:bc:05:01:85:
- 24:cd:22:79:47:26:4d:6a:9d:41:cf:31:80:20:1f:
- 5f:3a:87:2f:4f:ff:5c:23:ac:67:0b:f4:14:58:a7:
- 47:d7:76:03:53:fe:b3:0d:23:08:19:ff:b4:ac:47:
- bd:60:90:c8:04:94:05:cb:cf:1b:10:aa:bb:08:46:
- 54:42:a8:2b:cc:35:f9:6a:b9:46:9e:82:47:18:77:
- cf:c0:48:1f:5c:d2:9b:ed:fd:8d:3d:29:0b:20:b7:
- dd:02:60:27:62:18:73:1c:0c:b1:82:2d:3c:9c:1e:
- b6:3e:86:f4:0e:d3:02:50:f1:f8:01:87:32:8a:2d:
- c5:61:0b:aa:94:f0:b3:29:3f:49:a7:f6:4a:dd:75:
- 30:c0:62:97:14:6b:de:4d:71:44:40:39:8e:08:f5:
- b9:73:41:d5:eb:12:d8:ce:5d:be:29:76:ea:6b:94:
- 18:d7:2c:43:5e:89:12:f1:50:f2:2d:c0:6d:19:07:
- 99:96:f3:a8:46:f3:3b:e8:c8:1d:0d:fa:54:96:a0:
- 26:2c:4f:c0:60:84:a9:21:39:0f:44:28:e4:e3:11:
- 79:e4:a3:44:e2:20:e1:9d:65:54:a2:27:56:67:94:
- 02:27
+ 00:c6:b8:04:3d:d6:fa:31:a0:d7:f7:e9:88:4b:5a:
+ 5e:6f:6f:db:f4:c9:4b:7e:6c:2a:cf:34:7b:2a:ba:
+ 1a:71:ad:7f:78:6c:f7:1e:ca:07:d0:29:03:49:e4:
+ 63:86:4c:f6:67:3f:bd:32:69:cb:b8:15:e7:0e:cf:
+ 28:3d:9e:96:91:8e:4f:73:a9:27:77:4c:26:61:cd:
+ d6:e7:4e:3c:64:c3:13:ba:8e:ec:03:0f:bc:d4:83:
+ b3:94:f2:be:d0:18:30:c5:52:49:cb:9a:60:cf:f3:
+ b9:ca:2f:63:9d:34:ee:87:3a:58:e7:a1:99:dd:dc:
+ 56:87:e1:a0:d7:6b:37:ae:bb:13:db:7d:fa:2a:3d:
+ 9c:39:79:f6:01:a6:e3:3a:e7:18:14:cb:c7:57:b9:
+ 83:d1:ba:b8:2c:5a:c4:97:2f:ee:8d:68:48:37:f8:
+ 17:db:32:b9:ea:25:4f:28:57:01:39:13:dc:c0:f7:
+ d0:cc:65:f9:2b:b8:4c:a1:5b:11:ce:44:e2:28:b9:
+ 63:62:fd:08:fa:b6:cd:49:d5:b9:fe:9e:68:9c:9a:
+ b5:1a:3e:cc:bf:0e:74:db:52:3f:25:30:cd:7d:02:
+ 41:c7:c9:8a:58:12:35:25:21:95:c4:6b:c3:f5:79:
+ c2:00:cb:ef:7f:d7:9f:89:c9:ff:c0:b9:72:59:4c:
+ 33:47
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
@@ -97,48 +111,55 @@
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Key Identifier:
- D2:36:0A:53:12:B2:99:64:47:05:53:D2:17:69:12:FC:8E:DB:D7:07
+ 4A:F1:79:1B:13:71:A4:0F:F9:06:CC:B6:2C:CD:24:46:DF:E6:08:2D
X509v3 Authority Key Identifier:
- keyid:12:CA:BA:4B:46:04:A7:75:8A:2C:E8:0E:54:94:BC:12:65:A6:7B:CE
-
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
X509v3 Basic Constraints:
CA:FALSE
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
Signature Algorithm: sha256WithRSAEncryption
- 2a:cc:91:d3:be:49:63:2f:84:f2:cf:e8:43:e7:fa:fc:c5:b9:
- d7:6b:d7:40:2b:ee:89:58:98:24:57:cd:eb:51:a0:8b:22:18:
- 7d:57:81:f5:0c:06:14:d1:81:90:78:59:34:23:d6:68:19:c7:
- 8b:13:1c:b2:76:65:a1:9b:24:c8:b6:43:04:a5:2b:2e:c4:4b:
- c9:69:03:1f:ca:86:54:53:e5:25:a1:5d:a3:22:11:d9:2e:c8:
- 1a:e0:dd:04:3b:6f:3c:ea:a6:73:5f:80:bd:6c:3b:41:be:3b:
- 1e:fa:68:be:91:9f:85:c0:81:28:cb:38:23:eb:b4:16:bf:81:
- 1c:eb:67:9e:b3:03:84:b0:a1:2d:76:ba:7a:55:77:31:49:2d:
- 40:7a:bf:3f:e3:d2:50:11:ad:3a:06:fd:b5:75:36:50:29:5c:
- 26:e4:45:43:1d:25:78:f1:de:81:f1:d9:39:70:70:46:77:48:
- ca:64:7a:19:57:5f:4d:9b:0b:0d:57:bb:c1:b5:1f:d9:ab:26:
- fb:4b:54:2d:01:2a:f3:e4:6f:e7:b3:4a:05:4c:f3:0b:a6:d1:
- 10:5a:27:e4:15:6c:80:55:2c:63:50:f1:36:0d:eb:ff:e1:eb:
- 68:20:7e:a5:98:7c:0e:d0:1e:f5:68:7f:4f:3e:b9:b8:e0:0f:
- ea:34:a6:b1
+ Signature Value:
+ 67:ef:ad:8f:fa:ee:f1:fd:33:67:62:06:5f:09:55:7c:cf:82:
+ 1a:e8:fc:f5:97:ba:63:bd:d0:a0:8b:85:2c:fc:f0:34:4a:97:
+ b2:18:d7:63:34:63:f4:1f:50:c7:0e:13:d9:bc:3b:73:3d:41:
+ 93:16:b3:30:95:88:cd:75:c8:8c:58:4b:ab:96:e6:78:68:15:
+ 0f:84:e7:8e:17:94:1a:b3:f3:12:ab:26:fd:fa:73:31:33:36:
+ 85:83:2d:e3:3a:f2:a6:29:c6:37:30:3d:17:d2:39:31:d1:56:
+ 1b:8d:df:fb:07:ad:81:0b:91:e5:bd:7b:37:a0:a0:5a:2c:33:
+ 2b:8d:69:8b:d7:c1:45:61:85:ef:32:45:dd:00:a2:81:98:44:
+ 0d:eb:01:95:fc:ac:0f:b5:34:a4:5f:35:5c:68:63:50:5a:69:
+ 56:f3:99:c4:67:70:89:13:30:c0:64:ff:f1:a6:77:68:69:63:
+ 9e:6f:f8:3c:6f:cd:af:7f:de:0d:87:55:ae:39:b3:b2:f5:4f:
+ 47:79:1f:32:ee:ae:8f:32:dc:88:30:cd:38:6c:4b:28:55:c3:
+ 7d:74:6b:de:d0:49:c9:05:ea:62:71:a6:f8:1e:76:da:3c:a7:
+ 17:cd:1a:92:a3:c4:e8:85:d1:ad:34:0c:71:37:3f:6c:d3:7f:
+ 9a:d6:ca:de
-----BEGIN CERTIFICATE-----
-MIIDwzCCAqugAwIBAgIGDftmwfBTMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+MIIERDCCAyygAwIBAgIGDzR1USo8MA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
-Fw0xODA5MTkwNzEzMTRaFw0yNjEyMDYwNzEzMTRaMFQxCzAJBgNVBAYTAk5OMTEw
+Fw0yMjEyMjMxMjIxMzZaFw0zMTAzMTExMjIxMzZaMFQxCzAJBgNVBAYTAk5OMTEw
LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
-AoIBAQCfqTBQ+XC8M38fqsZeWgr2z5kizbw6Qed2vAUBhSTNInlHJk1qnUHPMYAg
-H186hy9P/1wjrGcL9BRYp0fXdgNT/rMNIwgZ/7SsR71gkMgElAXLzxsQqrsIRlRC
-qCvMNflquUaegkcYd8/ASB9c0pvt/Y09KQsgt90CYCdiGHMcDLGCLTycHrY+hvQO
-0wJQ8fgBhzKKLcVhC6qU8LMpP0mn9krddTDAYpcUa95NcURAOY4I9blzQdXrEtjO
-Xb4pduprlBjXLENeiRLxUPItwG0ZB5mW86hG8zvoyB0N+lSWoCYsT8BghKkhOQ9E
-KOTjEXnko0TiIOGdZVSiJ1ZnlAInAgMBAAGjgYYwgYMwFAYDVR0RBA0wC4IJbG9j
-YWxob3N0MAsGA1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4E
-FgQU0jYKUxKymWRHBVPSF2kS/I7b1wcwHwYDVR0jBBgwFoAUEsq6S0YEp3WKLOgO
-VJS8EmWme84wCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAKsyR075JYy+E
-8s/oQ+f6/MW512vXQCvuiViYJFfN61GgiyIYfVeB9QwGFNGBkHhZNCPWaBnHixMc
-snZloZskyLZDBKUrLsRLyWkDH8qGVFPlJaFdoyIR2S7IGuDdBDtvPOqmc1+AvWw7
-Qb47HvpovpGfhcCBKMs4I+u0Fr+BHOtnnrMDhLChLXa6elV3MUktQHq/P+PSUBGt
-Ogb9tXU2UClcJuRFQx0lePHegfHZOXBwRndIymR6GVdfTZsLDVe7wbUf2asm+0tU
-LQEq8+Rv57NKBUzzC6bREFon5BVsgFUsY1DxNg3r/+HraCB+pZh8DtAe9Wh/Tz65
-uOAP6jSmsQ==
+AoIBAQDGuAQ91voxoNf36YhLWl5vb9v0yUt+bCrPNHsquhpxrX94bPceygfQKQNJ
+5GOGTPZnP70yacu4FecOzyg9npaRjk9zqSd3TCZhzdbnTjxkwxO6juwDD7zUg7OU
+8r7QGDDFUknLmmDP87nKL2OdNO6HOljnoZnd3FaH4aDXazeuuxPbffoqPZw5efYB
+puM65xgUy8dXuYPRurgsWsSXL+6NaEg3+BfbMrnqJU8oVwE5E9zA99DMZfkruEyh
+WxHOROIouWNi/Qj6ts1J1bn+nmicmrUaPsy/DnTbUj8lMM19AkHHyYpYEjUlIZXE
+a8P1ecIAy+9/15+Jyf/AuXJZTDNHAgMBAAGjggEGMIIBAjAUBgNVHREEDTALggls
+b2NhbGhvc3QwCwYDVR0PBAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1Ud
+DgQWBBRK8XkbE3GkD/kGzLYszSRG3+YILTAfBgNVHSMEGDAWgBSHy7EzLsFnfnHj
+5StMTaSzbtJbqTAJBgNVHRMEAjAAMEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcw
+AoYnaHR0cDovL3Rlc3QuY3VybC5zZS9jYS9FZGVsQ3VybFJvb3QuY2VyMDgGA1Ud
+HwQxMC8wLaAroCmGJ2h0dHA6Ly90ZXN0LmN1cmwuc2UvY2EvRWRlbEN1cmxSb290
+LmNybDANBgkqhkiG9w0BAQsFAAOCAQEAZ++tj/ru8f0zZ2IGXwlVfM+CGuj89Ze6
+Y73QoIuFLPzwNEqXshjXYzRj9B9Qxw4T2bw7cz1BkxazMJWIzXXIjFhLq5bmeGgV
+D4TnjheUGrPzEqsm/fpzMTM2hYMt4zrypinGNzA9F9I5MdFWG43f+wetgQuR5b17
+N6CgWiwzK41pi9fBRWGF7zJF3QCigZhEDesBlfysD7U0pF81XGhjUFppVvOZxGdw
+iRMwwGT/8aZ3aGljnm/4PG/Nr3/eDYdVrjmzsvVPR3kfMu6ujzLciDDNOGxLKFXD
+fXRr3tBJyQXqYnGm+B522jynF80akqPE6IXRrTQMcTc/bNN/mtbK3g==
-----END CERTIFICATE-----
diff --git a/tests/certs/Server-localhost-sv.prm b/tests/certs/Server-localhost-sv.prm
index 50ccfd8..f587104 100644
--- a/tests/certs/Server-localhost-sv.prm
+++ b/tests/certs/Server-localhost-sv.prm
@@ -6,6 +6,19 @@
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
basicConstraints = CA:false
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
+
[ req ]
default_bits = 1024
distinguished_name = req_DN
diff --git a/tests/certs/Server-localhost-sv.pub.der b/tests/certs/Server-localhost-sv.pub.der
index 5cc9ce8..000c721 100644
--- a/tests/certs/Server-localhost-sv.pub.der
+++ b/tests/certs/Server-localhost-sv.pub.der
Binary files differ
diff --git a/tests/certs/Server-localhost-sv.pub.pem b/tests/certs/Server-localhost-sv.pub.pem
index ef27991..24fe144 100644
--- a/tests/certs/Server-localhost-sv.pub.pem
+++ b/tests/certs/Server-localhost-sv.pub.pem
@@ -1,9 +1,9 @@
-----BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn6kwUPlwvDN/H6rGXloK
-9s+ZIs28OkHndrwFAYUkzSJ5RyZNap1BzzGAIB9fOocvT/9cI6xnC/QUWKdH13YD
-U/6zDSMIGf+0rEe9YJDIBJQFy88bEKq7CEZUQqgrzDX5arlGnoJHGHfPwEgfXNKb
-7f2NPSkLILfdAmAnYhhzHAyxgi08nB62Pob0DtMCUPH4AYcyii3FYQuqlPCzKT9J
-p/ZK3XUwwGKXFGveTXFEQDmOCPW5c0HV6xLYzl2+KXbqa5QY1yxDXokS8VDyLcBt
-GQeZlvOoRvM76MgdDfpUlqAmLE/AYISpITkPRCjk4xF55KNE4iDhnWVUoidWZ5QC
-JwIDAQAB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrgEPdb6MaDX9+mIS1pe
+b2/b9MlLfmwqzzR7Kroaca1/eGz3HsoH0CkDSeRjhkz2Zz+9MmnLuBXnDs8oPZ6W
+kY5Pc6knd0wmYc3W5048ZMMTuo7sAw+81IOzlPK+0BgwxVJJy5pgz/O5yi9jnTTu
+hzpY56GZ3dxWh+Gg12s3rrsT2336Kj2cOXn2AabjOucYFMvHV7mD0bq4LFrEly/u
+jWhIN/gX2zK56iVPKFcBORPcwPfQzGX5K7hMoVsRzkTiKLljYv0I+rbNSdW5/p5o
+nJq1Gj7Mvw5021I/JTDNfQJBx8mKWBI1JSGVxGvD9XnCAMvvf9eficn/wLlyWUwz
+RwIDAQAB
-----END PUBLIC KEY-----
diff --git a/tests/certs/Server-localhost-sv.pubkey-pinned b/tests/certs/Server-localhost-sv.pubkey-pinned
new file mode 100644
index 0000000..96a362a
--- /dev/null
+++ b/tests/certs/Server-localhost-sv.pubkey-pinned
@@ -0,0 +1 @@
+AAUDLk4c98xcFUDvA9i/MnA9HuO03IPi15r+Cx9OXnc=
diff --git a/tests/certs/Server-localhost.nn-sv.crl b/tests/certs/Server-localhost.nn-sv.crl
index 6616a73..a944c33 100644
--- a/tests/certs/Server-localhost.nn-sv.crl
+++ b/tests/certs/Server-localhost.nn-sv.crl
@@ -1,13 +1,13 @@
-----BEGIN X509 CRL-----
-MIIB9TCB3gIBATANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJOTjExMC8GA1UE
+MIIB9TCB3gIBATANBgkqhkiG9w0BAQsFADBoMQswCQYDVQQGEwJOTjExMC8GA1UE
CgwoRWRlbCBDdXJsIEFyY3RpYyBJbGx1ZGl1bSBSZXNlYXJjaCBDbG91ZDEmMCQG
-A1UEAwwdTm9ydGhlcm4gTm93aGVyZSBUcnVzdCBBbmNob3IXDTE4MDkxOTA3MTQx
-MloXDTE4MTAxOTA3MTQxMlowMjAXAgYN+2bB8FMXDTE4MDkxOTA3MTMxNFowFwIG
-DftmyvGeFw0xODA5MTkwNzE0MTJaoA4wDDAKBgNVHRQEAwIBATANBgkqhkiG9w0B
-AQUFAAOCAQEAO28TB22Aen+HvwiNx9L6ordY5DD04ObE4D15D05T2XpSAZ0PQput
-tlLiiMGyEaBznFFyXv9AqdAEndfxWLhS3VosQxOrrv99mkug22il4mAc4V35QlrP
-EmHhvqFh1T2Wpyd6hYMbctg/9EBe7evadrVZT79AFo9piWTkuiLyq+npC2A9tPiH
-Q/q2Bg1t1qZBDM0O5wHaxtl1sz5CfDokfAT41Fju5p74mYOd50gIXOniWZVtIsfO
-bDwpZuG+R++MrYSsdaMicVDN9cwYAv+fAvrDQvMMd/ThU2H43pJLiCW7AzD6mQ3J
-3fuuhz8WAW7WVemqVrDOPuKku8t4+3fdDw==
+A1UEAwwdTm9ydGhlcm4gTm93aGVyZSBUcnVzdCBBbmNob3IXDTIyMTIyMzEyMjEz
+N1oXDTIzMDEyMjEyMjEzN1owMjAXAgYPNHVRKjwXDTIyMTIyMzEyMjEzNlowFwIG
+DzR1UVFhFw0yMjEyMjMxMjIxMzdaoA4wDDAKBgNVHRQEAwIBATANBgkqhkiG9w0B
+AQsFAAOCAQEAii+pMstYDtBKHc84kkIEwV+zwGAAJo+jf/AHnqbagpoPKn61ci74
+74Q8BlrYTOksAJhVA/DwFnB8rwGHtGpnDvXtjpVMpvrQSGwi6D6FdjwUkq1aTQrF
+AZEHps1FCWYrOprz3YF49xQAKuq6yX+UxJXdUOqXZPgbtdGZBHNAdVK3Hu45C25e
+7U1CWKOHRMLyGJ4ynzysf3cUiSqHZG1A+WB6BeSz6guOVyb8I8/VZ+e3whcxAa5+
+YORoKFRS24bO/c9/XBsSC3E6i3kuPg/UVdI726DQwOXBYwtrkESzMsMMgeEXrNFm
+j3IyctWm2G/i/WkCNrt3bfTKV4th8tHdlA==
-----END X509 CRL-----
diff --git a/tests/certs/Server-localhost.nn-sv.crt b/tests/certs/Server-localhost.nn-sv.crt
index 6769c27..7738e5b 100644
--- a/tests/certs/Server-localhost.nn-sv.crt
+++ b/tests/certs/Server-localhost.nn-sv.crt
@@ -1,41 +1,41 @@
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15373412528542 (0xdfb66caf19e)
+ Serial Number: 16717980979553 (0xf3475515161)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = Northern Nowhere Trust Anchor
Validity
- Not Before: Sep 19 07:14:12 2018 GMT
- Not After : Dec 6 07:14:12 2026 GMT
+ Not Before: Dec 23 12:21:37 2022 GMT
+ Not After : Mar 11 12:21:37 2031 GMT
Subject:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = localhost.nn
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:f4:1e:5e:4c:8c:87:9e:09:f8:d7:62:3d:38:fb:
- 5e:9b:62:5b:02:2e:95:f5:0a:14:82:d4:07:fc:e7:
- f3:96:c3:12:1a:b9:24:fa:f4:41:7f:76:56:3d:8d:
- 72:21:2a:49:cf:54:42:09:87:16:02:98:b0:a9:c5:
- c6:d3:f2:60:ad:bb:61:17:a2:ea:35:31:1c:df:bb:
- 27:fe:9d:f9:f7:ff:6a:72:10:a3:44:75:3b:b5:3e:
- 76:1b:f7:60:a6:31:ca:4f:62:0e:7e:6d:99:9c:8e:
- 30:61:ff:37:e6:c1:91:65:0c:a1:a3:61:01:ef:75:
- dc:8f:52:9c:5b:39:45:35:63:ca:fb:ca:dd:76:4a:
- 02:78:c4:b0:2c:ec:e2:c8:de:27:9f:d6:b9:eb:39:
- de:a1:23:99:d5:65:97:78:e2:7c:08:55:97:91:84:
- 70:f4:88:c0:59:9c:f2:f0:fe:5c:71:78:bf:86:8e:
- 12:92:85:1f:15:ed:d3:83:fc:25:50:f4:86:04:cd:
- 77:7b:0c:9a:eb:ab:e9:cb:43:98:c4:1e:6e:de:d2:
- 26:9d:8e:a1:c8:df:4f:a6:66:bf:29:3b:6e:7a:b9:
- d2:be:74:16:c6:b4:c3:46:9b:09:19:42:9b:05:75:
- ae:b5:9c:5b:a3:d5:e1:76:65:59:39:bc:99:5d:00:
- 90:87
+ 00:a3:9a:e4:0f:e0:bd:93:a9:5a:a7:5e:ad:85:5e:
+ d6:e0:98:b4:e9:22:e0:62:90:c3:d9:57:37:16:5d:
+ 57:3d:68:ca:e2:cf:2f:46:67:1a:0c:af:0e:89:86:
+ 01:06:df:d6:c9:80:15:0a:43:85:40:3f:da:ee:ee:
+ 78:09:7c:90:e4:89:63:92:40:0b:22:1c:e2:d3:16:
+ a9:93:62:e4:04:7a:b0:ab:25:3a:74:02:44:ea:f1:
+ 31:89:94:29:74:a0:e2:bb:ae:e7:0f:f1:38:6a:87:
+ 1e:dd:5b:e6:a4:cc:97:ac:d3:01:9a:71:27:a3:22:
+ 6d:d8:4a:c7:49:5c:16:ae:61:a7:06:3a:90:b4:df:
+ 71:af:a5:fd:51:46:75:cd:78:e0:0c:52:99:41:4f:
+ 56:29:a6:a2:a3:dd:d9:7e:29:3e:68:a5:af:c0:34:
+ b5:73:52:12:04:90:07:1b:f5:8b:a3:71:56:c5:95:
+ 4e:62:18:d4:ec:e9:4e:90:1b:91:25:bb:32:15:db:
+ 15:38:59:14:c9:c5:c6:0a:08:aa:2d:f5:67:aa:2f:
+ eb:97:74:8a:8b:3e:5f:09:27:b0:bf:b3:a3:85:e9:
+ 7a:f5:39:dc:1d:c7:f4:34:73:d8:f2:ed:b0:c9:1d:
+ 2a:85:ee:e2:fb:51:09:5e:ff:bf:bc:79:c3:6d:30:
+ 89:b9
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
@@ -45,48 +45,55 @@
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Key Identifier:
- DA:FC:ED:BF:82:CB:15:D8:7E:A1:4B:98:23:8E:83:2A:11:6E:49:C9
+ 85:A2:1D:76:BD:C6:8B:D6:D2:2D:05:77:24:EC:78:7B:70:71:77:C1
X509v3 Authority Key Identifier:
- keyid:12:CA:BA:4B:46:04:A7:75:8A:2C:E8:0E:54:94:BC:12:65:A6:7B:CE
-
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
X509v3 Basic Constraints:
CA:FALSE
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
Signature Algorithm: sha256WithRSAEncryption
- 98:27:7a:85:b6:39:0f:9f:ca:0f:68:ca:4a:f6:8b:11:2f:df:
- 52:e4:47:5f:30:09:9c:2c:d8:2c:62:3b:24:0a:3d:37:58:0e:
- be:7b:8b:c6:2d:3c:be:ad:49:1f:63:3a:8e:81:34:0e:9a:80:
- f0:f4:c2:7b:fd:6c:66:be:68:d9:27:a6:61:60:08:65:aa:f9:
- 66:89:fc:99:43:07:3c:57:d9:d4:1a:29:93:e3:b8:a4:54:57:
- 42:7c:15:6f:b4:92:af:9f:3e:d0:80:62:49:61:e3:d0:e2:0c:
- 21:c7:49:9e:eb:42:1c:04:bb:ed:e3:6a:25:d1:79:42:03:75:
- 1f:41:06:c4:cd:42:06:96:df:37:c6:c2:52:13:20:a3:98:b1:
- 1c:df:5a:47:08:08:f4:b4:d8:35:db:bf:69:07:12:29:dc:17:
- 30:11:2d:1b:d9:33:af:38:ab:35:f9:f4:9b:f9:a8:3b:d4:fe:
- 50:7d:19:82:5e:a3:92:ff:bb:59:76:74:42:83:ab:29:49:4c:
- 10:83:99:12:0f:8d:24:3e:b0:c4:e3:96:d3:a7:73:5f:7e:fb:
- a8:b6:74:53:46:af:82:93:6d:c0:99:62:0f:03:df:e9:1d:10:
- ab:f7:92:f9:52:cb:44:f3:f6:9e:49:21:e8:81:7b:fc:78:55:
- 5b:e2:18:90
+ Signature Value:
+ 66:8f:f5:ea:6a:5d:58:b6:50:b0:5b:7b:1f:c1:54:d9:a3:bb:
+ 36:1b:eb:19:4a:0e:1c:26:43:32:84:de:cb:c9:eb:08:9a:ee:
+ 9d:d5:a6:62:3e:70:de:61:89:a9:d0:11:20:2a:a6:5c:19:ab:
+ 91:71:78:f6:5f:ab:e6:03:94:b3:94:42:7b:42:c6:37:f0:4c:
+ b7:49:5d:90:c5:e3:24:2c:a0:ce:fe:be:71:11:3e:e6:0b:13:
+ 85:8d:36:e6:db:82:8b:fd:51:a3:3d:42:4c:0d:fd:cf:0b:d8:
+ 37:ab:f2:e5:53:15:3f:01:d7:a9:78:d5:99:fe:33:88:d7:c6:
+ 31:dd:bf:b1:d2:e6:31:17:6e:28:91:19:26:36:d7:bc:98:04:
+ 4c:30:cb:58:ec:b3:c9:1d:22:bf:28:bc:17:6d:2d:5d:36:c3:
+ e5:12:80:5d:02:4c:61:48:95:a8:77:96:49:e2:17:87:fd:3b:
+ cc:55:15:0d:b8:13:5e:31:97:05:78:78:7b:0d:8e:3d:ac:25:
+ 99:81:61:77:c4:a4:a2:25:f1:70:34:17:40:f7:cb:f3:fd:da:
+ ad:bd:6d:f1:dc:85:0f:dd:4d:21:9e:19:6a:97:b3:43:44:71:
+ db:74:3f:bf:8a:8d:06:54:48:fd:9e:88:e8:5d:d2:be:ee:b4:
+ 69:1b:63:11
-----BEGIN CERTIFICATE-----
-MIIDyTCCArGgAwIBAgIGDftmyvGeMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+MIIESjCCAzKgAwIBAgIGDzR1UVFhMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
-Fw0xODA5MTkwNzE0MTJaFw0yNjEyMDYwNzE0MTJaMFcxCzAJBgNVBAYTAk5OMTEw
+Fw0yMjEyMjMxMjIxMzdaFw0zMTAzMTExMjIxMzdaMFcxCzAJBgNVBAYTAk5OMTEw
LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
MRUwEwYDVQQDDAxsb2NhbGhvc3Qubm4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQD0Hl5MjIeeCfjXYj04+16bYlsCLpX1ChSC1Af85/OWwxIauST69EF/
-dlY9jXIhKknPVEIJhxYCmLCpxcbT8mCtu2EXouo1MRzfuyf+nfn3/2pyEKNEdTu1
-PnYb92CmMcpPYg5+bZmcjjBh/zfmwZFlDKGjYQHvddyPUpxbOUU1Y8r7yt12SgJ4
-xLAs7OLI3ief1rnrOd6hI5nVZZd44nwIVZeRhHD0iMBZnPLw/lxxeL+GjhKShR8V
-7dOD/CVQ9IYEzXd7DJrrq+nLQ5jEHm7e0iadjqHI30+mZr8pO256udK+dBbGtMNG
-mwkZQpsFda61nFuj1eF2ZVk5vJldAJCHAgMBAAGjgYkwgYYwFwYDVR0RBBAwDoIM
-bG9jYWxob3N0Lm5uMAsGA1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAd
-BgNVHQ4EFgQU2vztv4LLFdh+oUuYI46DKhFuSckwHwYDVR0jBBgwFoAUEsq6S0YE
-p3WKLOgOVJS8EmWme84wCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAmCd6
-hbY5D5/KD2jKSvaLES/fUuRHXzAJnCzYLGI7JAo9N1gOvnuLxi08vq1JH2M6joE0
-DpqA8PTCe/1sZr5o2SemYWAIZar5Zon8mUMHPFfZ1Bopk+O4pFRXQnwVb7SSr58+
-0IBiSWHj0OIMIcdJnutCHAS77eNqJdF5QgN1H0EGxM1CBpbfN8bCUhMgo5ixHN9a
-RwgI9LTYNdu/aQcSKdwXMBEtG9kzrzirNfn0m/moO9T+UH0Zgl6jkv+7WXZ0QoOr
-KUlMEIOZEg+NJD6wxOOW06dzX377qLZ0U0avgpNtwJliDwPf6R0Qq/eS+VLLRPP2
-nkkh6IF7/HhVW+IYkA==
+ggEKAoIBAQCjmuQP4L2TqVqnXq2FXtbgmLTpIuBikMPZVzcWXVc9aMrizy9GZxoM
+rw6JhgEG39bJgBUKQ4VAP9ru7ngJfJDkiWOSQAsiHOLTFqmTYuQEerCrJTp0AkTq
+8TGJlCl0oOK7rucP8Thqhx7dW+akzJes0wGacSejIm3YSsdJXBauYacGOpC033Gv
+pf1RRnXNeOAMUplBT1YppqKj3dl+KT5opa/ANLVzUhIEkAcb9YujcVbFlU5iGNTs
+6U6QG5EluzIV2xU4WRTJxcYKCKot9WeqL+uXdIqLPl8JJ7C/s6OF6Xr1Odwdx/Q0
+c9jy7bDJHSqF7uL7UQle/7+8ecNtMIm5AgMBAAGjggEJMIIBBTAXBgNVHREEEDAO
+ggxsb2NhbGhvc3Qubm4wCwYDVR0PBAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUFBwMB
+MB0GA1UdDgQWBBSFoh12vcaL1tItBXck7Hh7cHF3wTAfBgNVHSMEGDAWgBSHy7Ez
+LsFnfnHj5StMTaSzbtJbqTAJBgNVHRMEAjAAMEMGCCsGAQUFBwEBBDcwNTAzBggr
+BgEFBQcwAoYnaHR0cDovL3Rlc3QuY3VybC5zZS9jYS9FZGVsQ3VybFJvb3QuY2Vy
+MDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly90ZXN0LmN1cmwuc2UvY2EvRWRlbEN1
+cmxSb290LmNybDANBgkqhkiG9w0BAQsFAAOCAQEAZo/16mpdWLZQsFt7H8FU2aO7
+NhvrGUoOHCZDMoTey8nrCJrundWmYj5w3mGJqdARICqmXBmrkXF49l+r5gOUs5RC
+e0LGN/BMt0ldkMXjJCygzv6+cRE+5gsThY025tuCi/1Roz1CTA39zwvYN6vy5VMV
+PwHXqXjVmf4ziNfGMd2/sdLmMRduKJEZJjbXvJgETDDLWOyzyR0ivyi8F20tXTbD
+5RKAXQJMYUiVqHeWSeIXh/07zFUVDbgTXjGXBXh4ew2OPawlmYFhd8SkoiXxcDQX
+QPfL8/3arb1t8dyFD91NIZ4ZapezQ0Rx23Q/v4qNBlRI/Z6I6F3Svu60aRtjEQ==
-----END CERTIFICATE-----
diff --git a/tests/certs/Server-localhost.nn-sv.csr b/tests/certs/Server-localhost.nn-sv.csr
index eb4c85b..af0d1c4 100644
--- a/tests/certs/Server-localhost.nn-sv.csr
+++ b/tests/certs/Server-localhost.nn-sv.csr
@@ -1,16 +1,16 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICnDCCAYQCAQAwVzELMAkGA1UEBhMCTk4xMTAvBgNVBAoMKEVkZWwgQ3VybCBB
cmN0aWMgSWxsdWRpdW0gUmVzZWFyY2ggQ2xvdWQxFTATBgNVBAMMDGxvY2FsaG9z
-dC5ubjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPQeXkyMh54J+Ndi
-PTj7XptiWwIulfUKFILUB/zn85bDEhq5JPr0QX92Vj2NciEqSc9UQgmHFgKYsKnF
-xtPyYK27YRei6jUxHN+7J/6d+ff/anIQo0R1O7U+dhv3YKYxyk9iDn5tmZyOMGH/
-N+bBkWUMoaNhAe913I9SnFs5RTVjyvvK3XZKAnjEsCzs4sjeJ5/Wues53qEjmdVl
-l3jifAhVl5GEcPSIwFmc8vD+XHF4v4aOEpKFHxXt04P8JVD0hgTNd3sMmuur6ctD
-mMQebt7SJp2OocjfT6Zmvyk7bnq50r50Fsa0w0abCRlCmwV1rrWcW6PV4XZlWTm8
-mV0AkIcCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQAqoMuYYIZCrbVy+UJpkz4u
-AH3zBRsDepyJ/J2JVG9RANyKves0uD84x0m7kIntxvZR78vmCVlE4IMIeUb0lT8Z
-jVh0GkC9ppiY5X5Ro0pqtSaEZeGJVcP6/3rz4j7XzcHs8wLgBQ/11Guqjb9Zzr5a
-w+g0LpL9ebRRDWiYAqcnReqL5dYy1OEVzNHmYyMqKxfF4d1cyl7+rZoz2MmjwZH9
-3k+DKTIURtSr8TxPXO77CAfmRRGxo06zHhi9zMFV8Tb8e9B7GNINUAli92fmXWPo
-ISBxWL7+YE7fvertPLmA9qQZJPJDSdpAOdDaKr7c3gNKpbUTrie1AzZHsq+/IFzq
+dC5ubjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKOa5A/gvZOpWqde
+rYVe1uCYtOki4GKQw9lXNxZdVz1oyuLPL0ZnGgyvDomGAQbf1smAFQpDhUA/2u7u
+eAl8kOSJY5JACyIc4tMWqZNi5AR6sKslOnQCROrxMYmUKXSg4ruu5w/xOGqHHt1b
+5qTMl6zTAZpxJ6MibdhKx0lcFq5hpwY6kLTfca+l/VFGdc144AxSmUFPVimmoqPd
+2X4pPmilr8A0tXNSEgSQBxv1i6NxVsWVTmIY1OzpTpAbkSW7MhXbFThZFMnFxgoI
+qi31Z6ov65d0ios+XwknsL+zo4XpevU53B3H9DRz2PLtsMkdKoXu4vtRCV7/v7x5
+w20wibkCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQArdsmGDGMvCUZ4dOwsUDdP
+C0RCBrgwRM7jQf1f4u2avePF/sl0RYhNLYhGUT2KUqLNs5+j7wKErthD32lWSPpa
+orPnibZkEKaO7ZVFUtcN7EOmluXFXsapKilYPDCEeSsHwM5Aaofl8Mkb5e5H+idf
+Vea2DuEKFQfumczzaD9JK9tPzsVbJ6FwiPeI46XpH7vrf1DZmauDp83GfAXc1Mrm
+dd8QdoGhdNjTi7H+36l1jY+7xnZ+s1vwqxIt4BCf6p6iBy4GHApFaD7bP6dizEUq
+weTUXHllb2bgz4cHHvV5n3NXzC6oE9sVw0nLdnfPFiZpGn8VnUW1ZvE3pGcWkAzC
-----END CERTIFICATE REQUEST-----
diff --git a/tests/certs/Server-localhost.nn-sv.der b/tests/certs/Server-localhost.nn-sv.der
index c9f50a3..10b7e35 100644
--- a/tests/certs/Server-localhost.nn-sv.der
+++ b/tests/certs/Server-localhost.nn-sv.der
Binary files differ
diff --git a/tests/certs/Server-localhost.nn-sv.key b/tests/certs/Server-localhost.nn-sv.key
index cf6f3ce..3e4af20 100644
--- a/tests/certs/Server-localhost.nn-sv.key
+++ b/tests/certs/Server-localhost.nn-sv.key
@@ -1,27 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEA9B5eTIyHngn412I9OPtem2JbAi6V9QoUgtQH/OfzlsMSGrkk
-+vRBf3ZWPY1yISpJz1RCCYcWApiwqcXG0/JgrbthF6LqNTEc37sn/p359/9qchCj
-RHU7tT52G/dgpjHKT2IOfm2ZnI4wYf835sGRZQyho2EB73Xcj1KcWzlFNWPK+8rd
-dkoCeMSwLOziyN4nn9a56zneoSOZ1WWXeOJ8CFWXkYRw9IjAWZzy8P5ccXi/ho4S
-koUfFe3Tg/wlUPSGBM13ewya66vpy0OYxB5u3tImnY6hyN9Ppma/KTtuernSvnQW
-xrTDRpsJGUKbBXWutZxbo9XhdmVZObyZXQCQhwIDAQABAoIBABjku+L8dZvlEm4M
-Q4f7AiPAPN2VGI+bTookywe8M3fNPpxhAudgXwl7bMHsGZZONKaixfUoxFLRdTpq
-w6K7VaaBtB3v7AgukO4zrJlnTKVAc39cOPnzJnqN+wdRC5cG/sVnj2jPDloLmd10
-ZCPw2z29swHxE3xyvWIUH4Oh7G/MIVr4BKooTuFEZ8yYqDYWLTmXW+p6aqMgdDwU
-18Bpqc6I8m74Ax8n4aHj74ZrFi73UNjOC4a68r5x4IRE/dRyIlXB1YLNdt2d8yZv
-LFoKBVe+5yw80qEDHVI3mr7C1kFdry41hDFxMSvSqNuQCRYH2B58/iB3CIOGIM9a
-eTyHRlECgYEA/Kg3xIF7S7IzGma9WTC158tt0/XzL7H8Js9qn9H7E0Tw2G34ftV1
-wS3sAa3o66uRQLkxL6zk1oFBu3xJjjdCU5WhIrGy5MGJmXMuAhIQdNLk+p5eXnRR
-SAPkKJZgud3R+C5DxYJrixGW9uoiB2I0f9dFYGrmMjsoLEj2vPZgu0kCgYEA91k6
-xw0OamjSlopLsyqWNt/+gK7RgBpvwencVDCZQZtVsYscAwIJvBr3yvsLdTbtNck6
-25bP6w91Pa3tRX3Uaa0H9+h0uulTvNnGzRUF/pNeGfzQT6vTd1KlBt+PKkgZIgIf
-coSgJqmMuKdzckVBBiy1uik5gFLFzQDjkFzznU8CgYEAmeYdkiUM5V72oe5TCDET
-nM3daG84YqUX4swVNqTBO0uTKUJTS27a+4DtcVhtuKAZKkOkIlY+TisNzxY199rR
-G/jY3jk/rvf0yPPP4pL+UyrjL4WoFgDkQemc4Nw4rv7fFz2XKof22g8s1dpoP/ch
-431NVR3IenBuWAtZwGCTK4ECgYEA879728IzDYuk0vMP7EywYP1VqOwdyhbDQR27
-oT+PF4cC6IZEoXY1r6gHvoCsZuMs2Y8nMFQrKuI9z/2Az7VTSJxaOORbfAIJIhae
-AWWRVbFVz1hC0/Bo4LKRq/dM9wa7tbbP1KN7yv3Ujfd+HgK/NF2E7CJJ5voqsH4K
-wy3GaKMCgYAvYH8jKQVlxVpjVR0AW4X5WNTlCaV4jOY+1185IsJHkvzG4v50yQNS
-m/9Z/hexWxJ2k6uVm3rdAaOL522JJLmE08uibNU47Lv/uHwQ579hVrC5VG3rd32X
-nJ6hR/J47yStnrLhb+uj2zAawqeODrAMRjvss/UOVJ/aN93YST1nJw==
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCjmuQP4L2TqVqn
+Xq2FXtbgmLTpIuBikMPZVzcWXVc9aMrizy9GZxoMrw6JhgEG39bJgBUKQ4VAP9ru
+7ngJfJDkiWOSQAsiHOLTFqmTYuQEerCrJTp0AkTq8TGJlCl0oOK7rucP8Thqhx7d
+W+akzJes0wGacSejIm3YSsdJXBauYacGOpC033Gvpf1RRnXNeOAMUplBT1YppqKj
+3dl+KT5opa/ANLVzUhIEkAcb9YujcVbFlU5iGNTs6U6QG5EluzIV2xU4WRTJxcYK
+CKot9WeqL+uXdIqLPl8JJ7C/s6OF6Xr1Odwdx/Q0c9jy7bDJHSqF7uL7UQle/7+8
+ecNtMIm5AgMBAAECggEATTaCwAOfNRtOT4NdfX5fByzK5OSy5ZHQ/LgupX1z+OWG
+KzkA5McwAiB0Se9WeLoXko3CYE+xibsZRn6BZGjHsTQuLA3Rs03StzEQ4yBe4MZO
+rtcpGSsg/4jJilbEoeh0WYOYRWvg5lXS+UGwPsLYKpaDQTJ6NIHBOb1BBJxTkASA
+ti7+uGn5DvRlOgFICBpNzRl83akeV8oLOJAqMZAlGI54jZa+cHkGfkJp+JyMbtjA
+zML+oen1BYGHP++uM8fg4bn9bpixpg784qiJJsjzjQVofpZc1CaTJ32hzBCvEYrw
+kQS5zhFsEP6fn278VWijFd2QOnxoyergumVOvBbNCQKBgQC+hB56kNGVuPcfSekW
+xa5BytDlfAiAvo34N5VhHHNbe/RDtJ2w5z2ZqKg2AL0efWPb4kCMaiXZf9my0Kjm
+iRv4LQA/hj1M7W33ubg93LZ9gnVdZSzuslR6CgXoIkmP4GZPF6n7+HxKStmeqBiE
+TMc80OVE1ogXbPGcKOjxHvglawKBgQDb1tECQ9TFQtVveys69ycFSjQAFt569mQT
+PBnVLtJ8RT3JX5rTKHLmYSl7kNylIzqO43+R8HZLGj09euRjTcKpatNkg7l74/PM
+YUDQki8voWfXchpbN9pbRVhuw9TBNUvMiL9pEdoBl85MyDhydD/gC9809ljZyo+y
+q8RCrP4yawKBgBXI+cs+IBkky21SgErQU/rF/Fkhc791CrrlcDlojXBanjXXw2hl
+KNAXTxTNxNJluDN+ja8AvE9ApV4jKg0ihIY+bxbUfNH9HGQFYqIASQXVEyKY3Sh2
+T96cosxGj27aVBibNh7P7TZ5lKTlx9fpB6dWo8DZXzp+hKo8q1ZXGjz9AoGAdNuy
+zKZr8tO9Cv6JE1YPqvMvwyBk8S4KMmNPRBAYmTBhUKr+bOJieW4KlAGEGFAqr4vk
+4xnUd8Wh6g1qXBMYt9/uMM8IiP+6N9k2j+g1JveAcHjZ48VD0CKDiJWWgYGoIjhK
+rzprDU+5vPztbIG49oq5Ark0r8jKK+q8b8jvcrMCgYB/eTv2L5ReL99Hvrtm5oVE
+BkkLS4dr8hnA7QJyo84yy8yq1w5KzOiMpnnK7v6N9NkGMn7Ia8HMqFyGuqaINzlY
+NdYt+qoxLXdIDzKTSS91GAwfF25iyptx2DsdY2j2Smhp4put1/QygAbvlwXZy+kG
+T8c+FOuI1h2Bg0bSSoTfIQ==
+-----END PRIVATE KEY-----
diff --git a/tests/certs/Server-localhost.nn-sv.pem b/tests/certs/Server-localhost.nn-sv.pem
index 9782426..29dc52c 100644
--- a/tests/certs/Server-localhost.nn-sv.pem
+++ b/tests/certs/Server-localhost.nn-sv.pem
@@ -6,6 +6,19 @@
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
basicConstraints = CA:false
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
+
[ req ]
default_bits = 1024
distinguished_name = req_DN
@@ -23,71 +36,72 @@
# The key
# the certificate
# some dhparam
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEA9B5eTIyHngn412I9OPtem2JbAi6V9QoUgtQH/OfzlsMSGrkk
-+vRBf3ZWPY1yISpJz1RCCYcWApiwqcXG0/JgrbthF6LqNTEc37sn/p359/9qchCj
-RHU7tT52G/dgpjHKT2IOfm2ZnI4wYf835sGRZQyho2EB73Xcj1KcWzlFNWPK+8rd
-dkoCeMSwLOziyN4nn9a56zneoSOZ1WWXeOJ8CFWXkYRw9IjAWZzy8P5ccXi/ho4S
-koUfFe3Tg/wlUPSGBM13ewya66vpy0OYxB5u3tImnY6hyN9Ppma/KTtuernSvnQW
-xrTDRpsJGUKbBXWutZxbo9XhdmVZObyZXQCQhwIDAQABAoIBABjku+L8dZvlEm4M
-Q4f7AiPAPN2VGI+bTookywe8M3fNPpxhAudgXwl7bMHsGZZONKaixfUoxFLRdTpq
-w6K7VaaBtB3v7AgukO4zrJlnTKVAc39cOPnzJnqN+wdRC5cG/sVnj2jPDloLmd10
-ZCPw2z29swHxE3xyvWIUH4Oh7G/MIVr4BKooTuFEZ8yYqDYWLTmXW+p6aqMgdDwU
-18Bpqc6I8m74Ax8n4aHj74ZrFi73UNjOC4a68r5x4IRE/dRyIlXB1YLNdt2d8yZv
-LFoKBVe+5yw80qEDHVI3mr7C1kFdry41hDFxMSvSqNuQCRYH2B58/iB3CIOGIM9a
-eTyHRlECgYEA/Kg3xIF7S7IzGma9WTC158tt0/XzL7H8Js9qn9H7E0Tw2G34ftV1
-wS3sAa3o66uRQLkxL6zk1oFBu3xJjjdCU5WhIrGy5MGJmXMuAhIQdNLk+p5eXnRR
-SAPkKJZgud3R+C5DxYJrixGW9uoiB2I0f9dFYGrmMjsoLEj2vPZgu0kCgYEA91k6
-xw0OamjSlopLsyqWNt/+gK7RgBpvwencVDCZQZtVsYscAwIJvBr3yvsLdTbtNck6
-25bP6w91Pa3tRX3Uaa0H9+h0uulTvNnGzRUF/pNeGfzQT6vTd1KlBt+PKkgZIgIf
-coSgJqmMuKdzckVBBiy1uik5gFLFzQDjkFzznU8CgYEAmeYdkiUM5V72oe5TCDET
-nM3daG84YqUX4swVNqTBO0uTKUJTS27a+4DtcVhtuKAZKkOkIlY+TisNzxY199rR
-G/jY3jk/rvf0yPPP4pL+UyrjL4WoFgDkQemc4Nw4rv7fFz2XKof22g8s1dpoP/ch
-431NVR3IenBuWAtZwGCTK4ECgYEA879728IzDYuk0vMP7EywYP1VqOwdyhbDQR27
-oT+PF4cC6IZEoXY1r6gHvoCsZuMs2Y8nMFQrKuI9z/2Az7VTSJxaOORbfAIJIhae
-AWWRVbFVz1hC0/Bo4LKRq/dM9wa7tbbP1KN7yv3Ujfd+HgK/NF2E7CJJ5voqsH4K
-wy3GaKMCgYAvYH8jKQVlxVpjVR0AW4X5WNTlCaV4jOY+1185IsJHkvzG4v50yQNS
-m/9Z/hexWxJ2k6uVm3rdAaOL522JJLmE08uibNU47Lv/uHwQ579hVrC5VG3rd32X
-nJ6hR/J47yStnrLhb+uj2zAawqeODrAMRjvss/UOVJ/aN93YST1nJw==
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCjmuQP4L2TqVqn
+Xq2FXtbgmLTpIuBikMPZVzcWXVc9aMrizy9GZxoMrw6JhgEG39bJgBUKQ4VAP9ru
+7ngJfJDkiWOSQAsiHOLTFqmTYuQEerCrJTp0AkTq8TGJlCl0oOK7rucP8Thqhx7d
+W+akzJes0wGacSejIm3YSsdJXBauYacGOpC033Gvpf1RRnXNeOAMUplBT1YppqKj
+3dl+KT5opa/ANLVzUhIEkAcb9YujcVbFlU5iGNTs6U6QG5EluzIV2xU4WRTJxcYK
+CKot9WeqL+uXdIqLPl8JJ7C/s6OF6Xr1Odwdx/Q0c9jy7bDJHSqF7uL7UQle/7+8
+ecNtMIm5AgMBAAECggEATTaCwAOfNRtOT4NdfX5fByzK5OSy5ZHQ/LgupX1z+OWG
+KzkA5McwAiB0Se9WeLoXko3CYE+xibsZRn6BZGjHsTQuLA3Rs03StzEQ4yBe4MZO
+rtcpGSsg/4jJilbEoeh0WYOYRWvg5lXS+UGwPsLYKpaDQTJ6NIHBOb1BBJxTkASA
+ti7+uGn5DvRlOgFICBpNzRl83akeV8oLOJAqMZAlGI54jZa+cHkGfkJp+JyMbtjA
+zML+oen1BYGHP++uM8fg4bn9bpixpg784qiJJsjzjQVofpZc1CaTJ32hzBCvEYrw
+kQS5zhFsEP6fn278VWijFd2QOnxoyergumVOvBbNCQKBgQC+hB56kNGVuPcfSekW
+xa5BytDlfAiAvo34N5VhHHNbe/RDtJ2w5z2ZqKg2AL0efWPb4kCMaiXZf9my0Kjm
+iRv4LQA/hj1M7W33ubg93LZ9gnVdZSzuslR6CgXoIkmP4GZPF6n7+HxKStmeqBiE
+TMc80OVE1ogXbPGcKOjxHvglawKBgQDb1tECQ9TFQtVveys69ycFSjQAFt569mQT
+PBnVLtJ8RT3JX5rTKHLmYSl7kNylIzqO43+R8HZLGj09euRjTcKpatNkg7l74/PM
+YUDQki8voWfXchpbN9pbRVhuw9TBNUvMiL9pEdoBl85MyDhydD/gC9809ljZyo+y
+q8RCrP4yawKBgBXI+cs+IBkky21SgErQU/rF/Fkhc791CrrlcDlojXBanjXXw2hl
+KNAXTxTNxNJluDN+ja8AvE9ApV4jKg0ihIY+bxbUfNH9HGQFYqIASQXVEyKY3Sh2
+T96cosxGj27aVBibNh7P7TZ5lKTlx9fpB6dWo8DZXzp+hKo8q1ZXGjz9AoGAdNuy
+zKZr8tO9Cv6JE1YPqvMvwyBk8S4KMmNPRBAYmTBhUKr+bOJieW4KlAGEGFAqr4vk
+4xnUd8Wh6g1qXBMYt9/uMM8IiP+6N9k2j+g1JveAcHjZ48VD0CKDiJWWgYGoIjhK
+rzprDU+5vPztbIG49oq5Ark0r8jKK+q8b8jvcrMCgYB/eTv2L5ReL99Hvrtm5oVE
+BkkLS4dr8hnA7QJyo84yy8yq1w5KzOiMpnnK7v6N9NkGMn7Ia8HMqFyGuqaINzlY
+NdYt+qoxLXdIDzKTSS91GAwfF25iyptx2DsdY2j2Smhp4put1/QygAbvlwXZy+kG
+T8c+FOuI1h2Bg0bSSoTfIQ==
+-----END PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15373412528542 (0xdfb66caf19e)
+ Serial Number: 16717980979553 (0xf3475515161)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = Northern Nowhere Trust Anchor
Validity
- Not Before: Sep 19 07:14:12 2018 GMT
- Not After : Dec 6 07:14:12 2026 GMT
+ Not Before: Dec 23 12:21:37 2022 GMT
+ Not After : Mar 11 12:21:37 2031 GMT
Subject:
countryName = NN
organizationName = Edel Curl Arctic Illudium Research Cloud
commonName = localhost.nn
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:f4:1e:5e:4c:8c:87:9e:09:f8:d7:62:3d:38:fb:
- 5e:9b:62:5b:02:2e:95:f5:0a:14:82:d4:07:fc:e7:
- f3:96:c3:12:1a:b9:24:fa:f4:41:7f:76:56:3d:8d:
- 72:21:2a:49:cf:54:42:09:87:16:02:98:b0:a9:c5:
- c6:d3:f2:60:ad:bb:61:17:a2:ea:35:31:1c:df:bb:
- 27:fe:9d:f9:f7:ff:6a:72:10:a3:44:75:3b:b5:3e:
- 76:1b:f7:60:a6:31:ca:4f:62:0e:7e:6d:99:9c:8e:
- 30:61:ff:37:e6:c1:91:65:0c:a1:a3:61:01:ef:75:
- dc:8f:52:9c:5b:39:45:35:63:ca:fb:ca:dd:76:4a:
- 02:78:c4:b0:2c:ec:e2:c8:de:27:9f:d6:b9:eb:39:
- de:a1:23:99:d5:65:97:78:e2:7c:08:55:97:91:84:
- 70:f4:88:c0:59:9c:f2:f0:fe:5c:71:78:bf:86:8e:
- 12:92:85:1f:15:ed:d3:83:fc:25:50:f4:86:04:cd:
- 77:7b:0c:9a:eb:ab:e9:cb:43:98:c4:1e:6e:de:d2:
- 26:9d:8e:a1:c8:df:4f:a6:66:bf:29:3b:6e:7a:b9:
- d2:be:74:16:c6:b4:c3:46:9b:09:19:42:9b:05:75:
- ae:b5:9c:5b:a3:d5:e1:76:65:59:39:bc:99:5d:00:
- 90:87
+ 00:a3:9a:e4:0f:e0:bd:93:a9:5a:a7:5e:ad:85:5e:
+ d6:e0:98:b4:e9:22:e0:62:90:c3:d9:57:37:16:5d:
+ 57:3d:68:ca:e2:cf:2f:46:67:1a:0c:af:0e:89:86:
+ 01:06:df:d6:c9:80:15:0a:43:85:40:3f:da:ee:ee:
+ 78:09:7c:90:e4:89:63:92:40:0b:22:1c:e2:d3:16:
+ a9:93:62:e4:04:7a:b0:ab:25:3a:74:02:44:ea:f1:
+ 31:89:94:29:74:a0:e2:bb:ae:e7:0f:f1:38:6a:87:
+ 1e:dd:5b:e6:a4:cc:97:ac:d3:01:9a:71:27:a3:22:
+ 6d:d8:4a:c7:49:5c:16:ae:61:a7:06:3a:90:b4:df:
+ 71:af:a5:fd:51:46:75:cd:78:e0:0c:52:99:41:4f:
+ 56:29:a6:a2:a3:dd:d9:7e:29:3e:68:a5:af:c0:34:
+ b5:73:52:12:04:90:07:1b:f5:8b:a3:71:56:c5:95:
+ 4e:62:18:d4:ec:e9:4e:90:1b:91:25:bb:32:15:db:
+ 15:38:59:14:c9:c5:c6:0a:08:aa:2d:f5:67:aa:2f:
+ eb:97:74:8a:8b:3e:5f:09:27:b0:bf:b3:a3:85:e9:
+ 7a:f5:39:dc:1d:c7:f4:34:73:d8:f2:ed:b0:c9:1d:
+ 2a:85:ee:e2:fb:51:09:5e:ff:bf:bc:79:c3:6d:30:
+ 89:b9
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
@@ -97,48 +111,55 @@
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Key Identifier:
- DA:FC:ED:BF:82:CB:15:D8:7E:A1:4B:98:23:8E:83:2A:11:6E:49:C9
+ 85:A2:1D:76:BD:C6:8B:D6:D2:2D:05:77:24:EC:78:7B:70:71:77:C1
X509v3 Authority Key Identifier:
- keyid:12:CA:BA:4B:46:04:A7:75:8A:2C:E8:0E:54:94:BC:12:65:A6:7B:CE
-
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
X509v3 Basic Constraints:
CA:FALSE
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
Signature Algorithm: sha256WithRSAEncryption
- 98:27:7a:85:b6:39:0f:9f:ca:0f:68:ca:4a:f6:8b:11:2f:df:
- 52:e4:47:5f:30:09:9c:2c:d8:2c:62:3b:24:0a:3d:37:58:0e:
- be:7b:8b:c6:2d:3c:be:ad:49:1f:63:3a:8e:81:34:0e:9a:80:
- f0:f4:c2:7b:fd:6c:66:be:68:d9:27:a6:61:60:08:65:aa:f9:
- 66:89:fc:99:43:07:3c:57:d9:d4:1a:29:93:e3:b8:a4:54:57:
- 42:7c:15:6f:b4:92:af:9f:3e:d0:80:62:49:61:e3:d0:e2:0c:
- 21:c7:49:9e:eb:42:1c:04:bb:ed:e3:6a:25:d1:79:42:03:75:
- 1f:41:06:c4:cd:42:06:96:df:37:c6:c2:52:13:20:a3:98:b1:
- 1c:df:5a:47:08:08:f4:b4:d8:35:db:bf:69:07:12:29:dc:17:
- 30:11:2d:1b:d9:33:af:38:ab:35:f9:f4:9b:f9:a8:3b:d4:fe:
- 50:7d:19:82:5e:a3:92:ff:bb:59:76:74:42:83:ab:29:49:4c:
- 10:83:99:12:0f:8d:24:3e:b0:c4:e3:96:d3:a7:73:5f:7e:fb:
- a8:b6:74:53:46:af:82:93:6d:c0:99:62:0f:03:df:e9:1d:10:
- ab:f7:92:f9:52:cb:44:f3:f6:9e:49:21:e8:81:7b:fc:78:55:
- 5b:e2:18:90
+ Signature Value:
+ 66:8f:f5:ea:6a:5d:58:b6:50:b0:5b:7b:1f:c1:54:d9:a3:bb:
+ 36:1b:eb:19:4a:0e:1c:26:43:32:84:de:cb:c9:eb:08:9a:ee:
+ 9d:d5:a6:62:3e:70:de:61:89:a9:d0:11:20:2a:a6:5c:19:ab:
+ 91:71:78:f6:5f:ab:e6:03:94:b3:94:42:7b:42:c6:37:f0:4c:
+ b7:49:5d:90:c5:e3:24:2c:a0:ce:fe:be:71:11:3e:e6:0b:13:
+ 85:8d:36:e6:db:82:8b:fd:51:a3:3d:42:4c:0d:fd:cf:0b:d8:
+ 37:ab:f2:e5:53:15:3f:01:d7:a9:78:d5:99:fe:33:88:d7:c6:
+ 31:dd:bf:b1:d2:e6:31:17:6e:28:91:19:26:36:d7:bc:98:04:
+ 4c:30:cb:58:ec:b3:c9:1d:22:bf:28:bc:17:6d:2d:5d:36:c3:
+ e5:12:80:5d:02:4c:61:48:95:a8:77:96:49:e2:17:87:fd:3b:
+ cc:55:15:0d:b8:13:5e:31:97:05:78:78:7b:0d:8e:3d:ac:25:
+ 99:81:61:77:c4:a4:a2:25:f1:70:34:17:40:f7:cb:f3:fd:da:
+ ad:bd:6d:f1:dc:85:0f:dd:4d:21:9e:19:6a:97:b3:43:44:71:
+ db:74:3f:bf:8a:8d:06:54:48:fd:9e:88:e8:5d:d2:be:ee:b4:
+ 69:1b:63:11
-----BEGIN CERTIFICATE-----
-MIIDyTCCArGgAwIBAgIGDftmyvGeMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+MIIESjCCAzKgAwIBAgIGDzR1UVFhMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
-Fw0xODA5MTkwNzE0MTJaFw0yNjEyMDYwNzE0MTJaMFcxCzAJBgNVBAYTAk5OMTEw
+Fw0yMjEyMjMxMjIxMzdaFw0zMTAzMTExMjIxMzdaMFcxCzAJBgNVBAYTAk5OMTEw
LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
MRUwEwYDVQQDDAxsb2NhbGhvc3Qubm4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQD0Hl5MjIeeCfjXYj04+16bYlsCLpX1ChSC1Af85/OWwxIauST69EF/
-dlY9jXIhKknPVEIJhxYCmLCpxcbT8mCtu2EXouo1MRzfuyf+nfn3/2pyEKNEdTu1
-PnYb92CmMcpPYg5+bZmcjjBh/zfmwZFlDKGjYQHvddyPUpxbOUU1Y8r7yt12SgJ4
-xLAs7OLI3ief1rnrOd6hI5nVZZd44nwIVZeRhHD0iMBZnPLw/lxxeL+GjhKShR8V
-7dOD/CVQ9IYEzXd7DJrrq+nLQ5jEHm7e0iadjqHI30+mZr8pO256udK+dBbGtMNG
-mwkZQpsFda61nFuj1eF2ZVk5vJldAJCHAgMBAAGjgYkwgYYwFwYDVR0RBBAwDoIM
-bG9jYWxob3N0Lm5uMAsGA1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAd
-BgNVHQ4EFgQU2vztv4LLFdh+oUuYI46DKhFuSckwHwYDVR0jBBgwFoAUEsq6S0YE
-p3WKLOgOVJS8EmWme84wCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAmCd6
-hbY5D5/KD2jKSvaLES/fUuRHXzAJnCzYLGI7JAo9N1gOvnuLxi08vq1JH2M6joE0
-DpqA8PTCe/1sZr5o2SemYWAIZar5Zon8mUMHPFfZ1Bopk+O4pFRXQnwVb7SSr58+
-0IBiSWHj0OIMIcdJnutCHAS77eNqJdF5QgN1H0EGxM1CBpbfN8bCUhMgo5ixHN9a
-RwgI9LTYNdu/aQcSKdwXMBEtG9kzrzirNfn0m/moO9T+UH0Zgl6jkv+7WXZ0QoOr
-KUlMEIOZEg+NJD6wxOOW06dzX377qLZ0U0avgpNtwJliDwPf6R0Qq/eS+VLLRPP2
-nkkh6IF7/HhVW+IYkA==
+ggEKAoIBAQCjmuQP4L2TqVqnXq2FXtbgmLTpIuBikMPZVzcWXVc9aMrizy9GZxoM
+rw6JhgEG39bJgBUKQ4VAP9ru7ngJfJDkiWOSQAsiHOLTFqmTYuQEerCrJTp0AkTq
+8TGJlCl0oOK7rucP8Thqhx7dW+akzJes0wGacSejIm3YSsdJXBauYacGOpC033Gv
+pf1RRnXNeOAMUplBT1YppqKj3dl+KT5opa/ANLVzUhIEkAcb9YujcVbFlU5iGNTs
+6U6QG5EluzIV2xU4WRTJxcYKCKot9WeqL+uXdIqLPl8JJ7C/s6OF6Xr1Odwdx/Q0
+c9jy7bDJHSqF7uL7UQle/7+8ecNtMIm5AgMBAAGjggEJMIIBBTAXBgNVHREEEDAO
+ggxsb2NhbGhvc3Qubm4wCwYDVR0PBAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUFBwMB
+MB0GA1UdDgQWBBSFoh12vcaL1tItBXck7Hh7cHF3wTAfBgNVHSMEGDAWgBSHy7Ez
+LsFnfnHj5StMTaSzbtJbqTAJBgNVHRMEAjAAMEMGCCsGAQUFBwEBBDcwNTAzBggr
+BgEFBQcwAoYnaHR0cDovL3Rlc3QuY3VybC5zZS9jYS9FZGVsQ3VybFJvb3QuY2Vy
+MDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly90ZXN0LmN1cmwuc2UvY2EvRWRlbEN1
+cmxSb290LmNybDANBgkqhkiG9w0BAQsFAAOCAQEAZo/16mpdWLZQsFt7H8FU2aO7
+NhvrGUoOHCZDMoTey8nrCJrundWmYj5w3mGJqdARICqmXBmrkXF49l+r5gOUs5RC
+e0LGN/BMt0ldkMXjJCygzv6+cRE+5gsThY025tuCi/1Roz1CTA39zwvYN6vy5VMV
+PwHXqXjVmf4ziNfGMd2/sdLmMRduKJEZJjbXvJgETDDLWOyzyR0ivyi8F20tXTbD
+5RKAXQJMYUiVqHeWSeIXh/07zFUVDbgTXjGXBXh4ew2OPawlmYFhd8SkoiXxcDQX
+QPfL8/3arb1t8dyFD91NIZ4ZapezQ0Rx23Q/v4qNBlRI/Z6I6F3Svu60aRtjEQ==
-----END CERTIFICATE-----
diff --git a/tests/certs/Server-localhost.nn-sv.prm b/tests/certs/Server-localhost.nn-sv.prm
index 093d475..5e93bf8 100644
--- a/tests/certs/Server-localhost.nn-sv.prm
+++ b/tests/certs/Server-localhost.nn-sv.prm
@@ -6,6 +6,19 @@
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
basicConstraints = CA:false
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
+
[ req ]
default_bits = 1024
distinguished_name = req_DN
diff --git a/tests/certs/Server-localhost.nn-sv.pub.der b/tests/certs/Server-localhost.nn-sv.pub.der
index 8dabd342..af9bcfa 100644
--- a/tests/certs/Server-localhost.nn-sv.pub.der
+++ b/tests/certs/Server-localhost.nn-sv.pub.der
Binary files differ
diff --git a/tests/certs/Server-localhost.nn-sv.pub.pem b/tests/certs/Server-localhost.nn-sv.pub.pem
index 1ac1e43..85636dd 100644
--- a/tests/certs/Server-localhost.nn-sv.pub.pem
+++ b/tests/certs/Server-localhost.nn-sv.pub.pem
@@ -1,9 +1,9 @@
-----BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9B5eTIyHngn412I9OPte
-m2JbAi6V9QoUgtQH/OfzlsMSGrkk+vRBf3ZWPY1yISpJz1RCCYcWApiwqcXG0/Jg
-rbthF6LqNTEc37sn/p359/9qchCjRHU7tT52G/dgpjHKT2IOfm2ZnI4wYf835sGR
-ZQyho2EB73Xcj1KcWzlFNWPK+8rddkoCeMSwLOziyN4nn9a56zneoSOZ1WWXeOJ8
-CFWXkYRw9IjAWZzy8P5ccXi/ho4SkoUfFe3Tg/wlUPSGBM13ewya66vpy0OYxB5u
-3tImnY6hyN9Ppma/KTtuernSvnQWxrTDRpsJGUKbBXWutZxbo9XhdmVZObyZXQCQ
-hwIDAQAB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo5rkD+C9k6lap16thV7W
+4Ji06SLgYpDD2Vc3Fl1XPWjK4s8vRmcaDK8OiYYBBt/WyYAVCkOFQD/a7u54CXyQ
+5IljkkALIhzi0xapk2LkBHqwqyU6dAJE6vExiZQpdKDiu67nD/E4aoce3VvmpMyX
+rNMBmnEnoyJt2ErHSVwWrmGnBjqQtN9xr6X9UUZ1zXjgDFKZQU9WKaaio93Zfik+
+aKWvwDS1c1ISBJAHG/WLo3FWxZVOYhjU7OlOkBuRJbsyFdsVOFkUycXGCgiqLfVn
+qi/rl3SKiz5fCSewv7Ojhel69TncHcf0NHPY8u2wyR0qhe7i+1EJXv+/vHnDbTCJ
+uQIDAQAB
-----END PUBLIC KEY-----
diff --git a/tests/certs/Server-localhost.nn-sv.pubkey-pinned b/tests/certs/Server-localhost.nn-sv.pubkey-pinned
new file mode 100644
index 0000000..ce49b28
--- /dev/null
+++ b/tests/certs/Server-localhost.nn-sv.pubkey-pinned
@@ -0,0 +1 @@
+YRy84GLJxpJBGddJjhnqze5DJhkOUWytnCEqS0u0mTA=
diff --git a/tests/certs/Server-localhost0h-sv.crl b/tests/certs/Server-localhost0h-sv.crl
index d0a6982..f1d4401 100644
--- a/tests/certs/Server-localhost0h-sv.crl
+++ b/tests/certs/Server-localhost0h-sv.crl
@@ -1,14 +1,14 @@
-----BEGIN X509 CRL-----
-MIICDjCB9wIBATANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJOTjExMC8GA1UE
+MIICDjCB9wIBATANBgkqhkiG9w0BAQsFADBoMQswCQYDVQQGEwJOTjExMC8GA1UE
CgwoRWRlbCBDdXJsIEFyY3RpYyBJbGx1ZGl1bSBSZXNlYXJjaCBDbG91ZDEmMCQG
-A1UEAwwdTm9ydGhlcm4gTm93aGVyZSBUcnVzdCBBbmNob3IXDTE4MDkxOTA3MTQy
-M1oXDTE4MTAxOTA3MTQyM1owSzAXAgYN+2bB8FMXDTE4MDkxOTA3MTMxNFowFwIG
-DftmyvGeFw0xODA5MTkwNzE0MTJaMBcCBg37ZsyfbhcNMTgwOTE5MDcxNDIzWqAO
-MAwwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADggEBACbgkZUTmz5Uxff0KX1n
-havsvHZbQ97BQcI2n5QP34+lwEZTQrjKy9Zx1Hj4KV7ID7j5zS+4VdZIjSBfb5TI
-mkH3d1EAYkwLJ2YW/CyVTiEht5ewh02QIlWKf6SiwvYkT50tbf1Wwu/ADeqF0JVW
-Cc6TlSPRKWokkcPz3VYLrvZ3TsJbevLQ1eT0aRHjvItZ3FAzOZpDmpWZ8vONL6nB
-Npb2/zUQ+kmd+9OVB3qq6ok+sLl7s+gdQxjw7ZAEn4pPI2J1AjCJTCDD2ZfiZB0o
-Z5LNIemkbVF56lWPTgf8s6ZKjNEaF3MsBX6JX+oI6XG7V+0JQ9HcklqZ0d2VFbjK
-WGc=
+A1UEAwwdTm9ydGhlcm4gTm93aGVyZSBUcnVzdCBBbmNob3IXDTIyMTIyMzEyMjEz
+N1oXDTIzMDEyMjEyMjEzN1owSzAXAgYPNHVRKjwXDTIyMTIyMzEyMjEzNlowFwIG
+DzR1UVFhFw0yMjEyMjMxMjIxMzdaMBcCBg80dVFRdRcNMjIxMjIzMTIyMTM3WqAO
+MAwwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADggEBAEYPECPj+TzlRKUcYBwN
+SWqSBzua1dBket0sNYYnm2Jvst27guK10XwGcD4Jei7VDdTXfxLiXMQahWO/SIUE
+ZGrFhU6vdq7rSk179acREDYFgYDNxgSKgyU4SjzTJ+VantWs+ky0lsyiu2Sh8B4G
+bDmG4mEPXPykHufpbmkUCLqFd89JiuhNTripOUzJfAWLDPPYf4gn2ktenz/hFwJA
+o5CSWsn13iO+9NRVJ/5ErIuoLEdGzRVoCfDNKAJ2XE0ZhRPclmRHThaoxRnBeQFg
+AVGB+xLd3BSZQuOw3pxn4smGXg/9BW3qEba5W24P4WA4ldw2j4q8WviOygvUVBQ7
+pCw=
-----END X509 CRL-----
diff --git a/tests/certs/Server-localhost0h-sv.crt b/tests/certs/Server-localhost0h-sv.crt
index 4aabb45..e9892d0 100644
--- a/tests/certs/Server-localhost0h-sv.crt
+++ b/tests/certs/Server-localhost0h-sv.crt
Binary files differ
diff --git a/tests/certs/Server-localhost0h-sv.csr b/tests/certs/Server-localhost0h-sv.csr
index 5f3cae7..d2a021e 100644
--- a/tests/certs/Server-localhost0h-sv.csr
+++ b/tests/certs/Server-localhost0h-sv.csr
@@ -1,16 +1,16 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICmTCCAYECAQAwVDELMAkGA1UEBhMCTk4xMTAvBgNVBAoMKEVkZWwgQ3VybCBB
cmN0aWMgSWxsdWRpdW0gUmVzZWFyY2ggQ2xvdWQxEjAQBgNVBAMMCWxvY2FsaG9z
-dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALj+ariKDrs0kM9I590N
-JjJnCk6qnEz962/huJhdsUPUCU9i2E181gs2k1f7YQK5jTUgm959o9UNjkSY1JEx
-oh6ahMwAUkt4w1dXa9clKb8UUCBvGu48/Lu/Hh/NqLf9ja7MeAfAA4b97duGwSuB
-VUVKUAf9jYWk6Sncu+LV3d06+GIhPDDQWohxZ1OveOp+CEAyZRZ8v8m69QYeAvL4
-tznIhcB4FNLZ/SuLDD/ag0gvJiQ0G/pwB0a0AeoNzNeBqfFmxU49frSztGSj6g//
-AVTBix/pZdX8vHFDaS5Q9AMSpZGVIDbckeuqq48wbGYiIN4duFnRFqhxVUpm/nac
-nukCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCKLiSdRDn5ep/4kzMMQkSQv5Ys
-o/uj7HiJWw0IokMcgvTQWBMZ4TJzCDGmgfJ2C4y1qgfJOmFeae4mMUpNzzucZSaH
-ZlEyPk3gCj+EdcSADnxHq/2nD+19j2CGu/P/SIUSfGSLl103OIf+pYb97FxN3cN3
-2hqEJsFDQi4YAIsW+rBT+fcW35MZ+akJagLFVfq0cPbyQFIgtBu6ytnZlZBJCZYC
-u7y0yoCxikZdOQEGp6w0Nk0BvGh9SGYxkuV7oMgfNW3vzS1ay7wbjBlrhYBfLQFw
-LVu31CS6bi33f7QhjZf0yH+lEPV2B+Lqq5d4eqvwe1/pBuaS2aqfqjjCLdEd
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN8pk1iCHaK4Byqyj5MO
+3xVJcgaTGUotxb1Wklra9NOaARzuR1cOntjXDcTOS6Lw/AfskemVCPTpXfJJ8wuY
+8NjH1Gcv+/KUOxTIBto5cIr5S3CodGs/W9GkHOq98Z7B4ueYiE/pS7bI1p4B87fJ
+7s3i15ZoFNdExhETn2wGTleYU8hA3p1EH2r0AbBWR147tTwpm5bzmlp40RFRJQ5D
+gkrT31RaRgDesKIuZVREQJxk0+g/6KzjDPs2CsV5N6mi7wYUQ6yeIN4w0up5fe/y
+DJNwjbsU/0xWQeQq3pIKzmUs0/spD0/5FtdiVE5MqAU0XeYg44m8ex/fIVdmqSDO
+5rMCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQAMIFsOpe5YFYwa7F2qr1CoBYhR
+XNOEK5Yc6pY4ND+/1hbsSkT285Ar7yIA4+fFwYa4F4DkpzfZ0DLwHPqQE85pQf2M
+YyjwMIU97xwNKLHrrObpgVJ+hs8cDj0zYJVGnIWiK1556I5lotupuzzig7Fyo0XY
+OSbg+NxaXMHil4eLWIs8CapWAU4gHcZnDpkYL86aWfeFAYixB/FkcAzZJR+fOSif
+KYTc0kKR34nDpJVN1pck03tCvRY48SRliHnNpAP/Enf57BLSJvA15f64Iz3hthxL
+47xJsj2zs+CkHvfYnaLhDpTlOxr73uK4dhWcyynufvjElO2G+MOMcFRduWU6
-----END CERTIFICATE REQUEST-----
diff --git a/tests/certs/Server-localhost0h-sv.der b/tests/certs/Server-localhost0h-sv.der
index d4d7b07..cdadd76 100644
--- a/tests/certs/Server-localhost0h-sv.der
+++ b/tests/certs/Server-localhost0h-sv.der
Binary files differ
diff --git a/tests/certs/Server-localhost0h-sv.key b/tests/certs/Server-localhost0h-sv.key
index fc39dea..0e0533e 100644
--- a/tests/certs/Server-localhost0h-sv.key
+++ b/tests/certs/Server-localhost0h-sv.key
@@ -1,27 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAuP5quIoOuzSQz0jn3Q0mMmcKTqqcTP3rb+G4mF2xQ9QJT2LY
-TXzWCzaTV/thArmNNSCb3n2j1Q2ORJjUkTGiHpqEzABSS3jDV1dr1yUpvxRQIG8a
-7jz8u78eH82ot/2Nrsx4B8ADhv3t24bBK4FVRUpQB/2NhaTpKdy74tXd3Tr4YiE8
-MNBaiHFnU6946n4IQDJlFny/ybr1Bh4C8vi3OciFwHgU0tn9K4sMP9qDSC8mJDQb
-+nAHRrQB6g3M14Gp8WbFTj1+tLO0ZKPqD/8BVMGLH+ll1fy8cUNpLlD0AxKlkZUg
-NtyR66qrjzBsZiIg3h24WdEWqHFVSmb+dpye6QIDAQABAoIBAQCTb/GOcjmbaiGf
-kvN4cepncUf9umwn0Je766I7jTCiZnOlGZpa54uQFEcKcAa5LTklhn+zq17PhqZE
-dam0rmIPEgeUrwznqa/GBJ6mMbA74eyabPKBvYmP+JoBrt8xBJvPHJbtVlN5Wxgf
-Rh7elY1oU/nE5IfOY8iQ3KPB/cF9dw85EafIrQ/4neucBvV/I16XjhmNrOTOBdWS
-y1m0V3oj1238GlaWICdm1fhu8xfWiGbbUt7Lloj9Z2pm77eZwdSDF4Sa68BIyi3Z
-5xT6guXsoz2H59obzd0jardb60QjyQ93Bv8QhYHu4vHP3htlWeydwFYYE8LqoDlo
-HsLVbvwhAoGBAOElERBVjkWeI6VySeY2LfuOGLdkzp2QrXedr5yJzxaGeR1Zjcad
-TmzIMTgxk/lwmRxOaEKklRDhdgwsQVPEYjN/aknCjomsfPcYjsYVIIzOAJxL/1XB
-zDKuMIAwIiSKfp1LapKnawBKmG0SSL8T8zQMBZPUDR01REgpF9M+YpcbAoGBANJY
-s6HdvmmUkABA5iJWtwZ8ekkkVkCsq0qMxisglGcz6QW7r1w0ag1Gn4HtNFnhdzt+
-3CZZyhRzMt1SZJ0Z5i+RufH8ct9JpIiAPxmy/4vHrd3LnVvabxKtCerhtCmKUJNj
-vOSRp/rYr5bQQ+HYVS8gNwVjVJCmfG5eUZXZcq5LAoGAaoObwAuJ5Hu9R397YLNP
-K8x8+v5xFXAl8Qoj074KwBBcajs87LLtMF/BkWE7LW5MsWySvLyaXUMdEwM44MVu
-5Agqo7ysrItzD3+JxEKohJTNCySVJuApl+x6u5qJ/Jmc7xOH1tvnrlqcJDXbPrLU
-g1IQrXBLx/60UCNIx0KjZ/MCgYBLAGXMqYxjiR1vebSVOeY44dmYiuRWWzsYcemX
-Jx7DTbcg3DNC5U2LPktRwIqSIdqp1CobYpizgf/4+o/1lG6HN6bdqe4rv85y/YeC
-WljUNnbARwHs5o4EUr7eiWv8A92HMGEB/w2uW+UAGXKa7NAy5YG44hodGb/0ep0M
-mWRS0QKBgQDG5Zdh+MLMsGgujtCnp8z96IK0I1M5G7V0BWe9Rg2QpjcVCGqmucxB
-GCQwUdn8LL0kXKueC6v7GsQvOWsx+GLbLuQsAF+r4tHh+IQAQyPleLfs5bis/Kqf
-GiSMt5ahOx9q/n5HD9GK/sGjvmqJucVQ45mnZqdnhTGnS/htzQGWmw==
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDfKZNYgh2iuAcq
+so+TDt8VSXIGkxlKLcW9VpJa2vTTmgEc7kdXDp7Y1w3Ezkui8PwH7JHplQj06V3y
+SfMLmPDYx9RnL/vylDsUyAbaOXCK+UtwqHRrP1vRpBzqvfGeweLnmIhP6Uu2yNae
+AfO3ye7N4teWaBTXRMYRE59sBk5XmFPIQN6dRB9q9AGwVkdeO7U8KZuW85paeNER
+USUOQ4JK099UWkYA3rCiLmVURECcZNPoP+is4wz7NgrFeTepou8GFEOsniDeMNLq
+eX3v8gyTcI27FP9MVkHkKt6SCs5lLNP7KQ9P+RbXYlROTKgFNF3mIOOJvHsf3yFX
+ZqkgzuazAgMBAAECggEAa31sIpKx0aHQmeleLJhaLbetu6r44HkBqPxdDHQwvweM
+B7JiHHXHX2zejfBMEFUBIJP7iEYoBUeu37hs4CYvxEskbPt44NQzTQQ4AL7wDZCc
+nMwXH11qTaU95HfPPQfo0mLvLYaS2J0Oexc3nEwgwXzFGQZTG4ld2fXYsUCsVZX8
+PoHbkKWEHveQEFDmGezguc2UG3DrXaZv5gbMhVik048zX3P5cn0ic9TK9yEFZDXS
+8Qiq/SHTHEnkZV5J8s12pcDyQdi1cN96MVZ1/feeg1Pc06q7PN7xvkmZHCQ1tOdl
+b7STXNPrJ0P7OwbeB0Q3xNwqI25wicN1oaBvdR/PAQKBgQD4gN6+sR74FNC4q99T
+fuFqwJ36W8GG0jc9joJTbITXGSdArQHm838Mippp0P3MrUTLqXI0nhjH8ePjF83R
+KRWGoUvSc2Xe7LjzzEmg9CmtB+QD97Qir0468izqnlP1Ef16kbbIMLsoVgIht6YY
+klUYs7x3AtDBvHV7EKlP63kUgQKBgQDl5QDW+KZRvQU/G7tWsOZ6iQ3Ed8Zt4uRk
+EshPeCoz0S0ks8pzpa+YaAAUKsHvgiL7oLMFquuVHn7TctYBoe2/bwdj0/IW/1pP
+oDJqRJIbamjYj6qKG7Ihx0yx+z7f7vbKCgC5ifzy0Xl60E9fRIf3/dVopU+3qtwG
+qOphkrNRMwKBgQCrEixFIjGrnsjBGLC5DhOoJcmbXCcx5O1aVwyo2X/pg8td3rv8
+fYvs2k3KorDVgkJl4dRZHKz6mC7FWtG5N4s2DzvfOMncWSJJ00ysnOlD0LbLdG5x
+ojU8pxL8wNoTT7sr8bvevI1bCzqUc5TIPZSPWMxZMXr8o/xMKAAmoHfOAQKBgDBH
+VlTO5Qa3XlmxdjcvcUd8bsK6sJY1FueZNi3SO3KkVAmoJDUDL4wfEx0pGY810ijr
+x4zCJzUqsVGwhRbUrbwNEg053lZMC+g66Tt96P0O7LPF//d+93q2gvnBnKOkaHln
+fl14iAFqUkujYXfNSYyf5uhSBxq4K/rOEGKrTzMXAoGBAL3Hz3s5Gvy44SMV0UHl
+18gEqR0y9mXfgON9Rk0yE+fFYFRnFf4iHIxhodXPIGeu1CpqtXjEcG8JXVXniaao
+qNGbVs2QoBUVW81sHG9h/ulHCAwjFvZhFYgDiRQPcVd3lNJM4gigjRyw/nRnQH+2
+MVCJe5htDEMM58h8LepU4T8M
+-----END PRIVATE KEY-----
diff --git a/tests/certs/Server-localhost0h-sv.pem b/tests/certs/Server-localhost0h-sv.pem
index 869a70b..72f326d 100644
--- a/tests/certs/Server-localhost0h-sv.pem
+++ b/tests/certs/Server-localhost0h-sv.pem
Binary files differ
diff --git a/tests/certs/Server-localhost0h-sv.prm b/tests/certs/Server-localhost0h-sv.prm
index 619d825..439aefb 100644
--- a/tests/certs/Server-localhost0h-sv.prm
+++ b/tests/certs/Server-localhost0h-sv.prm
@@ -7,6 +7,19 @@
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
basicConstraints = CA:false
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
+
[ req ]
default_bits = 1024
distinguished_name = req_DN
diff --git a/tests/certs/Server-localhost0h-sv.pub.der b/tests/certs/Server-localhost0h-sv.pub.der
index 743471b..5c0e00d 100644
--- a/tests/certs/Server-localhost0h-sv.pub.der
+++ b/tests/certs/Server-localhost0h-sv.pub.der
Binary files differ
diff --git a/tests/certs/Server-localhost0h-sv.pub.pem b/tests/certs/Server-localhost0h-sv.pub.pem
index 8462ae8..b8a1ee9 100644
--- a/tests/certs/Server-localhost0h-sv.pub.pem
+++ b/tests/certs/Server-localhost0h-sv.pub.pem
@@ -1,9 +1,9 @@
-----BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuP5quIoOuzSQz0jn3Q0m
-MmcKTqqcTP3rb+G4mF2xQ9QJT2LYTXzWCzaTV/thArmNNSCb3n2j1Q2ORJjUkTGi
-HpqEzABSS3jDV1dr1yUpvxRQIG8a7jz8u78eH82ot/2Nrsx4B8ADhv3t24bBK4FV
-RUpQB/2NhaTpKdy74tXd3Tr4YiE8MNBaiHFnU6946n4IQDJlFny/ybr1Bh4C8vi3
-OciFwHgU0tn9K4sMP9qDSC8mJDQb+nAHRrQB6g3M14Gp8WbFTj1+tLO0ZKPqD/8B
-VMGLH+ll1fy8cUNpLlD0AxKlkZUgNtyR66qrjzBsZiIg3h24WdEWqHFVSmb+dpye
-6QIDAQAB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3ymTWIIdorgHKrKPkw7f
+FUlyBpMZSi3FvVaSWtr005oBHO5HVw6e2NcNxM5LovD8B+yR6ZUI9Old8knzC5jw
+2MfUZy/78pQ7FMgG2jlwivlLcKh0az9b0aQc6r3xnsHi55iIT+lLtsjWngHzt8nu
+zeLXlmgU10TGEROfbAZOV5hTyEDenUQfavQBsFZHXju1PCmblvOaWnjREVElDkOC
+StPfVFpGAN6woi5lVERAnGTT6D/orOMM+zYKxXk3qaLvBhRDrJ4g3jDS6nl97/IM
+k3CNuxT/TFZB5CrekgrOZSzT+ykPT/kW12JUTkyoBTRd5iDjibx7H98hV2apIM7m
+swIDAQAB
-----END PUBLIC KEY-----
diff --git a/tests/certs/Server-localhost0h-sv.pubkey-pinned b/tests/certs/Server-localhost0h-sv.pubkey-pinned
new file mode 100644
index 0000000..0347fc0
--- /dev/null
+++ b/tests/certs/Server-localhost0h-sv.pubkey-pinned
@@ -0,0 +1 @@
+uWdzTJv+PXoad5XzSPC85Nm6FcqVkGl+8tTRW5KCLbA=
diff --git a/tests/certs/scripts/Makefile.am b/tests/certs/scripts/Makefile.am
index c7e8a16..82b5f27 100644
--- a/tests/certs/scripts/Makefile.am
+++ b/tests/certs/scripts/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/tests/certs/scripts/genroot.sh b/tests/certs/scripts/genroot.sh
index 963f343..17fd308 100755
--- a/tests/certs/scripts/genroot.sh
+++ b/tests/certs/scripts/genroot.sh
@@ -1,9 +1,27 @@
#!/bin/bash
-
-# (c) CopyRight 2000 - 2020, EdelWeb for EdelKey and OpenEvidence
-# Author: Peter Sylvester
-
-# "libre" for integration with curl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) EdelWeb for EdelKey and OpenEvidence
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
OPENSSL=openssl
if [ -f /usr/local/ssl/bin/openssl ] ; then
@@ -40,10 +58,13 @@
GETSERIAL="\$t = time ;\$d = \$t . substr(\$t+$$ ,-4,4)-1;print \$d"
SERIAL=`/usr/bin/env perl -e "$GETSERIAL"`
+# exit on first fail
+set -e
+
echo SERIAL=$SERIAL PREFIX=$PREFIX DURATION=$DURATION KEYSIZE=$KEYSIZE
-echo "openssl genrsa -out $PREFIX-ca.key $KEYSIZE -passout XXX"
-openssl genrsa -out $PREFIX-ca.key $KEYSIZE -passout pass:secret
+echo "openssl genrsa -out $PREFIX-ca.key -passout XXX $KEYSIZE"
+openssl genrsa -out $PREFIX-ca.key -passout pass:secret $KEYSIZE
echo "openssl req -config $PREFIX-ca.prm -new -key $PREFIX-ca.key -out $PREFIX-ca.csr"
$OPENSSL req -config $PREFIX-ca.prm -new -key $PREFIX-ca.key -out $PREFIX-ca.csr -passin pass:secret
diff --git a/tests/certs/scripts/genserv.sh b/tests/certs/scripts/genserv.sh
index dcbc048..7e0b442 100755
--- a/tests/certs/scripts/genserv.sh
+++ b/tests/certs/scripts/genserv.sh
@@ -1,9 +1,27 @@
#!/bin/bash
-
-# (c) CopyRight 2000 - 2020, EdelWeb for EdelKey and OpenEvidence
-# Author: Peter Sylvester
-
-# "libre" for integration with curl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) EdelWeb for EdelKey and OpenEvidence
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
OPENSSL=openssl
if [ -f /usr/local/ssl/bin/openssl ] ; then
@@ -12,6 +30,9 @@
USAGE="echo Usage is genserv.sh <prefix> <caprefix>"
+# exit on first fail
+set -e
+
HOME=`pwd`
cd $HOME
@@ -115,4 +136,8 @@
cat $PREFIX-sv.prm $PREFIX-sv.key $PREFIX-sv.crt $PREFIX-sv.dhp >$PREFIX-sv.pem
chmod o-r $PREFIX-sv.prm
+$OPENSSL x509 -in $PREFIX-sv.pem -pubkey -noout | \
+$OPENSSL pkey -pubin -outform der | $OPENSSL dgst -sha256 -binary | \
+$OPENSSL enc -base64 >$PREFIX-sv.pubkey-pinned
+
echo "$PREFIX-sv.pem done"
diff --git a/tests/certs/stunnel-sv.crl b/tests/certs/stunnel-sv.crl
new file mode 100644
index 0000000..494ce73
--- /dev/null
+++ b/tests/certs/stunnel-sv.crl
@@ -0,0 +1,15 @@
+-----BEGIN X509 CRL-----
+MIICWzCCAUMCAQEwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UEBhMCTk4xMTAvBgNV
+BAoMKEVkZWwgQ3VybCBBcmN0aWMgSWxsdWRpdW0gUmVzZWFyY2ggQ2xvdWQxJjAk
+BgNVBAMMHU5vcnRoZXJuIE5vd2hlcmUgVHJ1c3QgQW5jaG9yFw0yMjEyMjMxMjIx
+MzlaFw0yMzAxMjIxMjIxMzlaMIGWMBcCBg80dVEqPBcNMjIxMjIzMTIyMTM2WjAX
+AgYPNHVRUWEXDTIyMTIyMzEyMjEzN1owFwIGDzR1UVF1Fw0yMjEyMjMxMjIxMzda
+MBcCBg80dVFRiRcNMjIxMjIzMTIyMTM4WjAXAgYPNHVReK4XDTIyMTIyMzEyMjEz
+OFowFwIGDzR1UZ/TFw0yMjEyMjMxMjIxMzlaoA4wDDAKBgNVHRQEAwIBATANBgkq
+hkiG9w0BAQsFAAOCAQEAMcVpjkRfr71+8t8qMGDR7jNycVDsEw8H+t4wXq44EkVu
+Z3uB7IPa5KQJ4HNZ5U/5yfWrLQ14YsOHEPIWaDyXG+MYKa82t/VGSzkWdiPE/onz
+Y3PBkclURacEZ5NHWTDGJXGttO7cHPPN4FsKxAsS7EWPRSCCKBGIxY3L+4QcziZV
+G9zsrzn0B7NI11E9+VGm0HbhSxXUthayPvHeUmjpeJ+711R22ANNTV2jAMqFn2ZP
+i6PNenZXC3xt1cZd4/T6343TT5jd0QB1JUiSFGYWZw3sSga6d57Mf5WTOCAfJsWL
+X1Wds0WsQ/XbsGySCLXPWfOaxrfhk3FJHSwIDjKoAg==
+-----END X509 CRL-----
diff --git a/tests/certs/stunnel-sv.crt b/tests/certs/stunnel-sv.crt
new file mode 100644
index 0000000..8228580
--- /dev/null
+++ b/tests/certs/stunnel-sv.crt
@@ -0,0 +1,99 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 16717980999635 (0xf3475519fd3)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer:
+ countryName = NN
+ organizationName = Edel Curl Arctic Illudium Research Cloud
+ commonName = Northern Nowhere Trust Anchor
+ Validity
+ Not Before: Dec 23 12:21:39 2022 GMT
+ Not After : Mar 11 12:21:39 2031 GMT
+ Subject:
+ countryName = NN
+ organizationName = Edel Curl Arctic Illudium Research Cloud
+ commonName = localhost
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ab:0a:b0:03:d0:76:fe:5e:ce:15:de:61:d5:e3:
+ 91:6f:7c:d6:bb:ca:26:8e:78:be:26:35:d1:a6:59:
+ f1:d5:3c:55:3e:09:2c:ec:a0:d4:af:0e:3c:5a:a2:
+ b5:b0:78:51:95:62:80:80:71:c8:4e:9f:59:59:93:
+ 40:12:b2:a9:ce:b2:cd:17:8b:9f:27:f3:e3:cf:23:
+ 78:06:d2:06:23:5f:9b:20:ec:42:77:66:ad:a4:5e:
+ 82:b4:4d:94:72:ea:13:64:72:fc:cb:83:2c:d7:a1:
+ 8b:f5:2e:4c:d3:c1:88:b2:c8:98:19:5f:ef:98:fc:
+ 62:80:b3:67:cc:1f:23:fc:5f:38:cd:82:6e:2d:96:
+ d9:35:93:fe:29:a2:69:65:c0:df:45:ab:3f:ac:17:
+ 18:00:80:4a:b7:c9:ba:b8:5f:29:bb:c4:ac:16:97:
+ cc:57:34:10:c9:36:65:6c:3e:d8:89:45:c8:a5:42:
+ 84:7c:5e:cd:1a:e8:f1:3e:55:b3:21:0f:d0:36:13:
+ f2:c4:2f:b9:73:41:fa:87:aa:dc:44:d6:64:96:e4:
+ 5a:50:f9:4a:9f:e0:a2:e7:69:f4:ad:5a:cf:3a:20:
+ e5:a7:09:e2:cf:e8:19:a1:00:ae:a8:bb:22:02:34:
+ 5c:b3:cf:b5:24:4c:76:bf:ad:e9:f1:b8:d3:86:ba:
+ 7d:93
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:localhost
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment, Key Agreement
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication
+ X509v3 Subject Key Identifier:
+ 9C:97:B0:3D:B3:50:B1:F6:D4:71:E2:EB:CB:80:EA:93:7C:98:CC:72
+ X509v3 Authority Key Identifier:
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
+ Signature Algorithm: sha256WithRSAEncryption
+ Signature Value:
+ 0b:8a:ed:6a:87:fa:71:15:88:25:58:85:1b:4a:09:bf:43:00:
+ 35:93:78:0d:72:14:30:51:e2:93:83:a1:da:1b:2f:a9:31:ae:
+ b7:c7:4c:72:c2:5e:32:24:f1:96:93:70:d5:3f:b5:85:80:13:
+ 75:32:cf:0e:f8:5d:c4:a2:29:84:43:2c:75:81:26:12:6a:a0:
+ cb:7b:57:c1:92:78:85:08:fa:64:50:c2:7b:83:02:4d:79:13:
+ bc:61:64:4d:b8:6b:d5:f1:84:6b:12:5c:69:90:ad:40:47:c0:
+ ed:dd:ea:8a:66:7e:87:85:19:aa:89:d3:3c:08:72:08:a1:4d:
+ 63:60:5b:9b:17:9e:00:12:a1:00:52:ca:78:01:88:18:c7:ed:
+ 5b:c7:e4:d9:eb:bd:3f:af:92:53:3f:fe:58:57:0d:fc:f4:7b:
+ 7b:a2:4f:e9:b9:5c:b5:a4:52:50:b4:56:5a:44:8e:d9:d0:ed:
+ de:8f:7e:ac:1c:58:76:5b:a8:79:c9:95:ab:85:1d:db:4c:13:
+ 82:4a:a5:41:1b:29:f5:d3:96:df:80:d1:1e:00:7d:ba:35:94:
+ 57:81:e1:08:2a:81:6b:1c:30:50:37:01:1a:0e:26:4f:6b:ed:
+ c9:50:17:37:2b:33:3f:68:fe:c6:f0:21:8c:e7:b2:79:55:f2:
+ 42:bd:2f:b0
+-----BEGIN CERTIFICATE-----
+MIIERDCCAyygAwIBAgIGDzR1UZ/TMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
+IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
+Fw0yMjEyMjMxMjIxMzlaFw0zMTAzMTExMjIxMzlaMFQxCzAJBgNVBAYTAk5OMTEw
+LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
+MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQCrCrAD0Hb+Xs4V3mHV45FvfNa7yiaOeL4mNdGmWfHVPFU+CSzsoNSvDjxa
+orWweFGVYoCAcchOn1lZk0ASsqnOss0Xi58n8+PPI3gG0gYjX5sg7EJ3Zq2kXoK0
+TZRy6hNkcvzLgyzXoYv1LkzTwYiyyJgZX++Y/GKAs2fMHyP8XzjNgm4tltk1k/4p
+omllwN9Fqz+sFxgAgEq3ybq4Xym7xKwWl8xXNBDJNmVsPtiJRcilQoR8Xs0a6PE+
+VbMhD9A2E/LEL7lzQfqHqtxE1mSW5FpQ+Uqf4KLnafStWs86IOWnCeLP6BmhAK6o
+uyICNFyzz7UkTHa/renxuNOGun2TAgMBAAGjggEGMIIBAjAUBgNVHREEDTALggls
+b2NhbGhvc3QwCwYDVR0PBAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1Ud
+DgQWBBScl7A9s1Cx9tRx4uvLgOqTfJjMcjAfBgNVHSMEGDAWgBSHy7EzLsFnfnHj
+5StMTaSzbtJbqTAJBgNVHRMEAjAAMEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcw
+AoYnaHR0cDovL3Rlc3QuY3VybC5zZS9jYS9FZGVsQ3VybFJvb3QuY2VyMDgGA1Ud
+HwQxMC8wLaAroCmGJ2h0dHA6Ly90ZXN0LmN1cmwuc2UvY2EvRWRlbEN1cmxSb290
+LmNybDANBgkqhkiG9w0BAQsFAAOCAQEAC4rtaof6cRWIJViFG0oJv0MANZN4DXIU
+MFHik4Oh2hsvqTGut8dMcsJeMiTxlpNw1T+1hYATdTLPDvhdxKIphEMsdYEmEmqg
+y3tXwZJ4hQj6ZFDCe4MCTXkTvGFkTbhr1fGEaxJcaZCtQEfA7d3qimZ+h4UZqonT
+PAhyCKFNY2BbmxeeABKhAFLKeAGIGMftW8fk2eu9P6+SUz/+WFcN/PR7e6JP6blc
+taRSULRWWkSO2dDt3o9+rBxYdluoecmVq4Ud20wTgkqlQRsp9dOW34DRHgB9ujWU
+V4HhCCqBaxwwUDcBGg4mT2vtyVAXNyszP2j+xvAhjOeyeVXyQr0vsA==
+-----END CERTIFICATE-----
diff --git a/tests/certs/stunnel-sv.csr b/tests/certs/stunnel-sv.csr
new file mode 100644
index 0000000..739cd68
--- /dev/null
+++ b/tests/certs/stunnel-sv.csr
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICmTCCAYECAQAwVDELMAkGA1UEBhMCTk4xMTAvBgNVBAoMKEVkZWwgQ3VybCBB
+cmN0aWMgSWxsdWRpdW0gUmVzZWFyY2ggQ2xvdWQxEjAQBgNVBAMMCWxvY2FsaG9z
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKsKsAPQdv5ezhXeYdXj
+kW981rvKJo54viY10aZZ8dU8VT4JLOyg1K8OPFqitbB4UZVigIBxyE6fWVmTQBKy
+qc6yzReLnyfz488jeAbSBiNfmyDsQndmraRegrRNlHLqE2Ry/MuDLNehi/UuTNPB
+iLLImBlf75j8YoCzZ8wfI/xfOM2Cbi2W2TWT/imiaWXA30WrP6wXGACASrfJurhf
+KbvErBaXzFc0EMk2ZWw+2IlFyKVChHxezRro8T5VsyEP0DYT8sQvuXNB+oeq3ETW
+ZJbkWlD5Sp/goudp9K1azzog5acJ4s/oGaEArqi7IgI0XLPPtSRMdr+t6fG404a6
+fZMCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQAauiYRPParSazzDjwG98G8YzZk
+1V/Q3rOzPN5a4veBMVO0kTxrTLImX/+BU6Bj6YgbpUGzIUqbkEunCQ5vtbFTrooD
+uT2tZtENXrj6i1fR3BArnLiP1Pg+PO1ONvTuY+384v2CIeE7AP6V0wZw5W9OJSkP
+eM8RU5OJn5zJkxhmUdREg5d3VuIE67ABcbCsxqMAhJuPw6mFgN6ffZl06nZ2cR5k
+TeOmze7EL8UCNByTtwqBdgryPQu3UEsBq0GxQJcBzcmB3vfClLhnTLic4sRHGdTO
+Ql+6CFqNnP5+bEMWqExPmWsdogFtwJsiQvr2nk/i2ogKAoRs+T0siTcF1+RM
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/certs/stunnel-sv.der b/tests/certs/stunnel-sv.der
new file mode 100644
index 0000000..9c015f8
--- /dev/null
+++ b/tests/certs/stunnel-sv.der
Binary files differ
diff --git a/zuul.d/playbooks/.zuul.ignore b/tests/certs/stunnel-sv.dhp
similarity index 100%
rename from zuul.d/playbooks/.zuul.ignore
rename to tests/certs/stunnel-sv.dhp
diff --git a/tests/certs/stunnel-sv.key b/tests/certs/stunnel-sv.key
new file mode 100644
index 0000000..84c86c2
--- /dev/null
+++ b/tests/certs/stunnel-sv.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCrCrAD0Hb+Xs4V
+3mHV45FvfNa7yiaOeL4mNdGmWfHVPFU+CSzsoNSvDjxaorWweFGVYoCAcchOn1lZ
+k0ASsqnOss0Xi58n8+PPI3gG0gYjX5sg7EJ3Zq2kXoK0TZRy6hNkcvzLgyzXoYv1
+LkzTwYiyyJgZX++Y/GKAs2fMHyP8XzjNgm4tltk1k/4pomllwN9Fqz+sFxgAgEq3
+ybq4Xym7xKwWl8xXNBDJNmVsPtiJRcilQoR8Xs0a6PE+VbMhD9A2E/LEL7lzQfqH
+qtxE1mSW5FpQ+Uqf4KLnafStWs86IOWnCeLP6BmhAK6ouyICNFyzz7UkTHa/renx
+uNOGun2TAgMBAAECggEAH0BsKb5Ax7h90jwYRzL141d9isFkaxq/r46c2FbN24bT
+EmstxKycP8ILoAnjxbMuQOvHC/D+RvNRqY7Aocn4Qdakp50wvuWOpc3Ww/RC/9qb
+pxfUCyn9Jy/HlPcp3RdM5MknzG2S13Fid7F2gyh0+CmztMs1JZBT1S0ylXbJJfbY
+1pdlHcf9oEbYo36vGd9rtJHAFzsFfwua0idl76XYuOnR3bpOkHl1B5cJ8jpOliPv
+VTmzn0cIgAmk7IByHHqGQ0u30PFiElI9kEbkKWoxAM1hq1pFU58jQhvp0ZkjVENL
+bSFB2B4DbyosxPlbUgvJCN4B7nclqzYqBdrrk6/ZLQKBgQC1lDrPSGIGXLwvkZYS
+xc0wtaCC7u6m7zV8rzh5HGcEoVvtmya/VyoZR8KGIpSor8COIkZqFtan6C77C3MH
+wClbu2Kn3FkGb76D5U2Xwl38zepzjn8Z5qXc3bZfccrsDY1gXPicgsmcKUY9xV5/
+T0RjESDKB+xxkJpCjia6klm2NQKBgQDxJNuqB6frDYKaj7mW/rvyHqkeT94J6eDY
+BcMZVKeHRNWcBMOvJDChVmpsCjJPOWHhHOlAE755NxWn8wpgyiUcac3BiysMgvTT
+pyH8UVWaP/DWYOfpuhtcLPkIjKnPijOvshpyWBxfXNIejiovoT6E3IXKOxr5g5yq
+U/9a5+I9pwKBgDyJG4YpkoyedBrDxa2ihkL7+nRMZgH/c+yKmiA+aNXxWa2AcU2P
+KLje5KpFcxw948s/AAy0aoH19Vu6uHHYDbHIah6eZouvy2s7kj/LC/yRRd2anyMq
+cxeMTxXI4ScLaZu7wyKis8Y9OG61k0iMS7dfaXgRZjGCTPttWtoOmpwVAoGAd2k+
+EXuLDl15UBpd18S6wxGlw2nfVN9oxPBNhUyjTNusP38oe6EbJ7mIJ4oBEbQjoPrV
+EjL0vkelxK4YdIeFSwWlqvLEVYS/wdNgg/auwhxpoW8JSHctNz7Z7v7g0/Hm2FkE
+uZyiKCLptdHGWCGruNUOt27/U5F10e6YY6ayJL8CgYEAoE/ddHIlrKFzcZ0cu47R
+ky4D4x32ceC2au4eGPLMDItPjceXe8I6zgB5P8/U5U3PRw5oWabpAf5lAcRwa12c
+23xgy9O5QNlyps/rAdnVjwxqGwEd5E2LrZ2+JDflPRGunx2VO5v9CxXvsxu9F3Rj
+tREtebHe2H7u5jNsIQArnRI=
+-----END PRIVATE KEY-----
diff --git a/tests/certs/stunnel-sv.pem b/tests/certs/stunnel-sv.pem
new file mode 100644
index 0000000..b7dd1e8
--- /dev/null
+++ b/tests/certs/stunnel-sv.pem
@@ -0,0 +1,165 @@
+extensions = x509v3
+[ x509v3 ]
+subjectAltName = DNS:localhost
+keyUsage = keyEncipherment,digitalSignature,keyAgreement
+extendedKeyUsage = serverAuth
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid
+basicConstraints = CA:false
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
+
+[ req ]
+default_bits = 12048
+distinguished_name = req_DN
+default_md = sha256
+string_mask = utf8only
+[ req_DN ]
+countryName = "Country Name is Northern Nowhere"
+countryName_value = NN
+organizationName = "Organization Name"
+organizationName_value = Edel Curl Arctic Illudium Research Cloud
+commonName = "Common Name"
+commonName_value = localhost
+
+[something]
+# The key
+# the certificate
+# some dhparam
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCrCrAD0Hb+Xs4V
+3mHV45FvfNa7yiaOeL4mNdGmWfHVPFU+CSzsoNSvDjxaorWweFGVYoCAcchOn1lZ
+k0ASsqnOss0Xi58n8+PPI3gG0gYjX5sg7EJ3Zq2kXoK0TZRy6hNkcvzLgyzXoYv1
+LkzTwYiyyJgZX++Y/GKAs2fMHyP8XzjNgm4tltk1k/4pomllwN9Fqz+sFxgAgEq3
+ybq4Xym7xKwWl8xXNBDJNmVsPtiJRcilQoR8Xs0a6PE+VbMhD9A2E/LEL7lzQfqH
+qtxE1mSW5FpQ+Uqf4KLnafStWs86IOWnCeLP6BmhAK6ouyICNFyzz7UkTHa/renx
+uNOGun2TAgMBAAECggEAH0BsKb5Ax7h90jwYRzL141d9isFkaxq/r46c2FbN24bT
+EmstxKycP8ILoAnjxbMuQOvHC/D+RvNRqY7Aocn4Qdakp50wvuWOpc3Ww/RC/9qb
+pxfUCyn9Jy/HlPcp3RdM5MknzG2S13Fid7F2gyh0+CmztMs1JZBT1S0ylXbJJfbY
+1pdlHcf9oEbYo36vGd9rtJHAFzsFfwua0idl76XYuOnR3bpOkHl1B5cJ8jpOliPv
+VTmzn0cIgAmk7IByHHqGQ0u30PFiElI9kEbkKWoxAM1hq1pFU58jQhvp0ZkjVENL
+bSFB2B4DbyosxPlbUgvJCN4B7nclqzYqBdrrk6/ZLQKBgQC1lDrPSGIGXLwvkZYS
+xc0wtaCC7u6m7zV8rzh5HGcEoVvtmya/VyoZR8KGIpSor8COIkZqFtan6C77C3MH
+wClbu2Kn3FkGb76D5U2Xwl38zepzjn8Z5qXc3bZfccrsDY1gXPicgsmcKUY9xV5/
+T0RjESDKB+xxkJpCjia6klm2NQKBgQDxJNuqB6frDYKaj7mW/rvyHqkeT94J6eDY
+BcMZVKeHRNWcBMOvJDChVmpsCjJPOWHhHOlAE755NxWn8wpgyiUcac3BiysMgvTT
+pyH8UVWaP/DWYOfpuhtcLPkIjKnPijOvshpyWBxfXNIejiovoT6E3IXKOxr5g5yq
+U/9a5+I9pwKBgDyJG4YpkoyedBrDxa2ihkL7+nRMZgH/c+yKmiA+aNXxWa2AcU2P
+KLje5KpFcxw948s/AAy0aoH19Vu6uHHYDbHIah6eZouvy2s7kj/LC/yRRd2anyMq
+cxeMTxXI4ScLaZu7wyKis8Y9OG61k0iMS7dfaXgRZjGCTPttWtoOmpwVAoGAd2k+
+EXuLDl15UBpd18S6wxGlw2nfVN9oxPBNhUyjTNusP38oe6EbJ7mIJ4oBEbQjoPrV
+EjL0vkelxK4YdIeFSwWlqvLEVYS/wdNgg/auwhxpoW8JSHctNz7Z7v7g0/Hm2FkE
+uZyiKCLptdHGWCGruNUOt27/U5F10e6YY6ayJL8CgYEAoE/ddHIlrKFzcZ0cu47R
+ky4D4x32ceC2au4eGPLMDItPjceXe8I6zgB5P8/U5U3PRw5oWabpAf5lAcRwa12c
+23xgy9O5QNlyps/rAdnVjwxqGwEd5E2LrZ2+JDflPRGunx2VO5v9CxXvsxu9F3Rj
+tREtebHe2H7u5jNsIQArnRI=
+-----END PRIVATE KEY-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 16717980999635 (0xf3475519fd3)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer:
+ countryName = NN
+ organizationName = Edel Curl Arctic Illudium Research Cloud
+ commonName = Northern Nowhere Trust Anchor
+ Validity
+ Not Before: Dec 23 12:21:39 2022 GMT
+ Not After : Mar 11 12:21:39 2031 GMT
+ Subject:
+ countryName = NN
+ organizationName = Edel Curl Arctic Illudium Research Cloud
+ commonName = localhost
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ab:0a:b0:03:d0:76:fe:5e:ce:15:de:61:d5:e3:
+ 91:6f:7c:d6:bb:ca:26:8e:78:be:26:35:d1:a6:59:
+ f1:d5:3c:55:3e:09:2c:ec:a0:d4:af:0e:3c:5a:a2:
+ b5:b0:78:51:95:62:80:80:71:c8:4e:9f:59:59:93:
+ 40:12:b2:a9:ce:b2:cd:17:8b:9f:27:f3:e3:cf:23:
+ 78:06:d2:06:23:5f:9b:20:ec:42:77:66:ad:a4:5e:
+ 82:b4:4d:94:72:ea:13:64:72:fc:cb:83:2c:d7:a1:
+ 8b:f5:2e:4c:d3:c1:88:b2:c8:98:19:5f:ef:98:fc:
+ 62:80:b3:67:cc:1f:23:fc:5f:38:cd:82:6e:2d:96:
+ d9:35:93:fe:29:a2:69:65:c0:df:45:ab:3f:ac:17:
+ 18:00:80:4a:b7:c9:ba:b8:5f:29:bb:c4:ac:16:97:
+ cc:57:34:10:c9:36:65:6c:3e:d8:89:45:c8:a5:42:
+ 84:7c:5e:cd:1a:e8:f1:3e:55:b3:21:0f:d0:36:13:
+ f2:c4:2f:b9:73:41:fa:87:aa:dc:44:d6:64:96:e4:
+ 5a:50:f9:4a:9f:e0:a2:e7:69:f4:ad:5a:cf:3a:20:
+ e5:a7:09:e2:cf:e8:19:a1:00:ae:a8:bb:22:02:34:
+ 5c:b3:cf:b5:24:4c:76:bf:ad:e9:f1:b8:d3:86:ba:
+ 7d:93
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ DNS:localhost
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment, Key Agreement
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication
+ X509v3 Subject Key Identifier:
+ 9C:97:B0:3D:B3:50:B1:F6:D4:71:E2:EB:CB:80:EA:93:7C:98:CC:72
+ X509v3 Authority Key Identifier:
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
+ Signature Algorithm: sha256WithRSAEncryption
+ Signature Value:
+ 0b:8a:ed:6a:87:fa:71:15:88:25:58:85:1b:4a:09:bf:43:00:
+ 35:93:78:0d:72:14:30:51:e2:93:83:a1:da:1b:2f:a9:31:ae:
+ b7:c7:4c:72:c2:5e:32:24:f1:96:93:70:d5:3f:b5:85:80:13:
+ 75:32:cf:0e:f8:5d:c4:a2:29:84:43:2c:75:81:26:12:6a:a0:
+ cb:7b:57:c1:92:78:85:08:fa:64:50:c2:7b:83:02:4d:79:13:
+ bc:61:64:4d:b8:6b:d5:f1:84:6b:12:5c:69:90:ad:40:47:c0:
+ ed:dd:ea:8a:66:7e:87:85:19:aa:89:d3:3c:08:72:08:a1:4d:
+ 63:60:5b:9b:17:9e:00:12:a1:00:52:ca:78:01:88:18:c7:ed:
+ 5b:c7:e4:d9:eb:bd:3f:af:92:53:3f:fe:58:57:0d:fc:f4:7b:
+ 7b:a2:4f:e9:b9:5c:b5:a4:52:50:b4:56:5a:44:8e:d9:d0:ed:
+ de:8f:7e:ac:1c:58:76:5b:a8:79:c9:95:ab:85:1d:db:4c:13:
+ 82:4a:a5:41:1b:29:f5:d3:96:df:80:d1:1e:00:7d:ba:35:94:
+ 57:81:e1:08:2a:81:6b:1c:30:50:37:01:1a:0e:26:4f:6b:ed:
+ c9:50:17:37:2b:33:3f:68:fe:c6:f0:21:8c:e7:b2:79:55:f2:
+ 42:bd:2f:b0
+-----BEGIN CERTIFICATE-----
+MIIERDCCAyygAwIBAgIGDzR1UZ/TMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
+IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
+Fw0yMjEyMjMxMjIxMzlaFw0zMTAzMTExMjIxMzlaMFQxCzAJBgNVBAYTAk5OMTEw
+LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
+MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQCrCrAD0Hb+Xs4V3mHV45FvfNa7yiaOeL4mNdGmWfHVPFU+CSzsoNSvDjxa
+orWweFGVYoCAcchOn1lZk0ASsqnOss0Xi58n8+PPI3gG0gYjX5sg7EJ3Zq2kXoK0
+TZRy6hNkcvzLgyzXoYv1LkzTwYiyyJgZX++Y/GKAs2fMHyP8XzjNgm4tltk1k/4p
+omllwN9Fqz+sFxgAgEq3ybq4Xym7xKwWl8xXNBDJNmVsPtiJRcilQoR8Xs0a6PE+
+VbMhD9A2E/LEL7lzQfqHqtxE1mSW5FpQ+Uqf4KLnafStWs86IOWnCeLP6BmhAK6o
+uyICNFyzz7UkTHa/renxuNOGun2TAgMBAAGjggEGMIIBAjAUBgNVHREEDTALggls
+b2NhbGhvc3QwCwYDVR0PBAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1Ud
+DgQWBBScl7A9s1Cx9tRx4uvLgOqTfJjMcjAfBgNVHSMEGDAWgBSHy7EzLsFnfnHj
+5StMTaSzbtJbqTAJBgNVHRMEAjAAMEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcw
+AoYnaHR0cDovL3Rlc3QuY3VybC5zZS9jYS9FZGVsQ3VybFJvb3QuY2VyMDgGA1Ud
+HwQxMC8wLaAroCmGJ2h0dHA6Ly90ZXN0LmN1cmwuc2UvY2EvRWRlbEN1cmxSb290
+LmNybDANBgkqhkiG9w0BAQsFAAOCAQEAC4rtaof6cRWIJViFG0oJv0MANZN4DXIU
+MFHik4Oh2hsvqTGut8dMcsJeMiTxlpNw1T+1hYATdTLPDvhdxKIphEMsdYEmEmqg
+y3tXwZJ4hQj6ZFDCe4MCTXkTvGFkTbhr1fGEaxJcaZCtQEfA7d3qimZ+h4UZqonT
+PAhyCKFNY2BbmxeeABKhAFLKeAGIGMftW8fk2eu9P6+SUz/+WFcN/PR7e6JP6blc
+taRSULRWWkSO2dDt3o9+rBxYdluoecmVq4Ud20wTgkqlQRsp9dOW34DRHgB9ujWU
+V4HhCCqBaxwwUDcBGg4mT2vtyVAXNyszP2j+xvAhjOeyeVXyQr0vsA==
+-----END CERTIFICATE-----
diff --git a/tests/certs/stunnel-sv.prm b/tests/certs/stunnel-sv.prm
new file mode 100644
index 0000000..3803da3
--- /dev/null
+++ b/tests/certs/stunnel-sv.prm
@@ -0,0 +1,38 @@
+extensions = x509v3
+[ x509v3 ]
+subjectAltName = DNS:localhost
+keyUsage = keyEncipherment,digitalSignature,keyAgreement
+extendedKeyUsage = serverAuth
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid
+basicConstraints = CA:false
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
+
+[ req ]
+default_bits = 12048
+distinguished_name = req_DN
+default_md = sha256
+string_mask = utf8only
+[ req_DN ]
+countryName = "Country Name is Northern Nowhere"
+countryName_value = NN
+organizationName = "Organization Name"
+organizationName_value = Edel Curl Arctic Illudium Research Cloud
+commonName = "Common Name"
+commonName_value = localhost
+
+[something]
+# The key
+# the certificate
+# some dhparam
diff --git a/tests/certs/stunnel-sv.pub.der b/tests/certs/stunnel-sv.pub.der
new file mode 100644
index 0000000..434e879
--- /dev/null
+++ b/tests/certs/stunnel-sv.pub.der
Binary files differ
diff --git a/tests/certs/stunnel-sv.pub.pem b/tests/certs/stunnel-sv.pub.pem
new file mode 100644
index 0000000..5458d65
--- /dev/null
+++ b/tests/certs/stunnel-sv.pub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqwqwA9B2/l7OFd5h1eOR
+b3zWu8omjni+JjXRplnx1TxVPgks7KDUrw48WqK1sHhRlWKAgHHITp9ZWZNAErKp
+zrLNF4ufJ/PjzyN4BtIGI1+bIOxCd2atpF6CtE2UcuoTZHL8y4Ms16GL9S5M08GI
+ssiYGV/vmPxigLNnzB8j/F84zYJuLZbZNZP+KaJpZcDfRas/rBcYAIBKt8m6uF8p
+u8SsFpfMVzQQyTZlbD7YiUXIpUKEfF7NGujxPlWzIQ/QNhPyxC+5c0H6h6rcRNZk
+luRaUPlKn+Ci52n0rVrPOiDlpwniz+gZoQCuqLsiAjRcs8+1JEx2v63p8bjThrp9
+kwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/tests/certs/stunnel-sv.pubkey-pinned b/tests/certs/stunnel-sv.pubkey-pinned
new file mode 100644
index 0000000..4829e49
--- /dev/null
+++ b/tests/certs/stunnel-sv.pubkey-pinned
@@ -0,0 +1 @@
+LpY019g4f7/9H+Q+AwdGYQsvwIj2JzM6m1jlyyJK1ro=
diff --git a/tests/check-deprecated.pl b/tests/check-deprecated.pl
new file mode 100755
index 0000000..36d461b
--- /dev/null
+++ b/tests/check-deprecated.pl
@@ -0,0 +1,329 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+#
+###########################################################################
+#
+# Check that the deprecated statuses of functions and enum values in header
+# files, man pages and symbols-in-versions are in sync.
+
+use strict;
+use warnings;
+
+use File::Basename;
+
+my $root=$ARGV[0] || ".";
+my $incdir = "$root/include/curl";
+my $docdir = "$root/docs";
+my $libdocdir = "$docdir/libcurl";
+my $errcode = 0;
+
+# Symbol-indexed hashes.
+# Values are:
+# X Not deprecated
+# ? Deprecated in unknown version
+# x.yy.z Deprecated in version x.yy.z
+my %syminver; # Symbols-in-versions deprecations.
+my %hdr; # Public header files deprecations.
+my %funcman; # Function man pages deprecations.
+my %optman; # Option man pages deprecations.
+
+
+# Scan header file for public function and enum values. Flag them with
+# the version they are deprecated in, if some.
+sub scan_header {
+ my ($f)=@_;
+ my $line = "";
+ my $incomment = 0;
+ my $inenum = 0;
+
+ open(my $h, "<", "$f");
+ while(<$h>) {
+ s/^\s*(.*?)\s*$/$1/; # Trim.
+ # Remove multi-line comment trail.
+ if($incomment) {
+ if($_ !~ /.*?\*\/\s*(.*)$/) {
+ next;
+ }
+ $_ = $1;
+ $incomment = 0;
+ }
+ if($line ne "") {
+ # Unfold line.
+ $_ = "$line $1";
+ $line = "";
+ }
+ # Remove comments.
+ while($_ =~ /^(.*?)\/\*.*?\*\/(.*)$/) {
+ $_ = "$1 $2";
+ }
+ if($_ =~ /^(.*)\/\*/) {
+ $_ = "$1 ";
+ $incomment = 1;
+ }
+ s/^\s*(.*?)\s*$/$1/; # Trim again.
+ # Ignore preprocessor directives and blank lines.
+ if($_ =~ /^(?:#|$)/) {
+ next;
+ }
+ # Handle lines that may be continued as if they were folded.
+ if($_ !~ /[;,{}]$/) {
+ # Folded line.
+ $line = $_;
+ next;
+ }
+ if($_ =~ /CURLOPTDEPRECATED\(/) {
+ # Handle deprecated CURLOPT_* option.
+ if($_ !~ /CURLOPTDEPRECATED\(\s*(\S+)\s*,(?:.*?,){2}\s*(.*?)\s*,.*"\)/) {
+ # Folded line.
+ $line = $_;
+ next;
+ }
+ $hdr{$1} = $2;
+ }
+ elsif($_ =~ /CURLOPT\(/) {
+ # Handle non-deprecated CURLOPT_* option.
+ if($_ !~ /CURLOPT\(\s*(\S+)\s*(?:,.*?){2}\)/) {
+ # Folded line.
+ $line = $_;
+ next;
+ }
+ $hdr{$1} = "X";
+ }
+ else {
+ my $version = "X";
+
+ # Get other kind of deprecation from this line.
+ if($_ =~ /CURL_DEPRECATED\(/) {
+ if($_ !~ /^(.*)CURL_DEPRECATED\(\s*(\S+?)\s*,.*?"\)(.*)$/) {
+ # Folded line.
+ $line = $_;
+ next;
+ }
+ $version = $2;
+ $_ = "$1 $3";
+ }
+ if($_ =~ /^CURL_EXTERN\s+.*\s+(\S+?)\s*\(/) {
+ # Flag public function.
+ $hdr{$1} = $version;
+ }
+ elsif($inenum && $_ =~ /(\w+)\s*[,=}]/) {
+ # Flag enum value.
+ $hdr{$1} = $version;
+ }
+ }
+ # Remember if we are in an enum definition.
+ $inenum |= ($_ =~ /\benum\b/);
+ if($_ =~ /}/) {
+ $inenum = 0;
+ }
+ }
+ close $h;
+}
+
+# Scan function man page for options.
+# Each option has to be declared as ".IP <option>" where <option> starts with
+# the prefix. Flag each option with its deprecation version, if some.
+sub scan_man_for_opts {
+ my ($f, $prefix)=@_;
+ my $opt = "";
+ my $line = "";
+
+ open(my $m, "<", "$f");
+ while(<$m>) {
+ if($_ =~ /^\./) {
+ # roff directive found: end current option paragraph.
+ my $o = $opt;
+ $opt = "";
+ if($_ =~ /^\.IP\s+((?:$prefix)_\w+)/) {
+ # A new option has been found.
+ $opt = $1;
+ }
+ $_ = $line; # Get full paragraph.
+ $line = "";
+ s/\\f.//g; # Remove font formatting.
+ s/\s+/ /g; # One line with single space only.
+ if($o) {
+ $funcman{$o} = "X";
+ # Check if paragraph is mentioning deprecation.
+ while($_ =~ /(?:deprecated|obsoleted?)\b\s*(?:in\b|since\b)?\s*(?:version\b|curl\b|libcurl\b)?\s*(\d[0-9.]*\d)?\b\s*(.*)$/i) {
+ $funcman{$o} = $1 || "?";
+ $_ = $2;
+ }
+ }
+ }
+ else {
+ # Text line: accumulate.
+ $line .= $_;
+ }
+ }
+ close $m;
+}
+
+# Scan man page for deprecation in DESCRIPTION and/or AVAILABILITY sections.
+sub scan_man_page {
+ my ($path, $sym, $table)=@_;
+ my $version = "X";
+
+ if(open(my $fh, "<", "$path")) {
+ my $section = "";
+ my $line = "";
+
+ while(<$fh>) {
+ if($_ =~ /\.so\s+man3\/(.*\.3\b)/) {
+ # Handle man page inclusion.
+ scan_man_page(dirname($path) . "/$1", $sym, $table);
+ $version = exists($$table{$sym})? $$table{$sym}: $version;
+ }
+ elsif($_ =~ /^\./) {
+ # Line is a roff directive.
+ if($_ =~ /^\.SH\b\s*(\w*)/) {
+ # Section starts. End previous one.
+ my $sh = $section;
+
+ $section = $1;
+ $_ = $line; # Previous section text.
+ $line = "";
+ s/\\f.//g;
+ s/\s+/ /g;
+ s/\\f.//g; # Remove font formatting.
+ s/\s+/ /g; # One line with single space only.
+ if($sh =~ /DESCRIPTION|AVAILABILITY/) {
+ while($_ =~ /(?:deprecated|obsoleted?)\b\s*(?:in\b|since\b)?\s*(?:version\b|curl\b|libcurl\b)?\s*(\d[0-9.]*\d)?\b\s*(.*)$/i) {
+ # Flag deprecation status.
+ if($version ne "X" && $version ne "?") {
+ if($1 && $1 ne $version) {
+ print "error: $sym man page lists unmatching deprecation versions $version and $1\n";
+ $errcode++;
+ }
+ }
+ else {
+ $version = $1 || "?";
+ }
+ $_ = $2;
+ }
+ }
+ }
+ }
+ else {
+ # Text line: accumulate.
+ $line .= $_;
+ }
+ }
+ close $fh;
+ $$table{$sym} = $version;
+ }
+}
+
+
+# Read symbols-in-versions.
+open(my $fh, "<", "$libdocdir/symbols-in-versions") ||
+ die "$libdocdir/symbols-in-versions";
+while(<$fh>) {
+ if($_ =~ /^((?:CURL|LIBCURL)\S+)\s+\S+\s*(\S*)\s*(\S*)$/) {
+ if($3 eq "") {
+ $syminver{$1} = "X";
+ if($2 ne "" && $2 ne ".") {
+ $syminver{$1} = $2;
+ }
+ }
+ }
+}
+close($fh);
+
+# Get header file names,
+opendir(my $dh, $incdir) || die "Can't opendir $incdir";
+my @hfiles = grep { /\.h$/ } readdir($dh);
+closedir $dh;
+
+# Get functions and enum symbols from header files.
+for(@hfiles) {
+ scan_header("$incdir/$_");
+}
+
+# Get function statuses from man pages.
+foreach my $sym (keys %hdr) {
+ if($sym =~/^(?:curl|curlx)_\w/) {
+ scan_man_page("$libdocdir/$sym.3", $sym, \%funcman);
+ }
+}
+
+# Get options from function man pages.
+scan_man_for_opts("$libdocdir/curl_easy_setopt.3", "CURLOPT");
+scan_man_for_opts("$libdocdir/curl_easy_getinfo.3", "CURLINFO");
+
+# Get deprecation status from option man pages.
+foreach my $sym (keys %syminver) {
+ if($sym =~ /^(?:CURLOPT|CURLINFO)_\w+$/) {
+ scan_man_page("$libdocdir/opts/$sym.3", $sym, \%optman);
+ }
+}
+
+# Print results.
+my %keys = (%syminver, %funcman, %optman, %hdr);
+my $leader = <<HEADER
+Legend:
+<empty> Not listed
+X Not deprecated
+? Deprecated in unknown version
+x.yy.z Deprecated in version x.yy.z
+
+Symbol symbols-in func man opt man .h
+ -versions
+HEADER
+ ;
+foreach my $sym (sort {$a cmp $b} keys %keys) {
+ if($sym =~ /^(?:CURLOPT|CURLINFO|curl|curlx)_\w/) {
+ my $s = exists($syminver{$sym})? $syminver{$sym}: " ";
+ my $f = exists($funcman{$sym})? $funcman{$sym}: " ";
+ my $o = exists($optman{$sym})? $optman{$sym}: " ";
+ my $h = exists($hdr{$sym})? $hdr{$sym}: " ";
+ my $r = " ";
+
+ # There are deprecated symbols in symbols-in-versions that are aliases
+ # and thus not listed anywhere else. Ignore them.
+ "$f$o$h" =~ /[X ]{3}/ && next;
+
+ # Check for inconsistencies between deprecations from the different sources.
+ foreach my $k ($s, $f, $o, $h) {
+ $r = $r eq " "? $k: $r;
+ if($k ne " " && $r ne $k) {
+ if($r eq "?") {
+ $r = $k ne "X"? $k: "!";
+ }
+ elsif($r eq "X" || $k ne "?") {
+ $r = "!";
+ }
+ }
+ }
+
+ if($r eq "!") {
+ print $leader;
+ $leader = "";
+ printf("%-38s %-11s %-9s %-9s %s\n", $sym, $s, $f, $o, $h);
+ $errcode++;
+ }
+ }
+}
+
+exit $errcode;
diff --git a/tests/fuzz/download_fuzzer.sh b/tests/config.in
old mode 100755
new mode 100644
similarity index 77%
copy from tests/fuzz/download_fuzzer.sh
copy to tests/config.in
index e9d6be4..f5aa986
--- a/tests/fuzz/download_fuzzer.sh
+++ b/tests/config.in
@@ -1,4 +1,3 @@
-#!/bin/bash
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
@@ -6,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -22,9 +21,4 @@
# SPDX-License-Identifier: curl
#
###########################################################################
-
-# If any commands fail, fail the script immediately.
-set -ex
-
-# Clone the curl-fuzzer repository to the specified directory.
-git clone --depth=1 https://github.com/curl/curl-fuzzer "$1"
+NGHTTPX: @TEST_NGHTTPX@
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..312fcdd
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,62 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 2008 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import sys, os
+
+sys.path.append(os.path.join(os.path.dirname(__file__), 'http'))
+
+import pytest
+from testenv import Env
+
+def pytest_report_header(config, startdir):
+ # Env inits its base properties only once, we can report them here
+ env = Env()
+ report = [
+ f'Testing curl {env.curl_version()}',
+ f' httpd: {env.httpd_version()}, http:{env.http_port} https:{env.https_port}',
+ f' httpd-proxy: {env.httpd_version()}, http:{env.proxy_port} https:{env.proxys_port}'
+ ]
+ if env.have_h3():
+ report.extend([
+ f' nghttpx: {env.nghttpx_version()}, h3:{env.https_port}'
+ ])
+ if env.has_caddy():
+ report.extend([
+ f' Caddy: {env.caddy_version()}, http:{env.caddy_http_port} https:{env.caddy_https_port}'
+ ])
+ return '\n'.join(report)
+
+
+def pytest_addoption(parser):
+ parser.addoption("--repeat", action="store", type=int, default=1,
+ help='Number of times to repeat each test')
+
+
+def pytest_generate_tests(metafunc):
+ if "repeat" in metafunc.fixturenames:
+ count = int(metafunc.config.getoption("repeat"))
+ metafunc.fixturenames.append('tmp_ct')
+ metafunc.parametrize('repeat', range(count))
+
+
diff --git a/tests/convsrctest.pl b/tests/convsrctest.pl
index 68d6f8b..fad9228 100755
--- a/tests/convsrctest.pl
+++ b/tests/convsrctest.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -42,7 +42,13 @@
# - URL as literal string vs. passed as argument
#=======================================================================
use strict;
-require "getpart.pm";
+use warnings;
+
+use getpart qw(
+ getpart
+ loadtest
+ fulltest
+ );
# Boilerplate code for test tool
my $head =
@@ -165,7 +171,7 @@
}
}
- print ("/* $comment */\n",
+ print("/* $comment */\n",
$head,
@decl,
$init,
@@ -196,7 +202,7 @@
# Traverse the pseudo-XML transforming as required
my @new;
my(@path,$path,$skip);
- foreach (getall()) {
+ foreach (fulltest()) {
if(my($end) = /\s*<(\/?)testcase>/) {
push @new, $_;
push @new, "# $comment\n"
diff --git a/tests/data/.gitattributes b/tests/data/.gitattributes
index 031f33c..bb1b928 100644
--- a/tests/data/.gitattributes
+++ b/tests/data/.gitattributes
@@ -1,4 +1,4 @@
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/tests/data/.gitignore b/tests/data/.gitignore
index 194773a..52ecd17 100644
--- a/tests/data/.gitignore
+++ b/tests/data/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/tests/data/CMakeLists.txt b/tests/data/CMakeLists.txt
index 7274d37..ed0b88f 100644
--- a/tests/data/CMakeLists.txt
+++ b/tests/data/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -24,7 +24,3 @@
# Loads 'TESTCASES' from for the 'make show' target in runtests.pl
transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
-
-# Prints all available test cases. Do not quote TESTCASES, it must be displayed
-# as a space-separated string rather than comma-separated (a list in CMake).
-add_custom_target(show COMMAND echo ${TESTCASES})
diff --git a/tests/data/DISABLED b/tests/data/DISABLED
index 00ebebc..3d23895 100644
--- a/tests/data/DISABLED
+++ b/tests/data/DISABLED
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -64,32 +64,28 @@
# hyper support remains EXPERIMENTAL as long as there's a test number
# listed below
%if hyper
-265
266
-565
579
587
-670
-671
-672
-673
# 1021 re-added here due to flakiness
1021
1117
-1274
1417
1533
1540
1591
-1940
-1941
-1942
1943
+2301
+2302
+2305
%endif
2043
-# Tests that are disabled here for rustls are SUPPOSED to work
+# The CRL test (313) doesn't work with rustls because rustls doesn't support
+# CRLs.
+# Tests that rely on connecting to an IP address over TLS don't work because
+# rustls doesn't support IP address certificates yet. That's the 400 series of
+# tests listed here, plus 1112 and 1272
%if rustls
-312
313
400
401
@@ -99,6 +95,9 @@
407
408
409
+987
+988
+989
1112
1272
%endif
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 5b4cb59..68148c1 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -29,21 +29,3 @@
include Makefile.inc
EXTRA_DIST = $(TESTCASES) DISABLED CMakeLists.txt
-
-filecheck:
- @mkdir test-place; \
- cp "$(top_srcdir)"/tests/data/test[0-9]* test-place/; \
- rm -f test-place/*~; \
- for f in $(EXTRA_DIST); do \
- if test -f "$(top_srcdir)/tests/data/$$f"; then \
- rm -f "test-place/$$f"; \
- else \
- echo "$$f is listed but missing!"; \
- fi \
- done; \
- echo "Local files not present in EXTRA_DIST:" ; \
- ls test-place; \
- ! ls test-place | grep . >/dev/null ; \
- RC=$$? ; \
- rm -rf test-place ; \
- exit $$RC
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 96f1428..a253b5c 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -64,18 +64,17 @@
test352 test353 test354 test355 test356 test357 test358 test359 test360 \
test361 test362 test363 test364 test365 test366 test367 test368 test369 \
test370 test371 test372 test373 test374 test375 test376 test378 test379 \
-test380 test381 test383 test384 test385 test386 test387 \
-\
+test380 test381 test383 test384 test385 test386 test387 test388 test389 \
test390 test391 test392 test393 test394 test395 test396 test397 test398 \
-\
-test400 test401 test402 test403 test404 test405 test406 test407 test408 \
-test409 test410 test411 test412 test413 test414 \
-\
+test399 test400 test401 test402 test403 test404 test405 test406 test407 \
+test408 test409 test410 test411 test412 test413 test414 test415 test416 \
+test417 test418 test419 test420 test421 test422 test423 test424 test425 \
+test426 test427 \
test430 test431 test432 test433 test434 test435 test436 \
\
-test440 test441 test442 test443 test444 \
+test440 test441 test442 test443 test444 test445 test446 test447 \
\
-test490 test491 test492 test493 test494 \
+test490 test491 test492 test493 test494 test495 test496 \
\
test500 test501 test502 test503 test504 test505 test506 test507 test508 \
test509 test510 test511 test512 test513 test514 test515 test516 test517 \
@@ -93,39 +92,38 @@
test617 test618 test619 test620 test621 test622 test623 test624 test625 \
test626 test627 test628 test629 test630 test631 test632 test633 test634 \
test635 test636 test637 test638 test639 test640 test641 test642 \
-test643 test645 test646 test647 test648 test649 test650 test651 \
+test643 test644 test645 test646 test647 test648 test649 test650 test651 \
test652 test653 test654 test655 test656 test658 test659 test660 test661 \
test662 test663 test664 test665 test666 test667 test668 test669 \
test670 test671 test672 test673 test674 test675 test676 test677 test678 \
-test679 test680 test681 \
+test679 test680 test681 test682 test683 test684 test685 test686 \
\
test700 test701 test702 test703 test704 test705 test706 test707 test708 \
test709 test710 test711 test712 test713 test714 test715 test716 test717 \
test718 test719 test720 test721 \
\
-test800 test801 test802 test803 test804 test805 test806 test807 test808 \
-test809 test810 test811 test812 test813 test814 test815 test816 test817 \
-test818 test819 test820 test821 test822 test823 test824 test825 test826 \
-test827 test828 test829 test830 test831 test832 test833 test834 test835 \
-test836 test837 test838 test839 test840 test841 test842 test843 test844 \
-test845 test846 test847 test848 test849 test850 test851 test852 test853 \
-test854 test855 test856 test857 test858 test859 test860 test861 test862 \
-test863 test864 test865 test866 test867 test868 test869 test870 test871 \
-test872 test873 test874 test875 test876 test877 test878 test879 test880 \
-test881 test882 test883 test884 test885 test886 test887 test888 test889 \
-test890 test891 test892 test893 test894 test895 test896 test897 test898 \
-\
-test900 test901 test902 test903 test904 test905 test906 test907 test908 \
-test909 test910 test911 test912 test913 test914 test915 test916 test917 \
-test918 test919 test920 test921 test922 test923 test924 test925 test926 \
-test927 test928 test929 test930 test931 test932 test933 test934 test935 \
-test936 test937 test938 test939 test940 test941 test942 test943 test944 \
-test945 test946 test947 test948 test949 test950 test951 test952 test953 \
-test954 test955 test956 test957 test958 test959 test960 test961 test962 \
-test963 test964 test965 test966 test967 test968 test969 test970 test971 \
-test972 test973 test974 test975 test976 test977 \
-\
-test980 test981 test982 test983 test984 test985 test986 \
+test799 test800 test801 test802 test803 test804 test805 test806 test807 \
+test808 test809 test810 test811 test812 test813 test814 test815 test816 \
+test817 test818 test819 test820 test821 test822 test823 test824 test825 \
+test826 test827 test828 test829 test830 test831 test832 test833 test834 \
+test835 test836 test837 test838 test839 test840 test841 test842 test843 \
+test844 test845 test846 test847 test848 test849 test850 test851 test852 \
+test853 test854 test855 test856 test857 test858 test859 test860 test861 \
+test862 test863 test864 test865 test866 test867 test868 test869 test870 \
+test871 test872 test873 test874 test875 test876 test877 test878 test879 \
+test880 test881 test882 test883 test884 test885 test886 test887 test888 \
+test889 test890 test891 test892 test893 test894 test895 test896 test897 \
+test898 test899 test900 test901 test902 test903 test904 test905 test906 \
+test907 test908 test909 test910 test911 test912 test913 test914 test915 \
+test916 test917 test918 test919 test920 test921 test922 test923 test924 \
+test925 test926 test927 test928 test929 test930 test931 test932 test933 \
+test934 test935 test936 test937 test938 test939 test940 test941 test942 \
+test943 test944 test945 test946 test947 test948 test949 test950 test951 \
+test952 test953 test954 test955 test956 test957 test958 test959 test960 \
+test961 test962 test963 test964 test965 test966 test967 test968 test969 \
+test970 test971 test972 test973 test974 test975 test976 test977 test978 \
+test979 test980 test981 test982 test983 test984 test985 test986 test987 \
+test988 test989 \
\
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
@@ -150,20 +148,18 @@
test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 \
test1168 test1169 test1170 test1171 test1172 test1173 test1174 test1175 \
test1176 test1177 test1178 test1179 test1180 test1181 test1182 test1183 \
-test1184 test1185 test1186 test1187 test1188 test1189 \
-\
-test1190 test1191 test1192 test1193 test1194 test1195 test1196 test1197 \
-test1198 test1199 \
-test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
-test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
-test1216 test1217 test1218 test1219 test1220 test1223 \
-test1224 test1225 test1226 test1227 test1228 test1229 test1230 test1231 \
-test1232 test1233 test1234 test1235 test1236 test1237 test1238 test1239 \
-test1240 test1241 test1242 test1243 test1244 test1245 test1246 test1247 \
-test1248 test1249 test1250 test1251 test1252 test1253 test1254 test1255 \
-test1256 test1257 test1258 test1259 test1260 test1261 test1262 test1263 \
-test1264 test1265 test1266 test1267 test1268 test1269 test1270 test1271 \
-test1272 test1273 test1274 \
+test1184 test1185 test1186 test1187 test1188 test1189 test1190 test1190 \
+test1191 test1192 test1193 test1194 test1195 test1196 test1197 test1198 \
+test1199 test1200 test1201 test1202 test1203 test1204 test1205 test1206 \
+test1207 test1208 test1209 test1210 test1211 test1212 test1213 test1214 \
+test1215 test1216 test1217 test1218 test1219 test1220 test1221 test1222 \
+test1223 test1224 test1225 test1226 test1227 test1228 test1229 test1230 \
+test1231 test1232 test1233 test1234 test1235 test1236 test1237 test1238 \
+test1239 test1240 test1241 test1242 test1243 test1244 test1245 test1246 \
+test1247 test1248 test1249 test1250 test1251 test1252 test1253 test1254 \
+test1255 test1256 test1257 test1258 test1259 test1260 test1261 test1262 \
+test1263 test1264 test1265 test1266 test1267 test1268 test1269 test1270 \
+test1271 test1272 test1273 test1274 test1275 test1276 test1277 test1278 \
\
test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 \
test1288 test1289 test1290 test1291 test1292 test1293 test1294 test1295 \
@@ -188,8 +184,8 @@
test1440 test1441 test1442 test1443 test1444 test1445 test1446 test1447 \
test1448 test1449 test1450 test1451 test1452 test1453 test1454 test1455 \
test1456 test1457 test1458 test1459 test1460 test1461 test1462 test1463 \
-test1464 test1465 test1466 test1467 test1468 \
-\
+test1464 test1465 test1466 test1467 test1468 test1469 test1470 test1471 \
+test1472 \
test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \
test1516 test1517 test1518 test1519 test1520 test1521 test1522 test1523 \
@@ -201,17 +197,17 @@
test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \
test1566 test1567 test1568 test1569 test1570 \
\
-test1590 test1591 test1592 test1593 test1594 test1595 test1596 \
+test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 \
\
test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 \
-test1608 test1609 test1610 test1611 test1612 test1613 \
+test1608 test1609 test1610 test1611 test1612 test1613 test1614 \
\
test1620 test1621 \
\
test1630 test1631 test1632 test1633 test1634 test1635 \
\
test1650 test1651 test1652 test1653 test1654 test1655 \
-test1660 test1661 \
+test1660 test1661 test1662 \
\
test1670 test1671 \
\
@@ -221,12 +217,14 @@
\
test1800 test1801 \
\
- test1904 test1905 test1906 test1907 \
+ test1903 test1904 test1905 test1906 test1907 \
test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \
test1916 test1917 test1918 test1919 \
\
test1933 test1934 test1935 test1936 test1937 test1938 test1939 test1940 \
-test1941 test1942 test1943 test1944 test1945 test1946 \
+test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 \
+test1955 test1956 test1957 test1958 test1959 test1960 \
+test1970 test1971 test1972 test1973 test1974 test1975 \
\
test2000 test2001 test2002 test2003 test2004 \
\
@@ -244,7 +242,19 @@
\
test2200 test2201 test2202 test2203 test2204 test2205 \
\
+test2300 test2301 test2302 test2303 test2304 test2305 test2306 \
+\
+test2400 test2401 test2402 test2403 test2404 \
+\
+test2500 test2501 test2502 test2503 \
+\
+test2600 test2601 test2602 test2603 \
+\
test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 \
test3008 test3009 test3010 test3011 test3012 test3013 test3014 test3015 \
test3016 test3017 test3018 test3019 test3020 test3021 test3022 test3023 \
-test3024 test3025 test3026
+test3024 test3025 test3026 test3027 test3028 test3029 test3030 \
+\
+test3100 test3101 \
+test3200 \
+test3201 test3202
diff --git a/tests/data/test1 b/tests/data/test1
index f39a08b..700bed8 100644
--- a/tests/data/test1
+++ b/tests/data/test1
@@ -9,7 +9,7 @@
#
# Server-side
<reply>
-<data>
+<data crlf="yes">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -42,12 +42,12 @@
#
# Verify data after the test has been "shot"
<verify>
-<protocol>
-GET /%TESTNUMBER HTTP/1.1
-Host: %HOSTIP:%HTTPPORT
-User-Agent: curl/%VERSION
-Accept: */*
-
+<protocol crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
</protocol>
</verify>
</testcase>
diff --git a/tests/data/test10 b/tests/data/test10
index 5b5534b..b52850f 100644
--- a/tests/data/test10
+++ b/tests/data/test10
@@ -26,9 +26,9 @@
simple HTTP PUT from file
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -T log/test%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
Weird
file
to
@@ -49,7 +49,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 78
-Expect: 100-continue
Weird
file
diff --git a/tests/data/test1001 b/tests/data/test1001
index df42f71..8900a80 100644
--- a/tests/data/test1001
+++ b/tests/data/test1001
@@ -72,9 +72,9 @@
HTTP POST --digest with PUT and resumed upload and modified method
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T log/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -C 2 -X GET
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T %LOGDIR/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -C 2 -X GET
</command>
-<file name="log/%TESTNUMBER">
+<file name="%LOGDIR/%TESTNUMBER">
test
</file>
</client>
@@ -98,7 +98,6 @@
Accept: */*
Proxy-Connection: Keep-Alive
Content-Length: 3
-Expect: 100-continue
st
</protocol>
diff --git a/tests/data/test1002 b/tests/data/test1002
index ca58be6..3a098f1 100644
--- a/tests/data/test1002
+++ b/tests/data/test1002
@@ -71,9 +71,9 @@
HTTP PUT with Digest auth, resumed upload and modified method, twice
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload1 -T log/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload2 -T log/%TESTNUMBER -u auser:apasswd --digest -x http://%HOSTIP:%HTTPPORT -C 2 -X GET
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload1 -T %LOGDIR/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload2 -T %LOGDIR/%TESTNUMBER -u auser:apasswd --digest -x http://%HOSTIP:%HTTPPORT -C 2 -X GET
</command>
-<file name="log/%TESTNUMBER">
+<file name="%LOGDIR/%TESTNUMBER">
test
</file>
</client>
@@ -97,7 +97,6 @@
Accept: */*
Proxy-Connection: Keep-Alive
Content-Length: 3
-Expect: 100-continue
st
GET http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload2 HTTP/1.1
@@ -116,7 +115,6 @@
Accept: */*
Proxy-Connection: Keep-Alive
Content-Length: 3
-Expect: 100-continue
st
</protocol>
diff --git a/tests/data/test1007 b/tests/data/test1007
index c50e97d..e9f11c8 100644
--- a/tests/data/test1007
+++ b/tests/data/test1007
@@ -17,9 +17,9 @@
TFTP send with invalid permission on server
</name>
<command>
--T log/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT//invalid-file
+-T %LOGDIR/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT//invalid-file -sS
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
This data will not be sent
</file>
</client>
@@ -30,13 +30,18 @@
<errorcode>
69
</errorcode>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 2
mode = octet
tsize = 27
blksize = 512
-timeout = 6
filename = /invalid-file
</protocol>
+<stderr mode="text">
+curl: (69) TFTP: Access Violation
+</stderr>
</verify>
</testcase>
diff --git a/tests/data/test1009 b/tests/data/test1009
index 9e1fa55..041d881 100644
--- a/tests/data/test1009
+++ b/tests/data/test1009
@@ -35,12 +35,14 @@
#
# Verify pseudo protocol after the test has been "shot"
<verify>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 1
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER
</protocol>
</verify>
diff --git a/tests/data/test1013 b/tests/data/test1013
index 17a3371..70c6455 100644
--- a/tests/data/test1013
+++ b/tests/data/test1013
@@ -23,7 +23,7 @@
--version
</command>
<postcheck>
-%SRCDIR/libtest/test%TESTNUMBER.pl ../curl-config log/stdout%TESTNUMBER protocols
+%SRCDIR/libtest/test%TESTNUMBER.pl ../curl-config %LOGDIR/stdout%TESTNUMBER protocols
</postcheck>
</client>
diff --git a/tests/data/test1014 b/tests/data/test1014
index 875fa77..8dc3f04 100644
--- a/tests/data/test1014
+++ b/tests/data/test1014
@@ -23,7 +23,7 @@
--version
</command>
<postcheck>
-%SRCDIR/libtest/test1013.pl ../curl-config log/stdout%TESTNUMBER features
+%SRCDIR/libtest/test1013.pl ../curl-config %LOGDIR/stdout%TESTNUMBER features
</postcheck>
</client>
diff --git a/tests/data/test1015 b/tests/data/test1015
index 28412c2..c9971fc 100644
--- a/tests/data/test1015
+++ b/tests/data/test1015
@@ -28,9 +28,9 @@
--data-urlencode
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --data-urlencode "my name is moo[]" --data-urlencode "y e s=s_i_r" --data-urlencode "v_alue@log/%TESTNUMBER.txt" --data-urlencode @log/%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --data-urlencode "my name is moo[]" --data-urlencode "y e s=s_i_r" --data-urlencode "v_alue@%LOGDIR/%TESTNUMBER.txt" --data-urlencode @%LOGDIR/%TESTNUMBER.txt
</command>
-<file name="log/%TESTNUMBER.txt">
+<file name="%LOGDIR/%TESTNUMBER.txt">
content to _?!#$'|<>
</file>
</client>
diff --git a/tests/data/test1016 b/tests/data/test1016
index 340dd96..91ac2da 100644
--- a/tests/data/test1016
+++ b/tests/data/test1016
@@ -23,9 +23,9 @@
X-Y range on a file:// URL to stdout
</name>
<command option="no-include">
--r 1-4 file://localhost%FILE_PWD/log/test%TESTNUMBER.txt
+-r 1-4 file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
1234567890
</file>
</client>
diff --git a/tests/data/test1017 b/tests/data/test1017
index 034c87a..59614b1 100644
--- a/tests/data/test1017
+++ b/tests/data/test1017
@@ -24,9 +24,9 @@
0-Y range on a file:// URL to stdout
</name>
<command option="no-include">
--r 0-3 file://localhost%FILE_PWD/log/test%TESTNUMBER.txt
+-r 0-3 file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
1234567890
</file>
</client>
diff --git a/tests/data/test1018 b/tests/data/test1018
index 25d8cb1..1fde0ca 100644
--- a/tests/data/test1018
+++ b/tests/data/test1018
@@ -23,9 +23,9 @@
X-X range on a file:// URL to stdout
</name>
<command option="no-include">
--r 4-4 file://localhost%FILE_PWD/log/test%TESTNUMBER.txt
+-r 4-4 file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
1234567890
</file>
</client>
diff --git a/tests/data/test1019 b/tests/data/test1019
index 02732b4..87f88f5 100644
--- a/tests/data/test1019
+++ b/tests/data/test1019
@@ -24,9 +24,9 @@
X- range on a file:// URL to stdout
</name>
<command option="no-include">
--r 7- file://localhost%FILE_PWD/log/test%TESTNUMBER.txt
+-r 7- file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
1234567890
1234567890
</file>
diff --git a/tests/data/test1020 b/tests/data/test1020
index 91c9b63..a17106e 100644
--- a/tests/data/test1020
+++ b/tests/data/test1020
@@ -24,9 +24,9 @@
-Y range on a file:// URL to stdout
</name>
<command option="no-include">
--r -9 file://localhost%FILE_PWD/log/test%TESTNUMBER.txt
+-r -9 file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
1234567890
1234567890
</file>
diff --git a/tests/data/test1022 b/tests/data/test1022
index e55b51f..2288e9b 100644
--- a/tests/data/test1022
+++ b/tests/data/test1022
@@ -23,7 +23,7 @@
--version
</command>
<postcheck>
-%SRCDIR/libtest/test%TESTNUMBER.pl ../curl-config log/stdout%TESTNUMBER version
+%SRCDIR/libtest/test%TESTNUMBER.pl ../curl-config %LOGDIR/stdout%TESTNUMBER version
</postcheck>
</client>
diff --git a/tests/data/test1023 b/tests/data/test1023
index 18071c6..27a144d 100644
--- a/tests/data/test1023
+++ b/tests/data/test1023
@@ -23,7 +23,7 @@
--version
</command>
<postcheck>
-%SRCDIR/libtest/test1022.pl ../curl-config log/stdout%TESTNUMBER vernum
+%SRCDIR/libtest/test1022.pl ../curl-config %LOGDIR/stdout%TESTNUMBER vernum
</postcheck>
</client>
diff --git a/tests/data/test1024 b/tests/data/test1024
index 5fba9d3..fbd1db4 100644
--- a/tests/data/test1024
+++ b/tests/data/test1024
@@ -75,8 +75,11 @@
HTTP Location: following with cookies
</name>
<command>
-http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -L -c log/jar%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -L -c %LOGDIR/jar%TESTNUMBER
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
diff --git a/tests/data/test1025 b/tests/data/test1025
index 5f96e11..039824c 100644
--- a/tests/data/test1025
+++ b/tests/data/test1025
@@ -75,8 +75,11 @@
HTTP Location: following with command-line and server cookies
</name>
<command>
-http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -L -c log/jar%TESTNUMBER -b forcedcookie=yes
+http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -L -c %LOGDIR/jar%TESTNUMBER -b forcedcookie=yes
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
diff --git a/tests/data/test1026 b/tests/data/test1026
index a702a1d..d240f91 100644
--- a/tests/data/test1026
+++ b/tests/data/test1026
@@ -28,7 +28,7 @@
# Search for these two sentinel lines in the manual output; if they are found,
# then chances are good the entire manual is there.
<postcheck>
-perl -e 'open(IN,$ARGV[0]); my $lines=grep(/(curl\s*-\s*transfer\sa\s*URL)|(CONTRIBUTORS)/, <IN>); exit ($lines != 2); # Let this file pass an XML syntax check: </IN>' log/stdout%TESTNUMBER
+perl -e 'open(IN,$ARGV[0]); my $lines=grep(/(curl\s*-\s*transfer\sa\s*URL)|(CONTRIBUTORS)/, <IN>); exit ($lines != 2); # Let this file pass an XML syntax check: </IN>' %LOGDIR/stdout%TESTNUMBER
</postcheck>
</client>
diff --git a/tests/data/test1027 b/tests/data/test1027
index 7574203..6ce71b0 100644
--- a/tests/data/test1027
+++ b/tests/data/test1027
@@ -25,7 +25,7 @@
# Search for these two sentinel lines in the help output; if they are found,
# then chances are good the entire help is there.
<postcheck>
-perl -e 'open(IN,$ARGV[0]); my $lines=grep(/(Usage: curl )|(--version\s*Show version)/, <IN>); exit ($lines != 2); # Let this file pass an XML syntax check: </IN>' log/stdout%TESTNUMBER
+perl -e 'open(IN,$ARGV[0]); my $lines=grep(/(Usage: curl )|(--version\s*Show version)/, <IN>); exit ($lines != 2); # Let this file pass an XML syntax check: </IN>' %LOGDIR/stdout%TESTNUMBER
</postcheck>
</client>
diff --git a/tests/data/test1030 b/tests/data/test1030
index bd4e18f..c84033a 100644
--- a/tests/data/test1030
+++ b/tests/data/test1030
@@ -67,9 +67,9 @@
HTTP PUT with --anyauth authorization (picking Digest)
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T log/put%TESTNUMBER -u testuser:testpass --anyauth
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T %LOGDIR/put%TESTNUMBER -u testuser:testpass --anyauth
</command>
-<file name="log/put%TESTNUMBER">
+<file name="%LOGDIR/put%TESTNUMBER">
This is data we upload with PUT
a second line
line three
@@ -85,7 +85,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 85
-Expect: 100-continue
This is data we upload with PUT
a second line
@@ -97,7 +96,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 85
-Expect: 100-continue
This is data we upload with PUT
a second line
diff --git a/tests/data/test1036 b/tests/data/test1036
index 4ab61a2..88183bc 100644
--- a/tests/data/test1036
+++ b/tests/data/test1036
@@ -33,7 +33,7 @@
<command>
ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -C -
</command>
-<file name="log/curl%TESTNUMBER.out">
+<file name="%LOGDIR/curl%TESTNUMBER.out">
This is the start!!
</file>
</client>
@@ -52,7 +52,7 @@
RETR %TESTNUMBER
QUIT
</protocol>
-<file name="log/curl%TESTNUMBER.out">
+<file name="%LOGDIR/curl%TESTNUMBER.out">
This is the start!!
expected to be a file without the first part
but we emulate that
diff --git a/tests/data/test1037 b/tests/data/test1037
index d9cacb2..6d3ede5 100644
--- a/tests/data/test1037
+++ b/tests/data/test1037
@@ -33,7 +33,7 @@
<command>
ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -C -
</command>
-<file name="log/curl%TESTNUMBER.out">
+<file name="%LOGDIR/curl%TESTNUMBER.out">
</file>
</client>
diff --git a/tests/data/test1038 b/tests/data/test1038
index acac84a..46fe821 100644
--- a/tests/data/test1038
+++ b/tests/data/test1038
@@ -23,9 +23,9 @@
FTP PASV upload resume from end of file
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -C -
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER -C -
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
this is the *****cr@p******** that we're gonna upload
worx?
diff --git a/tests/data/test1039 b/tests/data/test1039
index 53d7cb5..9f6d513 100644
--- a/tests/data/test1039
+++ b/tests/data/test1039
@@ -23,9 +23,9 @@
FTP PASV upload resume from end of empty file
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -C -
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER -C -
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
this is the *****cr@p******** that we're gonna upload
worx?
diff --git a/tests/data/test1040 b/tests/data/test1040
index 8899c5b..21410c6 100644
--- a/tests/data/test1040
+++ b/tests/data/test1040
@@ -49,7 +49,7 @@
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -C -
</command>
-<file name="log/curl%TESTNUMBER.out">
+<file name="%LOGDIR/curl%TESTNUMBER.out">
012345678
012345678
012345678
diff --git a/tests/data/test1041 b/tests/data/test1041
index 5580b95..4e23e2c 100644
--- a/tests/data/test1041
+++ b/tests/data/test1041
@@ -31,7 +31,7 @@
<name>
HTTP PUT with resume from end of already-uploaded file
</name>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
012345678
012345678
012345678
@@ -44,7 +44,7 @@
012345678
</file>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -Tlog/test%TESTNUMBER.txt -C -
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T%LOGDIR/test%TESTNUMBER.txt -C -
</command>
</client>
@@ -59,7 +59,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 100
-Expect: 100-continue
012345678
012345678
diff --git a/tests/data/test1042 b/tests/data/test1042
index 4a33ae8..f05c873 100644
--- a/tests/data/test1042
+++ b/tests/data/test1042
@@ -61,7 +61,7 @@
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -C 200
</command>
-<file name="log/curl%TESTNUMBER.out">
+<file name="%LOGDIR/curl%TESTNUMBER.out">
012345678
012345678
012345678
diff --git a/tests/data/test1043 b/tests/data/test1043
index c728b96..310256f 100644
--- a/tests/data/test1043
+++ b/tests/data/test1043
@@ -60,7 +60,7 @@
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -C -
</command>
-<file name="log/curl%TESTNUMBER.out">
+<file name="%LOGDIR/curl%TESTNUMBER.out">
012345678
012345678
012345678
diff --git a/tests/data/test1048 b/tests/data/test1048
index 5ed267b..e81e19f 100644
--- a/tests/data/test1048
+++ b/tests/data/test1048
@@ -7,7 +7,6 @@
PASV
LIST
--interface
-IPv6
</keywords>
</info>
diff --git a/tests/data/test1049 b/tests/data/test1049
index 54d2390..165ba1e 100644
--- a/tests/data/test1049
+++ b/tests/data/test1049
@@ -35,12 +35,14 @@
#
# Verify pseudo protocol after the test has been "shot"
<verify>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 1
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER
</protocol>
</verify>
diff --git a/tests/data/test1051 b/tests/data/test1051
index 5a1cf34..fab1dbf 100644
--- a/tests/data/test1051
+++ b/tests/data/test1051
@@ -56,9 +56,9 @@
HTTP PUT with Location: following
</name>
<command>
-http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -L -T log/test%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -L -T %LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
Weird
file
to
@@ -85,7 +85,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 78
-Expect: 100-continue
Weird
file
@@ -101,7 +100,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 78
-Expect: 100-continue
Weird
file
diff --git a/tests/data/test1052 b/tests/data/test1052
index 8f8ee61..0ae56d0 100644
--- a/tests/data/test1052
+++ b/tests/data/test1052
@@ -52,9 +52,9 @@
HTTP 1.0 PUT with Location: following
</name>
<command>
-http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -0 -L -T log/test%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -0 -L -T %LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
Weird
file
to
diff --git a/tests/data/test1053 b/tests/data/test1053
index bd5de25..6211e0d 100644
--- a/tests/data/test1053
+++ b/tests/data/test1053
@@ -51,6 +51,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -58,10 +61,10 @@
HTTP RFC1867-type formposting from file with Location: following
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -L -F name=daniel -F tool=curl -F file=@log/test%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -L -F name=daniel -F tool=curl -F file=@%LOGDIR/test%TESTNUMBER.txt
</command>
# We create this file before the command is invoked!
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo-
This is a moo-
bar
diff --git a/tests/data/test1054 b/tests/data/test1054
index d8b1d45..d972579 100644
--- a/tests/data/test1054
+++ b/tests/data/test1054
@@ -47,11 +47,11 @@
<name>
HTTP POST from file with 301 redirect and --post301
</name>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
field=data
</file>
<command>
-http://%HOSTIP:%HTTPPORT/blah/%TESTNUMBER -L -d @log/test%TESTNUMBER.txt --post301
+http://%HOSTIP:%HTTPPORT/blah/%TESTNUMBER -L -d @%LOGDIR/test%TESTNUMBER.txt --post301
</command>
</client>
diff --git a/tests/data/test1055 b/tests/data/test1055
index f6f3753..9370680 100644
--- a/tests/data/test1055
+++ b/tests/data/test1055
@@ -36,9 +36,9 @@
HTTP PUT Location: redirect to FTP URL
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -L -T log/test%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -L -T %LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
Weird
file
to
@@ -60,7 +60,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 78
-Expect: 100-continue
Weird
file
diff --git a/tests/data/test1063 b/tests/data/test1063
index ca1ba14..ae9922a 100644
--- a/tests/data/test1063
+++ b/tests/data/test1063
@@ -28,9 +28,9 @@
# This range value is 2**32+7, which will be truncated to the valid value 7
# if the large file support is not working correctly
<command>
--r 4294967303- file://localhost%FILE_PWD/log/test%TESTNUMBER.txt
+-r 4294967303- file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
1234567890
1234567890
</file>
diff --git a/tests/data/test1064 b/tests/data/test1064
index 1f5b452..2984866 100644
--- a/tests/data/test1064
+++ b/tests/data/test1064
@@ -35,9 +35,9 @@
HTTP PUT twice
</name>
<command>
--H "Expect:" -T log/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload1 -T log/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER0002.upload2
+-H "Expect:" -T %LOGDIR/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload1 -T %LOGDIR/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER0002.upload2
</command>
-<file name="log/%TESTNUMBER">
+<file name="%LOGDIR/%TESTNUMBER">
test
</file>
</client>
diff --git a/tests/data/test1065 b/tests/data/test1065
index 02e9a85..bd4be88 100644
--- a/tests/data/test1065
+++ b/tests/data/test1065
@@ -36,9 +36,9 @@
HTTP PUT with one file but two URLs
</name>
<command>
--H "Expect:" -T log/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload1 http://%HOSTIP:%HTTPPORT/%TESTNUMBER0002.url2
+-H "Expect:" -T %LOGDIR/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER.upload1 http://%HOSTIP:%HTTPPORT/%TESTNUMBER0002.url2
</command>
-<file name="log/%TESTNUMBER">
+<file name="%LOGDIR/%TESTNUMBER">
test
</file>
</client>
diff --git a/tests/data/test107 b/tests/data/test107
index 911de45..5feffac 100644
--- a/tests/data/test107
+++ b/tests/data/test107
@@ -15,7 +15,7 @@
<name>
FTP PASV upload file
</name>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
data
to
see
@@ -24,7 +24,7 @@
so does it?
</file>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt
</command>
</client>
diff --git a/tests/data/test1070 b/tests/data/test1070
index 3e4d37a..ce88a1f 100644
--- a/tests/data/test1070
+++ b/tests/data/test1070
@@ -32,9 +32,9 @@
HTTP POST with server closing connection before (all) data is received
</name>
<command>
- -d @log/input%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER -H "Expect: 100-continue"
+ -d @%LOGDIR/input%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER -H "Expect: 100-continue"
</command>
-<file name="log/input%TESTNUMBER">
+<file name="%LOGDIR/input%TESTNUMBER">
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. We create this file
rather large (larger than your typical TCP packet) so that not all of it can nor
diff --git a/tests/data/test1071 b/tests/data/test1071
index 6c69472..568471e 100644
--- a/tests/data/test1071
+++ b/tests/data/test1071
@@ -73,9 +73,9 @@
Downgraded HTTP PUT to HTTP 1.0 with authorization
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T log/put%TESTNUMBER -u testuser:testpass --anyauth
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T %LOGDIR/put%TESTNUMBER -u testuser:testpass --anyauth
</command>
-<file name="log/put%TESTNUMBER">
+<file name="%LOGDIR/put%TESTNUMBER">
This is data we upload with PUT
a second line
line three
@@ -91,7 +91,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 85
-Expect: 100-continue
This is data we upload with PUT
a second line
diff --git a/tests/data/test1074 b/tests/data/test1074
index 55a956e..08ff507 100644
--- a/tests/data/test1074
+++ b/tests/data/test1074
@@ -4,6 +4,7 @@
HTTP
HTTP GET
HTTP/1.0
+DELAY
</keywords>
</info>
diff --git a/tests/data/test1075 b/tests/data/test1075
index 2d111f2..2dac5bf 100644
--- a/tests/data/test1075
+++ b/tests/data/test1075
@@ -52,9 +52,9 @@
HTTP PUT with --anyauth authorization (picking Basic)
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T log/put%TESTNUMBER -u testuser:testpass --anyauth
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T %LOGDIR/put%TESTNUMBER -u testuser:testpass --anyauth
</command>
-<file name="log/put%TESTNUMBER">
+<file name="%LOGDIR/put%TESTNUMBER">
This is data we upload with PUT
a second line
line three
@@ -70,7 +70,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 85
-Expect: 100-continue
This is data we upload with PUT
a second line
@@ -82,7 +81,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 85
-Expect: 100-continue
This is data we upload with PUT
a second line
diff --git a/tests/data/test1078 b/tests/data/test1078
index 6f303d0..2e1defa 100644
--- a/tests/data/test1078
+++ b/tests/data/test1078
@@ -43,7 +43,7 @@
HTTP 1.0 CONNECT with proxytunnel and downgrade GET to HTTP/1.0
</name>
<command>
---proxy1.0 %HOSTIP:%PROXYPORT -p http://%HOSTIP.%TESTNUMBER:%HTTPPORT/we/want/that/page/%TESTNUMBER http://%HOSTIP.%TESTNUMBER:%HTTPPORT/we/want/that/page/%TESTNUMBER
+--proxy1.0 %HOSTIP:%PROXYPORT -p http://%HOSTIP:%HTTPPORT/we/want/that/page/%TESTNUMBER http://%HOSTIP:%HTTPPORT/we/want/that/page/%TESTNUMBER
</command>
<features>
proxy
@@ -54,20 +54,20 @@
# Verify data after the test has been "shot"
<verify>
<proxy>
-CONNECT %HOSTIP.%TESTNUMBER:%HTTPPORT HTTP/1.0
-Host: %HOSTIP.%TESTNUMBER:%HTTPPORT
+CONNECT %HOSTIP:%HTTPPORT HTTP/1.0
+Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Proxy-Connection: Keep-Alive
</proxy>
<protocol>
GET /we/want/that/page/%TESTNUMBER HTTP/1.1
-Host: %HOSTIP.%TESTNUMBER:%HTTPPORT
+Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
GET /we/want/that/page/%TESTNUMBER HTTP/1.0
-Host: %HOSTIP.%TESTNUMBER:%HTTPPORT
+Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
diff --git a/tests/data/test108 b/tests/data/test108
index 6f6e3c8..7efc748 100644
--- a/tests/data/test108
+++ b/tests/data/test108
@@ -21,9 +21,9 @@
FTP PORT upload with CWD
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/CWD/STOR/RETR/%TESTNUMBER -T log/upload%TESTNUMBER -P -
+ftp://%HOSTIP:%FTPPORT/CWD/STOR/RETR/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER -P -
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Moooooooooooo
upload this
</file>
diff --git a/tests/data/test1086 b/tests/data/test1086
index f081ebd..18b4641 100644
--- a/tests/data/test1086
+++ b/tests/data/test1086
@@ -6,6 +6,7 @@
RETR
timeout
FAILURE
+SLOWDOWN
flaky
</keywords>
</info>
diff --git a/tests/data/test109 b/tests/data/test109
index 739e90b..baab37b 100644
--- a/tests/data/test109
+++ b/tests/data/test109
@@ -21,9 +21,9 @@
FTP PASV upload append
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/upload%TESTNUMBER --append
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER --append
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Moooooooooooo
upload this
</file>
diff --git a/tests/data/test1093 b/tests/data/test1093
index 4fbc7b8..3d90341 100644
--- a/tests/data/test1093
+++ b/tests/data/test1093
@@ -35,12 +35,14 @@
#
# Verify pseudo protocol after the test has been "shot"
<verify>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 1
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER
</protocol>
</verify>
diff --git a/tests/data/test1094 b/tests/data/test1094
index dd1452b..1b2a585 100644
--- a/tests/data/test1094
+++ b/tests/data/test1094
@@ -41,12 +41,14 @@
#
# Verify pseudo protocol after the test has been "shot"
<verify>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 1
mode = netascii
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER
</protocol>
</verify>
diff --git a/tests/data/test1099 b/tests/data/test1099
index 7709991..34cd991 100644
--- a/tests/data/test1099
+++ b/tests/data/test1099
@@ -30,18 +30,19 @@
#
# Verify pseudo protocol after the test has been "shot"
<verify>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 1
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = an/invalid-file
opcode = 1
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER
</protocol>
<stdout>
diff --git a/tests/data/test1104 b/tests/data/test1104
index 27c4300..2401be9 100644
--- a/tests/data/test1104
+++ b/tests/data/test1104
@@ -59,9 +59,10 @@
HTTP cookie expiry date at Jan 1 00:00:00 GMT 1970
</name>
<command>
-http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -L -x %HOSTIP:%HTTPPORT -c log/cookies%TESTNUMBER.jar
+http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -L -x %HOSTIP:%HTTPPORT -c %LOGDIR/cookies%TESTNUMBER.jar
</command>
<features>
+cookies
proxy
</features>
</client>
diff --git a/tests/data/test1105 b/tests/data/test1105
index a06a051..6434ab2 100644
--- a/tests/data/test1105
+++ b/tests/data/test1105
@@ -11,15 +11,18 @@
# Server-side
<reply>
<data>
-HTTP/1.1 200 OK
-Date: Tue, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake
-Content-Type: text/html
-Funny-head: yesyes swsclose
-Set-Cookie: foobar=name;
-Set-Cookie: mismatch=this; domain=127.0.0.1; path="/silly/";
-Set-Cookie: partmatch=present; domain=.0.0.1; path=/;
-
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Funny-head: yesyes swsclose
+Set-Cookie: foobar=name;
+Set-Cookie: mismatch=this; domain=127.0.0.1; path="/silly/";
+Set-Cookie: partmatch=present; domain=.0.0.1; path=/;
+Set-Cookie: foo bar=barfoo
+Set-Cookie: bar foo=
+Set-Cookie: bar=foo bar
+
</data>
</reply>
@@ -32,11 +35,14 @@
HTTP with cookie parser and header recording
</name>
<command>
-"http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER?parm1=this*that/other/thing&parm2=foobar/%TESTNUMBER" -c log/cookie%TESTNUMBER.txt -d "userid=myname&password=mypassword"
+"http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER?parm1=this*that/other/thing&parm2=foobar/%TESTNUMBER" -c %LOGDIR/cookie%TESTNUMBER.txt -d "userid=myname&password=mypassword"
</command>
<precheck>
perl -e "print 'Test requires default test server host' if ( '%HOSTIP' ne '127.0.0.1' );"
</precheck>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
@@ -51,7 +57,7 @@
userid=myname&password=mypassword
</protocol>
-<file name="log/cookie%TESTNUMBER.txt" mode="text">
+<file name="%LOGDIR/cookie%TESTNUMBER.txt" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test1112 b/tests/data/test1112
index b918c73..7eefb61 100644
--- a/tests/data/test1112
+++ b/tests/data/test1112
@@ -6,6 +6,7 @@
RETR
timeout
FAILURE
+SLOWDOWN
</keywords>
</info>
diff --git a/tests/data/test1116 b/tests/data/test1116
index 3543e75..b106c07 100644
--- a/tests/data/test1116
+++ b/tests/data/test1116
@@ -4,6 +4,7 @@
HTTP
HTTP GET
chunked Transfer-Encoding
+DELAY
</keywords>
</info>
#
@@ -56,7 +57,7 @@
HTTP GET with chunked trailer without Trailer:
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -D %LOGDIR/heads%TESTNUMBER
</command>
</client>
@@ -70,7 +71,7 @@
Accept: */*
</protocol>
-<file name="log/heads%TESTNUMBER">
+<file name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 funky chunky!
Server: fakeit/0.9 fakeitbad/1.0
Transfer-Encoding: chunked
diff --git a/tests/data/test1117 b/tests/data/test1117
index 405aa86..b2b5a3b 100644
--- a/tests/data/test1117
+++ b/tests/data/test1117
@@ -4,6 +4,7 @@
HTTP
HTTP GET
Range
+DELAY
</keywords>
</info>
diff --git a/tests/data/test112 b/tests/data/test112
index 6d23c44..c48506c 100644
--- a/tests/data/test112
+++ b/tests/data/test112
@@ -20,9 +20,9 @@
FTP PASV upload resume
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -C 40
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER -C 40
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
this is the *****crap******** that we're gonna upload
worx?
diff --git a/tests/data/test1120 b/tests/data/test1120
index c7cd275..06d0b90 100644
--- a/tests/data/test1120
+++ b/tests/data/test1120
@@ -5,6 +5,8 @@
PORT
RETR
421
+timeout
+FAILURE
</keywords>
</info>
# Server-side
diff --git a/tests/data/test1129 b/tests/data/test1129
index df4a9b0..2591be6 100644
--- a/tests/data/test1129
+++ b/tests/data/test1129
@@ -41,7 +41,7 @@
# Client-side
<client>
# 1053700 x 'x'
-<file name="log/file%TESTNUMBER">
+<file name="%LOGDIR/file%TESTNUMBER">
%repeat[1053700 x x]%
</file>
<server>
@@ -51,7 +51,7 @@
HTTP POST expect 100-continue with a 404
</name>
<command option="no-output">
--d @log/file%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001
+-d @%LOGDIR/file%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001
</command>
</client>
diff --git a/tests/data/test1130 b/tests/data/test1130
index 50ebedd..1b43432 100644
--- a/tests/data/test1130
+++ b/tests/data/test1130
@@ -41,7 +41,7 @@
# Client-side
<client>
# 100 x 'x'
-<file name="log/file%TESTNUMBER">
+<file name="%LOGDIR/file%TESTNUMBER">
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
</file>
<server>
@@ -51,7 +51,7 @@
HTTP POST forced expect 100-continue with a 404
</name>
<command option="no-output">
--d @log/file%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 -H "Expect: 100-continue"
+-d @%LOGDIR/file%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 -H "Expect: 100-continue"
</command>
</client>
diff --git a/tests/data/test1131 b/tests/data/test1131
index 8ead289..13140da 100644
--- a/tests/data/test1131
+++ b/tests/data/test1131
@@ -41,7 +41,7 @@
# Client-side
<client>
# 100 x 'x'
-<file name="log/file%TESTNUMBER">
+<file name="%LOGDIR/file%TESTNUMBER">
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
</file>
<server>
@@ -51,7 +51,7 @@
HTTP PUT expect 100-continue with a 400
</name>
<command option="no-output">
--T log/file%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T log/file%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001
+-H "Expect: 100-continue" -T %LOGDIR/file%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T %LOGDIR/file%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001
</command>
</client>
@@ -79,15 +79,15 @@
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
-Content-Length: 100
Expect: 100-continue
+Content-Length: 100
PUT /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
-Content-Length: 100
Expect: 100-continue
+Content-Length: 100
</protocol>
</verify>
diff --git a/tests/data/test1133 b/tests/data/test1133
index cd15f54..f79ece9 100644
--- a/tests/data/test1133
+++ b/tests/data/test1133
@@ -19,6 +19,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -26,10 +29,10 @@
HTTP RFC1867-type formposting with filename/data contains ',', ';', '"'
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F "file=@\"log/test%TESTNUMBER,and;.txt\";type=mo/foo;filename=\"faker,and;.txt\"" -F 'file2=@"log/test%TESTNUMBER,and;.txt"' -F 'file3=@"log/test%TESTNUMBER,and;.txt";type=m/f,"log/test%TESTNUMBER,and;.txt"' -F a="{\"field1\":\"value1\",\"field2\":\"value2\"}" -F 'b=" \\value1;type=\"whatever\" "; type=text/foo; charset=utf-8 ; filename=param_b'
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F "file=@\"%LOGDIR/test%TESTNUMBER,and;.txt\";type=mo/foo;filename=\"faker,and;.txt\"" -F 'file2=@"%LOGDIR/test%TESTNUMBER,and;.txt"' -F 'file3=@"%LOGDIR/test%TESTNUMBER,and;.txt";type=m/f,"%LOGDIR/test%TESTNUMBER,and;.txt"' -F a="{\"field1\":\"value1\",\"field2\":\"value2\"}" -F 'b=" \\value1;type=\"whatever\" "; type=text/foo; charset=utf-8 ; filename=param_b'
</command>
# We create this file before the command is invoked!
-<file name="log/test%TESTNUMBER,and;.txt">
+<file name="%LOGDIR/test%TESTNUMBER,and;.txt">
foo bar
This is a bar foo
bar
diff --git a/tests/data/test1136 b/tests/data/test1136
index 1ce5336..a820792 100644
--- a/tests/data/test1136
+++ b/tests/data/test1136
@@ -45,14 +45,14 @@
TZ=GMT
</setenv>
<command>
-http://www.example.ck/%TESTNUMBER http://www.ck/%TESTNUMBER http://z-1.compute-1.amazonaws.com/%TESTNUMBER -b none -c log/jar%TESTNUMBER.txt -x %HOSTIP:%HTTPPORT
+http://www.example.ck/%TESTNUMBER http://www.ck/%TESTNUMBER http://z-1.compute-1.amazonaws.com/%TESTNUMBER -b none -c %LOGDIR/jar%TESTNUMBER.txt -x %HOSTIP:%HTTPPORT
</command>
</client>
# Verify data after the test has been "shot"
<verify>
-<file name="log/jar%TESTNUMBER.txt" mode="text">
+<file name="%LOGDIR/jar%TESTNUMBER.txt" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test1145 b/tests/data/test1145
index ce85552..570197e 100644
--- a/tests/data/test1145
+++ b/tests/data/test1145
@@ -19,9 +19,9 @@
# This command should not succeed since we only accept
# file:/// file://localhost/ file://127.0.0.1/
<command>
-file://bad-host%PWD/log/test%TESTNUMBER.txt
+file://bad-host%PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar
bar
diff --git a/tests/data/test1146 b/tests/data/test1146
index 0278ab8..55245bc 100644
--- a/tests/data/test1146
+++ b/tests/data/test1146
@@ -25,9 +25,9 @@
--proto-default file
</name>
<command option="no-include">
---proto-default file %PWD/log/test%TESTNUMBER.txt
+--proto-default file %PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar
bar
diff --git a/tests/data/test1147 b/tests/data/test1147
index 78cf49a..81c33a8 100644
--- a/tests/data/test1147
+++ b/tests/data/test1147
@@ -35,7 +35,7 @@
<name>
Get -H headers from a file
</name>
-<file name="log/heads%TESTNUMBER.txt">
+<file name="%LOGDIR/heads%TESTNUMBER.txt">
One: 1
Two: 2
no-colon
@@ -46,7 +46,7 @@
User-Agent:
</file>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -H @log/heads%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -H @%LOGDIR/heads%TESTNUMBER.txt
</command>
</client>
diff --git a/tests/data/test1148 b/tests/data/test1148
index 658cfca..dbd2592 100644
--- a/tests/data/test1148
+++ b/tests/data/test1148
@@ -35,7 +35,7 @@
progress-bar
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -# --stderr log/stderrlog%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -# --stderr %LOGDIR/stderrlog%TESTNUMBER
</command>
<setenv>
LC_ALL=
@@ -56,7 +56,7 @@
# Check that the progress finished at 100% and has the right bar width.
# Note the dot in 100.0% is regex to match any character since different
# locales use different separators.
-<file name="log/stderrlog%TESTNUMBER" mode="text">
+<file name="%LOGDIR/stderrlog%TESTNUMBER" mode="text">
correct
</file>
<stripfile>
diff --git a/tests/data/test1151 b/tests/data/test1151
index c31382c..bb24d1b 100644
--- a/tests/data/test1151
+++ b/tests/data/test1151
@@ -39,8 +39,11 @@
HTTP with too long cookies
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -c log/cookies%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -c %LOGDIR/cookies%TESTNUMBER.txt
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
@@ -52,7 +55,7 @@
Accept: */*
</protocol>
-<file name="log/cookies%TESTNUMBER.txt" mode="text">
+<file name="%LOGDIR/cookies%TESTNUMBER.txt" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test1155 b/tests/data/test1155
index 65d76b6..dbaf344 100644
--- a/tests/data/test1155
+++ b/tests/data/test1155
@@ -28,8 +28,11 @@
HTTP cookie with parameter word as name
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -c log/cookies%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -c %LOGDIR/cookies%TESTNUMBER.txt
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
@@ -41,7 +44,7 @@
Accept: */*
</protocol>
-<file name="log/cookies%TESTNUMBER.txt" mode="text">
+<file name="%LOGDIR/cookies%TESTNUMBER.txt" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test1157 b/tests/data/test1157
index 8c0bcc3..53f1b99 100644
--- a/tests/data/test1157
+++ b/tests/data/test1157
@@ -35,10 +35,10 @@
<name>
Get -H headers from empty file
</name>
-<file name="log/heads%TESTNUMBER.txt">
+<file name="%LOGDIR/heads%TESTNUMBER.txt">
</file>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -H @log/heads%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -H @%LOGDIR/heads%TESTNUMBER.txt
</command>
</client>
diff --git a/tests/data/test1158 b/tests/data/test1158
index 3771f5d..fa6f7b4 100644
--- a/tests/data/test1158
+++ b/tests/data/test1158
@@ -19,6 +19,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -26,13 +29,13 @@
HTTP RFC1867-type formposting with filename containing '"'
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F "file=@\"log/test%TESTNUMBER\\\".txt\";type=mo/foo;filename=\"test%TESTNUMBER\\\".txt\"" -F 'file2=@"log/test%TESTNUMBER\".txt"' -F 'file3=@"log/test%TESTNUMBER\".txt";type=m/f,"log/test%TESTNUMBER\".txt"'
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F "file=@\"%LOGDIR/test%TESTNUMBER\\\".txt\";type=mo/foo;filename=\"test%TESTNUMBER\\\".txt\"" -F 'file2=@"%LOGDIR/test%TESTNUMBER\".txt"' -F 'file3=@"%LOGDIR/test%TESTNUMBER\".txt";type=m/f,"%LOGDIR/test%TESTNUMBER\".txt"'
</command>
<precheck>
perl -e "print 'Test requires a system supporting double quotes in file names' if ($^O eq 'msys');"
</precheck>
# We create this file before the command is invoked!
-<file name=log/test%TESTNUMBER".txt>
+<file name=%LOGDIR/test%TESTNUMBER".txt>
foo bar
This is a bar foo
bar
diff --git a/tests/data/test1160 b/tests/data/test1160
index e24ce93..e683598 100644
--- a/tests/data/test1160
+++ b/tests/data/test1160
@@ -29,8 +29,11 @@
HTTP with long funny format cookie
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -c log/cookies%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -c %LOGDIR/cookies%TESTNUMBER.txt
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
@@ -42,7 +45,7 @@
Accept: */*
</protocol>
-<file name="log/cookies%TESTNUMBER.txt" mode="text">
+<file name="%LOGDIR/cookies%TESTNUMBER.txt" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test1161 b/tests/data/test1161
index 89c1e65..3b1a2fd 100644
--- a/tests/data/test1161
+++ b/tests/data/test1161
@@ -28,8 +28,11 @@
HTTP cookie with path set twice
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -c log/cookies%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -c %LOGDIR/cookies%TESTNUMBER.txt
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
@@ -41,7 +44,7 @@
Accept: */*
</protocol>
-<file name="log/cookies%TESTNUMBER.txt" mode="text">
+<file name="%LOGDIR/cookies%TESTNUMBER.txt" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test1169 b/tests/data/test1169
index e7f7df4..bba5d13 100644
--- a/tests/data/test1169
+++ b/tests/data/test1169
@@ -16,14 +16,13 @@
</name>
<command type="perl">
-%SRCDIR/runtests.pl -L %SRCDIR/log/test1196-library.pl
+%SRCDIR/runtests.pl -L %PWD/%LOGDIR/test%TESTNUMBER-library.pl
</command>
# Create a simple perl snippet that lets runtests.pl
# exit with a code we can check.
-<precheck>
-echo 'exit 123' > %SRCDIR/log/test1196-library.pl
-</precheck>
-
+<file name="%LOGDIR/test%TESTNUMBER-library.pl">
+exit 123
+</file>
</client>
<verify>
diff --git a/tests/data/test1176 b/tests/data/test1176
index d2471e1..9ad1150 100644
--- a/tests/data/test1176
+++ b/tests/data/test1176
@@ -34,7 +34,7 @@
--output using #0
</name>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o 'log/base-#0'
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o '%LOGDIR/base-#0'
</command>
</client>
@@ -48,7 +48,7 @@
Accept: */*
</protocol>
-<file name="log/base-#0">
+<file name="%LOGDIR/base-#0">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test1177 b/tests/data/test1177
index 85b520c..29ddf3f 100644
--- a/tests/data/test1177
+++ b/tests/data/test1177
@@ -14,11 +14,11 @@
</server>
<name>
-Verify that CURL_VERSION_* in headers and docs are in sync
+Verify that feature names and CURL_VERSION_* in lib and docs are in sync
</name>
<command type="perl">
-%SRCDIR/version-scan.pl %SRCDIR/../docs/libcurl/curl_version_info.3 %SRCDIR/../include/curl/curl.h
+%SRCDIR/version-scan.pl %SRCDIR/../docs/libcurl/curl_version_info.3 %SRCDIR/../include/curl/curl.h %SRCDIR/../lib/version.c
</command>
</client>
diff --git a/tests/data/test1182 b/tests/data/test1182
index 105d3d1..d1b8fb0 100644
--- a/tests/data/test1182
+++ b/tests/data/test1182
@@ -16,13 +16,13 @@
</name>
<command type="perl">
-%SRCDIR/runtests.pl -o TESTDIR=%SRCDIR/log/data -o LOGDIR=%SRCDIR/log/log -E %SRCDIR/log/test%TESTNUMBER-exclude-file 1
+%SRCDIR/runtests.pl -o TESTDIR=%LOGDIR/data -o LOGDIR=%LOGDIR/log -E %LOGDIR/test%TESTNUMBER-exclude-file 1
</command>
<precheck>
-mkdir %SRCDIR/log/data ; mkdir %SRCDIR/log/log; cp %SRCDIR/data/test1 %SRCDIR/log/data; echo 'test:1:Test should not run for unit test %TESTNUMBER' > %SRCDIR/log/test%TESTNUMBER-exclude-file
+mkdir %LOGDIR/data ; mkdir %LOGDIR/log; cp %SRCDIR/data/test1 %LOGDIR/data; echo 'test:1:Test should not run for unit test %TESTNUMBER' > %LOGDIR/test%TESTNUMBER-exclude-file
</precheck>
<postcheck>
-grep -q "Test should not run for unit test %TESTNUMBER" %SRCDIR/log/stdout%TESTNUMBER
+grep -q "Test should not run for unit test %TESTNUMBER" %LOGDIR/stdout%TESTNUMBER
</postcheck>
</client>
diff --git a/tests/data/test1185 b/tests/data/test1185
index eb672ef..94c3be1 100644
--- a/tests/data/test1185
+++ b/tests/data/test1185
@@ -16,9 +16,9 @@
</name>
<command type="perl">
-%SRCDIR/../scripts/checksrc.pl log/code%TESTNUMBER.c
+%SRCDIR/../scripts/checksrc.pl %LOGDIR/code%TESTNUMBER.c
</command>
-<file name="log/code%TESTNUMBER.c">
+<file name="%LOGDIR/code%TESTNUMBER.c">
/* test source code
* Violate each rule at least once.
**/
@@ -86,93 +86,93 @@
# Verify data after the test has been "shot"
<verify>
<stdout>
-./log/code1185.c:4:82: warning: Longer than 79 columns (LONGLINE)
+./%LOGDIR/code1185.c:4:82: warning: Longer than 79 columns (LONGLINE)
int hello; /*------------------------------------------------------------------*/
-./log/code1185.c:5:4: error: Contains TAB character (TABS)
+./%LOGDIR/code1185.c:5:4: error: Contains TAB character (TABS)
int tab;
^
-./log/code1185.c:7:13: warning: func with space (SPACEBEFOREPAREN)
+./%LOGDIR/code1185.c:7:13: warning: func with space (SPACEBEFOREPAREN)
int a = func ();
^
-./log/code1185.c:8:14: warning: space after open parenthesis (SPACEAFTERPAREN)
+./%LOGDIR/code1185.c:8:14: warning: space after open parenthesis (SPACEAFTERPAREN)
int b = func( b);
^
-./log/code1185.c:9:16: warning: space before close parenthesis (SPACEBEFORECLOSE)
+./%LOGDIR/code1185.c:9:16: warning: space before close parenthesis (SPACEBEFORECLOSE)
int b = func(b );
^
-./log/code1185.c:10:11: warning: space before comma (SPACEBEFORECOMMA)
+./%LOGDIR/code1185.c:10:11: warning: space before comma (SPACEBEFORECOMMA)
func(a, b , c);
^
-./log/code1185.c:14:9: warning: return without space before paren (RETURNNOSPACE)
+./%LOGDIR/code1185.c:14:9: warning: return without space before paren (RETURNNOSPACE)
return(2);
^
-./log/code1185.c:16:11: warning: comma without following space (COMMANOSPACE)
+./%LOGDIR/code1185.c:16:11: warning: comma without following space (COMMANOSPACE)
func(a, b,c);
^
-./log/code1185.c:18:12: warning: wrongly placed open brace (BRACEPOS)
+./%LOGDIR/code1185.c:18:12: warning: wrongly placed open brace (BRACEPOS)
if(a == 2) {
^
-./log/code1185.c:20:1: warning: else after closing brace on same line (BRACEELSE)
+./%LOGDIR/code1185.c:20:1: warning: else after closing brace on same line (BRACEELSE)
} else {
^
-./log/code1185.c:24:11: warning: missing space after close paren (PARENBRACE)
+./%LOGDIR/code1185.c:24:11: warning: missing space after close paren (PARENBRACE)
if(a == 2){
^
-./log/code1185.c:28:7: warning: no space before semicolon (SPACESEMICOLON)
+./%LOGDIR/code1185.c:28:7: warning: no space before semicolon (SPACESEMICOLON)
func() ;
^
-./log/code1185.c:30:5: warning: use of sprintf is banned (BANNEDFUNC)
+./%LOGDIR/code1185.c:30:5: warning: use of sprintf is banned (BANNEDFUNC)
a = sprintf(buffer, "%s", moo);
^
-./log/code1185.c:32:11: warning: use of non-binary fopen without FOPEN_* macro: r (FOPENMODE)
+./%LOGDIR/code1185.c:32:11: warning: use of non-binary fopen without FOPEN_* macro: r (FOPENMODE)
FILE *f = fopen("filename", "r");
^
-./log/code1185.c:34:30: warning: wrongly placed open brace (BRACEPOS)
+./%LOGDIR/code1185.c:34:30: warning: wrongly placed open brace (BRACEPOS)
void startfunc(int a, int b) {
^
-./log/code1185.c:39:6: warning: not indented 2 steps (uses 4) (INDENTATION)
+./%LOGDIR/code1185.c:39:6: warning: not indented 2 steps (uses 4) (INDENTATION)
func(1);
^
-./log/code1185.c:42:8: warning: space after declarative asterisk (ASTERISKSPACE)
+./%LOGDIR/code1185.c:42:8: warning: space after declarative asterisk (ASTERISKSPACE)
char * name = "hello";
^
-./log/code1185.c:43:7: warning: space after declarative asterisk (ASTERISKSPACE)
+./%LOGDIR/code1185.c:43:7: warning: space after declarative asterisk (ASTERISKSPACE)
char* name = "hello";
^
-./log/code1185.c:43:6: warning: no space before asterisk (ASTERISKNOSPACE)
+./%LOGDIR/code1185.c:43:6: warning: no space before asterisk (ASTERISKNOSPACE)
char* name = "hello";
^
-./log/code1185.c:45:10: warning: no space after equals sign (EQUALSNOSPACE)
+./%LOGDIR/code1185.c:45:10: warning: no space after equals sign (EQUALSNOSPACE)
int foo=bar;
^
-./log/code1185.c:46:9: warning: no space before equals sign (NOSPACEEQUALS)
+./%LOGDIR/code1185.c:46:9: warning: no space before equals sign (NOSPACEEQUALS)
int foo= bar;
^
-./log/code1185.c:48:16: warning: no space after semicolon (SEMINOSPACE)
+./%LOGDIR/code1185.c:48:16: warning: no space after semicolon (SEMINOSPACE)
int foo = bar;foo++;
^
-./log/code1185.c:49:10: warning: multiple spaces (MULTISPACE)
+./%LOGDIR/code1185.c:49:10: warning: multiple spaces (MULTISPACE)
for(;;) {
^
-./log/code1185.c:50:2: warning: not indented 2 steps (uses 0) (INDENTATION)
+./%LOGDIR/code1185.c:50:2: warning: not indented 2 steps (uses 0) (INDENTATION)
}
^
-./log/code1185.c:52:16: warning: sizeof without parenthesis (SIZEOFNOPAREN)
+./%LOGDIR/code1185.c:52:16: warning: sizeof without parenthesis (SIZEOFNOPAREN)
int a = sizeof int;
^
-./log/code1185.c:53:10: warning: use of snprintf is banned (SNPRINTF)
+./%LOGDIR/code1185.c:53:10: warning: use of snprintf is banned (SNPRINTF)
int a = snprintf(buffer, sizeof(buffer), "%d", 99);
^
-./log/code1185.c:55:7: warning: conditional block on the same line (ONELINECONDITION)
+./%LOGDIR/code1185.c:55:7: warning: conditional block on the same line (ONELINECONDITION)
if(a) b++;
^
-./log/code1185.c:57:2: warning: // comment (CPPCOMMENTS)
+./%LOGDIR/code1185.c:57:2: warning: // comment (CPPCOMMENTS)
// CPP comment?
^
-./log/code1185.c:1:1: error: Missing copyright statement (COPYRIGHT)
+./%LOGDIR/code1185.c:1:1: error: Missing copyright statement (COPYRIGHT)
^
-./log/code1185.c:1:1: error: Missing closing comment (OPENCOMMENT)
+./%LOGDIR/code1185.c:1:1: error: Missing closing comment (OPENCOMMENT)
^
checksrc: 0 errors and 30 warnings
diff --git a/tests/data/test1186 b/tests/data/test1186
index e4662b6..12faf09 100644
--- a/tests/data/test1186
+++ b/tests/data/test1186
@@ -19,6 +19,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -26,13 +29,13 @@
Multipart formposting with backslash-escaping filename containing '"'
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --form-escape -F "file=@\"log/test%TESTNUMBER\\\".txt\";type=mo/foo;filename=\"test%TESTNUMBER\\\".txt\"" -F 'file2=@"log/test%TESTNUMBER\".txt"' -F 'file3=@"log/test%TESTNUMBER\".txt";type=m/f,"log/test%TESTNUMBER\".txt"'
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --form-escape -F "file=@\"%LOGDIR/test%TESTNUMBER\\\".txt\";type=mo/foo;filename=\"test%TESTNUMBER\\\".txt\"" -F 'file2=@"%LOGDIR/test%TESTNUMBER\".txt"' -F 'file3=@"%LOGDIR/test%TESTNUMBER\".txt";type=m/f,"%LOGDIR/test%TESTNUMBER\".txt"'
</command>
<precheck>
perl -e "print 'Test requires a system supporting double quotes in file names' if ($^O eq 'msys');"
</precheck>
# We create this file before the command is invoked!
-<file name=log/test%TESTNUMBER".txt>
+<file name=%LOGDIR/test%TESTNUMBER".txt>
foo bar
This is a bar foo
bar
diff --git a/tests/data/test1187 b/tests/data/test1187
index 53abf90..a8be5c1 100644
--- a/tests/data/test1187
+++ b/tests/data/test1187
@@ -14,6 +14,9 @@
#
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
smtp
</server>
diff --git a/tests/data/test1189 b/tests/data/test1189
index 229e443..cacac5d 100644
--- a/tests/data/test1189
+++ b/tests/data/test1189
@@ -19,6 +19,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -26,10 +29,10 @@
Multipart formposting with backslash-escaping of name= and filename=
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --form-escape -F name=daniel -F tool=curl --form-string "str1=@literal" --form-string "str2=<verbatim;type=xxx/yyy" -F "file=@log/test%TESTNUMBER.txt;type=moo/foobar;filename=fakerfile" -F file2=@log/test%TESTNUMBER.txt -F "file3=@\"log/test%TESTNUMBER.txt\";type=mo/foo;filename=\"f\\\\\\\\ak\\\\\\er,\\\\an\\d;.t\\\"xt\"" -F 'file4=@"log/test%TESTNUMBER.txt"; filename="A\\AA\"\"\\\"ZZZ"'
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --form-escape -F name=daniel -F tool=curl --form-string "str1=@literal" --form-string "str2=<verbatim;type=xxx/yyy" -F "file=@%LOGDIR/test%TESTNUMBER.txt;type=moo/foobar;filename=fakerfile" -F file2=@%LOGDIR/test%TESTNUMBER.txt -F "file3=@\"%LOGDIR/test%TESTNUMBER.txt\";type=mo/foo;filename=\"f\\\\\\\\ak\\\\\\er,\\\\an\\d;.t\\\"xt\"" -F 'file4=@"%LOGDIR/test%TESTNUMBER.txt"; filename="A\\AA\"\"\\\"ZZZ"'
</command>
# We create this file before the command is invoked!
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo bar
This is a bar foo
bar
diff --git a/tests/data/test1193 b/tests/data/test1193
index bed10b2..531efa2 100644
--- a/tests/data/test1193
+++ b/tests/data/test1193
@@ -26,9 +26,9 @@
MQTT PUBLISH 2k payload
</name>
<command option="binary-trace">
-mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER -d @log/payload%TESTNUMBER
+mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER -d @%LOGDIR/payload%TESTNUMBER
</command>
-<file name="log/payload%TESTNUMBER">
+<file name="%LOGDIR/payload%TESTNUMBER">
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
diff --git a/tests/data/test1208 b/tests/data/test1208
index 47ceb64..2de619d 100644
--- a/tests/data/test1208
+++ b/tests/data/test1208
@@ -6,6 +6,8 @@
RETR
NODATACONN150
flaky
+timeout
+FAILURE
</keywords>
</info>
# Server-side
diff --git a/tests/data/test1209 b/tests/data/test1209
index 4d442d1..8a4f1f8 100644
--- a/tests/data/test1209
+++ b/tests/data/test1209
@@ -5,6 +5,8 @@
PORT
RETR
NODATACONN
+timeout
+FAILURE
</keywords>
</info>
# Server-side
diff --git a/tests/data/test1210 b/tests/data/test1210
index 037eb16..4a07147 100644
--- a/tests/data/test1210
+++ b/tests/data/test1210
@@ -36,10 +36,10 @@
HTTP GET with -J without Content-Disposition
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -O
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER?junk -J -O
</command>
</client>
@@ -47,13 +47,13 @@
# Verify data after the test has been "shot"
<verify>
<protocol>
-GET /%TESTNUMBER HTTP/1.1
+GET /%TESTNUMBER?junk HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
</protocol>
-<file name="log/%TESTNUMBER">
+<file name="%LOGDIR/%TESTNUMBER">
12345
</file>
diff --git a/tests/data/test1211 b/tests/data/test1211
index 6d31357..072aede 100644
--- a/tests/data/test1211
+++ b/tests/data/test1211
@@ -5,6 +5,8 @@
PORT
RETR
NODATACONN425
+timeout
+FAILURE
</keywords>
</info>
# Server-side
diff --git a/tests/data/test1215 b/tests/data/test1215
index 6fc59d3..31c8723 100644
--- a/tests/data/test1215
+++ b/tests/data/test1215
@@ -1,6 +1,6 @@
<testcase>
<info>
-# This test is a copy of test 67, modified to use a HTTP proxy.
+# This test is a copy of test 67, modified to use an HTTP proxy.
<keywords>
HTTP
HTTP GET
diff --git a/tests/data/test1216 b/tests/data/test1216
index 6686c75..b812f8d 100644
--- a/tests/data/test1216
+++ b/tests/data/test1216
@@ -31,15 +31,16 @@
HTTP cookie domains tailmatching the host name
</name>
<command>
-http://example.fake/c/%TESTNUMBER http://bexample.fake/c/%TESTNUMBER -b log/injar%TESTNUMBER -x %HOSTIP:%HTTPPORT
+http://example.fake/c/%TESTNUMBER http://bexample.fake/c/%TESTNUMBER -b %LOGDIR/injar%TESTNUMBER -x %HOSTIP:%HTTPPORT
</command>
-<file name="log/injar%TESTNUMBER">
+<file name="%LOGDIR/injar%TESTNUMBER">
example.fake FALSE /a FALSE 2139150993 mooo indeed
example.fake FALSE /b FALSE 0 moo1 indeed
example.fake FALSE /c FALSE 2139150993 moo2 indeed
example.fake TRUE /c FALSE 2139150993 moo3 indeed
</file>
<features>
+cookies
proxy
</features>
</client>
diff --git a/tests/data/test1218 b/tests/data/test1218
index ff80233..e176c47 100644
--- a/tests/data/test1218
+++ b/tests/data/test1218
@@ -33,6 +33,7 @@
http://example.fake/c/%TESTNUMBER http://example.fake/c/%TESTNUMBER http://bexample.fake/c/%TESTNUMBER -b nonexisting -x %HOSTIP:%HTTPPORT
</command>
<features>
+cookies
proxy
</features>
</client>
diff --git a/tests/data/test1220 b/tests/data/test1220
index 49cbf2c..d7e2ff9 100644
--- a/tests/data/test1220
+++ b/tests/data/test1220
@@ -21,9 +21,9 @@
file:// URLs with query string
</name>
<command option="no-include">
-file://localhost%FILE_PWD/log/test%TESTNUMBER.txt?a_query=foobar#afragment
+file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt?a_query=foobar#afragment
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
contents in a single file
</file>
</client>
diff --git a/tests/data/test1221 b/tests/data/test1221
new file mode 100644
index 0000000..42617e8
--- /dev/null
+++ b/tests/data/test1221
@@ -0,0 +1,53 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+--data-urlencode
+--url-query
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 I am cool swsclose
+Server: Cool server/10.0
+Content-Length: 0
+
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+--url-query with --data-urlencode
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --url-query "my name is moo[]" --url-query "yes=s i r" --url-query "v_alue@%LOGDIR/%TESTNUMBER.txt" --url-query @%LOGDIR/%TESTNUMBER.txt --url-query "+%3d%3d" --data-urlencode "start=once upon the time"
+</command>
+<file name="%LOGDIR/%TESTNUMBER.txt">
+content to _?!#$'|<>
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol nonewline="yes">
+POST /%TESTNUMBER?my+name+is+moo%5b%5d&yes=s+i+r&v_alue=content+to+_%3f%21%23%24%27%7c%3c%3e%0a&content+to+_%3f%21%23%24%27%7c%3c%3e%0a&%3d%3d HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Content-Length: 24
+Content-Type: application/x-www-form-urlencoded
+
+start=once+upon+the+time
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1222 b/tests/data/test1222
new file mode 100644
index 0000000..e65b514
--- /dev/null
+++ b/tests/data/test1222
@@ -0,0 +1,24 @@
+<testcase>
+<info>
+<keywords>
+source analysis
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+
+ <name>
+Verify deprecation statuses and versions
+ </name>
+
+<command type="perl">
+%SRCDIR/check-deprecated.pl %SRCDIR/..
+</command>
+</client>
+
+</testcase>
diff --git a/tests/data/test1228 b/tests/data/test1228
index 2a7faff..d33b742 100644
--- a/tests/data/test1228
+++ b/tests/data/test1228
@@ -32,6 +32,7 @@
http://example.fake/hoge/%TESTNUMBER http://example.fake/hogege/ -b nonexisting -x %HOSTIP:%HTTPPORT
</command>
<features>
+cookies
proxy
</features>
</client>
diff --git a/tests/data/test123 b/tests/data/test123
index 1604f0b..21d3b58 100644
--- a/tests/data/test123
+++ b/tests/data/test123
@@ -19,9 +19,9 @@
FTP upload resume with whole file already downloaded
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -C 51
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER -C 51
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
--------------------------------------------------
</file>
</client>
diff --git a/tests/data/test1232 b/tests/data/test1232
index 3f91ecf..b62a07d 100644
--- a/tests/data/test1232
+++ b/tests/data/test1232
@@ -1,6 +1,6 @@
<testcase>
<info>
-# This test is a copy of test 1231, modified to use a HTTP proxy.
+# This test is a copy of test 1231, modified to use an HTTP proxy.
<keywords>
HTTP
HTTP GET
diff --git a/tests/data/test1238 b/tests/data/test1238
index 5fbf640..3e36fbf 100644
--- a/tests/data/test1238
+++ b/tests/data/test1238
@@ -3,6 +3,9 @@
<keywords>
TFTP
TFTP RRQ
+timeout
+FAILURE
+DELAY
</keywords>
</info>
@@ -44,12 +47,14 @@
#
# Verify pseudo protocol after the test has been "shot"
<verify>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 1
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER
</protocol>
# 28 = CURLE_OPERATION_TIMEDOUT
diff --git a/tests/data/test1243 b/tests/data/test1243
index ba08a83..7f71631 100644
--- a/tests/data/test1243
+++ b/tests/data/test1243
@@ -16,9 +16,9 @@
TFTP send without TFTP options requests
</name>
<command>
--T log/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT// --tftp-no-options
+-T %LOGDIR/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT// --tftp-no-options
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
a chunk of
data
sent
diff --git a/tests/data/test1258 b/tests/data/test1258
index a4cef15..5a4ce0b 100644
--- a/tests/data/test1258
+++ b/tests/data/test1258
@@ -32,6 +32,9 @@
<command>
http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER http://%HOSTIP:%HTTPPORT/we/want?hoge=fuga -b non-existing -H "Host: localhost"
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
diff --git a/tests/data/test1268 b/tests/data/test1268
index 562f376..257b472 100644
--- a/tests/data/test1268
+++ b/tests/data/test1268
@@ -23,12 +23,12 @@
file name argument looks like a flag
</name>
<command>
---stderr log/moo%TESTNUMBER --unix-socket -k hej://moo
+--stderr %LOGDIR/moo%TESTNUMBER --unix-socket -k hej://moo
</command>
</client>
<verify>
-<file name="log/moo%TESTNUMBER" mode="text">
+<file name="%LOGDIR/moo%TESTNUMBER" mode="text">
Warning: The file name argument '-k' looks like a flag.
curl: (1) Protocol "hej" not supported or disabled in libcurl
</file>
diff --git a/tests/data/test1271 b/tests/data/test1271
index 184fd87..2d412a6 100644
--- a/tests/data/test1271
+++ b/tests/data/test1271
@@ -27,9 +27,9 @@
--write-out from file with empty file
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/our/%TESTNUMBER -w @log/blank%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/we/want/our/%TESTNUMBER -w @%LOGDIR/blank%TESTNUMBER
</command>
-<file name="log/blank%TESTNUMBER">
+<file name="%LOGDIR/blank%TESTNUMBER">
</file>
</client>
diff --git a/tests/data/test1273 b/tests/data/test1273
index 0c076cb..d724fdd 100644
--- a/tests/data/test1273
+++ b/tests/data/test1273
@@ -53,7 +53,7 @@
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -C - -f
</command>
-<file name="log/curl%TESTNUMBER.out">
+<file name="%LOGDIR/curl%TESTNUMBER.out">
012345678
012345678
012345678
diff --git a/tests/data/test1274 b/tests/data/test1274
index 21d6f61..5198537 100644
--- a/tests/data/test1274
+++ b/tests/data/test1274
@@ -10,7 +10,7 @@
#
# Server-side
<reply>
-<data>
+<data nocheck="yes">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/
@@ -36,7 +36,7 @@
HTTP header line folding
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -D log/out%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -D %LOGDIR/out%TESTNUMBER
</command>
</client>
@@ -50,17 +50,25 @@
Accept: */*
</protocol>
-<file name="log/out%TESTNUMBER">
+<file name="%LOGDIR/out%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
+%if hyper
+Server: test-server/ fake folded
+%else
Server: test-server/
fake
folded
+%endif
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Content-Length: 6
+%if hyper
+Connection: close
+%else
Connection:
close
+%endif
</file>
</verify>
diff --git a/tests/data/test1275 b/tests/data/test1275
new file mode 100644
index 0000000..d1cb223
--- /dev/null
+++ b/tests/data/test1275
@@ -0,0 +1,25 @@
+<testcase>
+<info>
+<keywords>
+documentation
+markdown
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+
+<name>
+Verify capital letters after period in markdown files
+</name>
+
+<command type="perl">
+%SRCDIR/markdown-uppercase.pl %SRCDIR/..
+</command>
+</client>
+
+</testcase>
diff --git a/tests/data/test1276 b/tests/data/test1276
new file mode 100644
index 0000000..2526cdf
--- /dev/null
+++ b/tests/data/test1276
@@ -0,0 +1,25 @@
+<testcase>
+<info>
+<keywords>
+source analysis
+documentation
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+
+ <name>
+Verify lib/optiontable.pl
+ </name>
+
+<command type="perl">
+%SRCDIR/option-check.pl %SRCDIR/..
+</command>
+</client>
+
+</testcase>
diff --git a/tests/data/test1277 b/tests/data/test1277
new file mode 100644
index 0000000..b705569
--- /dev/null
+++ b/tests/data/test1277
@@ -0,0 +1,206 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+compressed
+Transfer-Encoding
+Content-Encoding
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data base64="yes">
+SFRUUC8xLjEgMjAwIE9LDQpEYXRlOiBNb24sIDI5IE5vdiAyMDA0IDIxOjU2OjUzIEdNVA0KU2Vy
+dmVyOiBBcGFjaGUvMS4zLjMxIChEZWJpYW4gR05VL0xpbnV4KSBtb2RfZ3ppcC8xLjMuMjYuMWEg
+UEhQLzQuMy45LTEgbW9kX3NzbC8yLjguMjAgT3BlblNTTC8wLjkuN2QgbW9kX3BlcmwvMS4yOQ0K
+VmFyeTogQWNjZXB0LUVuY29kaW5nDQpDb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD1J
+U08tODg1OS0xDQpUcmFuc2Zlci1FbmNvZGluZzogZ3ppcCwgY2h1bmtlZA0KQ29udGVudC1FbmNv
+ZGluZzogZGVmbGF0ZQ0KDQo1MjINCh+LCAAHgbBjAv8BCwX0+nja3VjbbuM2EH03kH9g/dQCtm62
+EzlwtChy2QTNNsHaBbpPBi3RNhtJFEjKuTz02zuUKImxHK93g74ESGJy5pzD4QxJk5l8ekpitCFc
+UJaedV3L6SKShiyi6eqsezO96/v+aNx3u5+CzuSXi7vz2bf7S5Rx9g8JZT+mQgIQTb9NZ5dfUHct
+ZXZq20tOxDohWFopkfYChw8kjexl0tc80XesoRXJqAuiW1pBB6HKptpNb06jwD12vYltGEpEhCWZ
+4ygigBiP/b7j9z0XOcNTxz31xhPb8BuEPFMfUeA5zrDvOn3XR4536sHPQFMqxKs4UpyQuVgzLoMw
+53EdjmFv45d5HBdwhNMIxXTRphYQHR4RoZY6Z0lSUlKCJGO1AMf8GS0ZR2FMSSr7gkYE/fX1FkmO
+U7GEilowi0bIUN4ZDKIC4XIEpVqpcFXfJY2JOOrkQnXUGOI5lfjJQjcSiTzLQF+g69nsvlf8nfbQ
+FbSPOldF++LmfNZDs8vbPy/h8/bid4Bd3dxe9orhP9/dX19+hTYM8EhiiKmU6mdMyJ5u5tAKGXug
+RBTaKM9ihiMYApZanpComXUPZViIR8Yj1YTI0jxZFPbp9PaoExIu6ZKGUFcw/UE4+JgoQ4FqPMEI
+xbQgGxl7JJxER53Fc5WkHpJr8mbGq7JYR53ZGqgIw++CpmozCUhtnWqVYAabDnnOUSfG6SrHKyKK
+GEi6oZylCQwgQEeX0FgbGypxTOXzXISMk2B04g+t0cnE3rJvgTPCQ5AMBpZ7bGAr8xYa5vMAe21s
+IAuTXtcsy2PMm7GOR2OIYQjLedvTIlQDugPLd18RXodiOMpgnNErtBEOx8W54VsjZ2LrjumZhywH
+Xc+tvNrwClMO4g9qjDGAyBci5DSTcESKYKBOh9emEgalT8P1XO3l4IIscR7LiW0aSxjUf14dYBmU
+Pdh5aFYnpa3Wiz2xW6xGbM0S8rYQLGDKSxV1eNomQ+vWAo2mXL0cLgdgraRojcjixTtcBMBaRNEa
+kReaHS4CYC2iaI1IuIY9RmK2OlyqpmjBRqKR5VlyuCCAtZSiNSIRWRwuAmAtomiNCBNPh4sAWIso
+mlEvEanz8gdqVhKqumm6scxzDmkTJNDrt+oahdmIHyjJRlTF2AhDRN0cDldRaC1TEBudhHLO+OFK
+JV5rabJZ14QFVa2gWXpiCoccpODLzcz+G53D6QEpo3mCbkvHxK4QGq++p+Sck5jUmWuZ5/r+FpxY
+rmfBBekN9xtsda86OXb8UYtYXbDaHHUv2n1x2gUs52LvmswEzlECE14zOZdr+KqGnLVMJRLnEm4y
+og6p7Ffd2qBPYJxSEqOpJCl8w68mtulsUaBKu+v+7wKvIqKKbCBbdM5iEtw9poTXuMJURWqboVY9
+YVzJOE1oiqU5O8nhhlDUBgpad1pezzve5x7s5e5zur6/l+vuHReWxv6o97rd4+E+93gv2R/v9Tp7
+3e7oO3F/J7D9kQ1aY5f3u+3yw5rI4MkEDzG4jtY6tfEZyeeMnHU5CeF1oGzqJVUvygZnbmRHDbXL
+sZOo7y3gPhmqYux07WQaj7MWdfvh9hZXUqk2FNjhzo5+1bep33Zqldh6pzWIt/PGinsbjv+/pDk/
+nbHh4J0ZU++rj58o1xuM3Hdk6gWeYh8/SwPPGZ68I0vXhCYRjj9+oobD0cB7R6LCPjz1xc/kybDo
+s77+r1DQqZvNf8f+A904jtHT7+gYCwUAAA0KMA0KDQo=
+</data>
+
+
+<datacheck>
+HTTP/1.1 200 OK
+Date: Mon, 29 Nov 2004 21:56:53 GMT
+Server: Apache/1.3.31 (Debian GNU/Linux) mod_gzip/1.3.26.1a PHP/4.3.9-1 mod_ssl/2.8.20 OpenSSL/0.9.7d mod_perl/1.29
+Vary: Accept-Encoding
+Content-Type: text/html; charset=ISO-8859-1
+Transfer-Encoding: gzip, chunked
+Content-Encoding: deflate
+
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE project-listing SYSTEM "http://freshmeat.net/backend/fm-projects-0.4.dtd">
+<project-listing>
+ <project>
+ <project_id>1612</project_id>
+ <date_added>1998-08-21 04:01:29</date_added>
+ <date_updated>2004-10-18 02:22:23</date_updated>
+ <projectname_short>curl</projectname_short>
+ <projectname_full>curl and libcurl</projectname_full>
+ <desc_short>Command line tool and library for client-side URL transfers.</desc_short>
+ <desc_full>curl and libcurl is a tool for transferring files
+using URL syntax. It supports HTTP, HTTPS, FTP,
+FTPS, DICT, TELNET, LDAP, FILE, and GOPHER, as
+well as HTTP-post, HTTP-put, cookies, FTP upload,
+resumed transfers, passwords, portnumbers, SSL
+certificates, Kerberos, and proxies. It is powered
+by libcurl, the client-side URL transfer library.
+There are bindings to libcurl for over 20
+languages and environments.
+</desc_full>
+ <vitality_score>5784.57</vitality_score>
+ <vitality_percent>3.16</vitality_percent>
+ <vitality_rank>169</vitality_rank>
+ <popularity_score>6594.54</popularity_score>
+ <popularity_percent>13.81</popularity_percent>
+ <popularity_rank>105</popularity_rank>
+ <rating>8.50</rating>
+ <rating_count>21</rating_count>
+ <rating_rank>183</rating_rank>
+ <subscriptions>323</subscriptions>
+ <branch_name>Default</branch_name>
+ <url_project_page>http://freshmeat.net/projects/curl/</url_project_page>
+ <url_homepage>http://freshmeat.net/redir/curl/1612/url_homepage/</url_homepage>
+ <url_tgz>http://freshmeat.net/redir/curl/1612/url_tgz/</url_tgz>
+ <url_bz2>http://freshmeat.net/redir/curl/1612/url_bz2/</url_bz2>
+ <url_zip>http://freshmeat.net/redir/curl/1612/url_zip/</url_zip>
+ <url_changelog>http://freshmeat.net/redir/curl/1612/url_changelog/</url_changelog>
+ <url_rpm>http://freshmeat.net/redir/curl/1612/url_rpm/</url_rpm>
+ <url_deb>http://freshmeat.net/redir/curl/1612/url_deb/</url_deb>
+ <url_osx>http://freshmeat.net/redir/curl/1612/url_osx/</url_osx>
+ <url_bsdport>http://freshmeat.net/redir/curl/1612/url_bsdport/</url_bsdport>
+ <url_purchase></url_purchase>
+ <url_cvs>http://freshmeat.net/redir/curl/1612/url_cvs/</url_cvs>
+ <url_list>http://freshmeat.net/redir/curl/1612/url_list/</url_list>
+ <url_mirror>http://freshmeat.net/redir/curl/1612/url_mirror/</url_mirror>
+ <url_demo></url_demo>
+ <license>MIT/X Consortium License</license>
+ <latest_release>
+ <latest_release_version>7.12.2</latest_release_version>
+ <latest_release_id>176085</latest_release_id>
+ <latest_release_date>2004-10-18 02:22:23</latest_release_date>
+ </latest_release>
+ <screenshot_thumb></screenshot_thumb>
+ <authors>
+ <author>
+ <author_name>Daniel Stenberg</author_name>
+ <author_url>http://freshmeat.net/~bagder/</author_url>
+ <author_role>Owner</author_role>
+ </author>
+ </authors>
+ <descriminators>
+ <trove_id>12</trove_id>
+ <trove_id>226</trove_id>
+ <trove_id>3</trove_id>
+ <trove_id>2</trove_id>
+ <trove_id>188</trove_id>
+ <trove_id>216</trove_id>
+ <trove_id>200</trove_id>
+ <trove_id>220</trove_id>
+ <trove_id>164</trove_id>
+ <trove_id>90</trove_id>
+ <trove_id>89</trove_id>
+ <trove_id>809</trove_id>
+ <trove_id>150</trove_id>
+ <trove_id>224</trove_id>
+ <trove_id>900</trove_id>
+ <trove_id>839</trove_id>
+ </descriminators>
+ <dependencies>
+ <dependency type="recommended">
+ <dependency_release_id>0</dependency_release_id>
+ <dependency_branch_id>7464</dependency_branch_id>
+ <dependency_project_id>7464</dependency_project_id>
+ <dependency_project_title>OpenSSL (Default)</dependency_project_title>
+ </dependency>
+ <dependency type="optional">
+ <dependency_release_id>0</dependency_release_id>
+ <dependency_branch_id>0</dependency_branch_id>
+ <dependency_project_id>7443</dependency_project_id>
+ <dependency_project_title>OpenLDAP</dependency_project_title>
+ </dependency>
+ <dependency type="optional">
+ <dependency_release_id>0</dependency_release_id>
+ <dependency_branch_id>0</dependency_branch_id>
+ <dependency_project_id>12351</dependency_project_id>
+ <dependency_project_title>zlib</dependency_project_title>
+ </dependency>
+ <dependency type="optional">
+ <dependency_release_id>0</dependency_release_id>
+ <dependency_branch_id>0</dependency_branch_id>
+ <dependency_project_id>32047</dependency_project_id>
+ <dependency_project_title>Heimdal</dependency_project_title>
+ </dependency>
+ <dependency type="optional">
+ <dependency_release_id>0</dependency_release_id>
+ <dependency_branch_id>0</dependency_branch_id>
+ <dependency_project_id>44532</dependency_project_id>
+ <dependency_project_title>c-ares</dependency_project_title>
+ </dependency>
+ </dependencies>
+ </project>
+</project-listing>
+</datacheck>
+
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+libz
+</features>
+<server>
+http
+</server>
+ <name>
+HTTP GET with both content and transfer encoding
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --tr-encoding --compressed
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^Accept-Encoding: [a-zA-Z, ]*/Accept-Encoding: xxx/
+</strippart>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Connection: TE
+TE: gzip
+Accept-Encoding: xxx
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1278 b/tests/data/test1278
new file mode 100644
index 0000000..9516446
--- /dev/null
+++ b/tests/data/test1278
@@ -0,0 +1,48 @@
+<testcase>
+<info>
+<keywords>
+--no-remote-name
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes" nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+verify extra --no-remote-name
+</name>
+<command option="no-output">
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --no-progress-meter -o %LOGDIR/out%TESTNUMBER --no-remote-name -w '%{stderr}yes\n'
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<stderr mode="text">
+yes
+</stderr>
+</verify>
+</testcase>
diff --git a/tests/data/test128 b/tests/data/test128
index c9429c5..e3ed415 100644
--- a/tests/data/test128
+++ b/tests/data/test128
@@ -20,9 +20,9 @@
FTP upload with --crlf
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/upload%TESTNUMBER --crlf
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER --crlf
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
file
with unix newlines
meant to be
diff --git a/tests/data/test1283 b/tests/data/test1283
index df0458c..1e8e9d4 100644
--- a/tests/data/test1283
+++ b/tests/data/test1283
@@ -30,7 +30,7 @@
globbing range with same start and stop
</name>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/[a-a][1-1][b-b:1][2-2:1]/%TESTNUMBER -o "log/outfile%TESTNUMBER_#1#2#3#4.dump"
+http://%HOSTIP:%HTTPPORT/[a-a][1-1][b-b:1][2-2:1]/%TESTNUMBER -o "%LOGDIR/outfile%TESTNUMBER_#1#2#3#4.dump"
</command>
</client>
@@ -43,7 +43,7 @@
Accept: */*
</protocol>
-<file name="log/outfile%TESTNUMBER_a1b2.dump">
+<file name="%LOGDIR/outfile%TESTNUMBER_a1b2.dump">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Content-Length: 6
diff --git a/tests/data/test1285 b/tests/data/test1285
index e5a38e0..986cb92 100644
--- a/tests/data/test1285
+++ b/tests/data/test1285
@@ -60,9 +60,9 @@
# even when there is a user-specified Content-Length header.
# https://github.com/curl/curl/pull/1242
<command>
--H "Content-Length: 85" -u auser:apasswd --digest -T log/put%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+-H "Content-Length: 85" -u auser:apasswd --digest -T %LOGDIR/put%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
-<file name="log/put%TESTNUMBER">
+<file name="%LOGDIR/put%TESTNUMBER">
This is data we upload with PUT
a second line
line three
@@ -85,7 +85,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 85
-Expect: 100-continue
This is data we upload with PUT
a second line
diff --git a/tests/data/test1287 b/tests/data/test1287
index 0d0ad47..c481531 100644
--- a/tests/data/test1287
+++ b/tests/data/test1287
@@ -82,7 +82,7 @@
Accept: */*
</protocol>
-<file name="log/stderr%TESTNUMBER" mode="text">
+<file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
%if !hyper
* Ignoring Content-Length in CONNECT 200 response
* Ignoring Transfer-Encoding in CONNECT 200 response
diff --git a/tests/data/test1288 b/tests/data/test1288
index 583fc42..e94bd51 100644
--- a/tests/data/test1288
+++ b/tests/data/test1288
@@ -42,7 +42,7 @@
Suppress proxy CONNECT response headers
</name>
<command>
---proxytunnel --suppress-connect-headers --dump-header - --include --write-out "\nCONNECT CODE: %{http_connect}\nRECEIVED HEADER BYTE TOTAL: %{size_header}\n" --proxy %HOSTIP:%PROXYPORT http://%HOSTIP.%TESTNUMBER:%HTTPPORT/we/want/that/page/%TESTNUMBER
+--proxytunnel --suppress-connect-headers --dump-header - --include --write-out "\nCONNECT CODE: %{http_connect}\nRECEIVED HEADER BYTE TOTAL: %{size_header}\n" --proxy %HOSTIP:%PROXYPORT http://%HOSTIP:%HTTPPORT/we/want/that/page/%TESTNUMBER
</command>
<features>
proxy
@@ -53,15 +53,15 @@
# Verify data after the test has been "shot"
<verify>
<proxy>
-CONNECT %HOSTIP.%TESTNUMBER:%HTTPPORT HTTP/1.1
-Host: %HOSTIP.%TESTNUMBER:%HTTPPORT
+CONNECT %HOSTIP:%HTTPPORT HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Proxy-Connection: Keep-Alive
</proxy>
<protocol>
GET /we/want/that/page/%TESTNUMBER HTTP/1.1
-Host: %HOSTIP.%TESTNUMBER:%HTTPPORT
+Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
diff --git a/tests/data/test1291 b/tests/data/test1291
index 5997dcc..ea9a0c6 100644
--- a/tests/data/test1291
+++ b/tests/data/test1291
@@ -24,14 +24,14 @@
Attempt to upload 1000 files but fail immediately
</name>
<command>
--K log/cmd%TESTNUMBER --fail-early
+-K %LOGDIR/cmd%TESTNUMBER --fail-early
</command>
-<file name="log/upload-this">
+<file name="%LOGDIR/upload-this">
XXXXXXXx
</file>
# generate the config file
<precheck>
-perl -e 'for(1 .. 1000) { printf("upload-file=log/upload-this\nurl=htttttp://non-existing-host.haxx.se/upload/%TESTNUMBER\n", $_);}' > log/cmd%TESTNUMBER;
+perl -e 'for(1 .. 1000) { printf("upload-file=%LOGDIR/upload-this\nurl=htttttp://non-existing-host.haxx.se/upload/%TESTNUMBER\n", $_);}' > %LOGDIR/cmd%TESTNUMBER;
</precheck>
</client>
diff --git a/tests/data/test1293 b/tests/data/test1293
index 8248861..fb39ebc 100644
--- a/tests/data/test1293
+++ b/tests/data/test1293
@@ -29,6 +29,9 @@
#
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test1297 b/tests/data/test1297
index f410362..386154a 100644
--- a/tests/data/test1297
+++ b/tests/data/test1297
@@ -33,7 +33,7 @@
CONNECT to peer that returns nothing
</name>
<command>
---proxytunnel --proxy %HOSTIP:%PROXYPORT http://%HOSTIP.%TESTNUMBER:%HTTPPORT/we/want/that/page/%TESTNUMBER
+--proxytunnel --proxy %HOSTIP:%PROXYPORT http://%HOSTIP:%HTTPPORT/we/want/that/page/%TESTNUMBER
</command>
<features>
proxy
@@ -44,15 +44,15 @@
# Verify data after the test has been "shot"
<verify>
<proxy>
-CONNECT %HOSTIP.%TESTNUMBER:%HTTPPORT HTTP/1.1
-Host: %HOSTIP.%TESTNUMBER:%HTTPPORT
+CONNECT %HOSTIP:%HTTPPORT HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Proxy-Connection: Keep-Alive
</proxy>
<protocol>
GET /we/want/that/page/%TESTNUMBER HTTP/1.1
-Host: %HOSTIP.%TESTNUMBER:%HTTPPORT
+Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
diff --git a/tests/data/test130 b/tests/data/test130
index 31447cb..665d059 100644
--- a/tests/data/test130
+++ b/tests/data/test130
@@ -37,9 +37,9 @@
FTP (optional .netrc; no user/pass) dir list PASV
</name>
<command>
---netrc-optional --netrc-file log/netrc%TESTNUMBER ftp://%HOSTIP:%FTPPORT/
+--netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER ftp://%HOSTIP:%FTPPORT/
</command>
-<file name="log/netrc%TESTNUMBER" >
+<file name="%LOGDIR/netrc%TESTNUMBER" >
# the following two lines were created while testing curl
# machine %HOSTIP login user1 password commented
machine %HOSTIP login user1 password passwd1
diff --git a/tests/data/test1301 b/tests/data/test1301
index 5aea24b..08b43a8 100644
--- a/tests/data/test1301
+++ b/tests/data/test1301
@@ -1,8 +1,7 @@
<testcase>
<info>
<keywords>
-unittest
-curl_strcasecompare
+curl_strequal
</keywords>
</info>
@@ -12,11 +11,11 @@
<server>
none
</server>
-<features>
-unittest
-</features>
+<tool>
+lib%TESTNUMBER
+</tool>
<name>
-curl_strcasecompare unit tests
+curl_strequal tests
</name>
</client>
</testcase>
diff --git a/tests/data/test1304 b/tests/data/test1304
index 699a2e4..afc9aed 100644
--- a/tests/data/test1304
+++ b/tests/data/test1304
@@ -18,7 +18,10 @@
<name>
netrc parsing unit tests
</name>
-<file name="log/netrc%TESTNUMBER">
+<command>
+%LOGDIR/netrc%TESTNUMBER
+</command>
+<file name="%LOGDIR/netrc%TESTNUMBER">
machine example.com login admin password passwd
machine curl.example.com login none password none
</file>
diff --git a/tests/data/test1308 b/tests/data/test1308
index 0c7d1b0..7ec1b98 100644
--- a/tests/data/test1308
+++ b/tests/data/test1308
@@ -16,11 +16,15 @@
<features>
unittest
http
+Mime
</features>
<name>
formpost unit tests
</name>
-<file name="log/test-%TESTNUMBER">
+<command>
+%LOGDIR/test-%TESTNUMBER
+</command>
+<file name="%LOGDIR/test-%TESTNUMBER">
Piece of the file that is to uploaded as a formpost
</file>
</client>
diff --git a/tests/data/test131 b/tests/data/test131
index 63bd021..52bff92 100644
--- a/tests/data/test131
+++ b/tests/data/test131
@@ -38,9 +38,9 @@
FTP (optional .netrc; user/no pass) dir list PASV
</name>
<command>
---netrc-optional --netrc-file log/netrc%TESTNUMBER ftp://user2@%HOSTIP:%FTPPORT/
+--netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER ftp://user2@%HOSTIP:%FTPPORT/
</command>
-<file name="log/netrc%TESTNUMBER" >
+<file name="%LOGDIR/netrc%TESTNUMBER" >
# the following two lines were created while testing curl
machine %HOSTIP login user1 password passwd1
machine %HOSTIP login user2 password passwd2
diff --git a/tests/data/test1310 b/tests/data/test1310
index 11dcfef..f0d47e7 100644
--- a/tests/data/test1310
+++ b/tests/data/test1310
@@ -73,6 +73,8 @@
CURL_NTLM_WB_FILE=%PWD/server/fake_ntlm
# set source directory so fake_ntlm can find the test files
CURL_NTLM_AUTH_SRCDIR=%SRCDIR
+# set source directory so fake_ntlm can find the test and log files
+CURL_NTLM_LOGDIR=%LOGDIR
# set the test number
CURL_NTLM_AUTH_TESTNUM=%TESTNUMBER
</setenv>
diff --git a/tests/data/test1311 b/tests/data/test1311
index 6d5496f..8e48794 100644
--- a/tests/data/test1311
+++ b/tests/data/test1311
@@ -37,7 +37,7 @@
HTTP GET with -J and Content-Disposition
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -O
@@ -54,7 +54,7 @@
Accept: */*
</protocol>
-<file name="log/name%TESTNUMBER">
+<file name="%LOGDIR/name%TESTNUMBER">
12345
</file>
diff --git a/tests/data/test1312 b/tests/data/test1312
index 2d48914..c8170a8 100644
--- a/tests/data/test1312
+++ b/tests/data/test1312
@@ -37,7 +37,7 @@
HTTP GET with -J, Content-Disposition and ; in filename
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
%HOSTIP:%HTTPPORT/%TESTNUMBER -J -O
@@ -54,7 +54,7 @@
Accept: */*
</protocol>
-<file name="log/name%TESTNUMBER;weird">
+<file name="%LOGDIR/name%TESTNUMBER;weird">
12345
</file>
diff --git a/tests/data/test1313 b/tests/data/test1313
index b1ac1fc..8a28597 100644
--- a/tests/data/test1313
+++ b/tests/data/test1313
@@ -37,7 +37,7 @@
HTTP GET with -J, Content-Disposition, uneven quotes
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -O
@@ -54,7 +54,7 @@
Accept: */*
</protocol>
-<file name="log/name%TESTNUMBER">
+<file name="%LOGDIR/name%TESTNUMBER">
12345
</file>
diff --git a/tests/data/test1315 b/tests/data/test1315
index 3d3faa8..e1de8f6 100644
--- a/tests/data/test1315
+++ b/tests/data/test1315
@@ -22,6 +22,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -29,10 +32,10 @@
HTTP RFC1867-type formposting - -F with three files, one with explicit type
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F name=value -F 'file=@log/test%TESTNUMBER.txt,log/test%TESTNUMBER.txt;type=magic/content,log/test%TESTNUMBER.txt'
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F name=value -F 'file=@%LOGDIR/test%TESTNUMBER.txt,%LOGDIR/test%TESTNUMBER.txt;type=magic/content,%LOGDIR/test%TESTNUMBER.txt'
</command>
# We create this file before the command is invoked!
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
dummy data
</file>
</client>
diff --git a/tests/data/test132 b/tests/data/test132
index d33980f..b02d993 100644
--- a/tests/data/test132
+++ b/tests/data/test132
@@ -37,9 +37,9 @@
FTP (optional .netrc; user/passwd supplied) dir list PASV
</name>
<command>
---netrc-optional --netrc-file log/netrc%TESTNUMBER ftp://mary:mark@%HOSTIP:%FTPPORT/
+--netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER ftp://mary:mark@%HOSTIP:%FTPPORT/
</command>
-<file name="log/netrc%TESTNUMBER" >
+<file name="%LOGDIR/netrc%TESTNUMBER" >
# the following two lines were created while testing curl
machine %HOSTIP login user1 password passwd1
machine %HOSTIP login user2 password passwd2
diff --git a/tests/data/test1327 b/tests/data/test1327
index 791189b..5941e50 100644
--- a/tests/data/test1327
+++ b/tests/data/test1327
@@ -27,12 +27,12 @@
GET /ignore/for/%TESTNUMBER HTTP/1.0
</stdin>
-<file name="log/%TESTNUMBER.txt">
+<file name="%LOGDIR/%TESTNUMBER.txt">
GET /we/want/%TESTNUMBER HTTP/1.0
</file>
<command option="no-output">
-telnet://%HOSTIP:%HTTPPORT -T log/%TESTNUMBER.txt
+telnet://%HOSTIP:%HTTPPORT -T %LOGDIR/%TESTNUMBER.txt
</command>
</client>
diff --git a/tests/data/test1328 b/tests/data/test1328
index b7b3e32..a85c6b6 100644
--- a/tests/data/test1328
+++ b/tests/data/test1328
@@ -47,7 +47,7 @@
HTTP GET a globbed range with -f
</name>
<command>
--f 'http://%HOSTIP:%HTTPPORT/[%TESTNUMBER0000-%TESTNUMBER0001]' -o log/#1
+-f 'http://%HOSTIP:%HTTPPORT/[%TESTNUMBER0000-%TESTNUMBER0001]' -o %LOGDIR/#1
</command>
</client>
diff --git a/tests/data/test133 b/tests/data/test133
index ad0d2de..8b914cb 100644
--- a/tests/data/test133
+++ b/tests/data/test133
@@ -37,9 +37,9 @@
FTP compulsory .netrc; ignore passwd in URL
</name>
<command>
--n --netrc-file log/netrc%TESTNUMBER ftp://mary:mark@%HOSTIP:%FTPPORT/
+-n --netrc-file %LOGDIR/netrc%TESTNUMBER ftp://mary:mark@%HOSTIP:%FTPPORT/
</command>
-<file name="log/netrc%TESTNUMBER" >
+<file name="%LOGDIR/netrc%TESTNUMBER" >
# the following two lines were created while testing curl
machine %HOSTIP login user1 password passwd1
machine %HOSTIP login mary password drfrank
diff --git a/tests/data/test1330 b/tests/data/test1330
index 2cc5aed..0dd8f7d 100644
--- a/tests/data/test1330
+++ b/tests/data/test1330
@@ -31,7 +31,7 @@
#
# Verify data after the test has been "shot"
<verify>
-<file name="log/memdump">
+<file name="%LOGDIR/memdump">
MEM unit%TESTNUMBER.c: malloc()
MEM unit%TESTNUMBER.c: free()
</file>
diff --git a/tests/data/test1331 b/tests/data/test1331
index 4ef0c14..a233c63 100644
--- a/tests/data/test1331
+++ b/tests/data/test1331
@@ -62,9 +62,10 @@
HTTP --proxy-anyauth and 407 with cookies
</name>
<command>
--U myname:mypassword -x %HOSTIP:%HTTPPORT http://z.x.com/%TESTNUMBER --proxy-anyauth -c log/dump%TESTNUMBER
+-U myname:mypassword -x %HOSTIP:%HTTPPORT http://z.x.com/%TESTNUMBER --proxy-anyauth -c %LOGDIR/dump%TESTNUMBER
</command>
<features>
+cookies
proxy
</features>
</client>
diff --git a/tests/data/test1334 b/tests/data/test1334
index b191559..88a41d8 100644
--- a/tests/data/test1334
+++ b/tests/data/test1334
@@ -35,10 +35,10 @@
HTTP GET with -O without Content-Disposition, -D file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -O -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -O -D %LOGDIR/heads%TESTNUMBER
</command>
</client>
@@ -53,11 +53,11 @@
</protocol>
-<file1 name="log/%TESTNUMBER">
+<file1 name="%LOGDIR/%TESTNUMBER">
12345
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -67,7 +67,7 @@
</file2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1335 b/tests/data/test1335
index e350760..4d64ea8 100644
--- a/tests/data/test1335
+++ b/tests/data/test1335
@@ -35,7 +35,7 @@
HTTP GET with -O without Content-Disposition, -D stdout
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -O -D -
@@ -53,11 +53,11 @@
</protocol>
-<file1 name="log/%TESTNUMBER">
+<file1 name="%LOGDIR/%TESTNUMBER">
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test1336 b/tests/data/test1336
index 631f204..993d8c6 100644
--- a/tests/data/test1336
+++ b/tests/data/test1336
@@ -36,13 +36,13 @@
HTTP GET with -O and Content-Disposition, -D file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -O -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -O -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -57,11 +57,11 @@
</protocol>
-<file1 name="log/%TESTNUMBER">
+<file1 name="%LOGDIR/%TESTNUMBER">
12345
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -72,7 +72,7 @@
</file2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1337 b/tests/data/test1337
index 808c8a2..4b954d0 100644
--- a/tests/data/test1337
+++ b/tests/data/test1337
@@ -36,13 +36,13 @@
HTTP GET with -O and Content-Disposition, -D stdout
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -O -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -57,11 +57,11 @@
</protocol>
-<file1 name="log/%TESTNUMBER">
+<file1 name="%LOGDIR/%TESTNUMBER">
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test1338 b/tests/data/test1338
index 672e9ae..c1c271a 100644
--- a/tests/data/test1338
+++ b/tests/data/test1338
@@ -36,10 +36,10 @@
HTTP GET with -O -J without Content-Disposition, -D file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -O -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -O -D %LOGDIR/heads%TESTNUMBER
</command>
</client>
@@ -54,11 +54,11 @@
</protocol>
-<file1 name="log/%TESTNUMBER">
+<file1 name="%LOGDIR/%TESTNUMBER">
12345
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -68,7 +68,7 @@
</file2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1339 b/tests/data/test1339
index 4bc77e9..a46934d 100644
--- a/tests/data/test1339
+++ b/tests/data/test1339
@@ -36,7 +36,7 @@
HTTP GET with -O -J without Content-Disposition, -D stdout
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -O -D -
@@ -54,11 +54,11 @@
</protocol>
-<file1 name="log/%TESTNUMBER">
+<file1 name="%LOGDIR/%TESTNUMBER">
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test134 b/tests/data/test134
index 00d1732..d0716c3 100644
--- a/tests/data/test134
+++ b/tests/data/test134
@@ -39,9 +39,9 @@
# -u overrides netrc which overrides the URL
<command>
---netrc-optional --netrc-file log/netrc%TESTNUMBER -u romulus:rhemus ftp://mary:mark@%HOSTIP:%FTPPORT/
+--netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER -u romulus:rhemus ftp://mary:mark@%HOSTIP:%FTPPORT/
</command>
-<file name="log/netrc%TESTNUMBER" >
+<file name="%LOGDIR/netrc%TESTNUMBER" >
# the following two lines were created while testing curl
machine %HOSTIP login user1 password passwd1
machine %HOSTIP login user2 password passwd2
diff --git a/tests/data/test1340 b/tests/data/test1340
index e48907b..ebec701 100644
--- a/tests/data/test1340
+++ b/tests/data/test1340
@@ -37,10 +37,10 @@
HTTP GET with -O -J and Content-Disposition, -D file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%PWD/%LOGDIR
</setenv>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -O -D log/heads%TESTNUMBER -w "curl saved to filename %{filename_effective}\n"
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -O -D %LOGDIR/heads%TESTNUMBER -w "curl saved to filename %{filename_effective}\n"
</command>
</client>
@@ -55,11 +55,11 @@
</protocol>
-<file1 name="log/name%TESTNUMBER">
+<file1 name="%LOGDIR/name%TESTNUMBER">
12345
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -70,8 +70,8 @@
</file2>
-<file3 name="log/stdout%TESTNUMBER" mode="text">
-curl saved to filename %PWD/log/name%TESTNUMBER
+<file3 name="%LOGDIR/stdout%TESTNUMBER" mode="text">
+curl saved to filename %PWD/%LOGDIR/name%TESTNUMBER
</file3>
</verify>
diff --git a/tests/data/test1341 b/tests/data/test1341
index cf13a1f..75d9daa 100644
--- a/tests/data/test1341
+++ b/tests/data/test1341
@@ -37,7 +37,7 @@
HTTP GET with -O -J and Content-Disposition, -D stdout
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%PWD/%LOGDIR
</setenv>
<command option="no-output,no-include">
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -O -D - -w "curl saved to filename %{filename_effective}\n"
@@ -55,11 +55,11 @@
</protocol>
-<file1 name="log/name%TESTNUMBER">
+<file1 name="%LOGDIR/name%TESTNUMBER">
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -68,7 +68,7 @@
Content-Type: text/html
Content-Disposition: filename=name%TESTNUMBER; charset=funny; option=strange
-curl saved to filename %PWD/log/name%TESTNUMBER
+curl saved to filename %PWD/%LOGDIR/name%TESTNUMBER
</file2>
</verify>
diff --git a/tests/data/test1342 b/tests/data/test1342
index 6bab283..39dbfab 100644
--- a/tests/data/test1342
+++ b/tests/data/test1342
@@ -35,10 +35,10 @@
HTTP GET with -O -i without Content-Disposition, -D file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -O -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -O -D %LOGDIR/heads%TESTNUMBER
</command>
</client>
@@ -53,7 +53,7 @@
</protocol>
-<file1 name="log/%TESTNUMBER">
+<file1 name="%LOGDIR/%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -64,7 +64,7 @@
12345
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -74,7 +74,7 @@
</file2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1343 b/tests/data/test1343
index 3f0d630..6a9eb7d 100644
--- a/tests/data/test1343
+++ b/tests/data/test1343
@@ -35,7 +35,7 @@
HTTP GET with -O -i without Content-Disposition, -D stdout
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -O -D -
@@ -53,7 +53,7 @@
</protocol>
-<file1 name="log/%TESTNUMBER">
+<file1 name="%LOGDIR/%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -64,7 +64,7 @@
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test1344 b/tests/data/test1344
index bb33616..ba4b389 100644
--- a/tests/data/test1344
+++ b/tests/data/test1344
@@ -36,13 +36,13 @@
HTTP GET with -O -i and Content-Disposition, -D file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -O -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -O -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -57,7 +57,7 @@
</protocol>
-<file1 name="log/%TESTNUMBER">
+<file1 name="%LOGDIR/%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -69,7 +69,7 @@
12345
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -80,7 +80,7 @@
</file2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1345 b/tests/data/test1345
index bd9470c..a9298e4 100644
--- a/tests/data/test1345
+++ b/tests/data/test1345
@@ -36,13 +36,13 @@
HTTP GET with -O -i and Content-Disposition, -D stdout
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -O -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -57,7 +57,7 @@
</protocol>
-<file1 name="log/%TESTNUMBER">
+<file1 name="%LOGDIR/%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -69,7 +69,7 @@
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test1346 b/tests/data/test1346
index 32d434d..bab67cb 100644
--- a/tests/data/test1346
+++ b/tests/data/test1346
@@ -35,7 +35,7 @@
HTTP GET with -O -i without Content-Disposition, without -D
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -O
@@ -53,7 +53,7 @@
</protocol>
-<file1 name="log/%TESTNUMBER">
+<file1 name="%LOGDIR/%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -64,7 +64,7 @@
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
</file2>
</verify>
diff --git a/tests/data/test1347 b/tests/data/test1347
index 46e1ae6..868e261 100644
--- a/tests/data/test1347
+++ b/tests/data/test1347
@@ -36,13 +36,13 @@
HTTP GET with -O -i and Content-Disposition, without -D
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -O
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -57,7 +57,7 @@
</protocol>
-<file1 name="log/%TESTNUMBER">
+<file1 name="%LOGDIR/%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -69,7 +69,7 @@
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
</file2>
</verify>
diff --git a/tests/data/test1348 b/tests/data/test1348
index df7a620..3de0b4a 100644
--- a/tests/data/test1348
+++ b/tests/data/test1348
@@ -28,7 +28,7 @@
FTP download, file without Content-Disposition inside, using -O
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O
@@ -49,12 +49,12 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
fooo
mooo
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
</file2>
</verify>
diff --git a/tests/data/test1349 b/tests/data/test1349
index 10ba0bd..d256549 100644
--- a/tests/data/test1349
+++ b/tests/data/test1349
@@ -28,10 +28,10 @@
FTP download, file without C-D inside, using -O -D file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -D log/heads%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -D %LOGDIR/heads%TESTNUMBER
</command>
</client>
@@ -49,14 +49,14 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
fooo
mooo
</file1>
# The final "221 bye bye baby" response to QUIT will not be recorded
# since that is not considered part of this particular transfer!
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
@@ -76,7 +76,7 @@
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
</stripfile2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1350 b/tests/data/test1350
index e9ea522..b5568f5 100644
--- a/tests/data/test1350
+++ b/tests/data/test1350
@@ -28,7 +28,7 @@
FTP download, file without C-D inside, using -O -D stdout
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -D -
@@ -49,14 +49,14 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
fooo
mooo
</file1>
# The final "221 bye bye baby" response to QUIT will not be recorded
# since that is not considered part of this particular transfer!
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
diff --git a/tests/data/test1351 b/tests/data/test1351
index 4c8ed4c..93232d5 100644
--- a/tests/data/test1351
+++ b/tests/data/test1351
@@ -29,10 +29,10 @@
FTP download, file without C-D inside, using -O -J -D file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -J -D log/heads%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -J -D %LOGDIR/heads%TESTNUMBER
</command>
</client>
@@ -50,14 +50,14 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
fooo
mooo
</file1>
# The final "221 bye bye baby" response to QUIT will not be recorded
# since that is not considered part of this particular transfer!
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
@@ -77,7 +77,7 @@
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
</stripfile2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1352 b/tests/data/test1352
index 3af12a8..0649289 100644
--- a/tests/data/test1352
+++ b/tests/data/test1352
@@ -29,7 +29,7 @@
FTP download, file without C-D inside, using -O -J -D stdout
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -J -D -
@@ -50,14 +50,14 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
fooo
mooo
</file1>
# The final "221 bye bye baby" response to QUIT will not be recorded
# since that is not considered part of this particular transfer!
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
diff --git a/tests/data/test1353 b/tests/data/test1353
index 3404970..8e0ad50 100644
--- a/tests/data/test1353
+++ b/tests/data/test1353
@@ -28,10 +28,10 @@
FTP download, file without C-D inside, using -O -i -D file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -i -D log/heads%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -i -D %LOGDIR/heads%TESTNUMBER
</command>
</client>
@@ -49,14 +49,14 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
fooo
mooo
</file1>
# The final "221 bye bye baby" response to QUIT will not be recorded
# since that is not considered part of this particular transfer!
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
@@ -76,7 +76,7 @@
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
</stripfile2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1354 b/tests/data/test1354
index e5d1563..506ec90 100644
--- a/tests/data/test1354
+++ b/tests/data/test1354
@@ -28,7 +28,7 @@
FTP download, file without C-D inside, using -O -i -D stdout
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -i -D -
@@ -49,12 +49,12 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
fooo
mooo
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
diff --git a/tests/data/test1355 b/tests/data/test1355
index f008803..fa19fab 100644
--- a/tests/data/test1355
+++ b/tests/data/test1355
@@ -28,7 +28,7 @@
FTP download, file without C-D inside, using -O -i, without -D
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -i
@@ -49,12 +49,12 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
fooo
mooo
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
</file2>
</verify>
diff --git a/tests/data/test1356 b/tests/data/test1356
index 7be2247..0c326f4 100644
--- a/tests/data/test1356
+++ b/tests/data/test1356
@@ -36,13 +36,13 @@
FTP download, file with Content-Disposition inside, using -O
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -60,7 +60,7 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -72,7 +72,7 @@
MOOOO
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
</file2>
</verify>
diff --git a/tests/data/test1357 b/tests/data/test1357
index ebb102c..9d395a8 100644
--- a/tests/data/test1357
+++ b/tests/data/test1357
@@ -36,13 +36,13 @@
FTP download, file with C-D inside, using -O -D file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -D log/heads%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -60,7 +60,7 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -72,7 +72,7 @@
MOOOO
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
@@ -92,7 +92,7 @@
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
</stripfile2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1358 b/tests/data/test1358
index 983e1cd..973ef7c 100644
--- a/tests/data/test1358
+++ b/tests/data/test1358
@@ -36,13 +36,13 @@
FTP download, file with C-D inside, using -O -D stdout
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -60,7 +60,7 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -72,7 +72,7 @@
MOOOO
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
diff --git a/tests/data/test1359 b/tests/data/test1359
index c4fb2ee..fc1eb37 100644
--- a/tests/data/test1359
+++ b/tests/data/test1359
@@ -37,13 +37,13 @@
FTP download, file with C-D inside, using -O -J -D file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -J -D log/heads%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -J -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -61,7 +61,7 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -73,7 +73,7 @@
MOOOO
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
@@ -93,7 +93,7 @@
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
</stripfile2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1360 b/tests/data/test1360
index 3f7b435..1fb80ee 100644
--- a/tests/data/test1360
+++ b/tests/data/test1360
@@ -37,13 +37,13 @@
FTP download, file with C-D inside, using -O -J -D stdout
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -J -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -61,7 +61,7 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -73,7 +73,7 @@
MOOOO
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
diff --git a/tests/data/test1361 b/tests/data/test1361
index 3f1f378..6b9af1a 100644
--- a/tests/data/test1361
+++ b/tests/data/test1361
@@ -36,13 +36,13 @@
FTP download, file with C-D inside, using -O -i -D file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -i -D log/heads%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -i -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -60,7 +60,7 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -72,7 +72,7 @@
MOOOO
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
@@ -92,7 +92,7 @@
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
</stripfile2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1362 b/tests/data/test1362
index c5a09cb..03d9904 100644
--- a/tests/data/test1362
+++ b/tests/data/test1362
@@ -36,13 +36,13 @@
FTP download, file with C-D inside, using -O -i -D stdout
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -i -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -60,7 +60,7 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -72,7 +72,7 @@
MOOOO
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
diff --git a/tests/data/test1363 b/tests/data/test1363
index e48074b..009f68c 100644
--- a/tests/data/test1363
+++ b/tests/data/test1363
@@ -36,13 +36,13 @@
FTP download, file with C-D inside, using -O -i, without -D
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -O -i
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -60,7 +60,7 @@
QUIT
</protocol>
-<file1 name="log/file%TESTNUMBER">
+<file1 name="%LOGDIR/file%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -72,7 +72,7 @@
MOOOO
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
</file2>
</verify>
diff --git a/tests/data/test1364 b/tests/data/test1364
index ac2c423..0ea1e2b 100644
--- a/tests/data/test1364
+++ b/tests/data/test1364
@@ -30,10 +30,10 @@
HTTP GET -o fname without Content-Disposition, -D file
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/outfile%TESTNUMBER -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/outfile%TESTNUMBER -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER
</postcheck>
</client>
@@ -48,11 +48,11 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
12345
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -62,7 +62,7 @@
</file2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1365 b/tests/data/test1365
index cee54b3..abd371c 100644
--- a/tests/data/test1365
+++ b/tests/data/test1365
@@ -30,10 +30,10 @@
HTTP GET -o fname without Content-Disposition, -D stdout
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/outfile%TESTNUMBER -D -
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/outfile%TESTNUMBER -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER
</postcheck>
</client>
@@ -48,11 +48,11 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test1366 b/tests/data/test1366
index ae634cf..78f5573 100644
--- a/tests/data/test1366
+++ b/tests/data/test1366
@@ -31,10 +31,10 @@
HTTP GET -o fname and Content-Disposition, -D file
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/outfile%TESTNUMBER -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/outfile%TESTNUMBER -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -49,11 +49,11 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
12345
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -64,7 +64,7 @@
</file2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1367 b/tests/data/test1367
index a74a4c4..2492936 100644
--- a/tests/data/test1367
+++ b/tests/data/test1367
@@ -31,10 +31,10 @@
HTTP GET -o fname and Content-Disposition, -D stdout
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/outfile%TESTNUMBER -D -
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/outfile%TESTNUMBER -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -49,11 +49,11 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test1368 b/tests/data/test1368
index 629a635..1d6d181 100644
--- a/tests/data/test1368
+++ b/tests/data/test1368
@@ -31,10 +31,10 @@
HTTP GET -o fname -J without Content-Disposition, -D file
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -o log/outfile%TESTNUMBER -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -o %LOGDIR/outfile%TESTNUMBER -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER
</postcheck>
</client>
@@ -49,11 +49,11 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
12345
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -63,7 +63,7 @@
</file2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1369 b/tests/data/test1369
index 08665d1..48fd318 100644
--- a/tests/data/test1369
+++ b/tests/data/test1369
@@ -31,10 +31,10 @@
HTTP GET -o fname -J without Content-Disposition, -D stdout
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -o log/outfile%TESTNUMBER -D -
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -o %LOGDIR/outfile%TESTNUMBER -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER
</postcheck>
</client>
@@ -49,11 +49,11 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test1370 b/tests/data/test1370
index 96e7e74..d769401 100644
--- a/tests/data/test1370
+++ b/tests/data/test1370
@@ -32,10 +32,10 @@
HTTP GET -o fname -J and Content-Disposition, -D file
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -o log/outfile%TESTNUMBER -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -o %LOGDIR/outfile%TESTNUMBER -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -50,11 +50,11 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
12345
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -65,7 +65,7 @@
</file2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1371 b/tests/data/test1371
index aa5c69a..8565363 100644
--- a/tests/data/test1371
+++ b/tests/data/test1371
@@ -32,10 +32,10 @@
HTTP GET -o fname -J and Content-Disposition, -D stdout
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -o log/outfile%TESTNUMBER -D -
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -o %LOGDIR/outfile%TESTNUMBER -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -50,11 +50,11 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test1372 b/tests/data/test1372
index 29c478c..76b3671 100644
--- a/tests/data/test1372
+++ b/tests/data/test1372
@@ -30,10 +30,10 @@
HTTP GET -o fname -i without Content-Disposition, -D file
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -o log/outfile%TESTNUMBER -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -o %LOGDIR/outfile%TESTNUMBER -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER
</postcheck>
</client>
@@ -48,7 +48,7 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -59,7 +59,7 @@
12345
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -69,7 +69,7 @@
</file2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1373 b/tests/data/test1373
index b4c737d..c475deb 100644
--- a/tests/data/test1373
+++ b/tests/data/test1373
@@ -30,10 +30,10 @@
HTTP GET -o fname -i without Content-Disposition, -D stdout
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -o log/outfile%TESTNUMBER -D -
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -o %LOGDIR/outfile%TESTNUMBER -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER
</postcheck>
</client>
@@ -48,7 +48,7 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -59,7 +59,7 @@
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test1374 b/tests/data/test1374
index 07bd3bb..aa2b3e3 100644
--- a/tests/data/test1374
+++ b/tests/data/test1374
@@ -31,10 +31,10 @@
HTTP GET -o fname -i and Content-Disposition, -D file
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -o log/outfile%TESTNUMBER -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -o %LOGDIR/outfile%TESTNUMBER -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -49,7 +49,7 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -61,7 +61,7 @@
12345
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -72,7 +72,7 @@
</file2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1375 b/tests/data/test1375
index 2acdb54..6df5526 100644
--- a/tests/data/test1375
+++ b/tests/data/test1375
@@ -31,10 +31,10 @@
HTTP GET -o fname -i and Content-Disposition, -D stdout
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -o log/outfile%TESTNUMBER -D -
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -o %LOGDIR/outfile%TESTNUMBER -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -49,7 +49,7 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -61,7 +61,7 @@
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test1376 b/tests/data/test1376
index f81f35f..f3d36e0 100644
--- a/tests/data/test1376
+++ b/tests/data/test1376
@@ -30,10 +30,10 @@
HTTP GET -o fname -i without Content-Disposition, without -D
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -o log/outfile%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -o %LOGDIR/outfile%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER
</postcheck>
</client>
@@ -48,7 +48,7 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -59,7 +59,7 @@
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
</file2>
</verify>
diff --git a/tests/data/test1377 b/tests/data/test1377
index 745f08f..d1a6b72 100644
--- a/tests/data/test1377
+++ b/tests/data/test1377
@@ -31,10 +31,10 @@
HTTP GET -o fname -i and Content-Disposition, without -D
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -o log/outfile%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -i -o %LOGDIR/outfile%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -49,7 +49,7 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -61,7 +61,7 @@
12345
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
</file2>
</verify>
diff --git a/tests/data/test1378 b/tests/data/test1378
index d04e740..7348a3f 100644
--- a/tests/data/test1378
+++ b/tests/data/test1378
@@ -23,10 +23,10 @@
FTP DL, file without Content-Disposition inside, using -o fname
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER
</postcheck>
</client>
@@ -44,12 +44,12 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
fooo
mooo
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
</file2>
</verify>
diff --git a/tests/data/test1379 b/tests/data/test1379
index e611ac6..0b8d20a 100644
--- a/tests/data/test1379
+++ b/tests/data/test1379
@@ -23,10 +23,10 @@
FTP DL, file without C-D inside, using -o fname -D file
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -D log/heads%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER
</postcheck>
</client>
@@ -44,12 +44,12 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
fooo
mooo
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
@@ -69,7 +69,7 @@
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
</stripfile2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1380 b/tests/data/test1380
index 3cc5261..187dd8c 100644
--- a/tests/data/test1380
+++ b/tests/data/test1380
@@ -23,10 +23,10 @@
FTP DL, file without C-D inside, using -o fname -D stdout
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -D -
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER
</postcheck>
</client>
@@ -44,12 +44,12 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
fooo
mooo
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
diff --git a/tests/data/test1381 b/tests/data/test1381
index a62ee47..4ba20eb 100644
--- a/tests/data/test1381
+++ b/tests/data/test1381
@@ -24,10 +24,10 @@
FTP DL, file without C-D inside, using -o fname -J -D file
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -J -D log/heads%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -J -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER
</postcheck>
</client>
@@ -45,12 +45,12 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
fooo
mooo
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
@@ -70,7 +70,7 @@
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
</stripfile2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1382 b/tests/data/test1382
index 8c49877..26ff7ac 100644
--- a/tests/data/test1382
+++ b/tests/data/test1382
@@ -24,10 +24,10 @@
FTP DL, file without C-D inside, using -o fname -J -D stdout
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -J -D -
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -J -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER
</postcheck>
</client>
@@ -45,12 +45,12 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
fooo
mooo
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
diff --git a/tests/data/test1383 b/tests/data/test1383
index 34f3cf6..d4c5c82 100644
--- a/tests/data/test1383
+++ b/tests/data/test1383
@@ -23,10 +23,10 @@
FTP DL, file without C-D inside, using -o fname -i -D file
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -i -D log/heads%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -i -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER
</postcheck>
</client>
@@ -44,12 +44,12 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
fooo
mooo
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
@@ -69,7 +69,7 @@
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
</stripfile2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1384 b/tests/data/test1384
index f27d59a..af7afdf 100644
--- a/tests/data/test1384
+++ b/tests/data/test1384
@@ -23,10 +23,10 @@
FTP DL, file without C-D inside, using -o fname -i -D stdout
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -i -D -
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -i -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER
</postcheck>
</client>
@@ -44,12 +44,12 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
fooo
mooo
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
diff --git a/tests/data/test1385 b/tests/data/test1385
index e35c674..d2038ee 100644
--- a/tests/data/test1385
+++ b/tests/data/test1385
@@ -23,10 +23,10 @@
FTP DL, file without C-D inside, using -o fname -i, without -D
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -i
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -i
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER
</postcheck>
</client>
@@ -44,12 +44,12 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
fooo
mooo
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
</file2>
</verify>
diff --git a/tests/data/test1386 b/tests/data/test1386
index 471493b..0aaf664 100644
--- a/tests/data/test1386
+++ b/tests/data/test1386
@@ -31,10 +31,10 @@
FTP DL, file with Content-Disposition inside, using -o fname
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -52,7 +52,7 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -64,7 +64,7 @@
MOOOO
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
</file2>
</verify>
diff --git a/tests/data/test1387 b/tests/data/test1387
index c8f5ae6..0f124d8 100644
--- a/tests/data/test1387
+++ b/tests/data/test1387
@@ -31,10 +31,10 @@
FTP DL, file with C-D inside, using -o fname -D file
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -D log/heads%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -52,7 +52,7 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -64,7 +64,7 @@
MOOOO
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
@@ -84,7 +84,7 @@
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
</stripfile2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1388 b/tests/data/test1388
index 479ca42..d78844e 100644
--- a/tests/data/test1388
+++ b/tests/data/test1388
@@ -31,10 +31,10 @@
FTP DL, file with C-D inside, using -o fname -D stdout
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -D -
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -52,7 +52,7 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -64,7 +64,7 @@
MOOOO
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
diff --git a/tests/data/test1389 b/tests/data/test1389
index eb35d39..0863a40 100644
--- a/tests/data/test1389
+++ b/tests/data/test1389
@@ -32,10 +32,10 @@
FTP DL, file with C-D inside, using -o fname -J -D file
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -J -D log/heads%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -J -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -53,7 +53,7 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -65,7 +65,7 @@
MOOOO
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
@@ -85,7 +85,7 @@
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
</stripfile2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1390 b/tests/data/test1390
index fc30849..a856d1e 100644
--- a/tests/data/test1390
+++ b/tests/data/test1390
@@ -32,10 +32,10 @@
FTP DL, file with C-D inside, using -o fname -J -D stdout
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -J -D -
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -J -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -53,7 +53,7 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -65,7 +65,7 @@
MOOOO
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
diff --git a/tests/data/test1391 b/tests/data/test1391
index ce28e5a..ae1495e 100644
--- a/tests/data/test1391
+++ b/tests/data/test1391
@@ -31,10 +31,10 @@
FTP DL, file with C-D inside, using -o fname -i -D file
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -i -D log/heads%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -i -D %LOGDIR/heads%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -52,7 +52,7 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -64,7 +64,7 @@
MOOOO
</file1>
-<file2 name="log/heads%TESTNUMBER">
+<file2 name="%LOGDIR/heads%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
@@ -84,7 +84,7 @@
s/^(229 Entering Passive Mode \().*(\).*)/${1}stripped${2}/
</stripfile2>
-<file3 name="log/stdout%TESTNUMBER">
+<file3 name="%LOGDIR/stdout%TESTNUMBER">
</file3>
</verify>
diff --git a/tests/data/test1392 b/tests/data/test1392
index 99e13c3..f715fe8 100644
--- a/tests/data/test1392
+++ b/tests/data/test1392
@@ -31,10 +31,10 @@
FTP DL, file with C-D inside, using -o fname -i -D stdout
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -i -D -
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -i -D -
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -52,7 +52,7 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -64,7 +64,7 @@
MOOOO
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
220- _ _ ____ _
220- ___| | | | _ \| |
220- / __| | | | |_) | |
diff --git a/tests/data/test1393 b/tests/data/test1393
index 1402eaf..dc7a6f9 100644
--- a/tests/data/test1393
+++ b/tests/data/test1393
@@ -31,10 +31,10 @@
FTP DL, file with C-D inside, using -o fname -i, without -D
</name>
<command option="no-output,no-include">
-ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o log/download%TESTNUMBER -i
+ftp://%HOSTIP:%FTPPORT/path/file%TESTNUMBER -o %LOGDIR/download%TESTNUMBER -i
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/file%TESTNUMBER log/name%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/file%TESTNUMBER %LOGDIR/name%TESTNUMBER
</postcheck>
</client>
@@ -52,7 +52,7 @@
QUIT
</protocol>
-<file1 name="log/download%TESTNUMBER">
+<file1 name="%LOGDIR/download%TESTNUMBER">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -64,7 +64,7 @@
MOOOO
</file1>
-<file2 name="log/stdout%TESTNUMBER">
+<file2 name="%LOGDIR/stdout%TESTNUMBER">
</file2>
</verify>
diff --git a/tests/data/test1397 b/tests/data/test1397
index 84f962a..f31b2c2 100644
--- a/tests/data/test1397
+++ b/tests/data/test1397
@@ -2,8 +2,7 @@
<info>
<keywords>
unittest
-ssl
-wildcard
+Curl_cert_hostcheck
</keywords>
</info>
@@ -16,9 +15,8 @@
<features>
unittest
</features>
- <name>
-Check wildcard certificate matching function Curl_cert_hostcheck
- </name>
+<name>
+Curl_cert_hostcheck unit tests
+</name>
</client>
-
</testcase>
diff --git a/tests/data/test1400 b/tests/data/test1400
index b4d29d3..837a20b 100644
--- a/tests/data/test1400
+++ b/tests/data/test1400
@@ -31,7 +31,7 @@
SSL_CERT_FILE=
</setenv>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --libcurl log/test%TESTNUMBER.c
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --libcurl %LOGDIR/test%TESTNUMBER.c
</command>
</client>
@@ -55,7 +55,7 @@
$_ = '' if /CURLOPT_HTTP09_ALLOWED/
$_ = '' if /CURLOPT_INTERLEAVEDATA/
</stripfile>
-<file name="log/test%TESTNUMBER.c" mode="text">
+<file name="%LOGDIR/test%TESTNUMBER.c" mode="text">
/********* 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
@@ -82,18 +82,18 @@
as source easily. You may choose to either not use them or implement
them yourself.
- CURLOPT_WRITEDATA set to a objectpointer
- CURLOPT_WRITEFUNCTION set to a functionpointer
- CURLOPT_READDATA set to a objectpointer
- CURLOPT_READFUNCTION set to a functionpointer
- CURLOPT_SEEKDATA set to a objectpointer
- CURLOPT_SEEKFUNCTION set to a functionpointer
- CURLOPT_ERRORBUFFER set to a objectpointer
- CURLOPT_STDERR set to a objectpointer
- CURLOPT_DEBUGFUNCTION set to a functionpointer
- CURLOPT_DEBUGDATA set to a objectpointer
- CURLOPT_HEADERFUNCTION set to a functionpointer
- CURLOPT_HEADERDATA set to a objectpointer
+ CURLOPT_WRITEDATA was set to an object pointer
+ CURLOPT_WRITEFUNCTION was set to a function pointer
+ CURLOPT_READDATA was set to an object pointer
+ CURLOPT_READFUNCTION was set to a function pointer
+ CURLOPT_SEEKDATA was set to an object pointer
+ CURLOPT_SEEKFUNCTION was set to a function pointer
+ CURLOPT_ERRORBUFFER was set to an object pointer
+ CURLOPT_STDERR was set to an object pointer
+ CURLOPT_DEBUGFUNCTION was set to a function pointer
+ CURLOPT_DEBUGDATA was set to an object pointer
+ CURLOPT_HEADERFUNCTION was set to a function pointer
+ CURLOPT_HEADERDATA was set to an object pointer
*/
diff --git a/tests/data/test1401 b/tests/data/test1401
index 65efc47..1706545 100644
--- a/tests/data/test1401
+++ b/tests/data/test1401
@@ -31,11 +31,16 @@
<name>
--libcurl for GET with various options
</name>
+<features>
+http
+ftp
+file
+</features>
<setenv>
SSL_CERT_FILE=
</setenv>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --libcurl log/test%TESTNUMBER.c --basic -u fake:user -H "X-Files: Mulder" -H "X-Men: cyclops, iceman" -A MyUA -b chocolate=chip --proto "=http,ftp,file"
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --libcurl %LOGDIR/test%TESTNUMBER.c --basic -u fake:user -H "X-Files: Mulder" -H "X-Men: cyclops, iceman" -A MyUA -b chocolate=chip --proto "=http,ftp,file"
</command>
</client>
@@ -60,7 +65,7 @@
$_ = '' if /CURLOPT_HTTP_VERSION/
$_ = '' if /CURLOPT_INTERLEAVEDATA/
</stripfile>
-<file name="log/test%TESTNUMBER.c" mode="text">
+<file name="%LOGDIR/test%TESTNUMBER.c" mode="text">
/********* 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
@@ -91,26 +96,24 @@
curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
%endif
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
- curl_easy_setopt(hnd, CURLOPT_PROTOCOLS, (long)CURLPROTO_FILE |
- (long)CURLPROTO_FTP |
- (long)CURLPROTO_HTTP);
+ curl_easy_setopt(hnd, CURLOPT_PROTOCOLS_STR, "file,ftp,http");
/* 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.
- CURLOPT_WRITEDATA set to a objectpointer
- CURLOPT_WRITEFUNCTION set to a functionpointer
- CURLOPT_READDATA set to a objectpointer
- CURLOPT_READFUNCTION set to a functionpointer
- CURLOPT_SEEKDATA set to a objectpointer
- CURLOPT_SEEKFUNCTION set to a functionpointer
- CURLOPT_ERRORBUFFER set to a objectpointer
- CURLOPT_STDERR set to a objectpointer
- CURLOPT_DEBUGFUNCTION set to a functionpointer
- CURLOPT_DEBUGDATA set to a objectpointer
- CURLOPT_HEADERFUNCTION set to a functionpointer
- CURLOPT_HEADERDATA set to a objectpointer
+ CURLOPT_WRITEDATA was set to an object pointer
+ CURLOPT_WRITEFUNCTION was set to a function pointer
+ CURLOPT_READDATA was set to an object pointer
+ CURLOPT_READFUNCTION was set to a function pointer
+ CURLOPT_SEEKDATA was set to an object pointer
+ CURLOPT_SEEKFUNCTION was set to a function pointer
+ CURLOPT_ERRORBUFFER was set to an object pointer
+ CURLOPT_STDERR was set to an object pointer
+ CURLOPT_DEBUGFUNCTION was set to a function pointer
+ CURLOPT_DEBUGDATA was set to an object pointer
+ CURLOPT_HEADERFUNCTION was set to a function pointer
+ CURLOPT_HEADERDATA was set to an object pointer
*/
diff --git a/tests/data/test1402 b/tests/data/test1402
index c111af4..5003ba8 100644
--- a/tests/data/test1402
+++ b/tests/data/test1402
@@ -32,7 +32,7 @@
SSL_CERT_FILE=
</setenv>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --libcurl log/test%TESTNUMBER.c -d "foo=bar" -d "baz=quux"
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --libcurl %LOGDIR/test%TESTNUMBER.c -d "foo=bar" -d "baz=quux"
</command>
</client>
@@ -58,7 +58,7 @@
$_ = '' if /CURLOPT_HTTP_VERSION/
$_ = '' if /CURLOPT_INTERLEAVEDATA/
</stripfile>
-<file name="log/test%TESTNUMBER.c" mode="text">
+<file name="%LOGDIR/test%TESTNUMBER.c" mode="text">
/********* 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
@@ -87,18 +87,18 @@
as source easily. You may choose to either not use them or implement
them yourself.
- CURLOPT_WRITEDATA set to a objectpointer
- CURLOPT_WRITEFUNCTION set to a functionpointer
- CURLOPT_READDATA set to a objectpointer
- CURLOPT_READFUNCTION set to a functionpointer
- CURLOPT_SEEKDATA set to a objectpointer
- CURLOPT_SEEKFUNCTION set to a functionpointer
- CURLOPT_ERRORBUFFER set to a objectpointer
- CURLOPT_STDERR set to a objectpointer
- CURLOPT_DEBUGFUNCTION set to a functionpointer
- CURLOPT_DEBUGDATA set to a objectpointer
- CURLOPT_HEADERFUNCTION set to a functionpointer
- CURLOPT_HEADERDATA set to a objectpointer
+ CURLOPT_WRITEDATA was set to an object pointer
+ CURLOPT_WRITEFUNCTION was set to a function pointer
+ CURLOPT_READDATA was set to an object pointer
+ CURLOPT_READFUNCTION was set to a function pointer
+ CURLOPT_SEEKDATA was set to an object pointer
+ CURLOPT_SEEKFUNCTION was set to a function pointer
+ CURLOPT_ERRORBUFFER was set to an object pointer
+ CURLOPT_STDERR was set to an object pointer
+ CURLOPT_DEBUGFUNCTION was set to a function pointer
+ CURLOPT_DEBUGDATA was set to an object pointer
+ CURLOPT_HEADERFUNCTION was set to a function pointer
+ CURLOPT_HEADERDATA was set to an object pointer
*/
diff --git a/tests/data/test1403 b/tests/data/test1403
index 46bd63d..3eab622 100644
--- a/tests/data/test1403
+++ b/tests/data/test1403
@@ -32,7 +32,7 @@
SSL_CERT_FILE=
</setenv>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --libcurl log/test%TESTNUMBER.c -G -d "foo=bar" -d "baz=quux"
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --libcurl %LOGDIR/test%TESTNUMBER.c -G -d "foo=bar" -d "baz=quux"
</command>
</client>
@@ -55,7 +55,7 @@
$_ = '' if /CURLOPT_HTTP_VERSION/
$_ = '' if /CURLOPT_INTERLEAVEDATA/
</stripfile>
-<file name="log/test%TESTNUMBER.c" mode="text">
+<file name="%LOGDIR/test%TESTNUMBER.c" mode="text">
/********* 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
@@ -82,18 +82,18 @@
as source easily. You may choose to either not use them or implement
them yourself.
- CURLOPT_WRITEDATA set to a objectpointer
- CURLOPT_WRITEFUNCTION set to a functionpointer
- CURLOPT_READDATA set to a objectpointer
- CURLOPT_READFUNCTION set to a functionpointer
- CURLOPT_SEEKDATA set to a objectpointer
- CURLOPT_SEEKFUNCTION set to a functionpointer
- CURLOPT_ERRORBUFFER set to a objectpointer
- CURLOPT_STDERR set to a objectpointer
- CURLOPT_DEBUGFUNCTION set to a functionpointer
- CURLOPT_DEBUGDATA set to a objectpointer
- CURLOPT_HEADERFUNCTION set to a functionpointer
- CURLOPT_HEADERDATA set to a objectpointer
+ CURLOPT_WRITEDATA was set to an object pointer
+ CURLOPT_WRITEFUNCTION was set to a function pointer
+ CURLOPT_READDATA was set to an object pointer
+ CURLOPT_READFUNCTION was set to a function pointer
+ CURLOPT_SEEKDATA was set to an object pointer
+ CURLOPT_SEEKFUNCTION was set to a function pointer
+ CURLOPT_ERRORBUFFER was set to an object pointer
+ CURLOPT_STDERR was set to an object pointer
+ CURLOPT_DEBUGFUNCTION was set to a function pointer
+ CURLOPT_DEBUGDATA was set to an object pointer
+ CURLOPT_HEADERFUNCTION was set to a function pointer
+ CURLOPT_HEADERDATA was set to an object pointer
*/
diff --git a/tests/data/test1404 b/tests/data/test1404
index 3b41c5c..f18ad8a 100644
--- a/tests/data/test1404
+++ b/tests/data/test1404
@@ -23,6 +23,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -33,10 +36,10 @@
SSL_CERT_FILE=
</setenv>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F name=value -F 'file=@log/test%TESTNUMBER.txt,log/test%TESTNUMBER.txt;type=magic/content;encoder=8bit,log/test%TESTNUMBER.txt;headers=X-testheader-1: header 1;headers=X-testheader-2: header 2' --libcurl log/test%TESTNUMBER.c
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F name=value -F 'file=@%LOGDIR/test%TESTNUMBER.txt,%LOGDIR/test%TESTNUMBER.txt;type=magic/content;encoder=8bit,%LOGDIR/test%TESTNUMBER.txt;headers=X-testheader-1: header 1;headers=X-testheader-2: header 2' --libcurl %LOGDIR/test%TESTNUMBER.c
</command>
# We create this file before the command is invoked!
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
dummy data
</file>
</client>
@@ -98,7 +101,7 @@
# CURL_DOES_CONVERSION generates an extra comment.
$_ = '' if /\/\* "value" \*\//
</stripfile>
-<file name="log/test%TESTNUMBER.c" mode="text">
+<file name="%LOGDIR/test%TESTNUMBER.c" mode="text">
/********* 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
@@ -131,13 +134,13 @@
part1 = curl_mime_addpart(mime1);
mime2 = curl_mime_init(hnd);
part2 = curl_mime_addpart(mime2);
- curl_mime_filedata(part2, "log/test%TESTNUMBER.txt");
+ curl_mime_filedata(part2, "%LOGDIR/test%TESTNUMBER.txt");
part2 = curl_mime_addpart(mime2);
- curl_mime_filedata(part2, "log/test%TESTNUMBER.txt");
+ curl_mime_filedata(part2, "%LOGDIR/test%TESTNUMBER.txt");
curl_mime_encoder(part2, "8bit");
curl_mime_type(part2, "magic/content");
part2 = curl_mime_addpart(mime2);
- curl_mime_filedata(part2, "log/test%TESTNUMBER.txt");
+ curl_mime_filedata(part2, "%LOGDIR/test%TESTNUMBER.txt");
curl_mime_headers(part2, slist1, 1);
slist1 = NULL;
curl_mime_subparts(part1, mime2);
@@ -156,18 +159,18 @@
as source easily. You may choose to either not use them or implement
them yourself.
- CURLOPT_WRITEDATA set to a objectpointer
- CURLOPT_WRITEFUNCTION set to a functionpointer
- CURLOPT_READDATA set to a objectpointer
- CURLOPT_READFUNCTION set to a functionpointer
- CURLOPT_SEEKDATA set to a objectpointer
- CURLOPT_SEEKFUNCTION set to a functionpointer
- CURLOPT_ERRORBUFFER set to a objectpointer
- CURLOPT_STDERR set to a objectpointer
- CURLOPT_DEBUGFUNCTION set to a functionpointer
- CURLOPT_DEBUGDATA set to a objectpointer
- CURLOPT_HEADERFUNCTION set to a functionpointer
- CURLOPT_HEADERDATA set to a objectpointer
+ CURLOPT_WRITEDATA was set to an object pointer
+ CURLOPT_WRITEFUNCTION was set to a function pointer
+ CURLOPT_READDATA was set to an object pointer
+ CURLOPT_READFUNCTION was set to a function pointer
+ CURLOPT_SEEKDATA was set to an object pointer
+ CURLOPT_SEEKFUNCTION was set to a function pointer
+ CURLOPT_ERRORBUFFER was set to an object pointer
+ CURLOPT_STDERR was set to an object pointer
+ CURLOPT_DEBUGFUNCTION was set to a function pointer
+ CURLOPT_DEBUGDATA was set to an object pointer
+ CURLOPT_HEADERFUNCTION was set to a function pointer
+ CURLOPT_HEADERDATA was set to an object pointer
*/
diff --git a/tests/data/test1405 b/tests/data/test1405
index aa7cf4d..5bb0450 100644
--- a/tests/data/test1405
+++ b/tests/data/test1405
@@ -36,7 +36,7 @@
SSL_CERT_FILE=
</setenv>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -Q "NOOP 1" -Q "+NOOP 2" -Q "-NOOP 3" -Q "*FAIL" -Q "+*FAIL HARD" --libcurl log/test%TESTNUMBER.c
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -Q "NOOP 1" -Q "+NOOP 2" -Q "-NOOP 3" -Q "*FAIL" -Q "+*FAIL HARD" --libcurl %LOGDIR/test%TESTNUMBER.c
</command>
</client>
@@ -58,7 +58,7 @@
NOOP 3
QUIT
</protocol>
-<file name="log/test%TESTNUMBER.c" mode="text">
+<file name="%LOGDIR/test%TESTNUMBER.c" mode="text">
/********* 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
@@ -96,18 +96,18 @@
as source easily. You may choose to either not use them or implement
them yourself.
- CURLOPT_WRITEDATA set to a objectpointer
- CURLOPT_WRITEFUNCTION set to a functionpointer
- CURLOPT_READDATA set to a objectpointer
- CURLOPT_READFUNCTION set to a functionpointer
- CURLOPT_SEEKDATA set to a objectpointer
- CURLOPT_SEEKFUNCTION set to a functionpointer
- CURLOPT_ERRORBUFFER set to a objectpointer
- CURLOPT_STDERR set to a objectpointer
- CURLOPT_DEBUGFUNCTION set to a functionpointer
- CURLOPT_DEBUGDATA set to a objectpointer
- CURLOPT_HEADERFUNCTION set to a functionpointer
- CURLOPT_HEADERDATA set to a objectpointer
+ CURLOPT_WRITEDATA was set to an object pointer
+ CURLOPT_WRITEFUNCTION was set to a function pointer
+ CURLOPT_READDATA was set to an object pointer
+ CURLOPT_READFUNCTION was set to a function pointer
+ CURLOPT_SEEKDATA was set to an object pointer
+ CURLOPT_SEEKFUNCTION was set to a function pointer
+ CURLOPT_ERRORBUFFER was set to an object pointer
+ CURLOPT_STDERR was set to an object pointer
+ CURLOPT_DEBUGFUNCTION was set to a function pointer
+ CURLOPT_DEBUGDATA was set to an object pointer
+ CURLOPT_HEADERFUNCTION was set to a function pointer
+ CURLOPT_HEADERDATA was set to an object pointer
*/
diff --git a/tests/data/test1406 b/tests/data/test1406
index 969df63..3a00b44 100644
--- a/tests/data/test1406
+++ b/tests/data/test1406
@@ -28,14 +28,14 @@
<setenv>
SSL_CERT_FILE=
</setenv>
-<file name="log/test%TESTNUMBER.eml">
+<file name="%LOGDIR/test%TESTNUMBER.eml">
From: different
To: another
body
</file>
<command>
-smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient.one@example.com --mail-rcpt recipient.two@example.com --mail-from sender@example.com -T log/test%TESTNUMBER.eml --libcurl log/test%TESTNUMBER.c
+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient.one@example.com --mail-rcpt recipient.two@example.com --mail-from sender@example.com -T %LOGDIR/test%TESTNUMBER.eml --libcurl %LOGDIR/test%TESTNUMBER.c
</command>
</client>
@@ -57,7 +57,7 @@
body
.
</upload>
-<file name="log/test%TESTNUMBER.c" mode="text">
+<file name="%LOGDIR/test%TESTNUMBER.c" mode="text">
/********* 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
@@ -89,18 +89,18 @@
as source easily. You may choose to either not use them or implement
them yourself.
- CURLOPT_WRITEDATA set to a objectpointer
- CURLOPT_WRITEFUNCTION set to a functionpointer
- CURLOPT_READDATA set to a objectpointer
- CURLOPT_READFUNCTION set to a functionpointer
- CURLOPT_SEEKDATA set to a objectpointer
- CURLOPT_SEEKFUNCTION set to a functionpointer
- CURLOPT_ERRORBUFFER set to a objectpointer
- CURLOPT_STDERR set to a objectpointer
- CURLOPT_DEBUGFUNCTION set to a functionpointer
- CURLOPT_DEBUGDATA set to a objectpointer
- CURLOPT_HEADERFUNCTION set to a functionpointer
- CURLOPT_HEADERDATA set to a objectpointer
+ CURLOPT_WRITEDATA was set to an object pointer
+ CURLOPT_WRITEFUNCTION was set to a function pointer
+ CURLOPT_READDATA was set to an object pointer
+ CURLOPT_READFUNCTION was set to a function pointer
+ CURLOPT_SEEKDATA was set to an object pointer
+ CURLOPT_SEEKFUNCTION was set to a function pointer
+ CURLOPT_ERRORBUFFER was set to an object pointer
+ CURLOPT_STDERR was set to an object pointer
+ CURLOPT_DEBUGFUNCTION was set to a function pointer
+ CURLOPT_DEBUGDATA was set to an object pointer
+ CURLOPT_HEADERFUNCTION was set to a function pointer
+ CURLOPT_HEADERDATA was set to an object pointer
*/
diff --git a/tests/data/test1407 b/tests/data/test1407
index 7f48de2..160c864 100644
--- a/tests/data/test1407
+++ b/tests/data/test1407
@@ -30,7 +30,7 @@
SSL_CERT_FILE=
</setenv>
<command>
-pop3://%HOSTIP:%POP3PORT/%TESTNUMBER -l -u user:secret --libcurl log/test%TESTNUMBER.c
+pop3://%HOSTIP:%POP3PORT/%TESTNUMBER -l -u user:secret --libcurl %LOGDIR/test%TESTNUMBER.c
</command>
</client>
@@ -44,7 +44,7 @@
LIST %TESTNUMBER
QUIT
</protocol>
-<file name="log/test%TESTNUMBER.c" mode="text">
+<file name="%LOGDIR/test%TESTNUMBER.c" mode="text">
/********* 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
@@ -69,18 +69,18 @@
as source easily. You may choose to either not use them or implement
them yourself.
- CURLOPT_WRITEDATA set to a objectpointer
- CURLOPT_WRITEFUNCTION set to a functionpointer
- CURLOPT_READDATA set to a objectpointer
- CURLOPT_READFUNCTION set to a functionpointer
- CURLOPT_SEEKDATA set to a objectpointer
- CURLOPT_SEEKFUNCTION set to a functionpointer
- CURLOPT_ERRORBUFFER set to a objectpointer
- CURLOPT_STDERR set to a objectpointer
- CURLOPT_DEBUGFUNCTION set to a functionpointer
- CURLOPT_DEBUGDATA set to a objectpointer
- CURLOPT_HEADERFUNCTION set to a functionpointer
- CURLOPT_HEADERDATA set to a objectpointer
+ CURLOPT_WRITEDATA was set to an object pointer
+ CURLOPT_WRITEFUNCTION was set to a function pointer
+ CURLOPT_READDATA was set to an object pointer
+ CURLOPT_READFUNCTION was set to a function pointer
+ CURLOPT_SEEKDATA was set to an object pointer
+ CURLOPT_SEEKFUNCTION was set to a function pointer
+ CURLOPT_ERRORBUFFER was set to an object pointer
+ CURLOPT_STDERR was set to an object pointer
+ CURLOPT_DEBUGFUNCTION was set to a function pointer
+ CURLOPT_DEBUGDATA was set to an object pointer
+ CURLOPT_HEADERFUNCTION was set to a function pointer
+ CURLOPT_HEADERDATA was set to an object pointer
*/
diff --git a/tests/data/test1408 b/tests/data/test1408
index d4f40f7..e27923a 100644
--- a/tests/data/test1408
+++ b/tests/data/test1408
@@ -39,6 +39,7 @@
# Client-side
<client>
<features>
+cookies
ipv6
</features>
<server>
@@ -48,7 +49,7 @@
HTTP receive cookies over IPV6
</name>
<command>
--c log/jar%TESTNUMBER -g http://%HOST6IP:%HTTP6PORT/path/%TESTNUMBER0001 http://%HOST6IP:%HTTP6PORT/path/%TESTNUMBER0002
+-c %LOGDIR/jar%TESTNUMBER -g http://%HOST6IP:%HTTP6PORT/path/%TESTNUMBER0001 http://%HOST6IP:%HTTP6PORT/path/%TESTNUMBER0002
</command>
</client>
diff --git a/tests/data/test1411 b/tests/data/test1411
index a7d23ee..47b36f2 100644
--- a/tests/data/test1411
+++ b/tests/data/test1411
@@ -36,10 +36,10 @@
HTTP with zero size file PUT
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T log/empty%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T %LOGDIR/empty%TESTNUMBER
</command>
# create an empty file
-<file name="log/empty%TESTNUMBER">
+<file name="%LOGDIR/empty%TESTNUMBER">
</file>
</client>
diff --git a/tests/data/test1412 b/tests/data/test1412
index 2052170..32737dc 100644
--- a/tests/data/test1412
+++ b/tests/data/test1412
@@ -96,12 +96,6 @@
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u testuser:testpass --anyauth http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001
</command>
-<file name="log/put%TESTNUMBER">
-This is data we upload with PUT
-a second line
-line three
-four is the number of lines
-</file>
</client>
# Verify data after the test has been "shot"
diff --git a/tests/data/test1415 b/tests/data/test1415
index 79b14e6..82f8379 100644
--- a/tests/data/test1415
+++ b/tests/data/test1415
@@ -44,9 +44,10 @@
TZ=GMT
</setenv>
<command>
-http://example.com/we/want/%TESTNUMBER -b none -c log/jar%TESTNUMBER.txt -x %HOSTIP:%HTTPPORT
+http://example.com/we/want/%TESTNUMBER -b none -c %LOGDIR/jar%TESTNUMBER.txt -x %HOSTIP:%HTTPPORT
</command>
<features>
+cookies
proxy
</features>
</client>
@@ -62,7 +63,7 @@
</protocol>
-<file name="log/jar%TESTNUMBER.txt" mode="text">
+<file name="%LOGDIR/jar%TESTNUMBER.txt" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test1417 b/tests/data/test1417
index a0dd086..4400cec 100644
--- a/tests/data/test1417
+++ b/tests/data/test1417
@@ -49,7 +49,7 @@
HTTP GET with chunked encoding and chunked trailer without CRs
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -D %LOGDIR/heads%TESTNUMBER
</command>
</client>
@@ -63,7 +63,7 @@
Accept: */*
</protocol>
-<file name="log/heads%TESTNUMBER">
+<file name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 funky chunky!
Server: fakeit/0.9 fakeitbad/1.0
Transfer-Encoding: chunked
diff --git a/tests/data/test1420 b/tests/data/test1420
index 92905fa..e6f899f 100644
--- a/tests/data/test1420
+++ b/tests/data/test1420
@@ -36,7 +36,7 @@
SSL_CERT_FILE=
</setenv>
<command>
-'imap://%HOSTIP:%IMAPPORT/%TESTNUMBER/;MAILINDEX=1' -u user:secret --libcurl log/test%TESTNUMBER.c
+'imap://%HOSTIP:%IMAPPORT/%TESTNUMBER/;MAILINDEX=1' -u user:secret --libcurl %LOGDIR/test%TESTNUMBER.c
</command>
</client>
@@ -50,7 +50,7 @@
A004 FETCH 1 BODY[]
A005 LOGOUT
</protocol>
-<file name="log/test%TESTNUMBER.c" mode="text">
+<file name="%LOGDIR/test%TESTNUMBER.c" mode="text">
/********* 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
@@ -74,18 +74,18 @@
as source easily. You may choose to either not use them or implement
them yourself.
- CURLOPT_WRITEDATA set to a objectpointer
- CURLOPT_WRITEFUNCTION set to a functionpointer
- CURLOPT_READDATA set to a objectpointer
- CURLOPT_READFUNCTION set to a functionpointer
- CURLOPT_SEEKDATA set to a objectpointer
- CURLOPT_SEEKFUNCTION set to a functionpointer
- CURLOPT_ERRORBUFFER set to a objectpointer
- CURLOPT_STDERR set to a objectpointer
- CURLOPT_DEBUGFUNCTION set to a functionpointer
- CURLOPT_DEBUGDATA set to a objectpointer
- CURLOPT_HEADERFUNCTION set to a functionpointer
- CURLOPT_HEADERDATA set to a objectpointer
+ CURLOPT_WRITEDATA was set to an object pointer
+ CURLOPT_WRITEFUNCTION was set to a function pointer
+ CURLOPT_READDATA was set to an object pointer
+ CURLOPT_READFUNCTION was set to a function pointer
+ CURLOPT_SEEKDATA was set to an object pointer
+ CURLOPT_SEEKFUNCTION was set to a function pointer
+ CURLOPT_ERRORBUFFER was set to an object pointer
+ CURLOPT_STDERR was set to an object pointer
+ CURLOPT_DEBUGFUNCTION was set to a function pointer
+ CURLOPT_DEBUGDATA was set to an object pointer
+ CURLOPT_HEADERFUNCTION was set to a function pointer
+ CURLOPT_HEADERDATA was set to an object pointer
*/
diff --git a/tests/data/test1421 b/tests/data/test1421
index 5b55547..ec497ab 100644
--- a/tests/data/test1421
+++ b/tests/data/test1421
@@ -12,7 +12,7 @@
<reply>
<data nocheck="yes">
HTTP/1.1 200 OK
-Uknown-header: blrub
+Unknown-header: blrub
Content-Length: 6
-foo-
@@ -45,12 +45,12 @@
<verify>
<stdout>
HTTP/1.1 200 OK
-Uknown-header: blrub
+Unknown-header: blrub
Content-Length: 6
-foo-
HTTP/1.1 200 OK
-Uknown-header: blrub
+Unknown-header: blrub
Content-Length: 6
-foo-
diff --git a/tests/data/test1422 b/tests/data/test1422
index 7cd1d13..c62c2cb 100644
--- a/tests/data/test1422
+++ b/tests/data/test1422
@@ -37,10 +37,10 @@
HTTP GET with -O -J and Content-Disposition (empty file)
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -O file://%PWD/log/name%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -J -O file://%PWD/%LOGDIR/name%TESTNUMBER
</command>
</client>
@@ -55,7 +55,7 @@
</protocol>
-<file1 name="log/name%TESTNUMBER">
+<file1 name="%LOGDIR/name%TESTNUMBER">
</file1>
</verify>
diff --git a/tests/data/test1423 b/tests/data/test1423
index 2eb1d80..f269cc0 100644
--- a/tests/data/test1423
+++ b/tests/data/test1423
@@ -30,10 +30,10 @@
HTTP GET -o fname without Content-Disposition (empty file)
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/outfile%TESTNUMBER file://%PWD/log/outfile%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/outfile%TESTNUMBER file://%PWD/%LOGDIR/outfile%TESTNUMBER
</command>
<postcheck>
-perl %SRCDIR/libtest/notexists.pl log/%TESTNUMBER
+perl %SRCDIR/libtest/notexists.pl %LOGDIR/%TESTNUMBER
</postcheck>
</client>
@@ -48,7 +48,7 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
</file1>
</verify>
diff --git a/tests/data/test1424 b/tests/data/test1424
index ebe5f52..6405825 100644
--- a/tests/data/test1424
+++ b/tests/data/test1424
@@ -46,11 +46,11 @@
<name>
HTTP GET -o fname without Content-Disposition (unmet time condition)
</name>
-<file name="log/outfile%TESTNUMBER">
+<file name="%LOGDIR/outfile%TESTNUMBER">
original contents
</file>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -z "dec 12 11:00:00 1999 GMT" -o log/outfile%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -z "dec 12 11:00:00 1999 GMT" -o %LOGDIR/outfile%TESTNUMBER
</command>
</client>
@@ -66,7 +66,7 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
original contents
</file1>
diff --git a/tests/data/test1434 b/tests/data/test1434
index 4801ee2..75baba7 100644
--- a/tests/data/test1434
+++ b/tests/data/test1434
@@ -60,7 +60,7 @@
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -C 100
</command>
-<file name="log/curl%TESTNUMBER.out">
+<file name="%LOGDIR/curl%TESTNUMBER.out">
012345678
012345678
012345678
diff --git a/tests/data/test1440 b/tests/data/test1440
index e87cafb..dbdfc73 100644
--- a/tests/data/test1440
+++ b/tests/data/test1440
@@ -19,7 +19,7 @@
Check --write-out with trailing %{
</name>
<command>
-file://localhost/%PWD/log/non-existent-file.txt --write-out '%{'
+file://localhost/%PWD/%LOGDIR/non-existent-file.txt --write-out '%{'
</command>
</client>
diff --git a/tests/data/test1441 b/tests/data/test1441
index 8d841df..2ff6be0 100644
--- a/tests/data/test1441
+++ b/tests/data/test1441
@@ -19,7 +19,7 @@
Check --write-out with trailing %
</name>
<command>
-file://localhost/%PWD/log/non-existent-file.txt --write-out '%'
+file://localhost/%PWD/%LOGDIR/non-existent-file.txt --write-out '%'
</command>
</client>
diff --git a/tests/data/test1442 b/tests/data/test1442
index 255a4c9..02ecea6 100644
--- a/tests/data/test1442
+++ b/tests/data/test1442
@@ -19,7 +19,7 @@
Check --write-out with trailing \
</name>
<command>
-file://localhost/%PWD/log/non-existent-file.txt --write-out '\'
+file://localhost/%PWD/%LOGDIR/non-existent-file.txt --write-out '\'
</command>
</client>
diff --git a/tests/data/test1443 b/tests/data/test1443
index a59958a..bbfaf7f 100644
--- a/tests/data/test1443
+++ b/tests/data/test1443
@@ -37,7 +37,7 @@
HTTP GET with -O and --remote-time
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -O --remote-time
@@ -45,7 +45,7 @@
# Verify the mtime of the file. The mtime is specifically chosen to be an even
# number so that it can be represented exactly on a FAT filesystem.
<postcheck>
-perl -e 'exit((stat("log/%TESTNUMBER"))[9] != 960898200)'
+perl -e 'exit((stat("%LOGDIR/%TESTNUMBER"))[9] != 960898200)'
</postcheck>
</client>
@@ -59,7 +59,7 @@
Accept: */*
</protocol>
-<file name="log/%TESTNUMBER">
+<file name="%LOGDIR/%TESTNUMBER">
12345
</file>
</verify>
diff --git a/tests/data/test1444 b/tests/data/test1444
index 71b5f0e..7d79fbb 100644
--- a/tests/data/test1444
+++ b/tests/data/test1444
@@ -31,7 +31,7 @@
# Verify the mtime of the file. The mtime is specifically chosen to be an even
# number so that it can be represented exactly on a FAT filesystem.
<postcheck>
-perl -e 'exit((stat("log/curl%TESTNUMBER.out"))[9] != 1234567890)'
+perl -e 'exit((stat("%LOGDIR/curl%TESTNUMBER.out"))[9] != 1234567890)'
</postcheck>
</client>
diff --git a/tests/data/test1445 b/tests/data/test1445
index 1811e07..7fb1d1d 100644
--- a/tests/data/test1445
+++ b/tests/data/test1445
@@ -15,17 +15,17 @@
file
</server>
<precheck>
-perl %SRCDIR/libtest/test613.pl prepare %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test613.pl prepare %PWD/%LOGDIR/test%TESTNUMBER.dir
</precheck>
<name>
file:// with --remote-time
</name>
<command>
-file://localhost%FILE_PWD/log/test%TESTNUMBER.dir/plainfile.txt --remote-time
+file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.dir/plainfile.txt --remote-time
</command>
<postcheck>
-perl %SRCDIR/libtest/test613.pl postprocess %PWD/log/test%TESTNUMBER.dir && \
-perl -e 'exit((stat("log/curl%TESTNUMBER.out"))[9] != 946728000)'
+perl %SRCDIR/libtest/test613.pl postprocess %PWD/%LOGDIR/test%TESTNUMBER.dir && \
+perl -e 'exit((stat("%LOGDIR/curl%TESTNUMBER.out"))[9] != 946728000)'
</postcheck>
</client>
diff --git a/tests/data/test1446 b/tests/data/test1446
index 0088375..5e11f11 100644
--- a/tests/data/test1446
+++ b/tests/data/test1446
@@ -18,17 +18,17 @@
sftp
</server>
<precheck>
-perl %SRCDIR/libtest/test613.pl prepare %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test613.pl prepare %PWD/%LOGDIR/test%TESTNUMBER.dir
</precheck>
<name>
SFTP with --remote-time
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test%TESTNUMBER.dir/rofile.txt --insecure --remote-time
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/test%TESTNUMBER.dir/rofile.txt --insecure --remote-time
</command>
<postcheck>
-perl %SRCDIR/libtest/test613.pl postprocess %PWD/log/test%TESTNUMBER.dir && \
-perl -e 'exit((stat("log/curl%TESTNUMBER.out"))[9] != 978264000)'
+perl %SRCDIR/libtest/test613.pl postprocess %PWD/%LOGDIR/test%TESTNUMBER.dir && \
+perl -e 'exit((stat("%LOGDIR/curl%TESTNUMBER.out"))[9] != 978264000)'
</postcheck>
</client>
diff --git a/tests/data/test1459 b/tests/data/test1459
index e8c2b00..2a69a60 100644
--- a/tests/data/test1459
+++ b/tests/data/test1459
@@ -13,7 +13,7 @@
sftp
</server>
<precheck>
-mkdir -p %PWD/log/test%TESTNUMBER.dir/.ssh
+mkdir -p %PWD/%LOGDIR/test%TESTNUMBER.dir/.ssh
</precheck>
<features>
sftp
@@ -25,12 +25,12 @@
<command>
-u : sftp://%HOSTIP:%SSHPORT/ -l
</command>
-<file name="log/test%TESTNUMBER.dir/.ssh/known_hosts">
+<file name="%LOGDIR/test%TESTNUMBER.dir/.ssh/known_hosts">
|1|qy29Y1x/+/F39AzdG5515YSSw+c=|iB2WX5jrU3ZTWc+ZfGau7HHEvBc= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAynDN8cDJ3xNzRjTNNGciSHSxpubxhZ6YnkLdp1TkrGW8n\
R93Ey5VtBeBblYTRlFXBWJgKFcTKBRJ/O4qBZwbUgt10AHj31i6h8NehfT19tR8wG/YCmj3KtYLHmwdzmW1edEL9G2NdX2KiKYv7/zuly3QvmP0QA0NhWkAz0KdWNM=
</file>
<setenv>
-CURL_HOME=%PWD/log/test%TESTNUMBER.dir
+CURL_HOME=%PWD/%LOGDIR/test%TESTNUMBER.dir
</setenv>
</client>
diff --git a/tests/data/test1460 b/tests/data/test1460
index 8f6b5f2..c3180ff 100644
--- a/tests/data/test1460
+++ b/tests/data/test1460
@@ -34,12 +34,12 @@
HTTP GET with -Ji and Content-Disposition with existing file
</name>
<setenv>
-CURL_TESTDIR=%PWD/log
+CURL_TESTDIR=%LOGDIR
</setenv>
<command option="no-output,no-include">
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -Ji -O
</command>
-<file name="log/name%TESTNUMBER">
+<file name="%LOGDIR/name%TESTNUMBER">
initial content
</file>
</client>
@@ -51,7 +51,7 @@
<errorcode>
2
</errorcode>
-<file name="log/name%TESTNUMBER">
+<file name="%LOGDIR/name%TESTNUMBER">
initial content
</file>
diff --git a/tests/data/test1465 b/tests/data/test1465
index e8caaa2..341237d 100644
--- a/tests/data/test1465
+++ b/tests/data/test1465
Binary files differ
diff --git a/tests/data/test1467 b/tests/data/test1467
index 1be4c2c..4e1d68f 100644
--- a/tests/data/test1467
+++ b/tests/data/test1467
@@ -4,6 +4,7 @@
HTTP
HTTP GET
SOCKS5
+unix sockets
</keywords>
</info>
diff --git a/tests/data/test1468 b/tests/data/test1468
index 1ff6ada..b4030ba 100644
--- a/tests/data/test1468
+++ b/tests/data/test1468
@@ -5,6 +5,7 @@
HTTP GET
SOCKS5
SOCKS5h
+unix sockets
</keywords>
</info>
diff --git a/tests/data/test1469 b/tests/data/test1469
new file mode 100644
index 0000000..f2b3882
--- /dev/null
+++ b/tests/data/test1469
@@ -0,0 +1,30 @@
+<testcase>
+<info>
+<keywords>
+FTP
+URL
+FAILURE
+</keywords>
+</info>
+
+# Client-side
+<client>
+<server>
+none
+</server>
+ <name>
+Space in FTP upload URL
+ </name>
+ <command>
+"ftp://%HOSTIP:%NOLISTENPORT/%TESTNUMBER%/with space/" -T %LOGDIR/irrelevant-file
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+# 3 == CURLE_URL_MALFORMAT
+<errorcode>
+3
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test1470 b/tests/data/test1470
new file mode 100644
index 0000000..c9dd8f4
--- /dev/null
+++ b/tests/data/test1470
@@ -0,0 +1,66 @@
+<testcase>
+<info>
+<keywords>
+HTTPS
+HTTP
+HTTP GET
+SOCKS5
+SOCKS5h
+unix sockets
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+proxy
+unix-sockets
+!NSS
+</features>
+<server>
+https
+socks5unix
+</server>
+ <name>
+HTTPS GET with host name using SOCKS5h via unix sockets
+ </name>
+ <command>
+https://this.is.a.host.name:%HTTPSPORT/%TESTNUMBER -k --proxy socks5h://localhost%SOCKSUNIXPATH
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: this.is.a.host.name:%HTTPSPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+<socks>
+atyp 3 => this.is.a.host.name
+</socks>
+</verify>
+</testcase>
diff --git a/tests/data/test1471 b/tests/data/test1471
new file mode 100644
index 0000000..e8e4143
--- /dev/null
+++ b/tests/data/test1471
@@ -0,0 +1,42 @@
+<testcase>
+<info>
+<keywords>
+Onion
+Tor
+FAILURE
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<features>
+http
+</features>
+<name>
+Fail to resolve .onion TLD
+</name>
+<command>
+red.onion
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# Couldn't resolve host name
+<errorcode>
+6
+</errorcode>
+<stderr mode="text">
+curl: (6) Not resolving .onion address (RFC 7686)
+</stderr>
+</verify>
+</testcase>
diff --git a/tests/data/test1472 b/tests/data/test1472
new file mode 100644
index 0000000..07f0620
--- /dev/null
+++ b/tests/data/test1472
@@ -0,0 +1,42 @@
+<testcase>
+<info>
+<keywords>
+Onion
+Tor
+FAILURE
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<features>
+http
+</features>
+<name>
+Fail to resolve .onion. TLD
+</name>
+<command>
+tasty.onion.
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# Couldn't resolve host name
+<errorcode>
+6
+</errorcode>
+<stderr mode="text">
+curl: (6) Not resolving .onion address (RFC 7686)
+</stderr>
+</verify>
+</testcase>
diff --git a/tests/data/test149 b/tests/data/test149
index 94ca5f7..e01c3f1 100644
--- a/tests/data/test149
+++ b/tests/data/test149
@@ -18,9 +18,9 @@
FTP with multiple uploads
</name>
<command>
--T log/upload%TESTNUMBER ftp://%HOSTIP:%FTPPORT/dir1/%TESTNUMBER -T log/upload%TESTNUMBER ftp://%HOSTIP:%FTPPORT/dir2/%TESTNUMBER
+-T %LOGDIR/upload%TESTNUMBER ftp://%HOSTIP:%FTPPORT/dir1/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER ftp://%HOSTIP:%FTPPORT/dir2/%TESTNUMBER
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
send away this contents
</file>
</client>
@@ -46,7 +46,7 @@
STOR %TESTNUMBER
QUIT
</protocol>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
send away this contents
</file>
</verify>
diff --git a/tests/data/test1501 b/tests/data/test1501
index 9d9263a..68b5589 100644
--- a/tests/data/test1501
+++ b/tests/data/test1501
@@ -5,6 +5,7 @@
RETR
multi
LIST
+DELAY
</keywords>
</info>
diff --git a/tests/data/test1506 b/tests/data/test1506
index 07d3aac..aee53a9 100644
--- a/tests/data/test1506
+++ b/tests/data/test1506
@@ -82,11 +82,11 @@
<strip>
^Host:.*
</strip>
-<file name="log/stderr%TESTNUMBER" mode="text">
+<file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
* Connection #0 to host server1.example.com left intact
* Connection #1 to host server2.example.com left intact
* Connection #2 to host server3.example.com left intact
-* Closing connection 0
+* Closing connection
* Connection #3 to host server4.example.com left intact
</file>
<stripfile>
diff --git a/tests/data/test1508 b/tests/data/test1508
index 02cb90a..78ff18f 100644
--- a/tests/data/test1508
+++ b/tests/data/test1508
@@ -24,7 +24,7 @@
# Verify data after the test has been "shot"
<verify>
-<file name="log/stdout%TESTNUMBER">
+<file name="%LOGDIR/stdout%TESTNUMBER">
We are done
</file>
</verify>
diff --git a/tests/data/test1509 b/tests/data/test1509
index baa0a30..7c427bf 100644
--- a/tests/data/test1509
+++ b/tests/data/test1509
@@ -62,7 +62,7 @@
<command>
http://the.old.moo.%TESTNUMBER:%HTTPPORT/%TESTNUMBER %HOSTIP:%PROXYPORT
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar
bar
@@ -78,6 +78,7 @@
Host: the.old.moo.%TESTNUMBER:%HTTPPORT
Proxy-Connection: Keep-Alive
+[DISCONNECT]
</proxy>
<protocol>
GET /%TESTNUMBER HTTP/1.1
diff --git a/tests/data/test1510 b/tests/data/test1510
index d021dfe..eccbb6c 100644
--- a/tests/data/test1510
+++ b/tests/data/test1510
@@ -82,7 +82,7 @@
<strip>
^Host:.*
</strip>
-<file name="log/stderr%TESTNUMBER" mode="text">
+<file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
* Connection #0 to host server1.example.com left intact
* Connection #1 to host server2.example.com left intact
* Connection #2 to host server3.example.com left intact
diff --git a/tests/data/test1513 b/tests/data/test1513
index 189d3e3..a32d2eb 100644
--- a/tests/data/test1513
+++ b/tests/data/test1513
@@ -2,6 +2,7 @@
<info>
<keywords>
PROGRESSFUNCTION
+DELAY
</keywords>
</info>
diff --git a/tests/data/test1517 b/tests/data/test1517
index 5150ff6..539dd62 100644
--- a/tests/data/test1517
+++ b/tests/data/test1517
@@ -9,7 +9,11 @@
</keywords>
</info>
#
-# This reproduces issue #657, fixed with PR #668 - on Windows
+# This test checks to make sure curl can call recv() without failing after a
+# send() fails on the same socket (#657). Most OSes should support this
+# natively. On Windows there were reported problems and a workaround via
+# define USE_RECV_BEFORE_SEND_WORKAROUND was added.
+# This proved problematic in other cases and was removed again.
#
# Server-side
<reply>
@@ -39,6 +43,11 @@
<tool>
lib%TESTNUMBER
</tool>
+# precheck is a command line to run before the test, to see if we can execute
+# the test or not
+<precheck>
+./libtest/lib%TESTNUMBER check
+</precheck>
<name>
HTTP POST, server responds before completed send
diff --git a/tests/data/test1523 b/tests/data/test1523
index a22b076..7cc94ba 100644
--- a/tests/data/test1523
+++ b/tests/data/test1523
@@ -2,6 +2,7 @@
<info>
<keywords>
CURLINFO_LOW_SPEED_LIMIT
+DELAY
</keywords>
</info>
diff --git a/tests/data/test1524 b/tests/data/test1524
index 39da646..b5ac866 100644
--- a/tests/data/test1524
+++ b/tests/data/test1524
@@ -45,9 +45,9 @@
HTTP PUT with 303 redirect
</name>
<command>
-http://%HOSTIP:%HTTPPORT/blah/%TESTNUMBER -L -T log/upload%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/blah/%TESTNUMBER -L -T %LOGDIR/upload%TESTNUMBER.txt
</command>
-<file name="log/upload%TESTNUMBER.txt">
+<file name="%LOGDIR/upload%TESTNUMBER.txt">
moo
</file>
</client>
@@ -61,7 +61,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 4
-Expect: 100-continue
moo
GET /blah/moo.html&testcase=/%TESTNUMBER0002 HTTP/1.1
diff --git a/tests/data/test1525 b/tests/data/test1525
index 7870bdb..33f71c8 100644
--- a/tests/data/test1525
+++ b/tests/data/test1525
@@ -2,7 +2,7 @@
<info>
<keywords>
HTTP
-HTTP GET
+HTTP PUT
HTTP CONNECT
HTTP proxy
proxytunnel
@@ -71,7 +71,6 @@
Accept: */*
User-Agent: Http Agent
Content-Length: 13
-Expect: 100-continue
Hello Cloud!
</protocol>
diff --git a/tests/data/test1526 b/tests/data/test1526
index c3e3dda..4076124 100644
--- a/tests/data/test1526
+++ b/tests/data/test1526
@@ -2,7 +2,7 @@
<info>
<keywords>
HTTP
-HTTP GET
+HTTP PUT
HTTP CONNECT
HTTP proxy
proxytunnel
@@ -73,7 +73,6 @@
Accept: */*
User-Agent: Http Agent
Content-Length: 13
-Expect: 100-continue
Hello Cloud!
</protocol>
diff --git a/tests/data/test1527 b/tests/data/test1527
index d8b6a59..3f35cb8 100644
--- a/tests/data/test1527
+++ b/tests/data/test1527
@@ -2,7 +2,7 @@
<info>
<keywords>
HTTP
-HTTP GET
+HTTP PUT
HTTP CONNECT
HTTP proxy
proxytunnel
diff --git a/tests/data/test1538 b/tests/data/test1538
index e21d053..59cd162 100644
--- a/tests/data/test1538
+++ b/tests/data/test1538
@@ -107,7 +107,7 @@
e72: TFTP: Unknown transfer ID
e73: Remote file already exists
e74: TFTP: No such user
-e75: Conversion failed
+e75: Unknown error
e76: Unknown error
e77: Problem with the SSL CA cert (path? access rights?)
e78: Remote file not found
@@ -160,7 +160,7 @@
u2: An invalid 'part' argument was passed as argument
u3: Malformed input to a URL function
u4: Port number was not a decimal number between 0 and 65535
-u5: This libcurl build doesn't support the given URL scheme
+u5: Unsupported URL scheme
u6: URL decode error, most likely because of rubbish in the input
u7: A memory function failed
u8: Credentials was passed in the URL when prohibited
@@ -183,9 +183,10 @@
u25: Bad path
u26: Bad query
u27: Bad scheme
-u28: Unsupported number of slashes
+u28: Unsupported number of slashes following scheme
u29: Bad user
-u30: CURLUcode unknown
+u30: libcurl lacks IDN support
+u31: CURLUcode unknown
</stdout>
</verify>
diff --git a/tests/data/test154 b/tests/data/test154
index c0f7651..a05eb8a 100644
--- a/tests/data/test154
+++ b/tests/data/test154
@@ -10,9 +10,6 @@
# Server-side
<reply>
-<servercmd>
-auth_required
-</servercmd>
<data>
HTTP/1.1 401 Authorization Required swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
@@ -70,9 +67,9 @@
HTTP PUT with --anyauth authorization (picking Digest)
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T log/put%TESTNUMBER -u testuser:testpass --anyauth
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T %LOGDIR/put%TESTNUMBER -u testuser:testpass --anyauth
</command>
-<file name="log/put%TESTNUMBER">
+<file name="%LOGDIR/put%TESTNUMBER">
This is data we upload with PUT
a second line
line three
@@ -88,15 +85,17 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 85
-Expect: 100-continue
+This is data we upload with PUT
+a second line
+line three
+four is the number of lines
PUT /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Authorization: Digest username="testuser", realm="gimme all yer s3cr3ts", nonce="11223344", uri="/%TESTNUMBER", response="b71551e12d1c456e47d8388ecb2edeca"
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 85
-Expect: 100-continue
This is data we upload with PUT
a second line
diff --git a/tests/data/test1540 b/tests/data/test1540
index 2dc8265..0ef5101 100644
--- a/tests/data/test1540
+++ b/tests/data/test1540
@@ -6,6 +6,7 @@
CURLPAUSE_RECV
chunked Transfer-Encoding
Trailer:
+DELAY
</keywords>
</info>
diff --git a/tests/data/test1542 b/tests/data/test1542
index cead5a0..51f312b 100644
--- a/tests/data/test1542
+++ b/tests/data/test1542
@@ -54,11 +54,11 @@
Accept: */*
</protocol>
-<file name="log/stderr%TESTNUMBER" mode="text">
+<file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
== Info: Connection #0 to host %HOSTIP left intact
== Info: Connection #0 to host %HOSTIP left intact
== Info: Connection #0 to host %HOSTIP left intact
-== Info: Closing connection 0
+== Info: Closing connection
== Info: Connection #1 to host %HOSTIP left intact
</file>
<stripfile>
diff --git a/tests/data/test155 b/tests/data/test155
index 2d916c9..83aed11 100644
--- a/tests/data/test155
+++ b/tests/data/test155
@@ -10,9 +10,6 @@
# Server-side
<reply>
-<servercmd>
-auth_required
-</servercmd>
<data>
HTTP/1.1 401 NTLM Authorization Required swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
@@ -87,9 +84,9 @@
HTTP PUT with --anyauth authorization (picking NTLM)
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T log/put%TESTNUMBER -u testuser:testpass --anyauth
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T %LOGDIR/put%TESTNUMBER -u testuser:testpass --anyauth
</command>
-<file name="log/put%TESTNUMBER">
+<file name="%LOGDIR/put%TESTNUMBER">
This is data we upload with PUT
a second line
line three
@@ -105,8 +102,11 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 85
-Expect: 100-continue
+This is data we upload with PUT
+a second line
+line three
+four is the number of lines
PUT /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
@@ -120,7 +120,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 85
-Expect: 100-continue
This is data we upload with PUT
a second line
diff --git a/tests/data/test1553 b/tests/data/test1553
index bc83032..595eb5b 100644
--- a/tests/data/test1553
+++ b/tests/data/test1553
@@ -28,6 +28,9 @@
#
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
imap
</server>
diff --git a/tests/data/test1554 b/tests/data/test1554
index 812a2c8..c16195c 100644
--- a/tests/data/test1554
+++ b/tests/data/test1554
@@ -69,12 +69,6 @@
<- Mutex unlock
-> Mutex lock
<- Mutex unlock
-%if hyper
--> Mutex lock
-<- Mutex unlock
--> Mutex lock
-<- Mutex unlock
-%endif
run 1: foobar and so on fun!
-> Mutex lock
<- Mutex unlock
diff --git a/tests/data/test1555 b/tests/data/test1555
index 547ec39..6985630 100644
--- a/tests/data/test1555
+++ b/tests/data/test1555
@@ -2,6 +2,7 @@
<info>
<keywords>
RECURSIVE_API_CALL
+DELAY
</keywords>
</info>
diff --git a/tests/data/test1558 b/tests/data/test1558
index 26854c2..46332d1 100644
--- a/tests/data/test1558
+++ b/tests/data/test1558
@@ -24,9 +24,9 @@
CURLINFO_PROTOCOL for file:// transfer
</name>
<command>
-file://%FILE_PWD/log/data%TESTNUMBER
+file://%FILE_PWD/%LOGDIR/data%TESTNUMBER
</command>
-<file name="log/data%TESTNUMBER">
+<file name="%LOGDIR/data%TESTNUMBER">
hello
</file>
</client>
diff --git a/tests/data/test1559 b/tests/data/test1559
index 863a89e..c307f64 100644
--- a/tests/data/test1559
+++ b/tests/data/test1559
@@ -37,7 +37,7 @@
CURLOPT_URL 10000000 bytes URL == 43
CURLOPT_POSTFIELDS 10000000 bytes data == 0
CURLUPART_URL 10000000 bytes URL == 3 (Malformed input to a URL function)
-CURLUPART_SCHEME 10000000 bytes scheme == 27 (Bad scheme)
+CURLUPART_SCHEME 10000000 bytes scheme == 3 (Malformed input to a URL function)
CURLUPART_USER 10000000 bytes user == 3 (Malformed input to a URL function)
</stdout>
</verify>
diff --git a/tests/data/test156 b/tests/data/test156
index 94bb339..214b539 100644
--- a/tests/data/test156
+++ b/tests/data/test156
@@ -28,9 +28,9 @@
HTTP PUT with --anyauth (when the server requires none)
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T log/put%TESTNUMBER -u testuser:testpass --anyauth
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T %LOGDIR/put%TESTNUMBER -u testuser:testpass --anyauth
</command>
-<file name="log/put%TESTNUMBER">
+<file name="%LOGDIR/put%TESTNUMBER">
This is data we upload with PUT
a second line
line three
@@ -46,7 +46,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 85
-Expect: 100-continue
This is data we upload with PUT
a second line
diff --git a/tests/data/test1560 b/tests/data/test1560
index f6722fd..5ed0add 100644
--- a/tests/data/test1560
+++ b/tests/data/test1560
@@ -12,6 +12,9 @@
<server>
none
</server>
+<setenv>
+LANG=en_US.UTF-8
+</setenv>
<features>
file
https
@@ -22,7 +25,6 @@
ldap
dict
ftp
-ipv6
</features>
<name>
URL API
@@ -34,13 +36,6 @@
<verify>
<stdout>
-we got [fe80::20c:29ff:fe9c:409b]
-we got https://[::1]/hello.html
-we got https://example.com/hello.html
-we got https://[fe80::20c:29ff:fe9c:409b%25eth0]/hello.html
-we got [fe80::20c:29ff:fe9c:409b]
-we got eth0
-we got https://[fe80::20c:29ff:fe9c:409b%25clown]/hello.html
success
</stdout>
</verify>
diff --git a/tests/data/test1561 b/tests/data/test1561
index 882b257..7dbce11 100644
--- a/tests/data/test1561
+++ b/tests/data/test1561
@@ -19,7 +19,7 @@
Set-Cookie: super=secret; domain=example.com; path=/%TESTNUMBER; secure;
Set-Cookie: supersuper=secret; domain=example.com; path=/%TESTNUMBER/login/; secure;
Set-Cookie: __Secure-SID=12345; Domain=example.com
-Set-Cookie: __Secure-SID=12346; Secure; Domain=example.com
+Set-Cookie: __SecURE-SID=12346; Secure; Domain=example.com
Set-Cookie: supersupersuper=secret; __Secure-SID=12346; Secure; Domain=example.com
Set-Cookie: __Host-SID=22345
Set-Cookie: __Host-SID=22346; Secure
@@ -43,7 +43,7 @@
Set-Cookie: supersuper=plain; domain=example.com; path=/%TESTNUMBER/login;
Set-Cookie: secureoverhttp=yes; domain=example.com; path=/%TESTNUMBER; secure;
Set-Cookie: __Secure-SID=22345; Domain=example.com
-Set-Cookie: __Secure-SID=22346; Secure; Domain=example.com
+Set-Cookie: __SecuRE-SID=22346; Secure; Domain=example.com
Set-Cookie: __Host-SID=32345
Set-Cookie: __Host-SID=32346; Secure
Set-Cookie: __Host-SID=32347; Domain=example.com
@@ -72,7 +72,7 @@
Cookies set over HTTP can't override secure ones
</name>
<command>
--k https://%HOSTIP:%HTTPSPORT/%TESTNUMBER0001 -L -c log/jar%TESTNUMBER.txt -H "Host: www.example.com" http://%HOSTIP:%HTTPPORT/%TESTNUMBER0002 -L -c log/jar%TESTNUMBER.txt -H "Host: www.example.com"
+-k https://%HOSTIP:%HTTPSPORT/%TESTNUMBER0001 -L -c %LOGDIR/jar%TESTNUMBER.txt -H "Host: www.example.com" http://%HOSTIP:%HTTPPORT/%TESTNUMBER0002 -L -c %LOGDIR/jar%TESTNUMBER.txt -H "Host: www.example.com"
</command>
</client>
<verify>
@@ -88,7 +88,7 @@
Accept: */*
</protocol>
-<file name="log/jar%TESTNUMBER.txt" mode="text">
+<file name="%LOGDIR/jar%TESTNUMBER.txt" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
@@ -97,7 +97,7 @@
#HttpOnly_.example.com TRUE /15 FALSE 0 super plain
www.example.com FALSE / TRUE 0 __Host-SID 12346
.example.com TRUE / TRUE 0 supersupersuper secret
-.example.com TRUE / TRUE 0 __Secure-SID 12346
+.example.com TRUE / TRUE 0 __SecURE-SID 12346
.example.com TRUE /%TESTNUMBER/login/ TRUE 0 supersuper secret
.example.com TRUE /1561 TRUE 0 super secret
</file>
diff --git a/tests/data/test1566 b/tests/data/test1566
index b954c2a..be047dc 100644
--- a/tests/data/test1566
+++ b/tests/data/test1566
@@ -32,12 +32,12 @@
--etag-compare that gets a 304 back shouldn't overwrite the file
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/output%TESTNUMBER --etag-compare log/etag%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/output%TESTNUMBER --etag-compare %LOGDIR/etag%TESTNUMBER
</command>
-<file name="log/etag%TESTNUMBER">
+<file name="%LOGDIR/etag%TESTNUMBER">
"123456"
</file>
-<file1 name="log/output%TESTNUMBER">
+<file1 name="%LOGDIR/output%TESTNUMBER">
downloaded already
</file1>
@@ -56,7 +56,7 @@
</protocol>
# verify that the target file is untouched
-<file name="log/output%TESTNUMBER">
+<file name="%LOGDIR/output%TESTNUMBER">
downloaded already
</file>
</verify>
diff --git a/tests/data/test158 b/tests/data/test158
index 2fbaf65..2386136 100644
--- a/tests/data/test158
+++ b/tests/data/test158
@@ -17,6 +17,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test1590 b/tests/data/test1590
index bfaa754..dbb81cc 100644
--- a/tests/data/test1590
+++ b/tests/data/test1590
@@ -28,6 +28,9 @@
#
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
imap
</server>
diff --git a/tests/data/test1592 b/tests/data/test1592
index a2c0f1c..8de0734 100644
--- a/tests/data/test1592
+++ b/tests/data/test1592
@@ -5,6 +5,7 @@
multi
resolve
speedcheck
+flaky
</keywords>
</info>
diff --git a/tests/data/test1597 b/tests/data/test1597
new file mode 100644
index 0000000..047bf7b
--- /dev/null
+++ b/tests/data/test1597
@@ -0,0 +1,32 @@
+<testcase>
+<info>
+<keywords>
+CURLOPT_PROTOCOLS_STR
+</keywords>
+</info>
+
+# Server-side
+<reply>
+</reply>
+# Client-side
+<client>
+<server>
+none
+</server>
+<name>
+CURLOPT_PROTOCOLS_STR
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+<command>
+-
+</command>
+</client>
+
+<verify>
+<stdout>
+Tested 15 strings
+</stdout>
+</verify>
+</testcase>
diff --git a/tests/data/test160 b/tests/data/test160
index 778787e..32b0c73 100644
--- a/tests/data/test160
+++ b/tests/data/test160
@@ -3,6 +3,7 @@
<keywords>
HTTP
HTTP GET
+DELAY
</keywords>
</info>
diff --git a/tests/data/test1614 b/tests/data/test1614
new file mode 100644
index 0000000..73bdbb4
--- /dev/null
+++ b/tests/data/test1614
@@ -0,0 +1,25 @@
+<testcase>
+<info>
+<keywords>
+unittest
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<features>
+unittest
+proxy
+</features>
+ <name>
+noproxy and cidr comparisons
+ </name>
+</client>
+<errorcode>
+0
+</errorcode>
+</testcase>
diff --git a/tests/data/test163 b/tests/data/test163
index 344f104..45af183 100644
--- a/tests/data/test163
+++ b/tests/data/test163
@@ -20,6 +20,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -27,10 +30,10 @@
HTTP multipart formpost with contents from a file
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F "name=<log/field%TESTNUMBER" -F tool=curl
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F "name=<%LOGDIR/field%TESTNUMBER" -F tool=curl
</command>
# We create this file before the command is invoked!
-<file name="log/field%TESTNUMBER">
+<file name="%LOGDIR/field%TESTNUMBER">
contents
from
a
diff --git a/tests/data/test1654 b/tests/data/test1654
index ef66574..3bd6f65 100644
--- a/tests/data/test1654
+++ b/tests/data/test1654
@@ -24,9 +24,9 @@
alt-svc
</name>
<command>
-log/%TESTNUMBER
+%LOGDIR/%TESTNUMBER
</command>
-<file name="log/%TESTNUMBER" mode="text">
+<file name="%LOGDIR/%TESTNUMBER" mode="text">
h2 example.com 443 h3 shiny.example.com 8443 "20191231 00:00:00" 0 1
# a comment
h2 foo.example.com 443 h3 shiny.example.com 8443 "20291231 23:30:00" 0 1
@@ -38,7 +38,7 @@
</file>
</client>
<verify>
-<file name="log/%TESTNUMBER-out" mode="text">
+<file name="%LOGDIR/%TESTNUMBER-out" mode="text">
# Your alt-svc cache. https://curl.se/docs/alt-svc.html
# This file was generated by libcurl! Edit at your own risk.
h2 example.com 443 h3 shiny.example.com 8443 "20191231 00:00:00" 0 1
diff --git a/tests/data/test166 b/tests/data/test166
index 3ee1d69..40892a8 100644
--- a/tests/data/test166
+++ b/tests/data/test166
@@ -20,6 +20,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -27,10 +30,10 @@
HTTP formpost a file with spaces in name
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F "name=@log/fie ld %TESTNUMBER"
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F "name=@%LOGDIR/fie ld %TESTNUMBER"
</command>
# We create this file before the command is invoked!
-<file name="log/fie ld %TESTNUMBER">
+<file name="%LOGDIR/fie ld %TESTNUMBER">
data inside the file
</file>
</client>
diff --git a/tests/data/test1660 b/tests/data/test1660
index cbbcf75..f86126d 100644
--- a/tests/data/test1660
+++ b/tests/data/test1660
@@ -15,7 +15,7 @@
HSTS
</features>
-<file name="log/input%TESTNUMBER">
+<file name="%LOGDIR/hsts%TESTNUMBER">
# Your HSTS cache. https://curl.se/docs/hsts.html
# This file was generated by libcurl! Edit at your own risk.
.readfrom.example "20211001 04:47:41"
@@ -31,7 +31,7 @@
HSTS
</name>
<command>
--
+%LOGDIR/hsts%TESTNUMBER
</command>
</client>
@@ -72,7 +72,7 @@
'expire.example' is not HSTS
'expire.example' is not HSTS
</stdout>
-<file name="log/hsts%TESTNUMBER" mode="text">
+<file name="%LOGDIR/hsts%TESTNUMBER.save" mode="text">
# Your HSTS cache. https://curl.se/docs/hsts.html
# This file was generated by libcurl! Edit at your own risk.
.new.example "unlimited"
diff --git a/tests/data/test1662 b/tests/data/test1662
new file mode 100644
index 0000000..b2fbcce
--- /dev/null
+++ b/tests/data/test1662
@@ -0,0 +1,67 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 301 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Location: %TESTNUMBER0002
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+<data2 nocheck="yes">
+HTTP/1.1 200 OK
+Content-Length: 6
+Connection: close
+Funny-head: nono
+
+-bar-
+</data2>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+Mime
+debug
+</features>
+<server>
+http
+</server>
+<name>
+HTTP formpost from callback and a redirect and switch to GET
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+
+# This does not verify the protocol because the sending of data might be
+# aborted early making it hard to check properly.
+<stdout>
+-bar-
+</stdout>
+</verify>
+</testcase>
diff --git a/tests/data/test1670 b/tests/data/test1670
index 6d8722f..34d79f7 100644
--- a/tests/data/test1670
+++ b/tests/data/test1670
@@ -40,7 +40,7 @@
-w individual header output
</name>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -w '%header{etag} %header{nope} %header{DATE}\n' -o log/%TESTNUMBER.out
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -w '%header{etag} %header{nope} %header{DATE}\n' -o %LOGDIR/%TESTNUMBER.out
</command>
</client>
diff --git a/tests/data/test1671 b/tests/data/test1671
index e694fd7..43753b5 100644
--- a/tests/data/test1671
+++ b/tests/data/test1671
@@ -43,7 +43,7 @@
-w header JSON output
</name>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -w '%{header_json}\n' -o log/%TESTNUMBER.out
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -w '%{header_json}\n' -o %LOGDIR/%TESTNUMBER.out
</command>
</client>
@@ -64,10 +64,11 @@
"etag":["\"21025-dc7-39462498\""],
"accept-ranges":["bytes"],
"set-cookie":["firstcookie=want1; path=/","2cookie=want2; path=/","cookie3=want3; path=/"],
+"funny-head":["yesyes"],
+"content-type":["text/html"],
"content-length":["6"],
"connection":["close"]
}
</stdout>
</verify>
</testcase>
-o
\ No newline at end of file
diff --git a/tests/data/test1680 b/tests/data/test1680
index 7d8167c..4775a41 100644
--- a/tests/data/test1680
+++ b/tests/data/test1680
@@ -33,9 +33,9 @@
http
</features>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/exist%TESTNUMBER --clobber
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/exist%TESTNUMBER --clobber
</command>
-<file name="log/exist%TESTNUMBER">
+<file name="%LOGDIR/exist%TESTNUMBER">
to be overwritten
</file>
</client>
@@ -43,7 +43,7 @@
#
# Verify data after the test has been "shot"
<verify>
-<file name="log/exist%TESTNUMBER">
+<file name="%LOGDIR/exist%TESTNUMBER">
HTTP/1.0 200 OK
Connection: close
Content-Type: text/plain
diff --git a/tests/data/test1681 b/tests/data/test1681
index cfc8a5d..16c0d8c 100644
--- a/tests/data/test1681
+++ b/tests/data/test1681
@@ -33,9 +33,9 @@
http
</features>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/exist%TESTNUMBER --no-clobber -w '%{filename_effective}\n'
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/exist%TESTNUMBER --no-clobber -w '%{filename_effective}\n'
</command>
-<file name="log/exist%TESTNUMBER">
+<file name="%LOGDIR/exist%TESTNUMBER">
to stay the same
</file>
</client>
@@ -43,10 +43,10 @@
#
# Verify data after the test has been "shot"
<verify>
-<file name="log/exist%TESTNUMBER">
+<file name="%LOGDIR/exist%TESTNUMBER">
to stay the same
</file>
-<file1 name="log/exist%TESTNUMBER.1">
+<file1 name="%LOGDIR/exist%TESTNUMBER.1">
HTTP/1.0 200 OK
Connection: close
Content-Type: text/plain
@@ -55,7 +55,7 @@
foo
</file1>
<stdout mode="text">
-log/exist%TESTNUMBER.1
+%LOGDIR/exist%TESTNUMBER.1
</stdout>
</verify>
</testcase>
diff --git a/tests/data/test1682 b/tests/data/test1682
index e981c20..b5462ab 100644
--- a/tests/data/test1682
+++ b/tests/data/test1682
@@ -33,9 +33,9 @@
http
</features>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --output-dir log -o exist%TESTNUMBER --no-clobber
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --output-dir %LOGDIR -o exist%TESTNUMBER --no-clobber
</command>
-<file name="log/exist%TESTNUMBER">
+<file name="%LOGDIR/exist%TESTNUMBER">
to stay the same
</file>
</client>
@@ -43,10 +43,10 @@
#
# Verify data after the test has been "shot"
<verify>
-<file name="log/exist%TESTNUMBER">
+<file name="%LOGDIR/exist%TESTNUMBER">
to stay the same
</file>
-<file1 name="log/exist%TESTNUMBER.1">
+<file1 name="%LOGDIR/exist%TESTNUMBER.1">
HTTP/1.0 200 OK
Connection: close
Content-Type: text/plain
diff --git a/tests/data/test1683 b/tests/data/test1683
index 93d27d7..178b405 100644
--- a/tests/data/test1683
+++ b/tests/data/test1683
@@ -33,18 +33,18 @@
http
</features>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/exist%TESTNUMBER --no-clobber
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/exist%TESTNUMBER --no-clobber
</command>
-<file name="log/exist%TESTNUMBER">
+<file name="%LOGDIR/exist%TESTNUMBER">
to stay the same
</file>
<precheck>
-perl -e 'for my $i ((1..100)) { my $filename = "log/exist%TESTNUMBER.$i"; open(FH, ">", $filename) or die $!; print FH "to stay the same" ; close(FH) }'
-# python3 -c 'for i in range(1, 101): open("log/exist%TESTNUMBER.{}".format(i), mode="w").write("to stay the same")'
+perl -e 'for my $i ((1..100)) { my $filename = "%LOGDIR/exist%TESTNUMBER.$i"; open(FH, ">", $filename) or die $!; print FH "to stay the same" ; close(FH) }'
+# python3 -c 'for i in range(1, 101): open("%LOGDIR/exist%TESTNUMBER.{}".format(i), mode="w").write("to stay the same")'
</precheck>
<postcheck>
-perl -e 'for my $i ((1..100)) { my $filename = "log/exist%TESTNUMBER.$i"; open(FH, "<", $filename) or die $!; (<FH> eq "to stay the same" and <FH> eq "") or die "incorrect $filename" ; close(FH) }'
-# python3 -c 'for i in range(1, 101): assert open("log/exist%TESTNUMBER.{}".format(i), mode="r").read(17) == "to stay the same"'
+perl -e 'for my $i ((1..100)) { my $filename = "%LOGDIR/exist%TESTNUMBER.$i"; open(FH, "<", $filename) or die $!; (<FH> eq "to stay the same" and <FH> eq "") or die "incorrect $filename" ; close(FH) }'
+# python3 -c 'for i in range(1, 101): assert open("%LOGDIR/exist%TESTNUMBER.{}".format(i), mode="r").read(17) == "to stay the same"'
</postcheck>
</client>
@@ -54,7 +54,7 @@
<errorcode>
23
</errorcode>
-<file name="log/exist%TESTNUMBER">
+<file name="%LOGDIR/exist%TESTNUMBER">
to stay the same
</file>
</verify>
diff --git a/tests/data/test170 b/tests/data/test170
index 28874a9..22767cb 100644
--- a/tests/data/test170
+++ b/tests/data/test170
@@ -18,6 +18,7 @@
http
</server>
<features>
+Mime
NTLM
SSL
!SSPI
diff --git a/tests/data/test1700 b/tests/data/test1700
index 8b1ef4a..7f78bcf 100644
--- a/tests/data/test1700
+++ b/tests/data/test1700
@@ -11,26 +11,26 @@
# Server-side
<reply>
<data nocheck="yes">
-HTTP/1.1 200 OK
-Date: Tue, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake
-Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
-ETag: "21025-dc7-39462498"
-Accept-Ranges: bytes
-Content-Length: 6
-Connection: close
-Content-Type: text/html
-Funny-head: yesyes
-
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
-foo-
</data>
<data1>
-HTTP/1.1 200 OK
-Date: Tue, 09 Nov 2010 14:49:00 GMT
-Content-Length: 6
-Connection: close
-Content-Type: text/html
-
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+
-maa-
</data1>
</reply>
diff --git a/tests/data/test1701 b/tests/data/test1701
index 3c1a2bd..22f6147 100644
--- a/tests/data/test1701
+++ b/tests/data/test1701
@@ -11,17 +11,17 @@
# Server-side
<reply>
<data nocheck="yes">
-HTTP/1.1 200 OK
-Date: Tue, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake
-Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
-ETag: "21025-dc7-39462498"
-Accept-Ranges: bytes
-Content-Length: 6
-Connection: close
-Content-Type: text/html
-Funny-head: yesyes
-
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
-foo-
</data>
</reply>
diff --git a/tests/data/test1703 b/tests/data/test1703
index a6a4d9f..bdc6476 100644
--- a/tests/data/test1703
+++ b/tests/data/test1703
@@ -28,9 +28,9 @@
basic file:// file with UTF-8 characters
</name>
<command option="no-include">
-file://localhost%FILE_PWD/log/%E3%83%86%E3%82%B9%E3%83%88%TESTNUMBER.txt
+file://localhost%FILE_PWD/%LOGDIR/%E3%83%86%E3%82%B9%E3%83%88%TESTNUMBER.txt
</command>
-<file name="log/テスト%TESTNUMBER.txt">
+<file name="%LOGDIR/テスト%TESTNUMBER.txt">
foo
bar
bar
diff --git a/tests/data/test171 b/tests/data/test171
index c4f5b6c..d56296f 100644
--- a/tests/data/test171
+++ b/tests/data/test171
@@ -31,9 +31,10 @@
HTTP, get cookie with dot prefixed full domain
</name>
<command>
--c log/jar%TESTNUMBER -x %HOSTIP:%HTTPPORT http://z.x.com/%TESTNUMBER
+-c %LOGDIR/jar%TESTNUMBER -x %HOSTIP:%HTTPPORT http://z.x.com/%TESTNUMBER
</command>
<features>
+cookies
proxy
</features>
</client>
@@ -48,7 +49,7 @@
Proxy-Connection: Keep-Alive
</protocol>
-<file name="log/jar%TESTNUMBER" mode="text">
+<file name="%LOGDIR/jar%TESTNUMBER" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test172 b/tests/data/test172
index 9dbe64c..bf48719 100644
--- a/tests/data/test172
+++ b/tests/data/test172
@@ -27,9 +27,9 @@
HTTP with cookies file and custom added cookie
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -b log/jar%TESTNUMBER.txt -b "tool=curl; name=fool"
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -b %LOGDIR/jar%TESTNUMBER.txt -b "tool=curl; name=fool"
</command>
-<file name="log/jar%TESTNUMBER.txt">
+<file name="%LOGDIR/jar%TESTNUMBER.txt">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
@@ -38,6 +38,9 @@
.%HOSTIP TRUE / FALSE 0 partmatch present
%HOSTIP FALSE /we/want/ FALSE 2139150993 nodomain value
</file>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
diff --git a/tests/data/test173 b/tests/data/test173
index 0968616..a3356c9 100644
--- a/tests/data/test173
+++ b/tests/data/test173
@@ -21,6 +21,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test178 b/tests/data/test178
index ca59e9d..03c1a44 100644
--- a/tests/data/test178
+++ b/tests/data/test178
@@ -53,7 +53,7 @@
</protocol>
# Hyper curl returns unsupported protocol
-# bullt-in curl returns weird_server_reply
+# built-in curl returns weird_server_reply
<errorcode>
%if hyper
1
diff --git a/tests/data/test179 b/tests/data/test179
index b5aaec2..4bfceb1 100644
--- a/tests/data/test179
+++ b/tests/data/test179
@@ -31,14 +31,15 @@
HTTP using proxy and cookies with path checks
</name>
<command>
-http://supertrooper.fake/c/%TESTNUMBER -b log/injar%TESTNUMBER -x %HOSTIP:%HTTPPORT
+http://supertrooper.fake/c/%TESTNUMBER -b %LOGDIR/injar%TESTNUMBER -x %HOSTIP:%HTTPPORT
</command>
-<file name="log/injar%TESTNUMBER">
+<file name="%LOGDIR/injar%TESTNUMBER">
supertrooper.fake FALSE /a FALSE 2139150993 mooo indeed
supertrooper.fake FALSE /b FALSE 0 moo1 indeed
supertrooper.fake FALSE /c FALSE 2139150993 moo2 indeed
</file>
<features>
+cookies
proxy
</features>
</client>
diff --git a/tests/data/test180 b/tests/data/test180
index 32ecd00..dcb616f 100644
--- a/tests/data/test180
+++ b/tests/data/test180
@@ -27,9 +27,9 @@
HTTP 1.0 PUT
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -T log/test%TESTNUMBER.txt --http1.0
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt --http1.0
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
Weird
file
to
diff --git a/tests/data/test1800 b/tests/data/test1800
index d7cc73a..1f4472d 100644
--- a/tests/data/test1800
+++ b/tests/data/test1800
@@ -49,7 +49,7 @@
Accept: */*
Connection: Upgrade, HTTP2-Settings
Upgrade: %H2CVER
-HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA
+HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA
</protocol>
</verify>
diff --git a/tests/data/test181 b/tests/data/test181
index f496c29..71dd427 100644
--- a/tests/data/test181
+++ b/tests/data/test181
@@ -27,9 +27,9 @@
HTTP 1.0 POST
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --data-binary @log/test%TESTNUMBER.txt --http1.0
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER --data-binary @%LOGDIR/test%TESTNUMBER.txt --http1.0
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
Weird
file
to
diff --git a/tests/data/test186 b/tests/data/test186
index 35232b8..0f0c91c 100644
--- a/tests/data/test186
+++ b/tests/data/test186
@@ -21,6 +21,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test190 b/tests/data/test190
index 3a20ba2..3da48cd 100644
--- a/tests/data/test190
+++ b/tests/data/test190
@@ -2,6 +2,9 @@
<info>
<keywords>
FTP
+timeout
+FAILURE
+DELAY
</keywords>
</info>
diff --git a/tests/data/test1903 b/tests/data/test1903
new file mode 100644
index 0000000..ff5a0f2
--- /dev/null
+++ b/tests/data/test1903
@@ -0,0 +1,51 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+cookies
+CURLOPT_COOKIEFILE
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes" crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Funny-head: yesyes swsclose
+Set-Cookie: foobar=name;
+Set-Cookie: secondcookie=present;
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+CURLOPT_COOKIEFILE then reset then set again
+ </name>
+<tool>
+lib%TESTNUMBER
+</tool>
+<command>
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER %LOGDIR/cookies%TESTNUMBER
+</command>
+<file name="%LOGDIR/cookies%TESTNUMBER" mode="text">
+# Netscape HTTP Cookie File
+# https://curl.se/docs/http-cookies.html
+# This file was generated by libcurl! Edit at your own risk.
+
+%HOSTIP FALSE /we/want/ FALSE 0 secondcookie present
+%HOSTIP FALSE /we/want/ FALSE 0 foobar name
+</file>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+</verify>
+</testcase>
diff --git a/tests/data/test1905 b/tests/data/test1905
index 4d04f81..308dc9a 100644
--- a/tests/data/test1905
+++ b/tests/data/test1905
@@ -33,8 +33,11 @@
lib%TESTNUMBER
</tool>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER %LOGDIR/cookies%TESTNUMBER
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
@@ -45,7 +48,7 @@
Accept: */*
</protocol>
-<file name="log/cookies%TESTNUMBER" mode="text">
+<file name="%LOGDIR/cookies%TESTNUMBER" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test1906 b/tests/data/test1906
index c43b0a9..61cc045 100644
--- a/tests/data/test1906
+++ b/tests/data/test1906
@@ -30,7 +30,7 @@
lib%TESTNUMBER
</tool>
-# The tool does two requesets, the first sets CURLOPT_PORT to 1
+# The tool does two requests, the first sets CURLOPT_PORT to 1
# the second resets the port again and expects that request to work.
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER
diff --git a/tests/data/test1908 b/tests/data/test1908
index 0ac0e86..4ec55ed 100644
--- a/tests/data/test1908
+++ b/tests/data/test1908
@@ -51,7 +51,7 @@
</tool>
<command>
-%HOSTIP:%HTTPPORT/%TESTNUMBER
+%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/altsvc-%TESTNUMBER
</command>
</client>
@@ -72,7 +72,7 @@
# matches
s/\"([^\"]*)\"/TIMESTAMP/
</stripfile>
-<file name="log/altsvc-%TESTNUMBER" mode="text">
+<file name="%LOGDIR/altsvc-%TESTNUMBER" mode="text">
# Your alt-svc cache. https://curl.se/docs/alt-svc.html
# This file was generated by libcurl! Edit at your own risk.
h1 127.0.0.1 %HTTPPORT h2 3dbbdetxoyw4nsp6c3cc456oj2ays6s43ezxzsfxxri3h5xqd.example 443 TIMESTAMP 1 0
diff --git a/tests/data/test1909 b/tests/data/test1909
index 64e7b05..c412d41 100644
--- a/tests/data/test1909
+++ b/tests/data/test1909
@@ -36,7 +36,7 @@
HTTP GET --retry-all-errors to overcome partial transfer
</name>
<command option="no-output,no-include">
---retry 1 --retry-all-errors -o log/outfile%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+--retry 1 --retry-all-errors -o %LOGDIR/outfile%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
</client>
@@ -56,7 +56,7 @@
</protocol>
-<file1 name="log/outfile%TESTNUMBER">
+<file1 name="%LOGDIR/outfile%TESTNUMBER">
data
</file1>
diff --git a/tests/data/test1933 b/tests/data/test1933
index d2aabb1..3f3e8ac 100644
--- a/tests/data/test1933
+++ b/tests/data/test1933
@@ -47,7 +47,7 @@
</tool>
<command>
-http://xxx:yyy@%HOSTIP:%HTTPPORT/%TESTNUMBER/testapi/test
+http://xxx:yyy@127.0.0.1:9000/%TESTNUMBER/testapi/test 127.0.0.1:9000:%HOSTIP:%HTTPPORT
</command>
</client>
@@ -60,8 +60,8 @@
</strip>
<protocol>
GET /%TESTNUMBER/testapi/test HTTP/1.1
-Host: %HOSTIP:%HTTPPORT
-Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/0/127/xxx4_request, SignedHeaders=content-type;host;x-xxx-date, Signature=d2c2dff48c59ec49dc31ef94f18c5dc1ac3eae2a70d51633a4342dadc0683664
+Host: 127.0.0.1:9000
+Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/0/127/xxx4_request, SignedHeaders=content-type;host;x-xxx-date, Signature=3d8e00a02e437211a596143dcd590fcc805b731365c68f7f48951ea6eda39c4f
X-Xxx-Date: 19700101T000000Z
</protocol>
diff --git a/tests/data/test1934 b/tests/data/test1934
index 35fa318..a131df4 100644
--- a/tests/data/test1934
+++ b/tests/data/test1934
@@ -47,7 +47,7 @@
</tool>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER/testapi/test
+http://127.0.0.1:9000/%TESTNUMBER/testapi/test 127.0.0.1:9000:%HOSTIP:%HTTPPORT
</command>
</client>
@@ -60,8 +60,8 @@
</strip>
<protocol>
GET /%TESTNUMBER/testapi/test HTTP/1.1
-Host: %HOSTIP:%HTTPPORT
-Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/0/127/xxx4_request, SignedHeaders=content-type;host;x-yyy-date, Signature=938937ca7da6bb3dbf15e30928265ec6f061532d035d2afda92fa7cb10feb196
+Host: 127.0.0.1:9000
+Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/0/127/xxx4_request, SignedHeaders=content-type;host;x-yyy-date, Signature=cf8dc9a4af903a1a9bb1385d8e2366d780afb501e266436598438395e502d58c
X-Yyy-Date: 19700101T000000Z
</protocol>
diff --git a/tests/data/test1935 b/tests/data/test1935
index 6d48f32..d39a864 100644
--- a/tests/data/test1935
+++ b/tests/data/test1935
@@ -47,7 +47,7 @@
</tool>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER/testapi/test
+http://127.0.0.1:9000/%TESTNUMBER/testapi/test 127.0.0.1:9000:%HOSTIP:%HTTPPORT
</command>
</client>
@@ -60,8 +60,8 @@
</strip>
<protocol>
GET /%TESTNUMBER/testapi/test HTTP/1.1
-Host: %HOSTIP:%HTTPPORT
-Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/rrr/127/xxx4_request, SignedHeaders=content-type;host;x-yyy-date, Signature=240750deb9263d4c8ece71c016f3919b56e518249390ef075740f94ef8df846f
+Host: 127.0.0.1:9000
+Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/rrr/127/xxx4_request, SignedHeaders=content-type;host;x-yyy-date, Signature=a0b11b97b54689428d4188b788ed32865d607822d85d3e91cf06141f479dac0b
X-Yyy-Date: 19700101T000000Z
</protocol>
diff --git a/tests/data/test1936 b/tests/data/test1936
index 366abd6..a0d3840 100644
--- a/tests/data/test1936
+++ b/tests/data/test1936
@@ -47,7 +47,7 @@
</tool>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER/testapi/test
+http://127.0.0.1:9000/%TESTNUMBER/testapi/test 127.0.0.1:9000:%HOSTIP:%HTTPPORT
</command>
</client>
@@ -60,8 +60,8 @@
</strip>
<protocol>
GET /%TESTNUMBER/testapi/test HTTP/1.1
-Host: %HOSTIP:%HTTPPORT
-Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/rrr/sss/xxx4_request, SignedHeaders=content-type;host;x-yyy-date, Signature=f32cf87977cea5d3274b524b53e5d28f4aac54c372f710ae0cc3a9ececaf169f
+Host: 127.0.0.1:9000
+Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/rrr/sss/xxx4_request, SignedHeaders=content-type;host;x-yyy-date, Signature=026b713d76b0789bd224c5e41322f74eed088f8a22fd15183ca68376c575c5b0
X-Yyy-Date: 19700101T000000Z
</protocol>
diff --git a/tests/data/test1937 b/tests/data/test1937
index e24445a..ca1214b 100644
--- a/tests/data/test1937
+++ b/tests/data/test1937
@@ -48,7 +48,7 @@
</tool>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER/testapi/test
+http://127.0.0.1:9000/%TESTNUMBER/testapi/test 127.0.0.1:9000:%HOSTIP:%HTTPPORT
</command>
</client>
@@ -61,8 +61,8 @@
</strip>
<protocol nonewline="yes">
POST /%TESTNUMBER/testapi/test HTTP/1.1
-Host: %HOSTIP:%HTTPPORT
-Authorization: PROVIDER14-HMAC-SHA256 Credential=keyId/19700101/region/service/provider14_request, SignedHeaders=content-type;host;x-provider2-date, Signature=391e410177d0e9ee80728082446ef69d6b29157fe71f8b4805fce7c186fd956d
+Host: 127.0.0.1:9000
+Authorization: PROVIDER14-HMAC-SHA256 Credential=keyId/19700101/region/service/provider14_request, SignedHeaders=content-type;host;x-provider2-date, Signature=4928ccf97a9e71fe27f91db5a3b3c943b6080d25e6f4df8593d4c38e7d1e849b
X-Provider2-Date: 19700101T000000Z
Content-Length: 8
diff --git a/tests/data/test1938 b/tests/data/test1938
index 5341de0..565a54f 100644
--- a/tests/data/test1938
+++ b/tests/data/test1938
Binary files differ
diff --git a/tests/data/test1944 b/tests/data/test1944
index 3e8ed72..ad0920d 100644
--- a/tests/data/test1944
+++ b/tests/data/test1944
@@ -28,7 +28,7 @@
Set-Cookie: 1cookie=data1;
Set-Cookie: 2cookie=data2;
-</data>
+</data2>
</reply>
# Client-side
diff --git a/tests/data/test1946 b/tests/data/test1946
index f2f8ecc..220df01 100644
--- a/tests/data/test1946
+++ b/tests/data/test1946
@@ -28,7 +28,7 @@
Set-Cookie: 1cookie=data1;
Set-Cookie: 2cookie=data2;
-</data>
+</data2>
</reply>
# Client-side
diff --git a/tests/data/test1947 b/tests/data/test1947
new file mode 100644
index 0000000..f159e4d
--- /dev/null
+++ b/tests/data/test1947
@@ -0,0 +1,71 @@
+<testcase>
+<info>
+<keywords>
+curl_easy_nextheader
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 302 OK
+Date: Thu, 01 Nov 2001 14:49:00 GMT
+Server: test with trailing space
+Content-Type: text/html
+Content-Length: 0
+Set-Cookie: onecookie=data;
+Set-Cookie: secondcookie=2data;
+Set-Cookie: cookie3=data3;
+Location: /%TESTNUMBER0002
+
+</data>
+<data2 nocheck="yes">
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: the other one
+Content-Type: text/html
+Content-Length: 0
+Set-Cookie: 1cookie=data1;
+Set-Cookie: 2cookie=data2;
+
+</data2>
+
+<data3 nocheck="yes">
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: the other one
+Content-Type: text/html
+Content-Length: 0
+
+</data3>
+</reply>
+
+# Client-side
+<client>
+<features>
+headers-api
+</features>
+<server>
+http
+</server>
+
+<name>
+curl_easy_nextheader on second request after first did redirects
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER0003
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<stdout>
+count = 2
+count = 1
+</stdout>
+</verify>
+</testcase>
diff --git a/tests/data/test1948 b/tests/data/test1948
new file mode 100644
index 0000000..4c50b02
--- /dev/null
+++ b/tests/data/test1948
@@ -0,0 +1,72 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+HTTP PUT
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 01 Nov 2001 14:49:00 GMT
+Content-Type: text/html
+Content-Length: 6
+
+hello
+</data>
+<datacheck>
+HTTP/1.1 200 OK
+Date: Thu, 01 Nov 2001 14:49:00 GMT
+Content-Type: text/html
+Content-Length: 6
+
+hello
+HTTP/1.1 200 OK
+Date: Thu, 01 Nov 2001 14:49:00 GMT
+Content-Type: text/html
+Content-Length: 6
+
+hello
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+
+<name>
+CURLOPT_POST after CURLOPT_UPLOAD reusing handle
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+PUT /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 22
+
+This is test PUT data
+POST /1948 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 22
+Content-Type: application/x-www-form-urlencoded
+
+This is test PUT data
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1955 b/tests/data/test1955
new file mode 100644
index 0000000..342b7b7
--- /dev/null
+++ b/tests/data/test1955
@@ -0,0 +1,75 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+CURLOPT_AWS_SIGV4
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+Location: /%TESTNUMBER0002
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+
+</data2>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# this relies on the debug feature which allow to set the time
+<features>
+SSL
+debug
+crypto
+</features>
+<setenv>
+CURL_FORCEHOST=1
+</setenv>
+
+<name>
+HTTP AWS_SIGV4 without X-Xxx-Content-Sha256
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+^Content-Type:.*
+^Accept:.*
+</strip>
+<protocol>
+GET /aws_sigv4/testapi/test HTTP/1.1
+Host: exam.ple.com:9000
+Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/ple/exam/xxx4_request, SignedHeaders=content-type;host;tesmixcase;test0;test1;test2;test_space;x-xxx-date, Signature=779a8ff876528aece8bf03b1296702af0644a4745aa5feabb6ebb1a7bb0d907e
+X-Xxx-Date: 19700101T000000Z
+test2: 1234
+test_space: t s m end
+tesMixCase: MixCase
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1956 b/tests/data/test1956
new file mode 100644
index 0000000..76aaa93
--- /dev/null
+++ b/tests/data/test1956
@@ -0,0 +1,73 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+CURLOPT_AWS_SIGV4
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+Location: /%TESTNUMBER
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+
+</data2>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# this relies on the debug feature which allow to set the time
+<features>
+SSL
+debug
+crypto
+</features>
+<setenv>
+CURL_FORCEHOST=1
+</setenv>
+
+<name>
+HTTP AWS_SIGV4 with X-Xxx-Content-Sha256 of empty payload
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+^Content-Type:.*
+^Accept:.*
+</strip>
+<protocol>
+GET /aws_sigv4/testapi/test HTTP/1.1
+Host: exam.ple.com:9000
+Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/ple/exam/xxx4_request, SignedHeaders=content-type;host;x-xxx-content-sha256;x-xxx-date, Signature=dfe78c8846a9b7d65d1eb4c1d6ea7bc886650d03f3568088cb8d5b4c3778287f
+X-Xxx-Date: 19700101T000000Z
+X-Xxx-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1957 b/tests/data/test1957
new file mode 100644
index 0000000..add27db
--- /dev/null
+++ b/tests/data/test1957
@@ -0,0 +1,73 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+CURLOPT_AWS_SIGV4
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+Location: /%TESTNUMBER
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+
+</data2>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# this relies on the debug feature which allow to set the time
+<features>
+SSL
+debug
+crypto
+</features>
+<setenv>
+CURL_FORCEHOST=1
+</setenv>
+
+<name>
+HTTP AWS_SIGV4 with X-Xxx-Content-Sha256 of arbitrary payload
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+^Content-Type:.*
+^Accept:.*
+</strip>
+<protocol>
+GET /aws_sigv4/testapi/test HTTP/1.1
+Host: exam.ple.com:9000
+Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/ple/exam/xxx4_request, SignedHeaders=content-type;host;x-xxx-content-sha256;x-xxx-date, Signature=25b4cac711ea8f65010c485d3778885f5f3870d0b8ff0b3ab58a8d7eeab991ff
+X-Xxx-Date: 19700101T000000Z
+X-Xxx-Content-Sha256: arbitrary
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1958 b/tests/data/test1958
new file mode 100644
index 0000000..c54b179
--- /dev/null
+++ b/tests/data/test1958
@@ -0,0 +1,73 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+CURLOPT_AWS_SIGV4
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+Location: /%TESTNUMBER
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+
+</data2>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# this relies on the debug feature which allow to set the time
+<features>
+SSL
+debug
+crypto
+</features>
+<setenv>
+CURL_FORCEHOST=1
+</setenv>
+
+<name>
+HTTP AWS_SIGV4 with X-Xxx-Content-Sha256 of arbitrary payload with whitespace
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+^Content-Type:.*
+^Accept:.*
+</strip>
+<protocol>
+GET /aws_sigv4/testapi/test HTTP/1.1
+Host: exam.ple.com:9000
+Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/ple/exam/xxx4_request, SignedHeaders=content-type;host;x-xxx-content-sha256;x-xxx-date, Signature=25b4cac711ea8f65010c485d3778885f5f3870d0b8ff0b3ab58a8d7eeab991ff
+X-Xxx-Date: 19700101T000000Z
+X-Xxx-Content-Sha256: arbitrary
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1959 b/tests/data/test1959
new file mode 100644
index 0000000..2be813b
--- /dev/null
+++ b/tests/data/test1959
@@ -0,0 +1,73 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+CURLOPT_AWS_SIGV4
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+Location: /%TESTNUMBER
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+
+</data2>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# this relies on the debug feature which allow to set the time
+<features>
+SSL
+debug
+crypto
+</features>
+<setenv>
+CURL_FORCEHOST=1
+</setenv>
+
+<name>
+HTTP AWS_SIGV4 with long value for X-Xxx-Content-Sha256
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+^Content-Type:.*
+^Accept:.*
+</strip>
+<protocol>
+GET /aws_sigv4/testapi/test HTTP/1.1
+Host: exam.ple.com:9000
+Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/ple/exam/xxx4_request, SignedHeaders=content-type;host;x-xxx-content-sha256;x-xxx-date, Signature=7b343a4aa55d73ffc05005d84480bc705a3367373ed8cae1a1c0fbd2b3aa0483
+X-Xxx-Date: 19700101T000000Z
+X-Xxx-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1960 b/tests/data/test1960
new file mode 100644
index 0000000..1ab180c
--- /dev/null
+++ b/tests/data/test1960
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+CURLOPT_SOCKOPTFUNCTION
+CURL_SOCKOPT_ALREADY_CONNECTED
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<precheck>
+./libtest/lib%TESTNUMBER check
+</precheck>
+<server>
+http
+</server>
+
+<name>
+application hands over already connected socket
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://%HOSTIP:%HTTPPORT/file %HOSTIP %HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /file HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1970 b/tests/data/test1970
new file mode 100644
index 0000000..1fbe60b
--- /dev/null
+++ b/tests/data/test1970
@@ -0,0 +1,74 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+CURLOPT_AWS_SIGV4
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+Location: /%TESTNUMBER0002
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+
+</data2>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# this relies on the debug feature which allow to set the time
+<features>
+SSL
+debug
+crypto
+</features>
+<setenv>
+CURL_FORCEHOST=1
+</setenv>
+
+<name>
+HTTP AWS_SIGV4 for AWS S3: UPLOAD with INFILESIZE=0
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+^Content-Type:.*
+^Accept:.*
+</strip>
+<protocol>
+PUT /aws_sigv4/testapi/test HTTP/1.1
+Host: exam.ple.com:9000
+Authorization: AWS4-HMAC-SHA256 Credential=xxx/19700101/us-east-1/s3/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=a028756f42a859122e9609c1f90cae4b272d6b03bf60d9fd354138176dfa2260
+X-Amz-Date: 19700101T000000Z
+x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
+Content-Length: 0
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1971 b/tests/data/test1971
new file mode 100644
index 0000000..c311d17
--- /dev/null
+++ b/tests/data/test1971
@@ -0,0 +1,70 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+CURLOPT_AWS_SIGV4
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 100 Continue
+
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# this relies on the debug feature which allow to set the time
+<features>
+SSL
+debug
+crypto
+</features>
+<setenv>
+CURL_FORCEHOST=1
+</setenv>
+
+<name>
+HTTP AWS_SIGV4 for AWS S3: UPLOAD with unknown INFILESIZE
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+^Content-Type:.*
+^Accept:.*
+</strip>
+<protocol>
+PUT /aws_sigv4/testapi/test HTTP/1.1
+Host: exam.ple.com:9000
+Authorization: AWS4-HMAC-SHA256 Credential=xxx/19700101/us-east-1/s3/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=4a6e9b4af0542ffb83744c6852f8e1bfec14f2a67e6f6f037b39f172f79d62af
+X-Amz-Date: 19700101T000000Z
+x-amz-content-sha256: UNSIGNED-PAYLOAD
+Transfer-Encoding: chunked
+Expect: 100-continue
+
+0
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1972 b/tests/data/test1972
new file mode 100644
index 0000000..70c1837
--- /dev/null
+++ b/tests/data/test1972
@@ -0,0 +1,79 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+CURLOPT_AWS_SIGV4
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+Location: /%TESTNUMBER0002
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+
+</data2>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# this relies on the debug feature which allow to set the time
+<features>
+SSL
+debug
+crypto
+</features>
+<setenv>
+CURL_FORCEHOST=1
+</setenv>
+
+<name>
+HTTP AWS_SIGV4 for AWS S3: MIMEPOST
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+^Content-Type:.*
+^Accept:.*
+</strip>
+<protocol>
+POST /aws_sigv4/testapi/test HTTP/1.1
+Host: exam.ple.com:9000
+Authorization: AWS4-HMAC-SHA256 Credential=xxx/19700101/us-east-1/s3/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=eaee0f1c5984ad5d81c8bc7805f28c7b83b35322de654b2ace18cb8cf6d5a9cb
+X-Amz-Date: 19700101T000000Z
+x-amz-content-sha256: UNSIGNED-PAYLOAD
+Content-Length: 142
+
+--------------------------3433323135333231
+Content-Disposition: attachment; name="foo"
+
+bar
+--------------------------3433323135333231--
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1973 b/tests/data/test1973
new file mode 100644
index 0000000..559fd5f
--- /dev/null
+++ b/tests/data/test1973
@@ -0,0 +1,75 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+CURLOPT_AWS_SIGV4
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+Location: /%TESTNUMBER0002
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+
+</data2>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# this relies on the debug feature which allow to set the time
+<features>
+SSL
+debug
+crypto
+</features>
+<setenv>
+CURL_FORCEHOST=1
+</setenv>
+
+<name>
+HTTP AWS_SIGV4 for AWS S3: POSTFIELDS
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+^Content-Type:.*
+^Accept:.*
+</strip>
+<protocol>
+POST /aws_sigv4/testapi/test HTTP/1.1
+Host: exam.ple.com:9000
+Authorization: AWS4-HMAC-SHA256 Credential=xxx/19700101/us-east-1/s3/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=7eb34202214384872221b99a9c671b7517891ac6af56b0aff24ec51adf62b10a
+X-Amz-Date: 19700101T000000Z
+x-amz-content-sha256: 4b02e333ccf7cf530ddee3e10ebe54e935500b5e570e68650d63d743e8bbc045
+Content-Length: 12
+
+post fields
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1974 b/tests/data/test1974
new file mode 100644
index 0000000..9b5bb84
--- /dev/null
+++ b/tests/data/test1974
@@ -0,0 +1,73 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+CURLOPT_AWS_SIGV4
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+Location: /%TESTNUMBER0002
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+
+</data2>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# this relies on the debug feature which allow to set the time
+<features>
+SSL
+debug
+crypto
+</features>
+<setenv>
+CURL_FORCEHOST=1
+</setenv>
+
+<name>
+HTTP AWS_SIGV4 for AWS S3: GET
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+^Content-Type:.*
+^Accept:.*
+</strip>
+<protocol>
+GET /aws_sigv4/testapi/test HTTP/1.1
+Host: exam.ple.com:9000
+Authorization: AWS4-HMAC-SHA256 Credential=xxx/19700101/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=e6270423932feafe9b00ca5d60c9ed566be649f9ca9676144288273945153021
+X-Amz-Date: 19700101T000000Z
+x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1975 b/tests/data/test1975
new file mode 100644
index 0000000..09256de
--- /dev/null
+++ b/tests/data/test1975
@@ -0,0 +1,70 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+CURLOPT_AWS_SIGV4
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 100 Continue
+
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# this relies on the debug feature which allow to set the time
+<features>
+SSL
+debug
+crypto
+</features>
+<setenv>
+CURL_FORCEHOST=1
+</setenv>
+
+<name>
+HTTP AWS_SIGV4 for AWS S3: UPLOAD with given x-amz-content-sha256
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+^Content-Type:.*
+^Accept:.*
+</strip>
+<protocol>
+PUT /aws_sigv4/testapi/test HTTP/1.1
+Host: exam.ple.com:9000
+Authorization: AWS4-HMAC-SHA256 Credential=xxx/19700101/us-east-1/s3/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=a028756f42a859122e9609c1f90cae4b272d6b03bf60d9fd354138176dfa2260
+X-Amz-Date: 19700101T000000Z
+Transfer-Encoding: chunked
+X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
+Expect: 100-continue
+
+0
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test200 b/tests/data/test200
index e7c5146..7ce2cbc 100644
--- a/tests/data/test200
+++ b/tests/data/test200
@@ -24,9 +24,9 @@
basic file:// file
</name>
<command option="no-include">
-file://localhost%FILE_PWD/log/test%TESTNUMBER.txt
+file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar
bar
diff --git a/tests/data/test2000 b/tests/data/test2000
index 32604c6..b114dd8 100644
--- a/tests/data/test2000
+++ b/tests/data/test2000
@@ -32,9 +32,9 @@
FTP RETR followed by FILE
</name>
<command option="no-include">
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER file://localhost%FILE_PWD/log/test%TESTNUMBER.txt
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar
bar
diff --git a/tests/data/test2001 b/tests/data/test2001
index e85fd1f..f1e7146 100644
--- a/tests/data/test2001
+++ b/tests/data/test2001
@@ -49,9 +49,9 @@
HTTP GET followed by FTP RETR followed by FILE
</name>
<command option="no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 ftp://%HOSTIP:%FTPPORT/%TESTNUMBER0002 file://localhost%FILE_PWD/log/test%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 ftp://%HOSTIP:%FTPPORT/%TESTNUMBER0002 file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar
bar
diff --git a/tests/data/test2002 b/tests/data/test2002
index 2cd2801..e06490b 100644
--- a/tests/data/test2002
+++ b/tests/data/test2002
@@ -58,9 +58,9 @@
HTTP GET followed by FTP RETR followed by FILE followed by TFTP RRQ
</name>
<command option="no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 ftp://%HOSTIP:%FTPPORT/%TESTNUMBER0002 file://localhost%FILE_PWD/log/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT//%TESTNUMBER0003
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 ftp://%HOSTIP:%FTPPORT/%TESTNUMBER0002 file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT//%TESTNUMBER0003
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar
bar
@@ -72,6 +72,9 @@
#
# Verify data after the test has been "shot"
<verify>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
GET /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
@@ -89,7 +92,6 @@
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER0003
QUIT
</protocol>
diff --git a/tests/data/test2003 b/tests/data/test2003
index a1d5a9f..9054a8d 100644
--- a/tests/data/test2003
+++ b/tests/data/test2003
@@ -58,9 +58,9 @@
HTTP GET followed by FTP RETR followed by FILE followed by TFTP RRQ then again in reverse order
</name>
<command option="no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 ftp://%HOSTIP:%FTPPORT/%TESTNUMBER0002 file://localhost%FILE_PWD/log/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT//%TESTNUMBER0003 tftp://%HOSTIP:%TFTPPORT//%TESTNUMBER0003 file://localhost%FILE_PWD/log/test%TESTNUMBER.txt ftp://%HOSTIP:%FTPPORT/%TESTNUMBER0002 http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 ftp://%HOSTIP:%FTPPORT/%TESTNUMBER0002 file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT//%TESTNUMBER0003 tftp://%HOSTIP:%TFTPPORT//%TESTNUMBER0003 file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt ftp://%HOSTIP:%FTPPORT/%TESTNUMBER0002 http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar
bar
@@ -72,6 +72,9 @@
#
# Verify data after the test has been "shot"
<verify>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
GET /%TESTNUMBER0001 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
@@ -89,13 +92,11 @@
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER0003
opcode = 1
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER0003
EPSV
SIZE %TESTNUMBER0002
diff --git a/tests/data/test2004 b/tests/data/test2004
index 17a7316..8046356 100644
--- a/tests/data/test2004
+++ b/tests/data/test2004
@@ -30,9 +30,9 @@
TFTP RRQ followed by SFTP retrieval followed by FILE followed by SCP retrieval then again in reverse order
</name>
<command option="no-include">
---key curl_client_key --pubkey curl_client_key.pub -u %USER: tftp://%HOSTIP:%TFTPPORT//%TESTNUMBER sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test%TESTNUMBER.txt file://localhost%FILE_PWD/log/test%TESTNUMBER.txt scp://%HOSTIP:%SSHPORT%SSH_PWD/log/test%TESTNUMBER.txt file://localhost%FILE_PWD/log/test%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT//%TESTNUMBER --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: tftp://%HOSTIP:%TFTPPORT//%TESTNUMBER sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/test%TESTNUMBER.txt file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/test%TESTNUMBER.txt file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT//%TESTNUMBER --insecure
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
This is test data
for several protocols
</file>
@@ -41,18 +41,19 @@
#
# Verify data after the test has been "shot"
<verify>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 1
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER
opcode = 1
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER
</protocol>
<stdout>
diff --git a/tests/data/test201 b/tests/data/test201
index 8e9f190..b68abb8 100644
--- a/tests/data/test201
+++ b/tests/data/test201
@@ -21,7 +21,7 @@
missing file:// file
</name>
<command>
-file://localhost/%PWD/log/non-existent-file.txt
+file://localhost/%PWD/%LOGDIR/non-existent-file.txt
</command>
</client>
diff --git a/tests/data/test202 b/tests/data/test202
index f5efc07..f2fb078 100644
--- a/tests/data/test202
+++ b/tests/data/test202
@@ -20,9 +20,9 @@
two file:// URLs to stdout
</name>
<command option="no-include">
-file://localhost%FILE_PWD/log/test%TESTNUMBER.txt FILE://localhost%FILE_PWD/log/test%TESTNUMBER.txt
+file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt FILE://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
contents in a single file
</file>
</client>
diff --git a/tests/data/test203 b/tests/data/test203
index d193563..496a414 100644
--- a/tests/data/test203
+++ b/tests/data/test203
@@ -29,9 +29,9 @@
MSYS2_ARG_CONV_EXCL=file:
</setenv>
<command option="no-include">
-file:%FILE_PWD/log/test%TESTNUMBER.txt
+file:%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar
bar
diff --git a/tests/data/test2039 b/tests/data/test2039
index a10852a..25ecf27 100644
--- a/tests/data/test2039
+++ b/tests/data/test2039
@@ -37,9 +37,9 @@
FTP (optional .netrc with 'default' override; no user/pass) dir list PASV
</name>
<command>
---netrc-optional --netrc-file log/netrc%TESTNUMBER ftp://%HOSTIP:%FTPPORT/
+--netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER ftp://%HOSTIP:%FTPPORT/
</command>
-<file name="log/netrc%TESTNUMBER" >
+<file name="%LOGDIR/netrc%TESTNUMBER" >
# the following two lines were created while testing curl
default login userdef password passwddef
machine %HOSTIP login user1 password passwd1
diff --git a/tests/data/test204 b/tests/data/test204
index dcf0bb5..63d17cd 100644
--- a/tests/data/test204
+++ b/tests/data/test204
@@ -16,9 +16,9 @@
"upload" with file://
</name>
<command option="no-include">
-file://localhost%FILE_PWD/log/result%TESTNUMBER.txt -T log/upload%TESTNUMBER.txt
+file://localhost%FILE_PWD/%LOGDIR/result%TESTNUMBER.txt -T %LOGDIR/upload%TESTNUMBER.txt
</command>
-<file name="log/upload%TESTNUMBER.txt">
+<file name="%LOGDIR/upload%TESTNUMBER.txt">
data
in
file
@@ -29,7 +29,7 @@
# Verify data after the test has been "shot"
<verify>
-<file name="log/result%TESTNUMBER.txt">
+<file name="%LOGDIR/result%TESTNUMBER.txt">
data
in
file
diff --git a/tests/data/test2041 b/tests/data/test2041
index 1958bb7..f007f47 100644
--- a/tests/data/test2041
+++ b/tests/data/test2041
@@ -35,7 +35,7 @@
simple HTTPS GET with base64-sha256 public key pinning
</name>
<command>
---cacert %SRCDIR/certs/EdelCurlRoot-ca.crt --pinnedpubkey sha256//+JYNkp2GTGRgrvZMUkOxbFJQQqYpwNE6toGmBjz00D8= https://localhost:%HTTPSPORT/%TESTNUMBER
+--cacert %SRCDIR/certs/EdelCurlRoot-ca.crt --pinnedpubkey sha256//AAUDLk4c98xcFUDvA9i/MnA9HuO03IPi15r+Cx9OXnc= https://localhost:%HTTPSPORT/%TESTNUMBER
</command>
# Ensure that we're running on localhost because we're checking the host name
<precheck>
diff --git a/tests/data/test205 b/tests/data/test205
index de04997..e2165cc 100644
--- a/tests/data/test205
+++ b/tests/data/test205
@@ -17,9 +17,9 @@
"upload" with file://
</name>
<command option="no-include">
-file://localhost/%PWD/log/nonexisting/result%TESTNUMBER.txt -T log/upload%TESTNUMBER.txt
+file://localhost/%PWD/%LOGDIR/nonexisting/result%TESTNUMBER.txt -T %LOGDIR/upload%TESTNUMBER.txt
</command>
-<file name="log/upload%TESTNUMBER.txt">
+<file name="%LOGDIR/upload%TESTNUMBER.txt">
data
in
file
diff --git a/tests/data/test2058 b/tests/data/test2058
index c400f26..7561c28 100644
--- a/tests/data/test2058
+++ b/tests/data/test2058
@@ -72,9 +72,9 @@
HTTP POST --digest with PUT, resumed upload, modified method and SHA-256
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T log/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -C 2 -X GET
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T %LOGDIR/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -C 2 -X GET
</command>
-<file name="log/%TESTNUMBER">
+<file name="%LOGDIR/%TESTNUMBER">
test
</file>
</client>
@@ -98,7 +98,6 @@
Accept: */*
Proxy-Connection: Keep-Alive
Content-Length: 3
-Expect: 100-continue
st
</protocol>
diff --git a/tests/data/test2059 b/tests/data/test2059
index 3170c99..0bd5be8 100644
--- a/tests/data/test2059
+++ b/tests/data/test2059
@@ -72,9 +72,9 @@
HTTP POST --digest with PUT, resumed upload, modified method, SHA-256 and userhash=true
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T log/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -C 2 -X GET
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T %LOGDIR/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -C 2 -X GET
</command>
-<file name="log/%TESTNUMBER">
+<file name="%LOGDIR/%TESTNUMBER">
test
</file>
</client>
@@ -98,7 +98,6 @@
Accept: */*
Proxy-Connection: Keep-Alive
Content-Length: 3
-Expect: 100-continue
st
</protocol>
diff --git a/tests/data/test2060 b/tests/data/test2060
index 11dd155..8563715 100644
--- a/tests/data/test2060
+++ b/tests/data/test2060
@@ -72,9 +72,9 @@
HTTP POST --digest with PUT, resumed upload, modified method, SHA-512-256 and userhash=false
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T log/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -C 2 -X GET
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -u auser:apasswd --digest -T %LOGDIR/%TESTNUMBER -x http://%HOSTIP:%HTTPPORT -C 2 -X GET
</command>
-<file name="log/%TESTNUMBER">
+<file name="%LOGDIR/%TESTNUMBER">
test
</file>
</client>
@@ -98,7 +98,6 @@
Accept: */*
Proxy-Connection: Keep-Alive
Content-Length: 3
-Expect: 100-continue
st
</protocol>
diff --git a/tests/data/test2071 b/tests/data/test2071
index 900f0d5..45ee917 100644
--- a/tests/data/test2071
+++ b/tests/data/test2071
@@ -24,9 +24,9 @@
basic file:// file with "127.0.0.1" hostname
</name>
<command option="no-include">
-file://127.0.0.1%FILE_PWD/log/test2070.txt
+file://127.0.0.1%FILE_PWD/%LOGDIR/test2070.txt
</command>
-<file name="log/test2070.txt">
+<file name="%LOGDIR/test2070.txt">
foo
bar
bar
diff --git a/tests/data/test2072 b/tests/data/test2072
index 1791670..50cb4b6 100644
--- a/tests/data/test2072
+++ b/tests/data/test2072
@@ -24,12 +24,12 @@
file:// with unix path resolution behavior for the case of extra slashes
</name>
<command option="no-include">
-file:////%PWD/log/test%TESTNUMBER.txt
+file:////%PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
<precheck>
perl -e "print 'Test requires a unix system' if ( $^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'dos' || $^O eq 'msys');"
</precheck>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar
bar
diff --git a/tests/data/test2073 b/tests/data/test2073
index dd36415..c6b3dee 100644
--- a/tests/data/test2073
+++ b/tests/data/test2073
@@ -27,6 +27,9 @@
#
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test208 b/tests/data/test208
index d081b51..f3ad620 100644
--- a/tests/data/test208
+++ b/tests/data/test208
@@ -33,9 +33,9 @@
HTTP PUT to a FTP URL with username+password - over HTTP proxy
</name>
<command>
--x http://%HOSTIP:%HTTPPORT ftp://daniel:mysecret@host.com/we/want/%TESTNUMBER -T log/test%TESTNUMBER.txt
+-x http://%HOSTIP:%HTTPPORT ftp://daniel:mysecret@host.com/we/want/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
Weird
file
to
@@ -58,7 +58,6 @@
Accept: */*
Proxy-Connection: Keep-Alive
Content-Length: 78
-Expect: 100-continue
Weird
file
diff --git a/tests/data/test2080 b/tests/data/test2080
index 9c8d538..8b92c4f 100644
--- a/tests/data/test2080
+++ b/tests/data/test2080
Binary files differ
diff --git a/tests/data/test2087 b/tests/data/test2087
index 78751ea..e0fa9ed 100644
--- a/tests/data/test2087
+++ b/tests/data/test2087
@@ -39,7 +39,7 @@
CURL_SSL_BACKEND=schannel
</setenv>
<command>
---cacert %SRCDIR/certs/EdelCurlRoot-ca.crt --pinnedpubkey sha256//+JYNkp2GTGRgrvZMUkOxbFJQQqYpwNE6toGmBjz00D8= --ssl-revoke-best-effort https://localhost:%HTTPSPORT/%TESTNUMBER
+--cacert %SRCDIR/certs/EdelCurlRoot-ca.crt --pinnedpubkey sha256//AAUDLk4c98xcFUDvA9i/MnA9HuO03IPi15r+Cx9OXnc= --ssl-revoke-best-effort https://localhost:%HTTPSPORT/%TESTNUMBER
</command>
# Ensure that we're running on localhost because we're checking the host name
<precheck>
diff --git a/tests/data/test21 b/tests/data/test21
index 8e4e847..5c099cf 100644
--- a/tests/data/test21
+++ b/tests/data/test21
@@ -13,6 +13,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test216 b/tests/data/test216
index 0e74110..82629f5 100644
--- a/tests/data/test216
+++ b/tests/data/test216
@@ -18,9 +18,9 @@
FTP upload two files to the same dir
</name>
<command>
--T log/upload.%TESTNUMBER ftp://%HOSTIP:%FTPPORT/a/path/%TESTNUMBER/ -T log/upload.%TESTNUMBER ftp://%HOSTIP:%FTPPORT/a/path/%TESTNUMBER/%2e%2eanotherup.%TESTNUMBER
+-T %LOGDIR/upload.%TESTNUMBER ftp://%HOSTIP:%FTPPORT/a/path/%TESTNUMBER/ -T %LOGDIR/upload.%TESTNUMBER ftp://%HOSTIP:%FTPPORT/a/path/%TESTNUMBER/%2e%2eanotherup.%TESTNUMBER
</command>
-<file name="log/upload.%TESTNUMBER">
+<file name="%LOGDIR/upload.%TESTNUMBER">
upload this file twice
</file>
</client>
diff --git a/tests/data/test218 b/tests/data/test218
index dc71442..3b67095 100644
--- a/tests/data/test218
+++ b/tests/data/test218
@@ -29,9 +29,9 @@
HTTP PUT from a file but enforce chunked transfer-encoding
</name>
<command>
- -T log/file%TESTNUMBER -H "Transfer-Encoding: chunked" http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+ -T %LOGDIR/file%TESTNUMBER -H "Transfer-Encoding: chunked" http://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
-<file name="log/file%TESTNUMBER">
+<file name="%LOGDIR/file%TESTNUMBER">
just some tiny teeny contents
</file>
</client>
@@ -45,7 +45,6 @@
User-Agent: curl/%VERSION
Accept: */*
Transfer-Encoding: chunked
-Expect: 100-continue
%if hyper
1E
diff --git a/tests/data/test22 b/tests/data/test22
index f5593c4..92fded6 100644
--- a/tests/data/test22
+++ b/tests/data/test22
@@ -2,7 +2,6 @@
<info>
<keywords>
HTTP
-HTTP PUT
long URL
</keywords>
</info>
diff --git a/tests/data/test2205 b/tests/data/test2205
index 9bc8d32..da6f1dd 100644
--- a/tests/data/test2205
+++ b/tests/data/test2205
@@ -25,11 +25,11 @@
<name>
MQTT with very long user name
</name>
-<file name="log/input%TESTNUMBER">
+<file name="%LOGDIR/input%TESTNUMBER">
user = %repeat[65536 x a]%:fakepasswd
</file>
<command option="binary-trace">
-mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER -K log/input%TESTNUMBER
+mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER -K %LOGDIR/input%TESTNUMBER
</command>
</client>
diff --git a/tests/data/test2300 b/tests/data/test2300
new file mode 100644
index 0000000..997acfa
--- /dev/null
+++ b/tests/data/test2300
@@ -0,0 +1,62 @@
+<testcase>
+<info>
+<keywords>
+WebSockets
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 101 Switching to WebSockets swsclose
+Server: test-server/fake
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
+
+</data>
+# allow upgrade
+<servercmd>
+upgrade
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+# for the forced CURL_ENTROPY
+<features>
+debug
+ws
+</features>
+<server>
+http
+</server>
+ <name>
+WebSockets upgrade only
+ </name>
+ <command>
+ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol nocheck="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Version: 13
+Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ==
+
+</protocol>
+<errorcode>
+52
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test2301 b/tests/data/test2301
new file mode 100644
index 0000000..1f8ed66
--- /dev/null
+++ b/tests/data/test2301
@@ -0,0 +1,65 @@
+<testcase>
+<info>
+<keywords>
+WebSockets
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes" nonewline="yes">
+HTTP/1.1 101 Switching to WebSockets
+Server: test-server/fake
+Upgrade: websocket
+Connection: Upgrade
+Something: else
+Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
+
+%hex[%89%00]hex%
+</data>
+# allow upgrade
+<servercmd>
+upgrade
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+# require debug for the forced CURL_ENTROPY
+<features>
+debug
+ws
+</features>
+<server>
+http
+</server>
+<name>
+WebSockets via callback (raw mode) + curl_ws_send()
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+<command>
+ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol nocheck="yes" nonewline="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: webbie-sox/3
+Accept: */*
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Version: 13
+Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ==
+
+%hex[%8a%00]hex%
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test2302 b/tests/data/test2302
new file mode 100644
index 0000000..013c324
--- /dev/null
+++ b/tests/data/test2302
@@ -0,0 +1,70 @@
+<testcase>
+<info>
+<keywords>
+WebSockets
+</keywords>
+</info>
+
+#
+# Sends a PING + a 5 byte hello TEXT
+<reply>
+<data nocheck="yes" nonewline="yes">
+HTTP/1.1 101 Switching to WebSockets
+Server: test-server/fake
+Upgrade: websocket
+Connection: Upgrade
+Something: else
+Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
+
+%hex[%89%00%81%05hello]hex%
+</data>
+# allow upgrade
+<servercmd>
+upgrade
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+# require debug for the forced CURL_ENTROPY
+<features>
+debug
+ws
+</features>
+<server>
+http
+</server>
+<name>
+WebSockets via callback (frame mode) + curl_ws_send()
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+<command>
+ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# PONG with no data and the 32 bit mask
+#
+<verify>
+<protocol nocheck="yes" nonewline="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: webbie-sox/3
+Accept: */*
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Version: 13
+Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ==
+
+%hex[%8a%808321]hex%
+</protocol>
+<stdout mode="text">
+68 65 6c 6c 6f
+RECFLAGS: 1
+</stdout>
+</verify>
+</testcase>
diff --git a/tests/data/test2303 b/tests/data/test2303
new file mode 100644
index 0000000..dbd1115
--- /dev/null
+++ b/tests/data/test2303
@@ -0,0 +1,59 @@
+<testcase>
+<info>
+<keywords>
+WebSockets
+</keywords>
+</info>
+
+#
+<reply>
+<data nocheck="yes" nonewline="yes">
+HTTP/1.1 200 Oblivious
+Server: test-server/fake
+Something: else
+Content-Length: 6
+
+hello
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+# require debug for the forced CURL_ENTROPY
+<features>
+debug
+ws
+</features>
+<server>
+http
+</server>
+<name>
+WebSockets but gets a 200 back
+</name>
+<tool>
+lib2302
+</tool>
+<command>
+ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: webbie-sox/3
+Accept: */*
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Version: 13
+Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ==
+
+</protocol>
+# 22 == CURLE_HTTP_RETURNED_ERROR
+<errorcode>
+22
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test2304 b/tests/data/test2304
new file mode 100644
index 0000000..895518f
--- /dev/null
+++ b/tests/data/test2304
@@ -0,0 +1,69 @@
+<testcase>
+<info>
+<keywords>
+WebSockets
+</keywords>
+</info>
+
+#
+# Sends a PING + a 5 byte hello TEXT
+<reply>
+<data nocheck="yes" nonewline="yes">
+HTTP/1.1 101 Switching to WebSockets swsclose
+Server: test-server/fake
+Upgrade: websocket
+Connection: Upgrade
+Something: else
+Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
+
+%hex[%89%00%81%05hello]hex%
+</data>
+# allow upgrade
+<servercmd>
+upgrade
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+# require debug for the forced CURL_ENTROPY
+<features>
+debug
+ws
+</features>
+<server>
+http
+</server>
+<name>
+WebSockets curl_ws_recv() with closed connection
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+<command>
+ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# PONG with no data and the 32 bit mask
+#
+<verify>
+<protocol nocheck="yes" crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: websocket/2304
+Accept: */*
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Version: 13
+Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ==
+
+</protocol>
+
+# This test used to check that "connection closed" was output, but
+# that is flaky since the outgoing PING just before might fail already
+# and then the test exists before the output gets to be written
+</verify>
+</testcase>
diff --git a/tests/data/test2305 b/tests/data/test2305
new file mode 100644
index 0000000..869f6d3
--- /dev/null
+++ b/tests/data/test2305
@@ -0,0 +1,59 @@
+<testcase>
+<info>
+<keywords>
+WebSockets
+</keywords>
+</info>
+
+#
+# Sends three 4097 bytes TEXT frames, as one single message
+<reply>
+<data nocheck="yes">
+HTTP/1.1 101 Switching to WebSockets
+Server: test-server/fake
+Upgrade: websocket
+Connection: Upgrade
+Something: else
+Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
+
+%hex[%01%7e%10%01]hex%%repeat[256 x helothisisdaniel]%
+%hex[%01%7e%10%01]hex%%repeat[256 x helothisisdaniel]%
+%hex[%81%7e%10%01]hex%%repeat[256 x helothisisdaniel]%
+</data>
+# allow upgrade
+<servercmd>
+upgrade
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+# require debug for the forced CURL_ENTROPY
+<features>
+debug
+ws
+</features>
+<server>
+http
+</server>
+<name>
+WebSocket curl_ws_recv() loop reading three larger frames
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+<command>
+ws://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/save%TESTNUMBER
+</command>
+</client>
+
+#
+<verify>
+<file name="%LOGDIR/save%TESTNUMBER">
+%repeat[256 x helothisisdaniel]%
+%repeat[256 x helothisisdaniel]%
+%repeat[256 x helothisisdaniel]%
+</file>
+</verify>
+</testcase>
diff --git a/tests/data/test2306 b/tests/data/test2306
new file mode 100644
index 0000000..be0f5ee
--- /dev/null
+++ b/tests/data/test2306
@@ -0,0 +1,69 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+</keywords>
+</info>
+#
+# This reproduces the #11101 issue, when the second response comes back
+# with the first header being "folded"
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+<data2 nocheck="yes">
+HTTP/1.1 200 OK
+ Access-Control-Allow-Origin: *
+ Connection: Keep-Alive
+ Content-Type: text/html; charset=utf-8
+Date: Wed, 10 May 2023 14:58:08 GMT
+
+-foo-
+</data2>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# tool to run
+<tool>
+lib%TESTNUMBER
+</tool>
+
+ <name>
+HTTP GET re-used handle but only folded headers
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER0002
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test231 b/tests/data/test231
index c925eb1..64bafa1 100644
--- a/tests/data/test231
+++ b/tests/data/test231
@@ -23,9 +23,9 @@
file:// with resume
</name>
<command option="no-include">
-file://localhost%FILE_PWD/log/test%TESTNUMBER.txt -C 10
+file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt -C 10
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
A01234567
B01234567
C01234567
diff --git a/tests/data/test235 b/tests/data/test235
index e1f2a2f..3ff27cf 100644
--- a/tests/data/test235
+++ b/tests/data/test235
@@ -21,9 +21,9 @@
FTP resumed upload but no file present remotely
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -C -
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER -C -
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
this is the *****crap******** that we're gonna upload
worx?
diff --git a/tests/data/test236 b/tests/data/test236
index 3a89add..6f59e64 100644
--- a/tests/data/test236
+++ b/tests/data/test236
@@ -24,9 +24,9 @@
FTP resume upload but denied access to remote file
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/file%TESTNUMBER.txt -C -
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/file%TESTNUMBER.txt -C -
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
</file>
</client>
diff --git a/tests/data/test24 b/tests/data/test24
index bbd5f03..c275bfd 100644
--- a/tests/data/test24
+++ b/tests/data/test24
@@ -41,7 +41,7 @@
<errorcode>
22
</errorcode>
-<file2 name="log/stderr%TESTNUMBER" mode="text">
+<file2 name="%LOGDIR/stderr%TESTNUMBER" mode="text">
curl: (22) The requested URL returned error: 404
</file2>
</verify>
diff --git a/tests/data/test2400 b/tests/data/test2400
new file mode 100644
index 0000000..7f28f2f
--- /dev/null
+++ b/tests/data/test2400
@@ -0,0 +1,64 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP/2
+HTTPS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+debug
+h2c
+SSL
+</features>
+<server>
+http
+http/2
+</server>
+ <name>
+HTTP/2 GET
+ </name>
+<setenv>
+</setenv>
+ <command>
+-k --http2 "https://%HOSTIP:%HTTP2TLSPORT/%TESTNUMBER"
+</command>
+
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<stdout crlf="yes">
+HTTP/2 200
+date: Tue, 09 Nov 2010 14:49:00 GMT
+content-length: 6
+content-type: text/html
+funny-head: yesyes
+server: nghttpx
+via: 1.1 nghttpx
+
+-foo-
+</stdout>
+</verify>
+</testcase>
diff --git a/tests/data/test2401 b/tests/data/test2401
new file mode 100644
index 0000000..667974e
--- /dev/null
+++ b/tests/data/test2401
@@ -0,0 +1,72 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+HTTP/2
+HTTPS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 201 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Connection: close
+Content-Length: 0
+Funny-head: yesyes
+
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+debug
+h2c
+SSL
+</features>
+<server>
+http
+http/2
+</server>
+ <name>
+HTTP/2 GET
+ </name>
+<setenv>
+</setenv>
+ <command>
+-k --http2 "https://%HOSTIP:%HTTP2TLSPORT/%TESTNUMBER" -d "moo"
+</command>
+
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<stdout>
+HTTP/2 201
+date: Tue, 09 Nov 2010 14:49:00 GMT
+content-length: 0
+funny-head: yesyes
+server: nghttpx
+via: 1.1 nghttpx
+
+</stdout>
+<protocol nonewline="yes">
+POST /2401 HTTP/1.1
+Host: %HOSTIP:%HTTP2TLSPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+X-Forwarded-Proto: https
+Via: 2 nghttpx
+
+moo
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test2402 b/tests/data/test2402
new file mode 100644
index 0000000..57a26b9
--- /dev/null
+++ b/tests/data/test2402
@@ -0,0 +1,109 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP/2
+multi
+verbose logs
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data1 crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: server.example.com
+Content-Length: 47
+
+file contents should appear once for each file
+</data1>
+<data2>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: server.example.com
+Content-Length: 47
+
+file contents should appear once for each file
+</data2>
+<data3>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: server.example.com
+Content-Length: 47
+
+file contents should appear once for each file
+</data3>
+<data4>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: server.example.com
+Content-Length: 47
+
+file contents should appear once for each file
+</data4>
+</reply>
+
+# Client-side
+<client>
+<features>
+h2c
+SSL
+</features>
+<server>
+http
+http/2
+</server>
+<tool>
+lib%TESTNUMBER
+</tool>
+ <name>
+HTTP GET multiple over HTTP/2
+ </name>
+ <command>
+https://%HOSTIP:%HTTP2TLSPORT/path/%TESTNUMBER %HOSTIP %HTTP2TLSPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /path/%TESTNUMBER0001 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+X-Forwarded-Proto: https
+Via: 2 nghttpx
+
+GET /path/%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+X-Forwarded-Proto: https
+Via: 2 nghttpx
+
+GET /path/%TESTNUMBER0003 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+X-Forwarded-Proto: https
+Via: 2 nghttpx
+
+GET /path/%TESTNUMBER0004 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+X-Forwarded-Proto: https
+Via: 2 nghttpx
+
+</protocol>
+<strip>
+^Host:.*
+</strip>
+<file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
+* Connection #0 to host localhost left intact
+* Connection #0 to host localhost left intact
+* Connection #0 to host localhost left intact
+* Connection #0 to host localhost left intact
+</file>
+<stripfile>
+$_ = '' if (($_ !~ /left intact/) && ($_ !~ /Closing connection/))
+</stripfile>
+</verify>
+</testcase>
diff --git a/tests/data/test2403 b/tests/data/test2403
new file mode 100644
index 0000000..11aa74b
--- /dev/null
+++ b/tests/data/test2403
@@ -0,0 +1,73 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP/2
+HTTPS
+-w
+%header
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes" crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+h2c
+SSL
+headers-api
+</features>
+<server>
+http
+http/2
+</server>
+ <name>
+HTTP/2 GET
+ </name>
+<setenv>
+</setenv>
+ <command>
+-k --http2 -w '%{header_json}\n' "https://%HOSTIP:%HTTP2TLSPORT/%TESTNUMBER"
+</command>
+
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<stdout crlf="yes">
+HTTP/2 200
+date: Tue, 09 Nov 2010 14:49:00 GMT
+content-length: 6
+content-type: text/html
+funny-head: yesyes
+server: nghttpx
+via: 1.1 nghttpx
+
+-foo-
+{"date":["Tue, 09 Nov 2010 14:49:00 GMT"],
+"content-length":["6"],
+"content-type":["text/html"],
+"funny-head":["yesyes"],
+"server":["nghttpx"],
+"via":["1.1 nghttpx"]
+}
+</stdout>
+</verify>
+</testcase>
diff --git a/tests/data/test2404 b/tests/data/test2404
new file mode 100644
index 0000000..0e22bfe
--- /dev/null
+++ b/tests/data/test2404
@@ -0,0 +1,109 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP/2
+multi
+verbose logs
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data1 crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: server.example.com
+Content-Length: 47
+
+file contents should appear once for each file
+</data1>
+<data2>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: server.example.com
+Content-Length: 47
+
+file contents should appear once for each file
+</data2>
+<data3>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: server.example.com
+Content-Length: 47
+
+file contents should appear once for each file
+</data3>
+<data4>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: server.example.com
+Content-Length: 47
+
+file contents should appear once for each file
+</data4>
+</reply>
+
+# Client-side
+<client>
+<features>
+h2c
+SSL
+</features>
+<server>
+http
+http/2
+</server>
+<tool>
+lib%TESTNUMBER
+</tool>
+ <name>
+HTTP/2 using STREAM_WEIGHTs
+ </name>
+ <command>
+https://%HOSTIP:%HTTP2TLSPORT/path/%TESTNUMBER %HOSTIP %HTTP2TLSPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /path/%TESTNUMBER0001 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+X-Forwarded-Proto: https
+Via: 2 nghttpx
+
+GET /path/%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+X-Forwarded-Proto: https
+Via: 2 nghttpx
+
+GET /path/%TESTNUMBER0003 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+X-Forwarded-Proto: https
+Via: 2 nghttpx
+
+GET /path/%TESTNUMBER0004 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+X-Forwarded-Proto: https
+Via: 2 nghttpx
+
+</protocol>
+<strip>
+^Host:.*
+</strip>
+<file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
+* Connection #0 to host localhost left intact
+* Connection #0 to host localhost left intact
+* Connection #0 to host localhost left intact
+* Connection #0 to host localhost left intact
+</file>
+<stripfile>
+$_ = '' if (($_ !~ /left intact/) && ($_ !~ /Closing connection/))
+</stripfile>
+</verify>
+</testcase>
diff --git a/tests/data/test247 b/tests/data/test247
index 7e79d39..d51034c 100644
--- a/tests/data/test247
+++ b/tests/data/test247
@@ -19,7 +19,7 @@
<name>
FTP upload time condition evaluates TRUE => skip upload
</name>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
data
to
see
@@ -28,7 +28,7 @@
so does it?
</file>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt -z "apr 1 2005 08:00:00"
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt -z "apr 1 2005 08:00:00"
</command>
</client>
diff --git a/tests/data/test248 b/tests/data/test248
index 8881c99..4d4c1a6 100644
--- a/tests/data/test248
+++ b/tests/data/test248
@@ -19,7 +19,7 @@
<name>
FTP upload time condition evaluates FALSE => upload anyway
</name>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
data
to
see
@@ -28,7 +28,7 @@
so does it?
</file>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt -z "apr 1 2005 08:00:00"
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt -z "apr 1 2005 08:00:00"
</command>
</client>
diff --git a/tests/data/test250 b/tests/data/test250
index 3d0a8f3..b1879f2 100644
--- a/tests/data/test250
+++ b/tests/data/test250
@@ -2,6 +2,7 @@
<info>
<keywords>
FTP
+SLOWDOWN
</keywords>
</info>
diff --git a/tests/data/test2500 b/tests/data/test2500
new file mode 100644
index 0000000..0290a32
--- /dev/null
+++ b/tests/data/test2500
@@ -0,0 +1,78 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP/3
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes" crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+http/3
+nghttpx-h3
+</features>
+<server>
+http
+http/3
+</server>
+ <name>
+HTTP/3 GET:
+ </name>
+ <command>
+--cacert %SRCDIR/certs/EdelCurlRoot-ca.crt --http3 --resolve localhost:%HTTP3PORT:%HOSTIP https://localhost:%HTTP3PORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^X-Forwarded-Proto:.*
+^Via:.*
+</strip>
+<protocol crlf="yes">
+GET https://localhost:%HTTP3PORT/%TESTNUMBER HTTP/1.1
+Host: localhost:%HTTP3PORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+<stdout crlf="yes">
+HTTP/3 200
+date: Tue, 09 Nov 2010 14:49:00 GMT
+last-modified: Tue, 13 Jun 2000 12:10:00 GMT
+etag: "21025-dc7-39462498"
+accept-ranges: bytes
+content-length: 6
+content-type: text/html
+funny-head: yesyes
+via: 1.1 nghttpx
+
+-foo-
+</stdout>
+<stripfile>
+s/^server: nghttpx.*\r?\n//
+</stripfile>
+</verify>
+</testcase>
diff --git a/tests/data/test2501 b/tests/data/test2501
new file mode 100644
index 0000000..e7013e5
--- /dev/null
+++ b/tests/data/test2501
@@ -0,0 +1,70 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+HTTP/3
+HTTPS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 201 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Connection: close
+Content-Length: 0
+Funny-head: yesyes
+
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+debug
+http
+http/3
+</features>
+<server>
+http
+http/3
+</server>
+ <name>
+HTTP/3 POST
+ </name>
+<setenv>
+</setenv>
+ <command>
+-k --http3 "https://%HOSTIP:%HTTP3PORT/%TESTNUMBER" -d "moo"
+</command>
+
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<stdout>
+HTTP/3 201
+date: Tue, 09 Nov 2010 14:49:00 GMT
+content-length: 0
+funny-head: yesyes
+via: 1.1 nghttpx
+
+</stdout>
+<protocol nonewline="yes">
+POST https://%HOSTIP:%HTTP3PORT/2501 HTTP/1.1
+Host: %HOSTIP:%HTTP3PORT
+User-Agent: curl/%VERSION
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+Via: 3 nghttpx
+
+moo
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test2502 b/tests/data/test2502
new file mode 100644
index 0000000..5e4a0fd
--- /dev/null
+++ b/tests/data/test2502
@@ -0,0 +1,104 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP/3
+multi
+verbose logs
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data1 crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: server.example.com
+Content-Length: 47
+
+file contents should appear once for each file
+</data1>
+<data2>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: server.example.com
+Content-Length: 47
+
+file contents should appear once for each file
+</data2>
+<data3>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: server.example.com
+Content-Length: 47
+
+file contents should appear once for each file
+</data3>
+<data4>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: server.example.com
+Content-Length: 47
+
+file contents should appear once for each file
+</data4>
+</reply>
+
+# Client-side
+<client>
+<features>
+http/3
+</features>
+<server>
+http
+http/3
+</server>
+<tool>
+lib%TESTNUMBER
+</tool>
+ <name>
+HTTP GET multiple over HTTP/3
+ </name>
+ <command>
+https://%HOSTIP:%HTTP3PORT/path/%TESTNUMBER %HOSTIP %HTTP3PORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET https://localhost:%HTTP3PORT/path/%TESTNUMBER0001 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Via: 3 nghttpx
+
+GET https://localhost:%HTTP3PORT/path/%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Via: 3 nghttpx
+
+GET https://localhost:%HTTP3PORT/path/%TESTNUMBER0003 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Via: 3 nghttpx
+
+GET https://localhost:%HTTP3PORT/path/%TESTNUMBER0004 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Via: 3 nghttpx
+
+</protocol>
+<strip>
+^Host:.*
+</strip>
+<file name="%LOGDIR/stderr%TESTNUMBER" mode="text">
+* Connection #0 to host localhost left intact
+* Connection #0 to host localhost left intact
+* Connection #0 to host localhost left intact
+* Connection #0 to host localhost left intact
+</file>
+<stripfile>
+$_ = '' if (($_ !~ /left intact/) && ($_ !~ /Closing connection/))
+</stripfile>
+</verify>
+</testcase>
diff --git a/tests/data/test2503 b/tests/data/test2503
new file mode 100644
index 0000000..550eb8a
--- /dev/null
+++ b/tests/data/test2503
@@ -0,0 +1,70 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP/3
+HTTPS
+-w
+%header
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes" crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+http/3
+nghttpx-h3
+headers-api
+</features>
+<server>
+http
+http/3
+</server>
+ <name>
+HTTP/3 header-api
+ </name>
+<setenv>
+</setenv>
+ <command>
+-w '%{header_json}\n' --http3-only --cacert %SRCDIR/certs/EdelCurlRoot-ca.crt --resolve localhost:%HTTP3PORT:%HOSTIP https://localhost:%HTTP3PORT/%TESTNUMBER
+</command>
+
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<stdout crlf="yes">
+HTTP/3 200
+date: Tue, 09 Nov 2010 14:49:00 GMT
+content-length: 6
+content-type: text/html
+funny-head: yesyes
+via: 1.1 nghttpx
+
+-foo-
+{"date":["Tue, 09 Nov 2010 14:49:00 GMT"],
+"content-length":["6"],
+"content-type":["text/html"],
+"funny-head":["yesyes"],
+"via":["1.1 nghttpx"]
+}
+</stdout>
+</verify>
+</testcase>
diff --git a/tests/data/test251 b/tests/data/test251
index cc8cbfa..04ad017 100644
--- a/tests/data/test251
+++ b/tests/data/test251
@@ -2,6 +2,7 @@
<info>
<keywords>
FTP
+SLOWDOWN
</keywords>
</info>
diff --git a/tests/data/test256 b/tests/data/test256
index 6816bb7..cbb8714 100644
--- a/tests/data/test256
+++ b/tests/data/test256
@@ -29,9 +29,9 @@
HTTP resume request over proxy with auth without server supporting it
</name>
<command option="no-output">
--x http://%HOSTIP:%HTTPPORT http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -C - --no-include -o log/fewl%TESTNUMBER.txt -U daniel:stenberg
+-x http://%HOSTIP:%HTTPPORT http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -C - --no-include -o %LOGDIR/fewl%TESTNUMBER.txt -U daniel:stenberg
</command>
-<file name="log/fewl%TESTNUMBER.txt">
+<file name="%LOGDIR/fewl%TESTNUMBER.txt">
This text is here to simulate a partly downloaded file to resume
download on.
</file>
@@ -57,7 +57,7 @@
</protocol>
# the download target file must remain untouched
-<file name="log/fewl%TESTNUMBER.txt">
+<file name="%LOGDIR/fewl%TESTNUMBER.txt">
This text is here to simulate a partly downloaded file to resume
download on.
</file>
diff --git a/tests/data/test257 b/tests/data/test257
index 701abb7..ac38ac5 100644
--- a/tests/data/test257
+++ b/tests/data/test257
@@ -71,13 +71,13 @@
HTTP Location: following with --netrc-optional
</name>
<command>
-http://supersite.com/want/%TESTNUMBER -L -x http://%HOSTIP:%HTTPPORT --netrc-optional --netrc-file log/netrc%TESTNUMBER
+http://supersite.com/want/%TESTNUMBER -L -x http://%HOSTIP:%HTTPPORT --netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER
</command>
<features>
proxy
</features>
# netrc auth for two out of three sites:
-<file name="log/netrc%TESTNUMBER">
+<file name="%LOGDIR/netrc%TESTNUMBER">
machine supersite.com login user1 password passwd1
machine anotherone.com login user2 password passwd2
</file>
diff --git a/tests/data/test258 b/tests/data/test258
index c0f8c18..3587b57 100644
--- a/tests/data/test258
+++ b/tests/data/test258
@@ -56,6 +56,7 @@
http
</server>
<features>
+Mime
!SSPI
crypto
proxy
@@ -64,10 +65,10 @@
HTTP POST multipart without Expect: header using proxy anyauth (Digest)
</name>
<command>
--x http://%HOSTIP:%HTTPPORT http://remotehost:54321/we/want/%TESTNUMBER -F name=daniel -F tool=curl -F file=@log/test%TESTNUMBER.txt -H "Expect:" -U uuuser:pppassword --proxy-anyauth
+-x http://%HOSTIP:%HTTPPORT http://remotehost:54321/we/want/%TESTNUMBER -F name=daniel -F tool=curl -F file=@%LOGDIR/test%TESTNUMBER.txt -H "Expect:" -U uuuser:pppassword --proxy-anyauth
</command>
# We create this file before the command is invoked!
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo-
This is a moo-
bar
diff --git a/tests/data/test259 b/tests/data/test259
index 4b5deee..cc09c5b 100644
--- a/tests/data/test259
+++ b/tests/data/test259
@@ -52,6 +52,7 @@
http
</server>
<features>
+Mime
!SSPI
crypto
proxy
@@ -60,10 +61,10 @@
HTTP POST multipart with Expect: header using proxy anyauth (Digest)
</name>
<command>
--x http://%HOSTIP:%HTTPPORT http://remotehost:54321/we/want/%TESTNUMBER -F name=daniel -F tool=curl -F file=@log/test%TESTNUMBER.txt -U uuuser:pppassword --proxy-anyauth -H "Expect: 100-continue"
+-x http://%HOSTIP:%HTTPPORT http://remotehost:54321/we/want/%TESTNUMBER -F name=daniel -F tool=curl -F file=@%LOGDIR/test%TESTNUMBER.txt -U uuuser:pppassword --proxy-anyauth -H "Expect: 100-continue"
</command>
# We create this file before the command is invoked!
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo-
This is a moo-
bar
diff --git a/tests/data/test2600 b/tests/data/test2600
new file mode 100644
index 0000000..d6d0725
--- /dev/null
+++ b/tests/data/test2600
@@ -0,0 +1,24 @@
+<testcase>
+<info>
+<keywords>
+unittest
+cfilter
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<features>
+unittest
+debug
+http
+</features>
+ <name>
+connection filter connect/destroy unit tests
+ </name>
+</client>
+</testcase>
diff --git a/tests/data/test2601 b/tests/data/test2601
new file mode 100644
index 0000000..1ca0b9c
--- /dev/null
+++ b/tests/data/test2601
@@ -0,0 +1,22 @@
+<testcase>
+<info>
+<keywords>
+unittest
+bufq
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<features>
+unittest
+</features>
+ <name>
+bufq unit tests
+ </name>
+</client>
+</testcase>
diff --git a/tests/data/test2602 b/tests/data/test2602
new file mode 100644
index 0000000..e811f29
--- /dev/null
+++ b/tests/data/test2602
@@ -0,0 +1,22 @@
+<testcase>
+<info>
+<keywords>
+unittest
+dynhds
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<features>
+unittest
+</features>
+ <name>
+dynhds unit tests
+ </name>
+</client>
+</testcase>
diff --git a/tests/data/test2603 b/tests/data/test2603
new file mode 100644
index 0000000..dfb3735
--- /dev/null
+++ b/tests/data/test2603
@@ -0,0 +1,22 @@
+<testcase>
+<info>
+<keywords>
+unittest
+http1
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<features>
+unittest
+</features>
+ <name>
+http1 parser unit tests
+ </name>
+</client>
+</testcase>
diff --git a/tests/data/test265 b/tests/data/test265
index c6db896..fd0a097 100644
--- a/tests/data/test265
+++ b/tests/data/test265
@@ -17,6 +17,7 @@
<connect1001>
HTTP/1.0 407 Authorization Required to proxy me my dear
Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAAgACADAAAACGggEAc51AYVDgyNcAAAAAAAAAAG4AbgAyAAAAQ0MCAAQAQwBDAAEAEgBFAEwASQBTAEEAQgBFAFQASAAEABgAYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAwAsAGUAbABpAHMAYQBiAGUAdABoAC4AYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAAAAAA==
+Connection: Keep-Alive
Content-Length: 1033
And you should ignore this data.
@@ -55,6 +56,7 @@
<datacheck>
HTTP/1.0 407 Authorization Required to proxy me my dear
Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAAgACADAAAACGggEAc51AYVDgyNcAAAAAAAAAAG4AbgAyAAAAQ0MCAAQAQwBDAAEAEgBFAEwASQBTAEEAQgBFAFQASAAEABgAYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAwAsAGUAbABpAHMAYQBiAGUAdABoAC4AYwBjAC4AaQBjAGUAZABlAHYALgBuAHUAAAAAAA==
+Connection: Keep-Alive
Content-Length: 1033
HTTP/1.1 200 Things are fine in proxy land
diff --git a/tests/data/test266 b/tests/data/test266
index 4f5f359..d30c70a 100644
--- a/tests/data/test266
+++ b/tests/data/test266
@@ -4,6 +4,7 @@
HTTP
HTTP GET
chunked Transfer-Encoding
+DELAY
</keywords>
</info>
#
@@ -52,7 +53,7 @@
HTTP GET with chunked Transfer-Encoding and chunked trailer
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -D log/heads%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -D %LOGDIR/heads%TESTNUMBER
</command>
</client>
@@ -66,7 +67,7 @@
Accept: */*
</protocol>
-<file name="log/heads%TESTNUMBER">
+<file name="%LOGDIR/heads%TESTNUMBER">
HTTP/1.1 200 funky chunky!
Server: fakeit/0.9 fakeitbad/1.0
Transfer-Encoding: chunked
diff --git a/tests/data/test27 b/tests/data/test27
index 4147413..fba1695 100644
--- a/tests/data/test27
+++ b/tests/data/test27
@@ -29,6 +29,9 @@
<command>
"http://%HOSTIP:%HTTPPORT/want/{%TESTNUMBER,%TESTNUMBER,%TESTNUMBER}" -b none
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
diff --git a/tests/data/test271 b/tests/data/test271
index f6d5ad7..a825198 100644
--- a/tests/data/test271
+++ b/tests/data/test271
@@ -34,12 +34,14 @@
#
# Verify pseudo protocol after the test has been "shot"
<verify>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 1
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER
</protocol>
</verify>
diff --git a/tests/data/test277 b/tests/data/test277
index 466b793..62d264f 100644
--- a/tests/data/test277
+++ b/tests/data/test277
@@ -20,6 +20,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test281 b/tests/data/test281
index 4210f7b..06ca27b 100644
--- a/tests/data/test281
+++ b/tests/data/test281
@@ -28,9 +28,9 @@
HTTP PUT from file with 100 + 401 responses and -f without auth given
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -f -T log/test%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -f -T %LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
Weird
file
to
@@ -49,7 +49,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 38
-Expect: 100-continue
Weird
file
diff --git a/tests/data/test283 b/tests/data/test283
index 2c1ebd2..0f2d008 100644
--- a/tests/data/test283
+++ b/tests/data/test283
@@ -27,12 +27,14 @@
<errorcode>
69
</errorcode>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 1
mode = octet
tsize = 0
blksize = 1024
-timeout = 6
filename = /invalid-file
</protocol>
</verify>
diff --git a/tests/data/test284 b/tests/data/test284
index 2f4ea43..a18f492 100644
--- a/tests/data/test284
+++ b/tests/data/test284
@@ -58,12 +58,14 @@
#
# Verify pseudo protocol after the test has been "shot"
<verify>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 1
mode = octet
tsize = 0
blksize = 512
-timeout = 6
filename = /%TESTNUMBER
</protocol>
</verify>
diff --git a/tests/data/test285 b/tests/data/test285
index ab055e4..8cb479a 100644
--- a/tests/data/test285
+++ b/tests/data/test285
@@ -16,9 +16,9 @@
TFTP send
</name>
<command>
--T log/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT//
+-T %LOGDIR/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT// --connect-time 549
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
a chunk of
data
sent
@@ -40,7 +40,7 @@
mode = octet
tsize = 32
blksize = 512
-timeout = 6
+timeout = 10
filename = /test%TESTNUMBER.txt
</protocol>
</verify>
diff --git a/tests/data/test286 b/tests/data/test286
index febd5e3..d51ec10 100644
--- a/tests/data/test286
+++ b/tests/data/test286
@@ -16,9 +16,9 @@
TFTP send of boundary case 512 byte file
</name>
<command>
--T log/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT//
+-T %LOGDIR/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT//
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
A chunk of data which exactly fits into
a 512 byte TFTP block, testing a boundary
condition in the TFTP transmit code.
@@ -83,12 +83,14 @@
123456789ABCDEF
123456789ABCDEF
</upload>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 2
mode = octet
tsize = 512
blksize = 512
-timeout = 6
filename = /test%TESTNUMBER.txt
</protocol>
</verify>
diff --git a/tests/data/test288 b/tests/data/test288
index 6ee19d4..164cf20 100644
--- a/tests/data/test288
+++ b/tests/data/test288
@@ -31,9 +31,9 @@
all_proxy=http://fake:user@%HOSTIP:%NOLISTENPORT/
</setenv>
<command option="no-include">
-file://localhost%FILE_PWD/log/test%TESTNUMBER.txt
+file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar
bar
diff --git a/tests/data/test289 b/tests/data/test289
index 481eacf..4b80c90 100644
--- a/tests/data/test289
+++ b/tests/data/test289
@@ -17,7 +17,7 @@
FTP resume upload but denied access to local file
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/illegal-nonexistent-file -C -
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/illegal-nonexistent-file -C -
</command>
</client>
diff --git a/tests/data/test3008 b/tests/data/test3008
index 31aa4f7..51afb04 100644
--- a/tests/data/test3008
+++ b/tests/data/test3008
@@ -36,7 +36,7 @@
--output-dir
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/this/is/the/%TESTNUMBER -O --output-dir %PWD/log
+http://%HOSTIP:%HTTPPORT/this/is/the/%TESTNUMBER -O --output-dir %PWD/%LOGDIR
</command>
</client>
@@ -50,7 +50,7 @@
Accept: */*
</protocol>
-<file name="log/%TESTNUMBER">
+<file name="%LOGDIR/%TESTNUMBER">
-foo-
</file>
</verify>
diff --git a/tests/data/test3011 b/tests/data/test3011
index c282cdb..f5b2f1d 100644
--- a/tests/data/test3011
+++ b/tests/data/test3011
@@ -36,7 +36,7 @@
--output-dir with --create-dirs
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/this/is/the/%TESTNUMBER -O --output-dir %PWD/log/tmp --create-dirs
+http://%HOSTIP:%HTTPPORT/this/is/the/%TESTNUMBER -O --output-dir %PWD/%LOGDIR/tmp --create-dirs
</command>
</client>
@@ -50,7 +50,7 @@
Accept: */*
</protocol>
-<file name="log/tmp/%TESTNUMBER">
+<file name="%LOGDIR/tmp/%TESTNUMBER">
-foo-
</file>
</verify>
diff --git a/tests/data/test3012 b/tests/data/test3012
index 1889c93..2bd3294 100644
--- a/tests/data/test3012
+++ b/tests/data/test3012
@@ -39,7 +39,7 @@
--output-dir with -J
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/this/is/the/%TESTNUMBER -OJ --output-dir %PWD/log
+http://%HOSTIP:%HTTPPORT/this/is/the/%TESTNUMBER -OJ --output-dir %PWD/%LOGDIR
</command>
</client>
@@ -53,7 +53,7 @@
Accept: */*
</protocol>
-<file name="log/MMM%TESTNUMBERMMM">
+<file name="%LOGDIR/MMM%TESTNUMBERMMM">
-foo-
</file>
</verify>
diff --git a/tests/data/test3013 b/tests/data/test3013
index 9c0ce44..183667e 100644
--- a/tests/data/test3013
+++ b/tests/data/test3013
@@ -39,7 +39,7 @@
Two --output-dir with --next in between
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/this/is/the/%TESTNUMBER -O --output-dir %PWD/log http://%HOSTIP:%HTTPPORT/another/%TESTNUMBER -o second%TESTNUMBER --output-dir %PWD/log
+http://%HOSTIP:%HTTPPORT/this/is/the/%TESTNUMBER -O --output-dir %PWD/%LOGDIR http://%HOSTIP:%HTTPPORT/another/%TESTNUMBER -o second%TESTNUMBER --output-dir %PWD/%LOGDIR
</command>
</client>
@@ -58,10 +58,10 @@
Accept: */*
</protocol>
-<file name="log/%TESTNUMBER">
+<file name="%LOGDIR/%TESTNUMBER">
-foo-
</file>
-<file2 name="log/second%TESTNUMBER">
+<file2 name="%LOGDIR/second%TESTNUMBER">
-foo-
</file2>
</verify>
diff --git a/tests/data/test3021 b/tests/data/test3021
index 775dd91..cc12677 100644
--- a/tests/data/test3021
+++ b/tests/data/test3021
@@ -28,14 +28,14 @@
SFTP correct sha256 host key
</name>
<command>
---hostpubsha256 %SSHSRVSHA256 --key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt
+--hostpubsha256 %SSHSRVSHA256 --key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt
</command>
<setenv>
# Needed for MSYS2 to not treat the argument as a POSIX path list
# that has to be converted to Windows paths
MSYS2_ARG_CONV_EXCL=*
</setenv>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
test
</file>
</client>
diff --git a/tests/data/test3022 b/tests/data/test3022
index a9dbcb0..45cdf87 100644
--- a/tests/data/test3022
+++ b/tests/data/test3022
@@ -28,14 +28,14 @@
SCP correct sha256 host key
</name>
<command>
---hostpubsha256 %SSHSRVSHA256 --key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt
+--hostpubsha256 %SSHSRVSHA256 --key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt
</command>
<setenv>
# Needed for MSYS2 to not treat the argument as a POSIX path list
# that has to be converted to Windows paths
MSYS2_ARG_CONV_EXCL=*
</setenv>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
test
</file>
</client>
diff --git a/tests/data/test3026 b/tests/data/test3026
index fb80cc8..ee9b306 100644
--- a/tests/data/test3026
+++ b/tests/data/test3026
@@ -18,8 +18,8 @@
# require the threaded resolver only because it means pthreads might
# be used for it
<features>
+threadsafe
threaded-resolver
-!win32
</features>
<server>
none
diff --git a/tests/data/test3027 b/tests/data/test3027
new file mode 100644
index 0000000..6d7aeb6
--- /dev/null
+++ b/tests/data/test3027
@@ -0,0 +1,55 @@
+<testcase>
+<info>
+<keywords>
+FTP
+CURLOPT_FILETIME
+MDTM fail
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<servercmd>
+REPLY MDTM 550 Permission denied
+</servercmd>
+<data>
+data blobb
+</data>
+
+# data is sent to stdout
+</reply>
+
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+Get a file via FTP but 550 after MDTM command
+ </name>
+<tool>
+lib3027
+</tool>
+<command option="no-include">
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER
+</command>
+<stdout>
+data blobb
+</stdout>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous
+PASS ftp@example.com
+PWD
+MDTM %TESTNUMBER
+EPSV
+TYPE I
+SIZE %TESTNUMBER
+RETR %TESTNUMBER
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test3028 b/tests/data/test3028
new file mode 100644
index 0000000..bc69e86
--- /dev/null
+++ b/tests/data/test3028
@@ -0,0 +1,73 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP CONNECT
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<connect>
+HTTP/1.1 200 Mighty fine indeed
+
+</connect>
+
+<data nocheck="yes">
+HTTP/1.1 404 Not Found
+Server: nginx/1.23.2
+Date: Wed, 09 Nov 2022 09:44:58 GMT
+Content-Type: text/plain; charset=utf-8
+Content-Length: 4
+Connection: keep-alive
+X-Content-Type-Options: nosniff
+
+haha
+</data>
+
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+http-proxy
+</server>
+<name>
+HTTP GET when PROXY Protocol enabled behind a proxy
+</name>
+<command>
+--haproxy-protocol http://%HOSTIP:%HTTPPORT/page --proxytunnel -x %HOSTIP:%PROXYPORT
+</command>
+<features>
+proxy
+</features>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^PROXY TCP4 %CLIENTIP %HOSTIP (\d*) %PROXYPORT/proxy-line/
+</strippart>
+
+<proxy>
+CONNECT %HOSTIP:%HTTPPORT HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Proxy-Connection: Keep-Alive
+
+</proxy>
+
+<protocol>
+proxy-line
+GET /page HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+
+</verify>
+</testcase>
diff --git a/tests/data/test3029 b/tests/data/test3029
new file mode 100644
index 0000000..2e51bbe
--- /dev/null
+++ b/tests/data/test3029
@@ -0,0 +1,39 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+</keywords>
+</info>
+
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+
+-foo-
+</data>
+</reply>
+
+<client>
+<server>
+http
+</server>
+<name>
+HTTP with multiple -D
+</name>
+<command>
+-D %LOGDIR/heads%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER --next -D %LOGDIR/heads%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+<verify>
+<file name="%LOGDIR/heads%TESTNUMBER">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+
+</file>
+</verify>
+
+</testcase>
\ No newline at end of file
diff --git a/tests/data/test303 b/tests/data/test303
index 318cbe6..ea48b50 100644
--- a/tests/data/test303
+++ b/tests/data/test303
@@ -4,6 +4,7 @@
HTTPS
HTTP GET
timeout
+FAILURE
</keywords>
</info>
@@ -29,6 +30,9 @@
<server>
https
</server>
+<killserver>
+https
+</killserver>
<name>
HTTPS with 8 secs timeout
</name>
diff --git a/tests/data/test3030 b/tests/data/test3030
new file mode 100644
index 0000000..7e169cf
--- /dev/null
+++ b/tests/data/test3030
@@ -0,0 +1,43 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+</keywords>
+</info>
+
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+
+-foo-
+</data>
+</reply>
+
+<client>
+<server>
+http
+</server>
+<name>
+HTTP with multiple transfers in one -D
+</name>
+<command>
+-D %LOGDIR/heads%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+<verify>
+<file name="%LOGDIR/heads%TESTNUMBER">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+
+</file>
+</verify>
+
+</testcase>
\ No newline at end of file
diff --git a/tests/data/test304 b/tests/data/test304
index b403072..1f6bafb 100644
--- a/tests/data/test304
+++ b/tests/data/test304
@@ -21,6 +21,7 @@
# Client-side
<client>
<features>
+Mime
SSL
</features>
<server>
@@ -30,10 +31,10 @@
HTTPS multipart formpost
</name>
<command>
--k https://%HOSTIP:%HTTPSPORT/we/want/%TESTNUMBER -F name=daniel -F tool=curl -F file=@log/test%TESTNUMBER.txt
+-k https://%HOSTIP:%HTTPSPORT/we/want/%TESTNUMBER -F name=daniel -F tool=curl -F file=@%LOGDIR/test%TESTNUMBER.txt
</command>
# We create this file before the command is invoked!
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</file>
</client>
diff --git a/tests/data/test31 b/tests/data/test31
index ac27726..821fed9 100644
--- a/tests/data/test31
+++ b/tests/data/test31
@@ -11,7 +11,7 @@
#
# The cookies set come in two versions. This is because when curl is built
# with Hyper, the API provides the headers already "sanitized" so we cannot
-# compapare with the exact server contents unlesss it too sends the data
+# compare with the exact server contents unless it too sends the data
# "clean".
<reply>
@@ -22,6 +22,7 @@
Content-Length: 4
Content-Type: text/html
Funny-head: yesyes
+Set-Cookie: blankdomain=sure; domain=; path=/
%if !hyper
Set-Cookie: foobar=name; domain=anything.com; path=/ ; secure
Set-Cookie:ismatch=this ; domain=test31.curl; path=/silly/
@@ -127,11 +128,14 @@
TZ=GMT
</setenv>
<command>
-http://test31.curl:%HTTPPORT/we/want/%TESTNUMBER -b none -c log/jar%TESTNUMBER.txt --resolve test31.curl:%HTTPPORT:127.0.0.1
+http://test31.curl:%HTTPPORT/we/want/%TESTNUMBER -b none -c %LOGDIR/jar%TESTNUMBER.txt --resolve test31.curl:%HTTPPORT:127.0.0.1
</command>
<precheck>
perl -e "print 'Test requires default test server host' if ( '%HOSTIP' ne '127.0.0.1' );"
</precheck>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
@@ -143,7 +147,7 @@
Accept: */*
</protocol>
-<file name="log/jar%TESTNUMBER.txt" mode="text">
+<file name="%LOGDIR/jar%TESTNUMBER.txt" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
@@ -162,6 +166,7 @@
#HttpOnly_.test31.curl TRUE /p1/ FALSE 0 httpo1 value1
.test31.curl TRUE /overwrite FALSE 0 overwrite this2
.test31.curl TRUE /silly/ FALSE 0 ismatch this
+test31.curl FALSE / FALSE 0 blankdomain sure
</file>
</verify>
</testcase>
diff --git a/tests/data/test3100 b/tests/data/test3100
new file mode 100644
index 0000000..23ec417
--- /dev/null
+++ b/tests/data/test3100
@@ -0,0 +1,85 @@
+<testcase>
+
+#Informational
+<info>
+<keywords>
+RTSP
+RTSP Basic auth
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data>
+RTSP/1.0 401 Unauthorized please swsbounce
+Server: RTSPD/libcurl-test
+CSeq: 1
+WWW-Authenticate: Basic realm="please-auth-me"
+
+</data>
+<data1>
+RTSP/1.0 200 OK
+Server: RTSPD/libcurl-test
+CSeq: 2
+Content-Base: rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER
+Content-Length: 80
+Curl-private: swsclose
+
+v=0
+s=rtspd SDP
+i=A fake SDP reply
+u=http://www.curl.example.com/fakesdp.ps
+</data1>
+<datacheck>
+RTSP/1.0 401 Unauthorized please swsbounce
+Server: RTSPD/libcurl-test
+CSeq: 1
+WWW-Authenticate: Basic realm="please-auth-me"
+
+RTSP/1.0 200 OK
+Server: RTSPD/libcurl-test
+CSeq: 2
+Content-Base: rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER
+Content-Length: 80
+Curl-private: swsclose
+
+v=0
+s=rtspd SDP
+i=A fake SDP reply
+u=http://www.curl.example.com/fakesdp.ps
+</datacheck>
+</reply>
+
+# Client-Side
+<client>
+<server>
+rtsp
+</server>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<name>
+RTSP Authentication check
+</name>
+<command>
+rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+DESCRIBE rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER RTSP/1.0
+CSeq: 1
+Accept: application/sdp
+
+DESCRIBE rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER RTSP/1.0
+CSeq: 2
+Accept: application/sdp
+Authorization: Basic dXNlcjpwYXNzd29yZA==
+
+</protocol>
+</verify>
+
+</testcase>
diff --git a/tests/data/test3101 b/tests/data/test3101
new file mode 100644
index 0000000..8e3d41f
--- /dev/null
+++ b/tests/data/test3101
@@ -0,0 +1,88 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP Basic auth
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data>
+HTTP/1.1 401 Authorization Required swsbounce
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+WWW-Authenticate: Blackmagic realm="gimme all yer s3cr3ts"
+WWW-Authenticate: Basic realm="gimme all yer s3cr3ts"
+Content-Length: 26
+Content-Type: text/html; charset=iso-8859-1
+
+This is not the real page
+</data>
+
+# This is supposed to be returned when the server gets a
+# Authorization: Digest line passed-in from the client
+<data1>
+HTTP/1.1 200 OK
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+Content-Type: text/html; charset=iso-8859-1
+Content-Length: 23
+Connection: close
+
+This IS the real page!
+</data1>
+
+<datacheck>
+HTTP/1.1 401 Authorization Required swsbounce
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+WWW-Authenticate: Blackmagic realm="gimme all yer s3cr3ts"
+WWW-Authenticate: Basic realm="gimme all yer s3cr3ts"
+Content-Length: 26
+Content-Type: text/html; charset=iso-8859-1
+
+HTTP/1.1 200 OK
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+Content-Type: text/html; charset=iso-8859-1
+Content-Length: 23
+Connection: close
+
+This IS the real page!
+</datacheck>
+</reply>
+
+# Client-Side
+<client>
+# require https because the code sets that as an acceptable redirect proto
+<features>
+https
+</features>
+<server>
+http
+</server>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<name>
+HTTP auth without redirection protocols
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic dXNlcjpwYXNzd29yZA==
+Accept: */*
+
+</protocol>
+</verify>
+
+</testcase>
diff --git a/tests/data/test320 b/tests/data/test320
index 88f99cc..77f684b 100644
--- a/tests/data/test320
+++ b/tests/data/test320
@@ -58,7 +58,7 @@
<verify>
<protocol>
</protocol>
-<file name="log/curl%TESTNUMBER.out">
+<file name="%LOGDIR/curl%TESTNUMBER.out">
HTTP/1.0 200 OK
Content-type: text/html
diff --git a/tests/data/test3200 b/tests/data/test3200
new file mode 100644
index 0000000..a2f9074
--- /dev/null
+++ b/tests/data/test3200
@@ -0,0 +1,25 @@
+<testcase>
+<info>
+<keywords>
+unittest
+curl_get_line
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<features>
+unittest
+</features>
+ <name>
+curl_get_line unit tests
+ </name>
+<command>
+%LOGDIR/curl_get_line%TESTNUMBER
+</command>
+</client>
+</testcase>
diff --git a/tests/data/test3201 b/tests/data/test3201
new file mode 100644
index 0000000..4fb0b8f
--- /dev/null
+++ b/tests/data/test3201
@@ -0,0 +1,63 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+proxy
+haproxy
+</keywords>
+</info>
+
+#
+# Server-side
+<reply name="%TESTNUMBER">
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: barkbark
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+HTTP GET when PROXY Protocol enabled and spoofed client IP
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --haproxy-clientip "192.168.1.1" -H "Testno: %TESTNUMBER"
+</command>
+<features>
+proxy
+</features>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^PROXY TCP4 %CLIENTIP 192.168.1.1 (\d*) %HTTPPORT/proxy-line/
+</strippart>
+<protocol>
+proxy-line
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Testno: %TESTNUMBER
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test3202 b/tests/data/test3202
new file mode 100644
index 0000000..8990abc
--- /dev/null
+++ b/tests/data/test3202
@@ -0,0 +1,67 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+proxy
+haproxy
+IPv6
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+These data aren't actually sent to the client
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+ipv6
+</features>
+<server>
+http-ipv6
+</server>
+ <name>
+HTTP-IPv6 GET with PROXY protocol with spoofed client IP
+ </name>
+ <command>
+-g "http://%HOST6IP:%HTTP6PORT/%TESTNUMBER" --haproxy-clientip "2001:db8::"
+</command>
+<features>
+proxy
+</features>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# Strip off the (random) local port number. This test used to use a fixed
+# local port number that frequently causes the test to fail
+<strippart>
+s/PROXY TCP6 ::1 2001:db8:: (\d+) (\d+)/PROXY TCP6 ::1 2001:db8:: $2/
+</strippart>
+<protocol>
+PROXY TCP6 ::1 2001:db8:: %HTTP6PORT
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOST6IP:%HTTP6PORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test327 b/tests/data/test327
index 73cedb6..19d7c0f 100644
--- a/tests/data/test327
+++ b/tests/data/test327
@@ -43,8 +43,11 @@
HTTP with cookiejar without cookies left
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -b none -c log/cookies%TESTNUMBER http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER0002
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -b none -c %LOGDIR/cookies%TESTNUMBER http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER0002
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
@@ -62,7 +65,7 @@
Cookie: foobar=name
</protocol>
-<file name="log/cookies%TESTNUMBER" mode="text">
+<file name="%LOGDIR/cookies%TESTNUMBER" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test329 b/tests/data/test329
index d25f968..1f03d3c 100644
--- a/tests/data/test329
+++ b/tests/data/test329
@@ -14,6 +14,7 @@
Server: test-server/fake
Content-Type: text/html
Funny-head: yesyes
+Set-Cookie: testn1=yes; path=/we/want/; domain=.host.foo.com; Max-Age=-1;
Set-Cookie: test=yes; path=/we/want/; domain=.host.foo.com; Max-Age=0;
Content-Length: 4
@@ -30,10 +31,10 @@
# Client-side
<client>
-<file name="log/jar%TESTNUMBER.txt" mode="text">
+<file name="%LOGDIR/jar%TESTNUMBER.txt" mode="text">
.host.foo.com TRUE /we/want/ FALSE 2147483647 test no
</file>
-<file name="log/jar%TESTNUMBER-2.txt" mode="text">
+<file name="%LOGDIR/jar%TESTNUMBER-2.txt" mode="text">
.host.foo.com TRUE /we/want/ FALSE 2147483647 tester yes
</file>
<server>
@@ -49,8 +50,11 @@
TZ=GMT
</setenv>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -b log/jar%TESTNUMBER.txt -b log/jar%TESTNUMBER-2.txt -H "Host: host.foo.com" http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER0002
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -b %LOGDIR/jar%TESTNUMBER.txt -b %LOGDIR/jar%TESTNUMBER-2.txt -H "Host: host.foo.com" http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER0002
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
diff --git a/tests/data/test33 b/tests/data/test33
index 1b9c898..bd02e00 100644
--- a/tests/data/test33
+++ b/tests/data/test33
@@ -23,7 +23,7 @@
<name>
HTTP PUT with resume
</name>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
012345678
012345678
012345678
@@ -36,7 +36,7 @@
012345678
</file>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -Tlog/test%TESTNUMBER.txt -C 50
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T%LOGDIR/test%TESTNUMBER.txt -C 50
</command>
</client>
@@ -49,7 +49,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 50
-Expect: 100-continue
012345678
012345678
diff --git a/tests/data/test331 b/tests/data/test331
index 8fc6898..34d9a78 100644
--- a/tests/data/test331
+++ b/tests/data/test331
@@ -43,6 +43,7 @@
-x http://%HOSTIP:%HTTPPORT http://moo/we/want/%TESTNUMBER -b none http://moo/we/want/%TESTNUMBER0002
</command>
<features>
+cookies
proxy
</features>
</client>
diff --git a/tests/data/test332 b/tests/data/test332
index d2bd8bb..54763ed 100644
--- a/tests/data/test332
+++ b/tests/data/test332
@@ -33,12 +33,14 @@
#
# Verify pseudo protocol after the test has been "shot"
<verify>
+<strip>
+^timeout = [5-6]$
+</strip>
<protocol>
opcode = 1
mode = octet
tsize = 0
blksize = 400
-timeout = 6
filename = /%TESTNUMBER
</protocol>
</verify>
diff --git a/tests/data/test339 b/tests/data/test339
index 8d5b90b..8c43402 100644
--- a/tests/data/test339
+++ b/tests/data/test339
@@ -39,7 +39,7 @@
Check if --etag-save saved correct etag to a file
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-save log/etag%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-save %LOGDIR/etag%TESTNUMBER
</command>
</client>
@@ -53,7 +53,7 @@
Accept: */*
</protocol>
-<file name="log/etag%TESTNUMBER">
+<file name="%LOGDIR/etag%TESTNUMBER">
W/"asdf"
</file>
</verify>
diff --git a/tests/data/test341 b/tests/data/test341
index 3c9f72a..4ebee11 100644
--- a/tests/data/test341
+++ b/tests/data/test341
@@ -39,7 +39,7 @@
Try to open a non existing file with --etag-compare should return an error
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-compare log/etag%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-compare %LOGDIR/etag%TESTNUMBER
</command>
</client>
diff --git a/tests/data/test342 b/tests/data/test342
index ca8957a..79f6025 100644
--- a/tests/data/test342
+++ b/tests/data/test342
@@ -33,11 +33,11 @@
<name>
Check if --etag-compare set correct etag in header
</name>
-<file name="log/etag%TESTNUMBER">
+<file name="%LOGDIR/etag%TESTNUMBER">
"21025-dc7-39462498"
</file>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-compare log/etag%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-compare %LOGDIR/etag%TESTNUMBER
</command>
</client>
diff --git a/tests/data/test343 b/tests/data/test343
index faf6c9a..dd13708 100644
--- a/tests/data/test343
+++ b/tests/data/test343
@@ -33,11 +33,11 @@
<name>
Both --etag-compare and --etag-save to save new Etag
</name>
-<file name="log/etag%TESTNUMBER">
+<file name="%LOGDIR/etag%TESTNUMBER">
"21025-dc7-39462498"
</file>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-compare log/etag%TESTNUMBER --etag-save log/out%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-compare %LOGDIR/etag%TESTNUMBER --etag-save %LOGDIR/out%TESTNUMBER
</command>
</client>
@@ -52,7 +52,7 @@
If-None-Match: "21025-dc7-39462498"
</protocol>
-<file name="log/out%TESTNUMBER">
+<file name="%LOGDIR/out%TESTNUMBER">
"21025-dc7-11111"
</file>
</verify>
diff --git a/tests/data/test344 b/tests/data/test344
index ec671d4..197c004 100644
--- a/tests/data/test344
+++ b/tests/data/test344
@@ -34,7 +34,7 @@
Both --etag-compare and -save store new Etag using non-existing file
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-compare log/etag%TESTNUMBER --etag-save log/etag%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-compare %LOGDIR/etag%TESTNUMBER --etag-save %LOGDIR/etag%TESTNUMBER
</command>
</client>
@@ -49,7 +49,7 @@
If-None-Match: ""
</protocol>
-<file name="log/etag%TESTNUMBER">
+<file name="%LOGDIR/etag%TESTNUMBER">
"21025-dc7-11111"
</file>
</verify>
diff --git a/tests/data/test345 b/tests/data/test345
index 5619d44..c6da676 100644
--- a/tests/data/test345
+++ b/tests/data/test345
@@ -33,11 +33,11 @@
<name>
Both --etag-compare and -save store new Etag using one pre-existing file
</name>
-<file name="log/etag%TESTNUMBER">
+<file name="%LOGDIR/etag%TESTNUMBER">
"21025-dc7-39462498"
</file>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-compare log/etag%TESTNUMBER --etag-save log/etag%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-compare %LOGDIR/etag%TESTNUMBER --etag-save %LOGDIR/etag%TESTNUMBER
</command>
</client>
@@ -52,7 +52,7 @@
If-None-Match: "21025-dc7-39462498"
</protocol>
-<file name="log/etag%TESTNUMBER">
+<file name="%LOGDIR/etag%TESTNUMBER">
"21025-dc7-11111"
</file>
</verify>
diff --git a/tests/data/test347 b/tests/data/test347
index ef85d9d..606335c 100644
--- a/tests/data/test347
+++ b/tests/data/test347
@@ -39,7 +39,7 @@
--etag-save with blank incoming header
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-save log/etag%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-save %LOGDIR/etag%TESTNUMBER
</command>
</client>
@@ -53,7 +53,7 @@
Accept: */*
</protocol>
-<file name="log/etag%TESTNUMBER">
+<file name="%LOGDIR/etag%TESTNUMBER">
</file>
</verify>
diff --git a/tests/data/test348 b/tests/data/test348
index 8832a38..c9aa2ce 100644
--- a/tests/data/test348
+++ b/tests/data/test348
@@ -21,7 +21,7 @@
<name>
FTP upload file with 552 disk full response
</name>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
data
to
see
@@ -30,7 +30,7 @@
so does it?
</file>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt
</command>
</client>
diff --git a/tests/data/test35 b/tests/data/test35
index b5feb19..33e6eac 100644
--- a/tests/data/test35
+++ b/tests/data/test35
Binary files differ
diff --git a/tests/data/test355 b/tests/data/test355
index 98e5907..8b32c92 100644
--- a/tests/data/test355
+++ b/tests/data/test355
@@ -36,7 +36,7 @@
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER --alt-svc ""
</command>
-<file name="log/altsvc-%TESTNUMBER">
+<file name="%LOGDIR/altsvc-%TESTNUMBER">
h1 example.com 80 h1 %HOSTIP %HTTPPORT "20290222 22:19:28" 0 0
</file>
</client>
diff --git a/tests/data/test356 b/tests/data/test356
index 0f87958..2597f15 100644
--- a/tests/data/test356
+++ b/tests/data/test356
@@ -16,7 +16,10 @@
Connection: close
Content-Type: text/html
Funny-head: yesyes
+Alt-Svc: h1="nowhere.foo:-1"
+Alt-Svc: h1="nowhere.foo:-18446744073709551614"
Alt-Svc: h1="nowhere.foo:81", un-kno22!wn=":82"
+Alt-Svc: h1="nowhere.foo:70000"
-foo-
</data>
@@ -40,7 +43,7 @@
CURL_ALTSVC_HTTP="yeah"
</setenv>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --alt-svc "log/altsvc-%TESTNUMBER"
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --alt-svc "%LOGDIR/altsvc-%TESTNUMBER"
</command>
</client>
@@ -59,7 +62,7 @@
# matches
s/\"([^\"]*)\"/TIMESTAMP/
</stripfile>
-<file name="log/altsvc-%TESTNUMBER" mode="text">
+<file name="%LOGDIR/altsvc-%TESTNUMBER" mode="text">
# Your alt-svc cache. https://curl.se/docs/alt-svc.html
# This file was generated by libcurl! Edit at your own risk.
h1 %HOSTIP %HTTPPORT h1 nowhere.foo 81 TIMESTAMP 0 0
diff --git a/tests/data/test357 b/tests/data/test357
index 8ddcdc9..4a7e6dc 100644
--- a/tests/data/test357
+++ b/tests/data/test357
@@ -51,18 +51,11 @@
HTTP PUT with Expect: 100-continue and 417 response
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -T log/test%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
-Weird
- file
- to
- upload
-for
- testing
-the
- PUT
- feature
+# 1053700 x 'x', large enough to invoke the 100-continue behaviour
+<file name="%LOGDIR/test%TESTNUMBER.txt">
+%repeat[1053700 x x]%
</file>
</client>
@@ -73,24 +66,16 @@
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
-Content-Length: 78
+Content-Length: 1053701
Expect: 100-continue
PUT /we/want/%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
-Content-Length: 78
+Content-Length: 1053701
-Weird
- file
- to
- upload
-for
- testing
-the
- PUT
- feature
+%repeat[1053700 x x]%
</protocol>
</verify>
</testcase>
diff --git a/tests/data/test358 b/tests/data/test358
index 8b4f660..47afc58 100644
--- a/tests/data/test358
+++ b/tests/data/test358
@@ -12,14 +12,14 @@
# Server-side
<reply>
<data nocheck="yes">
-HTTP/1.1 200 OK
-Date: Tue, 09 Nov 2010 14:49:00 GMT
-Content-Length: 6
-Connection: close
-Content-Type: text/html
-Funny-head: yesyes
-Alt-Svc: h2=":%HTTP2PORT", ma=315360000; persist=0
-
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+Alt-Svc: h2=":%HTTP2PORT", ma=315360000; persist=0
+
-foo-
</data>
</reply>
@@ -44,9 +44,9 @@
CURL_ALTSVC_HTTP="yeah"
</setenv>
<command>
---http2 --alt-svc "log/altsvc-%TESTNUMBER" "http://%HOSTIP:%HTTPPORT/%TESTNUMBER" "http://%HOSTIP:%HTTPPORT/%TESTNUMBER"
+--http2 --alt-svc "%LOGDIR/altsvc-%TESTNUMBER" "http://%HOSTIP:%HTTPPORT/%TESTNUMBER" "http://%HOSTIP:%HTTPPORT/%TESTNUMBER"
</command>
-<file name="log/altsvc-%TESTNUMBER">
+<file name="%LOGDIR/altsvc-%TESTNUMBER">
h2 %HOSTIP %HTTPPORT h2 %HOSTIP %HTTP2PORT "20290222 22:19:28" 0 0
</file>
@@ -85,7 +85,7 @@
# matches
s/\"2([^\"]*)\"/TIMESTAMP/
</stripfile>
-<file name="log/altsvc-%TESTNUMBER" mode="text">
+<file name="%LOGDIR/altsvc-%TESTNUMBER" mode="text">
# Your alt-svc cache. https://curl.se/docs/alt-svc.html
# This file was generated by libcurl! Edit at your own risk.
h2 %HOSTIP %HTTPPORT h2 %HOSTIP %HTTP2PORT TIMESTAMP 0 0
diff --git a/tests/data/test359 b/tests/data/test359
index a5ba4e3..9b466b7 100644
--- a/tests/data/test359
+++ b/tests/data/test359
@@ -12,14 +12,14 @@
# Server-side
<reply>
<data nocheck="yes">
-HTTP/1.1 200 OK
-Date: Tue, 09 Nov 2010 14:49:00 GMT
-Content-Length: 6
-Connection: close
-Content-Type: text/html
-Funny-head: yesyes
-Alt-Svc: h2=":%HTTP2PORT", ma=315360000; persist=0
-
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+Alt-Svc: h2=":%HTTP2PORT", ma=315360000; persist=0
+
-foo-
</data>
</reply>
@@ -44,9 +44,9 @@
CURL_ALTSVC_HTTP="yeah"
</setenv>
<command>
---http2 --alt-svc "log/altsvc-%TESTNUMBER" "http://%HOSTIP:%HTTPSPORT/%TESTNUMBER" "http://%HOSTIP:%HTTPSPORT/%TESTNUMBER"
+--http2 --alt-svc "%LOGDIR/altsvc-%TESTNUMBER" "http://%HOSTIP:%HTTPSPORT/%TESTNUMBER" "http://%HOSTIP:%HTTPSPORT/%TESTNUMBER"
</command>
-<file name="log/altsvc-%TESTNUMBER">
+<file name="%LOGDIR/altsvc-%TESTNUMBER">
h2 %HOSTIP %HTTPSPORT h2 %HOSTIP %HTTP2PORT "20290222 22:19:28" 0 0
</file>
@@ -85,7 +85,7 @@
# matches
s/\"2([^\"]*)\"/TIMESTAMP/
</stripfile>
-<file name="log/altsvc-%TESTNUMBER" mode="text">
+<file name="%LOGDIR/altsvc-%TESTNUMBER" mode="text">
# Your alt-svc cache. https://curl.se/docs/alt-svc.html
# This file was generated by libcurl! Edit at your own risk.
h2 %HOSTIP %HTTPSPORT h2 %HOSTIP %HTTP2PORT TIMESTAMP 0 0
diff --git a/tests/data/test362 b/tests/data/test362
index ad852c2..9007619 100644
--- a/tests/data/test362
+++ b/tests/data/test362
@@ -15,7 +15,7 @@
<name>
FTP resume upload file with nothing to start from
</name>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
data
to
see
@@ -24,7 +24,7 @@
so does it?
</file>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt --continue-at -
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt --continue-at -
</command>
</client>
diff --git a/tests/data/test363 b/tests/data/test363
index cd8fc43..2417917 100644
--- a/tests/data/test363
+++ b/tests/data/test363
@@ -55,9 +55,9 @@
</name>
<setenv>
# make the first send cut off after this amount of data
-CURL_SMALLREQSEND=48
+CURL_SMALLREQSEND=8
# make repeated sends small too
-CURL_SMALLSENDS=40
+CURL_SMALLSENDS=8
</setenv>
<command>
http://test.%TESTNUMBER:%HTTPPORT/we/want/that/page/%TESTNUMBER -p -x %HOSTIP:%PROXYPORT -d "datatopost=ohthatsfunyesyes"
diff --git a/tests/data/test364 b/tests/data/test364
index 5afb8c9..627bc31 100644
--- a/tests/data/test364
+++ b/tests/data/test364
@@ -28,9 +28,9 @@
HTTPS PUT of small file
</name>
<command>
--k https://%HOSTIP:%HTTPSPORT/we/want/%TESTNUMBER -T log/test%TESTNUMBER.txt
+-k https://%HOSTIP:%HTTPSPORT/we/want/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
%repeat[200 x banana]%
</file>
</client>
@@ -43,7 +43,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 1201
-Expect: 100-continue
%repeat[200 x banana]%
</protocol>
diff --git a/tests/data/test368 b/tests/data/test368
index 2f13b57..505ce34 100644
--- a/tests/data/test368
+++ b/tests/data/test368
@@ -27,7 +27,7 @@
http
</server>
<name>
-Appened dash if -r range specified without one
+Append dash if -r range specified without one
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER -r 4
diff --git a/tests/data/test369 b/tests/data/test369
index e1e2b32..17a6b44 100644
--- a/tests/data/test369
+++ b/tests/data/test369
@@ -29,7 +29,7 @@
--etag-save with bad path then working transfer
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-save log/nowhere/etag%TESTNUMBER --next http://%HOSTIP:%HTTPPORT/%TESTNUMBER --include --output log/curl%TESTNUMBER.out
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --etag-save %LOGDIR/nowhere/etag%TESTNUMBER --next http://%HOSTIP:%HTTPPORT/%TESTNUMBER --include --output %LOGDIR/curl%TESTNUMBER.out
</command>
</client>
diff --git a/tests/data/test370 b/tests/data/test370
index 8a5af1e..671e35f 100644
--- a/tests/data/test370
+++ b/tests/data/test370
@@ -22,7 +22,7 @@
--etag-save with bad path - no transfer
</name>
<command>
-http://%HOSTIP:%NOLISTENPORT/%TESTNUMBER --etag-save log/nowhere/etag%TESTNUMBER
+http://%HOSTIP:%NOLISTENPORT/%TESTNUMBER --etag-save %LOGDIR/nowhere/etag%TESTNUMBER
</command>
</client>
diff --git a/tests/data/test371 b/tests/data/test371
index 3a44db5..83ea5c7 100644
--- a/tests/data/test371
+++ b/tests/data/test371
@@ -35,7 +35,7 @@
using more -o than URLs in the command line
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/dump -o log/dump2 --no-progress-meter
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/dump -o %LOGDIR/dump2 --no-progress-meter
</command>
</client>
diff --git a/tests/data/test376 b/tests/data/test376
index 34924c7..8d15ec0 100644
--- a/tests/data/test376
+++ b/tests/data/test376
@@ -35,7 +35,7 @@
--remove-on-error
</name>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/save-%TESTNUMBER --remove-on-error
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/save-%TESTNUMBER --remove-on-error
</command>
</client>
@@ -58,7 +58,7 @@
</protocol>
# the file should be empty now
-<file name="log/save-%TESTNUMBER">
+<file name="%LOGDIR/save-%TESTNUMBER">
</file>
</verify>
</testcase>
diff --git a/tests/data/test378 b/tests/data/test378
index 650e7d4..ca908b7 100644
--- a/tests/data/test378
+++ b/tests/data/test378
@@ -21,7 +21,7 @@
Reject using -T and -d at once
</name>
<command>
--T log/%TESTNUMBER -d input http://never-accessed
+-T %LOGDIR/%TESTNUMBER -d input http://never-accessed
</command>
</client>
diff --git a/tests/data/test379 b/tests/data/test379
index c7ffc17..491d815 100644
--- a/tests/data/test379
+++ b/tests/data/test379
@@ -28,7 +28,7 @@
#
# Client-side
<client>
-<file name="log/save">
+<file name="%LOGDIR/save">
exists before command runs
</file>
<server>
@@ -38,7 +38,7 @@
--remove-on-error with --no-clobber and an added number
</name>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/save --remove-on-error --no-clobber
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/save --remove-on-error --no-clobber
</command>
</client>
@@ -61,11 +61,11 @@
</protocol>
# this file should be untouched
-<file name="log/save">
+<file name="%LOGDIR/save">
exists before command runs
</file>
# the file should be empty now
-<file2 name="log/save.1">
+<file2 name="%LOGDIR/save.1">
</file2>
</verify>
</testcase>
diff --git a/tests/data/test38 b/tests/data/test38
index 0558700..da352d7 100644
--- a/tests/data/test38
+++ b/tests/data/test38
@@ -28,9 +28,9 @@
HTTP resume request without server supporting it
</name>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -C - --no-include -o log/fewl%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/want/%TESTNUMBER -C - --no-include -o %LOGDIR/fewl%TESTNUMBER.txt
</command>
-<file name="log/fewl%TESTNUMBER.txt">
+<file name="%LOGDIR/fewl%TESTNUMBER.txt">
This text is here to simulate a partly downloaded file to resume
download on.
</file>
@@ -51,7 +51,7 @@
</protocol>
# the download target file must remain untouched
-<file name="log/fewl%TESTNUMBER.txt">
+<file name="%LOGDIR/fewl%TESTNUMBER.txt">
This text is here to simulate a partly downloaded file to resume
download on.
</file>
diff --git a/tests/data/test380 b/tests/data/test380
index a1849c1..bd0c697 100644
--- a/tests/data/test380
+++ b/tests/data/test380
@@ -38,9 +38,9 @@
</name>
<command>
---netrc --netrc-file log/netrc%TESTNUMBER ftp://mary@%HOSTIP:%FTPPORT/
+--netrc --netrc-file %LOGDIR/netrc%TESTNUMBER ftp://mary@%HOSTIP:%FTPPORT/
</command>
-<file name="log/netrc%TESTNUMBER" >
+<file name="%LOGDIR/netrc%TESTNUMBER" >
# the following two lines were created while testing curl
machine %HOSTIP login frankenstein password wrongone
machine %HOSTIP login mary password yram
diff --git a/tests/data/test381 b/tests/data/test381
index c44fa74..902cc91 100644
--- a/tests/data/test381
+++ b/tests/data/test381
@@ -42,9 +42,9 @@
</name>
<command>
---netrc-optional --netrc-file log/netrc%TESTNUMBER ftp://mary:drfrank@%HOSTIP:%FTPPORT/
+--netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER ftp://mary:drfrank@%HOSTIP:%FTPPORT/
</command>
-<file name="log/netrc%TESTNUMBER" >
+<file name="%LOGDIR/netrc%TESTNUMBER" >
# the following two lines were created while testing curl
machine %HOSTIP login frankenstein password wrongone
machine %HOSTIP login mary password yram
diff --git a/tests/data/test387 b/tests/data/test387
index 015ec25..d0e5c95 100644
--- a/tests/data/test387
+++ b/tests/data/test387
@@ -9,10 +9,11 @@
#
# Server-side
<reply>
-<data nocheck="yes">
-HTTP/1.1 200 OK
-Transfer-Encoding: gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip
-
+<data nocheck="yes" crlf="yes">
+HTTP/1.1 200 OK
+Content-Length: 6
+Transfer-Encoding: gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip,gzip
+
-foo-
</data>
</reply>
@@ -23,11 +24,14 @@
<server>
http
</server>
- <name>
+<features>
+libz
+</features>
+<name>
Response with overly long compression chain
- </name>
- <command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -sS
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -sS --tr-encoding
</command>
</client>
@@ -39,6 +43,8 @@
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
+Connection: TE
+TE: gzip
</protocol>
@@ -47,7 +53,7 @@
61
</errorcode>
<stderr mode="text">
-curl: (61) Reject response due to 5 content encodings
+curl: (61) Reject response due to more than 5 content encodings
</stderr>
</verify>
</testcase>
diff --git a/tests/data/test388 b/tests/data/test388
new file mode 100644
index 0000000..3a0214a
--- /dev/null
+++ b/tests/data/test388
@@ -0,0 +1,156 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP Digest auth
+</keywords>
+</info>
+
+# Server-side
+<reply>
+# First reply back and ask for Digest auth
+<data1>
+HTTP/1.1 401 Authorization Required swsclose
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+WWW-Authenticate: Digest realm="testrealm", nonce="1053604145"
+Content-Type: text/html; charset=iso-8859-1
+Content-Length: 26
+
+This is not the real page
+</data1>
+
+# second reply back
+<data2>
+HTTP/1.1 401 Authorization Required swsclose
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+WWW-Authenticate: Digest realm="testrealm", nonce="1053604145"
+Content-Type: text/html; charset=iso-8859-1
+Content-Length: 26
+
+This is not the real page
+</data2>
+
+# This is supposed to be returned when the server gets a
+# Authorization: Digest line passed-in from the client
+<data1001>
+HTTP/1.1 200 OK
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+Content-Type: text/html; charset=iso-8859-1
+Content-Length: 23
+
+This IS the real page!
+</data1001>
+
+#
+# This is the second request, and this sends back a response saying that
+# the request contained stale data. We want an update. Set swsbounce to
+# bounce on to data1003 on the second request.
+<data1002>
+HTTP/1.1 401 Authorization re-negotiation please swsbounce
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+WWW-Authenticate: Digest realm="testrealm", algorithm=MD5, nonce="999999", stale=true, qop="crazy, auth"
+Content-Type: text/html; charset=iso-8859-1
+Content-Length: 26
+
+This is not the real page
+</data1002>
+
+# The second request to the 1002 section will bounce this one back instead
+# thanks to the swsbounce keyword up there
+<data1003>
+HTTP/1.1 200 OK
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+Content-Type: text/html; charset=iso-8859-1
+Content-Length: 30
+
+This IS the second real page!
+</data1003>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<features>
+!SSPI
+crypto
+</features>
+ <name>
+HTTP with Digest and multiple qop values with leading space
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 -u testuser:testpass --digest http://%HOSTIP:%HTTPPORT/%TESTNUMBER0002
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^Authorization.*cnonce
+</strip>
+<protocol>
+GET /%TESTNUMBER0001 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+GET /%TESTNUMBER0001 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Digest username="testuser", realm="testrealm", nonce="1053604145", uri="/%TESTNUMBER0001", response="ea598bbfdb5c54b7352c977e3885e44d"
+User-Agent: curl/%VERSION
+Accept: */*
+
+GET /%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+GET /%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Digest username="testuser", realm="testrealm", nonce="1053604145", uri="/%TESTNUMBER0002", response="921a8e6db782d6359db1f40d9ed7e6a6"
+User-Agent: curl/%VERSION
+Accept: */*
+
+GET /%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Digest username="testuser", realm="testrealm", nonce="999999", uri="/%TESTNUMBER0002", cnonce="MTA4MzIy", nc="00000001", qop="auth", response="25291c357671604a16c0242f56721c07", algorithm=MD5
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+<stdout>
+HTTP/1.1 401 Authorization Required swsclose
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+WWW-Authenticate: Digest realm="testrealm", nonce="1053604145"
+Content-Type: text/html; charset=iso-8859-1
+Content-Length: 26
+
+HTTP/1.1 200 OK
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+Content-Type: text/html; charset=iso-8859-1
+Content-Length: 23
+
+This IS the real page!
+HTTP/1.1 401 Authorization Required swsclose
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+WWW-Authenticate: Digest realm="testrealm", nonce="1053604145"
+Content-Type: text/html; charset=iso-8859-1
+Content-Length: 26
+
+HTTP/1.1 401 Authorization re-negotiation please swsbounce
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+WWW-Authenticate: Digest realm="testrealm", algorithm=MD5, nonce="999999", stale=true, qop="crazy, auth"
+Content-Type: text/html; charset=iso-8859-1
+Content-Length: 26
+
+HTTP/1.1 200 OK
+Server: Apache/1.3.27 (Darwin) PHP/4.1.2
+Content-Type: text/html; charset=iso-8859-1
+Content-Length: 30
+
+This IS the second real page!
+</stdout>
+</verify>
+</testcase>
diff --git a/tests/data/test389 b/tests/data/test389
new file mode 100644
index 0000000..f805bc2
--- /dev/null
+++ b/tests/data/test389
@@ -0,0 +1,57 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+.localhost
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+*.localhost is a local host
+ </name>
+ <command>
+http://curlmachine.localhost:%HTTPPORT/%TESTNUMBER
+</command>
+# Ensure that we're running on localhost
+<precheck>
+perl -e "print 'Test requires default test server host' if ( '%HOSTIP' ne '127.0.0.1' );"
+</precheck>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: curlmachine.localhost:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test39 b/tests/data/test39
index 81c7119..5bfb226 100644
--- a/tests/data/test39
+++ b/tests/data/test39
@@ -19,6 +19,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -26,10 +29,10 @@
HTTP RFC1867-type formposting with filename= and type=
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F name=daniel -F tool=curl --form-string "str1=@literal" --form-string "str2=<verbatim;type=xxx/yyy" -F "file=@log/test%TESTNUMBER.txt;type=moo/foobar;filename=fakerfile" -F file2=@log/test%TESTNUMBER.txt -F "file3=@\"log/test%TESTNUMBER.txt\";type=mo/foo;filename=\"f\\\\\\\\ak\\\\\\er,\\\\an\\d;.t\\\"xt\"" -F 'file4=@"log/test%TESTNUMBER.txt"; filename="A\\AA\"\"\\\"ZZZ"'
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F name=daniel -F tool=curl --form-string "str1=@literal" --form-string "str2=<verbatim;type=xxx/yyy" -F "file=@%LOGDIR/test%TESTNUMBER.txt;type=moo/foobar;filename=fakerfile" -F file2=@%LOGDIR/test%TESTNUMBER.txt -F "file3=@\"%LOGDIR/test%TESTNUMBER.txt\";type=mo/foo;filename=\"f\\\\\\\\ak\\\\\\er,\\\\an\\d;.t\\\"xt\"" -F 'file4=@"%LOGDIR/test%TESTNUMBER.txt"; filename="A\\AA\"\"\\\"ZZZ"'
</command>
# We create this file before the command is invoked!
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo bar
This is a bar foo
bar
diff --git a/tests/data/test390 b/tests/data/test390
index 80e8c2b..83f1cec 100644
--- a/tests/data/test390
+++ b/tests/data/test390
@@ -27,7 +27,7 @@
#
# Client-side
<client>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
%repeat[1000 x hellofile!]%
</file>
<server>
@@ -38,7 +38,7 @@
curl HTTP, FILE and FTP in parallel
</name>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER file://localhost%FILE_PWD/log/test%TESTNUMBER.txt ftp://%HOSTIP:%FTPPORT/%TESTNUMBER0002 --parallel -o log/%TESTNUMBER.a -o log/%TESTNUMBER.b -o log/%TESTNUMBER.c
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER file://localhost%FILE_PWD/%LOGDIR/test%TESTNUMBER.txt ftp://%HOSTIP:%FTPPORT/%TESTNUMBER0002 --parallel -o %LOGDIR/%TESTNUMBER.a -o %LOGDIR/%TESTNUMBER.b -o %LOGDIR/%TESTNUMBER.c
</command>
</client>
diff --git a/tests/data/test392 b/tests/data/test392
index 24430c1..71d4486 100644
--- a/tests/data/test392
+++ b/tests/data/test392
@@ -40,6 +40,9 @@
<precheck>
perl -e "print 'Test requires default test server host' if ( '%HOSTIP' ne '127.0.0.1' );"
</precheck>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
diff --git a/tests/data/test399 b/tests/data/test399
new file mode 100644
index 0000000..da4b3f7
--- /dev/null
+++ b/tests/data/test399
@@ -0,0 +1,32 @@
+<testcase>
+<info>
+<keywords>
+URL
+</keywords>
+</info>
+
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+65536 bytes long host name in URL
+</name>
+<file name="%LOGDIR/input%TESTNUM">
+url = http://%repeat[65536 x a]%/399
+</file>
+<command>
+-K %LOGDIR/input%TESTNUM
+</command>
+</client>
+
+<verify>
+# 3 == CURLE_URL_MALFORMAT
+<errorcode>
+3
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test401 b/tests/data/test401
index ac4af97..043b660 100644
--- a/tests/data/test401
+++ b/tests/data/test401
@@ -19,7 +19,7 @@
<name>
FTPS PASV upload file
</name>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
data
to
see
@@ -28,7 +28,7 @@
so does it?
</file>
<command>
--k --ftp-ssl-control ftps://%HOSTIP:%FTPSPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt
+-k --ftp-ssl-control ftps://%HOSTIP:%FTPSPORT/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt
</command>
</client>
diff --git a/tests/data/test408 b/tests/data/test408
index 2516fc3..676ec9d 100644
--- a/tests/data/test408
+++ b/tests/data/test408
@@ -25,9 +25,9 @@
FTPS PORT upload with CWD
</name>
<command>
--k --ftp-ssl-control ftps://%HOSTIP:%FTPSPORT/CWD/STOR/RETR/%TESTNUMBER -T log/upload%TESTNUMBER -P -
+-k --ftp-ssl-control ftps://%HOSTIP:%FTPSPORT/CWD/STOR/RETR/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER -P -
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Moooooooooooo
upload this
</file>
diff --git a/tests/data/test409 b/tests/data/test409
index ea6e795..4160a11 100644
--- a/tests/data/test409
+++ b/tests/data/test409
@@ -19,7 +19,7 @@
<name>
FTPS PASV upload file
</name>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
data
to
see
@@ -28,7 +28,7 @@
so does it?
</file>
<command>
--k --ftp-ssl-control ftps://%HOSTIP:%FTPSPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt
+-k --ftp-ssl-control ftps://%HOSTIP:%FTPSPORT/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt
</command>
</client>
diff --git a/tests/data/test41 b/tests/data/test41
index aaf0ae7..7a13330 100644
--- a/tests/data/test41
+++ b/tests/data/test41
@@ -12,6 +12,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test410 b/tests/data/test410
index 06999fb..4fec0b7 100644
--- a/tests/data/test410
+++ b/tests/data/test410
@@ -32,11 +32,11 @@
HTTPS GET with very long request header
</name>
# 14 characters repeated 3500 times makes 49000 bytes
-<file name="log/file%TESTNUMBER">
+<file name="%LOGDIR/file%TESTNUMBER">
Long: %repeat[3500 x header content]%
</file>
<command>
--k https://%HOSTIP:%HTTPSPORT/%TESTNUMBER -H @log/file%TESTNUMBER
+-k https://%HOSTIP:%HTTPSPORT/%TESTNUMBER -H @%LOGDIR/file%TESTNUMBER
</command>
</client>
diff --git a/tests/data/test411 b/tests/data/test411
index 912f07c..eb6fad1 100644
--- a/tests/data/test411
+++ b/tests/data/test411
@@ -20,7 +20,7 @@
-K with missing file causes error
</name>
<command>
--K log/missing http://localhost
+-K %LOGDIR/missing http://localhost
</command>
</client>
@@ -28,7 +28,7 @@
# Verify data after the test has been "shot"
<verify>
<stderr mode="text">
-curl: cannot read config from 'log/missing'
+curl: cannot read config from '%LOGDIR/missing'
curl: option -K: error encountered when reading a file
%if manual
curl: try 'curl --help' or 'curl --manual' for more information
diff --git a/tests/data/test412 b/tests/data/test412
index 0dbc0ce..3f740f1 100644
--- a/tests/data/test412
+++ b/tests/data/test412
@@ -41,9 +41,9 @@
CURL_ALTSVC_HTTP="yeah"
</setenv>
<command>
---alt-svc "log/altsvc-%TESTNUMBER" "http://whohoo.:12345/%TESTNUMBER"
+--alt-svc "%LOGDIR/altsvc-%TESTNUMBER" "http://whohoo.:12345/%TESTNUMBER"
</command>
-<file name="log/altsvc-%TESTNUMBER">
+<file name="%LOGDIR/altsvc-%TESTNUMBER">
h1 whohoo 12345 h1 %HOSTIP %HTTPPORT "20290222 22:19:28" 0 0
</file>
diff --git a/tests/data/test413 b/tests/data/test413
index 975b3e3..cfb7a72 100644
--- a/tests/data/test413
+++ b/tests/data/test413
@@ -41,9 +41,9 @@
CURL_ALTSVC_HTTP="yeah"
</setenv>
<command>
---alt-svc "log/altsvc-%TESTNUMBER" "http://whohoo:12345/%TESTNUMBER"
+--alt-svc "%LOGDIR/altsvc-%TESTNUMBER" "http://whohoo:12345/%TESTNUMBER"
</command>
-<file name="log/altsvc-%TESTNUMBER">
+<file name="%LOGDIR/altsvc-%TESTNUMBER">
h1 whohoo. 12345 h1 %HOSTIP %HTTPPORT "20290222 22:19:28" 0 0
</file>
diff --git a/tests/data/test414 b/tests/data/test414
index 2211d0f..391ed0d 100644
--- a/tests/data/test414
+++ b/tests/data/test414
@@ -55,7 +55,7 @@
HTTPS sec-cookie, HTTP redirect, same name cookie, redirect back
</name>
<command>
-https://attack.invalid:%HTTPSPORT/a/b/%TESTNUMBER -k -c log/cookie%TESTNUMBER --resolve attack.invalid:%HTTPSPORT:%HOSTIP --resolve attack.invalid:%HTTPPORT:%HOSTIP -L
+https://attack.invalid:%HTTPSPORT/a/b/%TESTNUMBER -k -c %LOGDIR/cookie%TESTNUMBER --resolve attack.invalid:%HTTPSPORT:%HOSTIP --resolve attack.invalid:%HTTPPORT:%HOSTIP -L
</command>
</client>
diff --git a/tests/data/test415 b/tests/data/test415
new file mode 100644
index 0000000..099ec83
--- /dev/null
+++ b/tests/data/test415
Binary files differ
diff --git a/tests/data/test416 b/tests/data/test416
new file mode 100644
index 0000000..93dc067
--- /dev/null
+++ b/tests/data/test416
@@ -0,0 +1,51 @@
+<testcase>
+<info>
+<keywords>
+FTP
+EPSV
+RETR
+Range
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+0123456789abcdef0123456789abcdef0123456789abcdef
+</data>
+<datacheck>
+0123456789abcdef0123456789abcdef0123456789abcdef
+</datacheck>
+<servercmd>
+RETRSIZE 7
+</servercmd>
+<size>
+8
+</size>
+</reply>
+
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+FTP growing file support
+ </name>
+ <command>
+--ignore-content-length ftp://%HOSTIP:%FTPPORT/%TESTNUMBER
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous
+PASS ftp@example.com
+PWD
+EPSV
+TYPE I
+RETR %TESTNUMBER
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test417 b/tests/data/test417
new file mode 100644
index 0000000..9061f83
--- /dev/null
+++ b/tests/data/test417
@@ -0,0 +1,83 @@
+<testcase>
+<info>
+<keywords>
+HTTPS
+%{certs}
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 7
+
+nomnom
+</data>
+</reply>
+
+# Client-side
+<client>
+<features>
+SSL
+!wolfssl
+!bearssl
+!mbedtls
+!rustls
+</features>
+<server>
+http
+https
+</server>
+<name>
+%{certs}
+</name>
+<command option="no-include">
+--insecure https://%HOSTIP:%HTTPSPORT/%TESTNUMBER -w '%{certs}'
+</command>
+</client>
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPSPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+<stripfile>
+s/^(.*):(.*)[\r\n]*//
+</stripfile>
+<stdout>
+nomnom
+-----BEGIN CERTIFICATE-----
+MIIERDCCAyygAwIBAgIGDzR1UZ/TMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
+IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
+Fw0yMjEyMjMxMjIxMzlaFw0zMTAzMTExMjIxMzlaMFQxCzAJBgNVBAYTAk5OMTEw
+LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
+MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQCrCrAD0Hb+Xs4V3mHV45FvfNa7yiaOeL4mNdGmWfHVPFU+CSzsoNSvDjxa
+orWweFGVYoCAcchOn1lZk0ASsqnOss0Xi58n8+PPI3gG0gYjX5sg7EJ3Zq2kXoK0
+TZRy6hNkcvzLgyzXoYv1LkzTwYiyyJgZX++Y/GKAs2fMHyP8XzjNgm4tltk1k/4p
+omllwN9Fqz+sFxgAgEq3ybq4Xym7xKwWl8xXNBDJNmVsPtiJRcilQoR8Xs0a6PE+
+VbMhD9A2E/LEL7lzQfqHqtxE1mSW5FpQ+Uqf4KLnafStWs86IOWnCeLP6BmhAK6o
+uyICNFyzz7UkTHa/renxuNOGun2TAgMBAAGjggEGMIIBAjAUBgNVHREEDTALggls
+b2NhbGhvc3QwCwYDVR0PBAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1Ud
+DgQWBBScl7A9s1Cx9tRx4uvLgOqTfJjMcjAfBgNVHSMEGDAWgBSHy7EzLsFnfnHj
+5StMTaSzbtJbqTAJBgNVHRMEAjAAMEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcw
+AoYnaHR0cDovL3Rlc3QuY3VybC5zZS9jYS9FZGVsQ3VybFJvb3QuY2VyMDgGA1Ud
+HwQxMC8wLaAroCmGJ2h0dHA6Ly90ZXN0LmN1cmwuc2UvY2EvRWRlbEN1cmxSb290
+LmNybDANBgkqhkiG9w0BAQsFAAOCAQEAC4rtaof6cRWIJViFG0oJv0MANZN4DXIU
+MFHik4Oh2hsvqTGut8dMcsJeMiTxlpNw1T+1hYATdTLPDvhdxKIphEMsdYEmEmqg
+y3tXwZJ4hQj6ZFDCe4MCTXkTvGFkTbhr1fGEaxJcaZCtQEfA7d3qimZ+h4UZqonT
+PAhyCKFNY2BbmxeeABKhAFLKeAGIGMftW8fk2eu9P6+SUz/+WFcN/PR7e6JP6blc
+taRSULRWWkSO2dDt3o9+rBxYdluoecmVq4Ud20wTgkqlQRsp9dOW34DRHgB9ujWU
+V4HhCCqBaxwwUDcBGg4mT2vtyVAXNyszP2j+xvAhjOeyeVXyQr0vsA==
+-----END CERTIFICATE-----
+</stdout>
+
+</verify>
+
+</testcase>
diff --git a/tests/data/test418 b/tests/data/test418
new file mode 100644
index 0000000..6031b86
--- /dev/null
+++ b/tests/data/test418
@@ -0,0 +1,67 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+gzip
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 swsclose OK
+Content-Length: 6
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+Transfer-Encoding: gzip
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<features>
+libz
+</features>
+<name>
+Response with multiple Transfer-Encoding headers
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -sS --tr-encoding
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Connection: TE
+TE: gzip
+
+</protocol>
+
+# CURLE_BAD_CONTENT_ENCODING is 61
+<errorcode>
+61
+</errorcode>
+<stderr mode="text">
+curl: (61) Reject response due to more than 5 content encodings
+</stderr>
+</verify>
+</testcase>
diff --git a/tests/data/test419 b/tests/data/test419
new file mode 100644
index 0000000..35e1259
--- /dev/null
+++ b/tests/data/test419
@@ -0,0 +1,35 @@
+<testcase>
+<info>
+<keywords>
+--dump-header
+failure
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+--dump-header to file that cannot be created
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -D loggg/save-here/fails
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+23
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test420 b/tests/data/test420
new file mode 100644
index 0000000..3d6b624
--- /dev/null
+++ b/tests/data/test420
@@ -0,0 +1,75 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+cookies
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Accept-Ranges: bytes
+Content-Length: 6
+Content-Type: text/html
+Set-Cookie: mycookie=; Max-Age=-1; Expires=Thu, 01 Jan 1970 00:00:00 GMT
+Set-Cookie: mycookie3=; Path=/func_test; Max-Age=-1; Expires=Thu, 01 Jan 1970 00:00:00 GMT
+Set-Cookie: mycookie4=; Path=/func_test; Max-Age=-1; Expires=Thu, 01 Jan 1970 00:00:
+Set-Cookie: mycookie5=; Path=/func_test; Max-Age=-1; Expires=Thu, 01 Jan 1970 00:00:00 GMT
+Set-Cookie: mycookie6=; Path=/func_test; Max-Age=-1; Expires=Thu, 01 Jan 1970 00:00:00 GMT
+Set-Cookie: mycookie1=; Path=/; Max-Age=-1; Expires=Thu, 01 Jan 1970 00:00:00 GMT
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+Setting cookies set with expired dates that were loaded from jar
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/func_test/del_cookie -b %LOGDIR/cookie%TESTNUMBER -c %LOGDIR/save%TESTNUMBER
+</command>
+<file name="%LOGDIR/cookie%TESTNUMBER" mode="text">
+%HOSTIP FALSE /func_test FALSE 1709598616 mycookie6 991
+#HttpOnly_%HOSTIP FALSE /func_test FALSE 1709598616 mycookie5 990
+#HttpOnly_%HOSTIP FALSE /func_test FALSE 1709598616 mycookie4 950
+#HttpOnly_%HOSTIP FALSE /func_test FALSE 1709598616 mycookie3 900
+#HttpOnly_%HOSTIP FALSE /func_test/ FALSE 1709598616 mycookie2 5900
+#HttpOnly_%HOSTIP FALSE / FALSE 1709598616 mycookie1 4900
+#HttpOnly_%HOSTIP FALSE /func_test/ FALSE 0 mycookie 1200
+</file>
+<features>
+cookies
+</features>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /func_test/del_cookie HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Cookie: mycookie2=5900; mycookie=1200; mycookie3=900; mycookie4=950; mycookie5=990; mycookie6=991; mycookie1=4900
+
+</protocol>
+<file name="%LOGDIR/save%TESTNUMBER" mode="text">
+# Netscape HTTP Cookie File
+# https://curl.se/docs/http-cookies.html
+# This file was generated by libcurl! Edit at your own risk.
+
+#HttpOnly_127.0.0.1 FALSE /func_test/ FALSE 1709598616 mycookie2 5900
+</file>
+</verify>
+</testcase>
diff --git a/tests/data/test421 b/tests/data/test421
new file mode 100644
index 0000000..0e4130b
--- /dev/null
+++ b/tests/data/test421
@@ -0,0 +1,85 @@
+<testcase>
+<info>
+<keywords>
+header_json
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 200 OK
+server: nginx
+date: Tue, 07 Mar 2023 15:14:41 GMT
+content-type: application/json
+content-length: 6
+vary: Accept-Encoding
+access-control-allow-origin: *
+vary: Accept-Encoding
+referrer-policy: strict-origin-when-cross-origin
+access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS
+access-control-max-age: 1728000
+access-control-allow-headers: Authorization, Content-Type, AuthorizationOauth, X-EARLY-ACCESS
+access-control-expose-headers:
+vary: Accept
+etag: W/"2678f9ab2ba550d164e7cc014aefd31e"
+cache-control: max-age=0, private, must-revalidate
+x-request-id: 375b343b3d2ecf9b442c0daf00fc4a9a
+strict-transport-security: max-age=31536000; includeSubDomains
+x-content-type-options: nosniff
+x-xss-protection: 1; mode=block
+referrer-policy: strict-origin-when-cross-origin
+feature-policy: accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+HTTP GET multiple headers and %{header_json}
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -w '%{stderr}%{header_json}\n' -s
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+<stderr mode="text">
+{"server":["nginx"],
+"date":["Tue, 07 Mar 2023 15:14:41 GMT"],
+"content-type":["application/json"],
+"content-length":["6"],
+"vary":["Accept-Encoding","Accept-Encoding","Accept"],
+"access-control-allow-origin":["*"],
+"referrer-policy":["strict-origin-when-cross-origin","strict-origin-when-cross-origin"],
+"access-control-allow-methods":["GET, POST, PUT, DELETE, OPTIONS"],
+"access-control-max-age":["1728000"],
+"access-control-allow-headers":["Authorization, Content-Type, AuthorizationOauth, X-EARLY-ACCESS"],
+"access-control-expose-headers":["\r"],
+"etag":["W/\"2678f9ab2ba550d164e7cc014aefd31e\""],
+"cache-control":["max-age=0, private, must-revalidate"],
+"x-request-id":["375b343b3d2ecf9b442c0daf00fc4a9a"],
+"strict-transport-security":["max-age=31536000; includeSubDomains"],
+"x-content-type-options":["nosniff"],
+"x-xss-protection":["1; mode=block"],
+"feature-policy":["accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'"]
+}
+</stderr>
+</verify>
+</testcase>
diff --git a/tests/data/test422 b/tests/data/test422
new file mode 100644
index 0000000..2caaa49
--- /dev/null
+++ b/tests/data/test422
@@ -0,0 +1,44 @@
+<testcase>
+<info>
+<keywords>
+cmdline
+--next
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<name>
+use --next with missing URL before it
+</name>
+<command>
+-O -I --next http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<stderr mode="text">
+curl: missing URL before --next
+curl: option --next: is badly used here
+%if manual
+curl: try 'curl --help' or 'curl --manual' for more information
+%else
+curl: try 'curl --help' for more information
+%endif
+</stderr>
+<errorcode>
+2
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test423 b/tests/data/test423
new file mode 100644
index 0000000..6c6e725
--- /dev/null
+++ b/tests/data/test423
@@ -0,0 +1,51 @@
+<testcase>
+<info>
+<keywords>
+-w
+--write-out
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes" nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+-w with url.* variables
+</name>
+<command option="no-include">
+"http://uuuu:pppp@%HOSTIP:%HTTPPORT/%TESTNUMBER?qqqq#ffff" "h55p://hello2000:1/%TESTNUMBER?qqqq#ffff" "local host" "http://u22u:p22p@%HOSTIP:%HTTPPORT/%TESTNUMBER?qqqq#ffff" -w '%{url.host}+%{url.path}+%{url.scheme}+%{url.user}+%{url.password}+%{url.port}+%{url.query}+%{url.fragment}\n'
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<stdout>
+%HOSTIP+/%TESTNUMBER+http+uuuu+pppp+%HTTPPORT+qqqq+ffff
+hello2000+/%TESTNUMBER+h55p+++1+qqqq+ffff
++++++++
+%HOSTIP+/%TESTNUMBER+http+u22u+p22p+%HTTPPORT+qqqq+ffff
+</stdout>
+</verify>
+</testcase>
diff --git a/tests/data/test424 b/tests/data/test424
new file mode 100644
index 0000000..36ba8c4
--- /dev/null
+++ b/tests/data/test424
@@ -0,0 +1,68 @@
+<testcase>
+<info>
+<keywords>
+-w
+--write-out
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes" nocheck="yes">
+HTTP/1.1 301 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+Location: http://anotherhost.example:2023/%TESTNUMBER0002?moo.html
+
+</data>
+<data2 crlf="yes" nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+</data2>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+proxy
+</features>
+<server>
+http
+</server>
+<name>
+-w with urle.* variables
+</name>
+<command option="no-include">
+"http://uuuu:pppp@%HOSTIP:%HTTPPORT/%TESTNUMBER?qqqq#ffff" "h55p://hello2000:1/%TESTNUMBER?qqqq#ffff" "local host" "http://u22u:p22p@%HOSTIP:%HTTPPORT/%TESTNUMBER?qqqq#ffff" -w '%{urle.host}+%{urle.path}+%{urle.scheme}+%{urle.user}+%{urle.password}+%{urle.port}+%{urle.query}+%{urle.fragment}\n' -x http://%HOSTIP:%HTTPPORT/ -L
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<stdout>
+anotherhost.example+/%TESTNUMBER0002+http+uuuu+pppp+2023+moo.html+
+hello2000+/%TESTNUMBER+h55p+++1+qqqq+ffff
++++++++
+anotherhost.example+/%TESTNUMBER0002+http+u22u+p22p+2023+moo.html+
+</stdout>
+</verify>
+</testcase>
diff --git a/tests/data/test425 b/tests/data/test425
new file mode 100644
index 0000000..dff6ab4
--- /dev/null
+++ b/tests/data/test425
@@ -0,0 +1,53 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP PUT
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP PUT with path ending with slash + query
+ </name>
+ <command>
+-T %LOGDIR/up%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER/?fullpath
+</command>
+<file name="%LOGDIR/up%TESTNUMBER">
+content
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+PUT /%TESTNUMBER/?fullpath HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Content-Length: 8
+
+content
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test426 b/tests/data/test426
new file mode 100644
index 0000000..34c80c6
--- /dev/null
+++ b/tests/data/test426
@@ -0,0 +1,34 @@
+<testcase>
+<info>
+<keywords>
+error detection
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+try --data with --continue-at
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -d foobar -C 3
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+2
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test427 b/tests/data/test427
new file mode 100644
index 0000000..1e08810
--- /dev/null
+++ b/tests/data/test427
@@ -0,0 +1,76 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+cookies
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes" nocheck="yes">
+HTTP/1.1 301 move along
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Set-Cookie: long1=%repeat[400 x abcdefgh]%; path="/"
+Set-Cookie: long2=%repeat[400 x abcdefgh]%; path="/"
+Set-Cookie: long3=%repeat[400 x abcdefgh]%; path="/"
+Location: %TESTNUMBER0002
+
+-foo-
+</data>
+
+<data2 crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+
+-foo-
+</data2>
+
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+Keep Cookie: header within 8190 bytes
+</name>
+
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -c %LOGDIR/cookies%TESTNUMBER -L
+</command>
+<features>
+cookies
+</features>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+GET /%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Cookie: long3=%repeat[400 x abcdefgh]%; long2=%repeat[400 x abcdefgh]%
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test430 b/tests/data/test430
index e3aae0b..3826f15 100644
--- a/tests/data/test430
+++ b/tests/data/test430
@@ -37,19 +37,19 @@
#
# Client-side
<client>
-<file1 name="log/config%TESTNUMBER-a">
+<file1 name="%LOGDIR/config%TESTNUMBER-a">
--next
url = %HOSTIP:%HTTPPORT/%TESTNUMBER0001
header = "a: a"
data = "a"
</file1>
-<file2 name="log/config%TESTNUMBER-b">
+<file2 name="%LOGDIR/config%TESTNUMBER-b">
--next
url = %HOSTIP:%HTTPPORT/%TESTNUMBER0002
header = "b: b"
data = "b"
</file2>
-<file3 name="log/config%TESTNUMBER-c">
+<file3 name="%LOGDIR/config%TESTNUMBER-c">
--next
url = %HOSTIP:%HTTPPORT/%TESTNUMBER0003
header = "c: c"
@@ -63,7 +63,7 @@
Three -K uses with --next and --data in each
</name>
<command>
--K log/config%TESTNUMBER-a -K log/config%TESTNUMBER-b -K log/config%TESTNUMBER-c
+-K %LOGDIR/config%TESTNUMBER-a -K %LOGDIR/config%TESTNUMBER-b -K %LOGDIR/config%TESTNUMBER-c
</command>
</client>
diff --git a/tests/data/test431 b/tests/data/test431
index bebe620..52c39d1 100644
--- a/tests/data/test431
+++ b/tests/data/test431
@@ -37,13 +37,13 @@
#
# Client-side
<client>
-<file1 name="log/config%TESTNUMBER-a">
+<file1 name="%LOGDIR/config%TESTNUMBER-a">
--next
url = %HOSTIP:%HTTPPORT/%TESTNUMBER0001
header = "a: a"
data = "a"
</file1>
-<file2 name="log/config%TESTNUMBER-b">
+<file2 name="%LOGDIR/config%TESTNUMBER-b">
--next
url = %HOSTIP:%HTTPPORT/%TESTNUMBER0002
header = "b: b"
@@ -57,7 +57,7 @@
Two -K uses with --next and then one on cmdline
</name>
<command>
--K log/config%TESTNUMBER-a -K log/config%TESTNUMBER-b --next -d c %HOSTIP:%HTTPPORT/%TESTNUMBER0003 -H "c: c"
+-K %LOGDIR/config%TESTNUMBER-a -K %LOGDIR/config%TESTNUMBER-b --next -d c %HOSTIP:%HTTPPORT/%TESTNUMBER0003 -H "c: c"
</command>
</client>
diff --git a/tests/data/test432 b/tests/data/test432
index e7fe45b..fd056c3 100644
--- a/tests/data/test432
+++ b/tests/data/test432
@@ -37,7 +37,7 @@
#
# Client-side
<client>
-<file1 name="log/config%TESTNUMBER">
+<file1 name="%LOGDIR/config%TESTNUMBER">
--next
url = %HOSTIP:%HTTPPORT/%TESTNUMBER0001
header = "a: a"
@@ -46,9 +46,9 @@
url = %HOSTIP:%HTTPPORT/%TESTNUMBER0002
header = "b: b"
data = "b"
-config = "log/config%TESTNUMBER-c"
+config = "%LOGDIR/config%TESTNUMBER-c"
</file1>
-<file2 name="log/config%TESTNUMBER-c">
+<file2 name="%LOGDIR/config%TESTNUMBER-c">
--next
url = %HOSTIP:%HTTPPORT/%TESTNUMBER0003
header = "c: c"
@@ -62,7 +62,7 @@
Use -K with --next and --config from within
</name>
<command>
--K log/config%TESTNUMBER
+-K %LOGDIR/config%TESTNUMBER
</command>
</client>
diff --git a/tests/data/test433 b/tests/data/test433
index 34ea4a7..e86f3de 100644
--- a/tests/data/test433
+++ b/tests/data/test433
@@ -20,7 +20,7 @@
#
# Client-side
<client>
-<file1 name="log/.curlrc">
+<file1 name="%LOGDIR/.curlrc">
--next
header = "a: a"
data = "curlrc read"
@@ -29,7 +29,7 @@
http
</server>
<setenv>
-XDG_CONFIG_HOME=%PWD/log
+XDG_CONFIG_HOME=%PWD/%LOGDIR
HOME=
CURL_HOME=
</setenv>
diff --git a/tests/data/test434 b/tests/data/test434
index d411b16..63d8ce7 100644
--- a/tests/data/test434
+++ b/tests/data/test434
@@ -19,7 +19,7 @@
#
<client>
-<file name="log/config%TESTNUMBER" nonewline="yes">
+<file name="%LOGDIR/config%TESTNUMBER" nonewline="yes">
url = %HOSTIP:%HTTPPORT/%TESTNUMBER
</file>
<server>
@@ -29,7 +29,7 @@
-K with a single line without newline
</name>
<command>
--K log/config%TESTNUMBER
+-K %LOGDIR/config%TESTNUMBER
</command>
</client>
diff --git a/tests/data/test435 b/tests/data/test435
index eed9e29..cfcca66 100644
--- a/tests/data/test435
+++ b/tests/data/test435
@@ -23,7 +23,7 @@
http
</server>
<name>
-verify -w local/remote port+ip after connecton re-use
+verify -w local/remote port+ip after connection re-use
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER -w 'local port == %{local_port}\nlocal ip == %{local_ip}\nremote_ip == %{remote_ip}\nremote_port == %{remote_port}\n'
diff --git a/tests/data/test436 b/tests/data/test436
index 0a62cfb..d435b51 100644
--- a/tests/data/test436
+++ b/tests/data/test436
@@ -20,7 +20,7 @@
#
# Client-side
<client>
-<file1 name="log/.config/curlrc">
+<file1 name="%LOGDIR/.config/curlrc">
--next
header = "a: a"
data = "curlrc read"
@@ -29,7 +29,7 @@
http
</server>
<setenv>
-CURL_HOME=%PWD/log
+CURL_HOME=%PWD/%LOGDIR
XDG_CONFIG_HOME=
</setenv>
<name>
diff --git a/tests/data/test44 b/tests/data/test44
index 0ec2f4b..880c7ae 100644
--- a/tests/data/test44
+++ b/tests/data/test44
@@ -20,6 +20,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -27,10 +30,10 @@
HTTP RFC1867-type formposting without Expect: header
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F name=daniel -F tool=curl -F file=@log/test%TESTNUMBER.txt -H "Expect:"
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F name=daniel -F tool=curl -F file=@%LOGDIR/test%TESTNUMBER.txt -H "Expect:"
</command>
# We create this file before the command is invoked!
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo-
This is a moo-
bar
diff --git a/tests/data/test440 b/tests/data/test440
index 0986cda..a77ef60 100644
--- a/tests/data/test440
+++ b/tests/data/test440
@@ -34,7 +34,7 @@
</features>
# no trailing dot in the file only in the URL
-<file name="log/input%TESTNUMBER">
+<file name="%LOGDIR/input%TESTNUMBER">
this.hsts.example "99991001 04:47:41"
</file>
@@ -42,7 +42,7 @@
HSTS with trailing-dot host name in URL but none in hsts file
</name>
<command>
--x http://%HOSTIP:%HTTPPORT http://this.hsts.example./%TESTNUMBER --hsts log/input%TESTNUMBER -w '%{url_effective}\n'
+-x http://%HOSTIP:%HTTPPORT http://this.hsts.example./%TESTNUMBER --hsts %LOGDIR/input%TESTNUMBER -w '%{url_effective}\n'
</command>
</client>
diff --git a/tests/data/test441 b/tests/data/test441
index 6fbf7be..29b990b 100644
--- a/tests/data/test441
+++ b/tests/data/test441
@@ -34,7 +34,7 @@
</features>
# no trailing dot in the file only in the URL
-<file name="log/input%TESTNUMBER">
+<file name="%LOGDIR/input%TESTNUMBER">
this.hsts.example. "99991001 04:47:41"
</file>
@@ -42,7 +42,7 @@
HSTS with no t-dot host name in URL but t-dot in file
</name>
<command>
--x http://%HOSTIP:%HTTPPORT http://this.hsts.example/%TESTNUMBER --hsts log/input%TESTNUMBER -w '%{url_effective}\n'
+-x http://%HOSTIP:%HTTPPORT http://this.hsts.example/%TESTNUMBER --hsts %LOGDIR/input%TESTNUMBER -w '%{url_effective}\n'
</command>
</client>
diff --git a/tests/data/test442 b/tests/data/test442
index 1b00d20..2787c02 100644
--- a/tests/data/test442
+++ b/tests/data/test442
@@ -1,3 +1,4 @@
+<testcase>
# perl:
#
# for(1 .. 151) {
@@ -6,11 +7,11 @@
# "name$_", "could-be-large-$_")."\n";
# }
#
-<testcase>
<info>
<keywords>
HTTP
cookies
+--resolve
</keywords>
</info>
@@ -37,9 +38,9 @@
Send capped huge number of matching cookies
</name>
<command>
-http://attack.invalid:%HTTPPORT/a/b/%TESTNUMBER -b log/cookie%TESTNUMBER --resolve attack.invalid:%HTTPPORT:%HOSTIP -L
+http://attack.invalid:%HTTPPORT/a/b/%TESTNUMBER -b %LOGDIR/cookie%TESTNUMBER --resolve attack.invalid:%HTTPPORT:%HOSTIP -L
</command>
-<file name="log/cookie%TESTNUMBER" mode="text">
+<file name="%LOGDIR/cookie%TESTNUMBER" mode="text">
attack.invalid TRUE / FALSE 0 name1 could-be-large-1
attack.invalid TRUE / FALSE 0 name2 could-be-large-2
attack.invalid TRUE / FALSE 0 name3 could-be-large-3
@@ -192,6 +193,9 @@
attack.invalid TRUE / FALSE 0 name150 could-be-large-150
attack.invalid TRUE / FALSE 0 name151 could-be-large-151
</file>
+<features>
+cookies
+</features>
</client>
#
diff --git a/tests/data/test443 b/tests/data/test443
index 996b1d3..975d8fd 100644
--- a/tests/data/test443
+++ b/tests/data/test443
@@ -1,3 +1,4 @@
+<testcase>
# perl:
#
#for(1 .. 20) {
@@ -6,11 +7,11 @@
# "huge-$_", ('a' x 500)."-$_")."\n";
#}
#
-<testcase>
<info>
<keywords>
HTTP
cookies
+--resolve
</keywords>
</info>
@@ -37,9 +38,9 @@
Cookie header in request no longer than 8K
</name>
<command>
-http://attack.invalid:%HTTPPORT/a/b/%TESTNUMBER -b log/cookie%TESTNUMBER --resolve attack.invalid:%HTTPPORT:%HOSTIP -L
+http://attack.invalid:%HTTPPORT/a/b/%TESTNUMBER -b %LOGDIR/cookie%TESTNUMBER --resolve attack.invalid:%HTTPPORT:%HOSTIP -L
</command>
-<file name="log/cookie%TESTNUMBER" mode="text">
+<file name="%LOGDIR/cookie%TESTNUMBER" mode="text">
attack.invalid TRUE / FALSE 0 huge-1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-1
attack.invalid TRUE / FALSE 0 huge-2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-2
attack.invalid TRUE / FALSE 0 huge-3 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-3
@@ -61,6 +62,9 @@
attack.invalid TRUE / FALSE 0 huge-19 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-19
attack.invalid TRUE / FALSE 0 huge-20 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-20
</file>
+<features>
+cookies
+</features>
</client>
#
diff --git a/tests/data/test444 b/tests/data/test444
index 9bdd4a7..8df9902 100644
--- a/tests/data/test444
+++ b/tests/data/test444
@@ -1,14 +1,15 @@
+<testcase>
# perl:
#
#for(1 .. 200) {
#
#}
#
-<testcase>
<info>
<keywords>
HTTP
cookies
+--resolve
</keywords>
</info>
@@ -115,8 +116,11 @@
Many Set-Cookie response headers
</name>
<command>
-http://attack.invalid:%HTTPPORT/a/b/%TESTNUMBER -c log/cookie%TESTNUMBER --resolve attack.invalid:%HTTPPORT:%HOSTIP
+http://attack.invalid:%HTTPPORT/a/b/%TESTNUMBER -c %LOGDIR/cookie%TESTNUMBER --resolve attack.invalid:%HTTPPORT:%HOSTIP
</command>
+<features>
+cookies
+</features>
</client>
#
@@ -129,7 +133,7 @@
Accept: */*
</protocol>
-<file name="log/cookie%TESTNUMBER" mode="text">
+<file name="%LOGDIR/cookie%TESTNUMBER" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test445 b/tests/data/test445
new file mode 100644
index 0000000..0406c0f
--- /dev/null
+++ b/tests/data/test445
@@ -0,0 +1,61 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP proxy
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<connect>
+HTTP/1.1 503 no just no
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+
+-foo-
+</connect>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+gopher
+dict
+http
+ftp
+imap
+ldap
+mqtt
+pop3
+rtsp
+scp
+sftp
+smb
+smtp
+</features>
+<server>
+http-proxy
+</server>
+ <name>
+Refuse tunneling protocols through HTTP proxy
+ </name>
+ <command>
+-x http://%HOSTIP:%PROXYPORT/%TESTNUMBER -p gopher://127.0.0.1 dict://127.0.0.1 http://moo https://example telnet://another ftp://yes ftps://again imap://more ldap://perhaps mqtt://yes pop3://mail rtsp://harder scp://copy sftp://files smb://wird smtp://send
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# refused in the CONNECT
+<errorcode>
+56
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test446 b/tests/data/test446
new file mode 100644
index 0000000..b8e719d
--- /dev/null
+++ b/tests/data/test446
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP proxy
+HSTS
+trailing-dot
+</keywords>
+</info>
+
+<reply>
+
+# we use this as response to a CONNECT
+<connect nocheck="yes">
+HTTP/1.1 200 OK
+
+</connect>
+<data crlf="yes">
+HTTP/1.1 200 OK
+Content-Length: 6
+Strict-Transport-Security: max-age=604800
+
+-foo-
+</data>
+<data2 crlf="yes">
+HTTP/1.1 200 OK
+Content-Length: 6
+Strict-Transport-Security: max-age=6048000
+
+-baa-
+</data2>
+</reply>
+
+<client>
+<server>
+https
+http-proxy
+</server>
+<features>
+HSTS
+proxy
+https
+debug
+</features>
+<setenv>
+CURL_HSTS_HTTP=yes
+CURL_TIME=2000000000
+</setenv>
+
+<name>
+HSTS with two URLs
+</name>
+<command>
+-x http://%HOSTIP:%PROXYPORT --hsts %LOGDIR/hsts%TESTNUMBER http://this.hsts.example./%TESTNUMBER http://another.example.com/%TESTNUMBER0002
+</command>
+</client>
+
+<verify>
+# we let it CONNECT to the server to confirm HSTS but deny from there
+<proxy crlf="yes">
+GET http://this.hsts.example./%TESTNUMBER HTTP/1.1
+Host: this.hsts.example.
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+GET http://another.example.com/%TESTNUMBER0002 HTTP/1.1
+Host: another.example.com
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</proxy>
+
+<file name="%LOGDIR/hsts%TESTNUMBER" mode="text">
+# Your HSTS cache. https://curl.se/docs/hsts.html
+# This file was generated by libcurl! Edit at your own risk.
+this.hsts.example "20330525 03:33:20"
+another.example.com "20330727 03:33:20"
+</file>
+
+</verify>
+</testcase>
diff --git a/tests/data/test447 b/tests/data/test447
new file mode 100644
index 0000000..f514a13
--- /dev/null
+++ b/tests/data/test447
@@ -0,0 +1,65 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP PUT
+growing file
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+debug
+</features>
+<server>
+http
+</server>
+<name>
+HTTP PUT with growing file
+</name>
+<setenv>
+CURL_UPLOAD_SIZE=498
+</setenv>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER
+</command>
+<file name="%LOGDIR/upload%TESTNUMBER">
+%repeat[100 x hello]%
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes" nonewline="yes">
+PUT /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Content-Length: 498
+
+%repeat[99 x hello]%hel
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test46 b/tests/data/test46
index 91e24cb..d36787d 100644
--- a/tests/data/test46
+++ b/tests/data/test46
@@ -43,9 +43,9 @@
TZ=GMT
</setenv>
<command>
-domain..tld:%HTTPPORT/want/%TESTNUMBER --resolve domain..tld:%HTTPPORT:%HOSTIP -c log/jar%TESTNUMBER -b log/injar%TESTNUMBER
+domain..tld:%HTTPPORT/want/%TESTNUMBER --resolve domain..tld:%HTTPPORT:%HOSTIP -c %LOGDIR/jar%TESTNUMBER -b %LOGDIR/injar%TESTNUMBER
</command>
-<file name="log/injar%TESTNUMBER">
+<file name="%LOGDIR/injar%TESTNUMBER">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This is generated by libcurl! Do not edit.
@@ -56,6 +56,9 @@
#HttpOnly_domain..tld FALSE /want FALSE 2139150993 mooo2 indeed2
domain..tld FALSE /want FALSE 0 empty
</file>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
@@ -68,7 +71,7 @@
Cookie: empty=; mooo2=indeed2; mooo=indeed
</protocol>
-<file name="log/jar%TESTNUMBER" mode="text">
+<file name="%LOGDIR/jar%TESTNUMBER" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test490 b/tests/data/test490
index 2d4cf16..e94ea0d 100644
--- a/tests/data/test490
+++ b/tests/data/test490
@@ -35,9 +35,9 @@
Two globbed HTTP PUTs
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T '{log/in%TESTNUMBER,log/in%TESTNUMBER}'
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T '{%LOGDIR/in%TESTNUMBER,%LOGDIR/in%TESTNUMBER}'
</command>
-<file name="log/in%TESTNUMBER">
+<file name="%LOGDIR/in%TESTNUMBER">
surprise!
</file>
</client>
@@ -51,7 +51,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 10
-Expect: 100-continue
surprise!
PUT /%TESTNUMBER HTTP/1.1
@@ -59,7 +58,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 10
-Expect: 100-continue
surprise!
</protocol>
diff --git a/tests/data/test491 b/tests/data/test491
index 5f2c27d..a3c93aa 100644
--- a/tests/data/test491
+++ b/tests/data/test491
@@ -35,9 +35,9 @@
Two globbed HTTP PUTs, the second upload file is missing
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T '{log/in%TESTNUMBER,log/bad%TESTNUMBER}'
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T '{%LOGDIR/in%TESTNUMBER,%LOGDIR/bad%TESTNUMBER}'
</command>
-<file name="log/in%TESTNUMBER">
+<file name="%LOGDIR/in%TESTNUMBER">
surprise!
</file>
</client>
@@ -51,7 +51,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 10
-Expect: 100-continue
surprise!
</protocol>
diff --git a/tests/data/test492 b/tests/data/test492
index aedaf5b..dcf18eb 100644
--- a/tests/data/test492
+++ b/tests/data/test492
@@ -35,12 +35,12 @@
Two globbed HTTP PUTs to two globbed URLs
</name>
<command>
-'http://%HOSTIP:%HTTPPORT/{one,two}/' -T '{log/first%TESTNUMBER,log/second%TESTNUMBER}' -H "Testno: %TESTNUMBER"
+'http://%HOSTIP:%HTTPPORT/{one,two}/' -T '{%LOGDIR/first%TESTNUMBER,%LOGDIR/second%TESTNUMBER}' -H "Testno: %TESTNUMBER"
</command>
-<file name="log/first%TESTNUMBER">
+<file name="%LOGDIR/first%TESTNUMBER">
first %TESTNUMBER contents
</file>
-<file1 name="log/second%TESTNUMBER">
+<file1 name="%LOGDIR/second%TESTNUMBER">
second %TESTNUMBER contents
</file1>
</client>
@@ -55,7 +55,6 @@
Accept: */*
Testno: %TESTNUMBER
Content-Length: 19
-Expect: 100-continue
first %TESTNUMBER contents
PUT /two/first%TESTNUMBER HTTP/1.1
@@ -64,7 +63,6 @@
Accept: */*
Testno: %TESTNUMBER
Content-Length: 19
-Expect: 100-continue
first %TESTNUMBER contents
PUT /one/second%TESTNUMBER HTTP/1.1
@@ -73,7 +71,6 @@
Accept: */*
Testno: %TESTNUMBER
Content-Length: 20
-Expect: 100-continue
second %TESTNUMBER contents
PUT /two/second%TESTNUMBER HTTP/1.1
@@ -82,7 +79,6 @@
Accept: */*
Testno: %TESTNUMBER
Content-Length: 20
-Expect: 100-continue
second %TESTNUMBER contents
</protocol>
diff --git a/tests/data/test493 b/tests/data/test493
index f0c4110..1a677d3 100644
--- a/tests/data/test493
+++ b/tests/data/test493
@@ -33,7 +33,7 @@
https
</features>
-<file name="log/input%TESTNUMBER">
+<file name="%LOGDIR/input%TESTNUMBER">
.hsts.example "99991001 04:47:41"
</file>
@@ -41,7 +41,7 @@
HSTS and %{url_effective} after upgrade
</name>
<command>
--x http://%HOSTIP:%HTTPPORT http://this.hsts.example/%TESTNUMBER --hsts log/input%TESTNUMBER -w '%{url_effective}\n'
+-x http://%HOSTIP:%HTTPPORT http://this.hsts.example/%TESTNUMBER --hsts %LOGDIR/input%TESTNUMBER -w '%{url_effective}\n'
</command>
</client>
diff --git a/tests/data/test494 b/tests/data/test494
index 4417446..78faab6 100644
--- a/tests/data/test494
+++ b/tests/data/test494
@@ -25,9 +25,9 @@
skip 'macdef' when parsing netrc
</name>
<command>
---netrc --netrc-file log/netrc%TESTNUMBER ftp://%HOSTIP:%FTPPORT/%TESTNUMBER
+--netrc --netrc-file %LOGDIR/netrc%TESTNUMBER ftp://%HOSTIP:%FTPPORT/%TESTNUMBER
</command>
-<file name="log/netrc%TESTNUMBER" >
+<file name="%LOGDIR/netrc%TESTNUMBER" >
macdef testmacro
bin
diff --git a/tests/data/test495 b/tests/data/test495
new file mode 100644
index 0000000..deba48a
--- /dev/null
+++ b/tests/data/test495
@@ -0,0 +1,56 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+netrc
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+user+password in URL with optional netrc
+</name>
+# the key is the URL encoded user, which needs to be sent encoded in the
+# Authorization: header
+<command>
+http://foo%40bar:secret@%HOSTIP:%HTTPPORT/%TESTNUMBER --netrc-optional
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic Zm9vQGJhcjpzZWNyZXQ=
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test496 b/tests/data/test496
new file mode 100644
index 0000000..19050f3
--- /dev/null
+++ b/tests/data/test496
@@ -0,0 +1,36 @@
+<testcase>
+<info>
+<keywords>
+curl tool
+cmdline
+parallel
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<name>
+parallel upload missing file
+</name>
+ <command>
+0 -Z -Tz
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+26
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test500 b/tests/data/test500
index 514d0b9..384de1b 100644
--- a/tests/data/test500
+++ b/tests/data/test500
@@ -38,14 +38,14 @@
simple libcurl HTTP GET tool
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER log/ip%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/ip%TESTNUMBER
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
-<file name="log/ip%TESTNUMBER">
+<file name="%LOGDIR/ip%TESTNUMBER">
IP %HOSTIP
</file>
<protocol>
diff --git a/tests/data/test502 b/tests/data/test502
index 1121257..4a6d60f 100644
--- a/tests/data/test502
+++ b/tests/data/test502
@@ -30,9 +30,9 @@
simple multi file:// get
</name>
<command>
-file://%PWD/log/test%TESTNUMBER.txt
+file://%PWD/%LOGDIR/test%TESTNUMBER.txt
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar swsclose
bar
diff --git a/tests/data/test503 b/tests/data/test503
index 1ad7a55..d8e04aa 100644
--- a/tests/data/test503
+++ b/tests/data/test503
@@ -59,7 +59,7 @@
<command>
http://machine.%TESTNUMBER:%HTTPPORT/%TESTNUMBER %HOSTIP:%PROXYPORT
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo
bar
bar
@@ -76,6 +76,7 @@
Proxy-Authorization: Basic dGVzdDppbmc=
Proxy-Connection: Keep-Alive
+[DISCONNECT]
</proxy>
<protocol>
GET /%TESTNUMBER HTTP/1.1
diff --git a/tests/data/test505 b/tests/data/test505
index 13ddc62..0343706 100644
--- a/tests/data/test505
+++ b/tests/data/test505
@@ -23,9 +23,9 @@
FTP upload with rename after transfer
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER log/upload%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER %LOGDIR/upload%TESTNUMBER
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Contents
of
a file
diff --git a/tests/data/test506 b/tests/data/test506
index 44f3afd..30d4c62 100644
--- a/tests/data/test506
+++ b/tests/data/test506
@@ -74,7 +74,7 @@
lib%TESTNUMBER
</tool>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/jar%TESTNUMBER
</command>
</client>
@@ -233,7 +233,7 @@
unlock: share [Pigs in space]: 99
GLOBAL_CLEANUP
</stdout>
-<file name="log/jar%TESTNUMBER" mode="text">
+<file name="%LOGDIR/jar%TESTNUMBER" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test511 b/tests/data/test511
index 994907a..6bcf25d 100644
--- a/tests/data/test511
+++ b/tests/data/test511
@@ -44,6 +44,8 @@
PASS ftp@example.com
PWD
MDTM %TESTNUMBER
+TYPE I
+SIZE %TESTNUMBER
QUIT
</protocol>
</verify>
diff --git a/tests/data/test516 b/tests/data/test516
index c441cfb..a47b051 100644
--- a/tests/data/test516
+++ b/tests/data/test516
@@ -21,6 +21,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -30,7 +33,7 @@
</tool>
<name>
-make a HTTPPOST set to NULL
+make an HTTPPOST set to NULL
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER
diff --git a/tests/data/test525 b/tests/data/test525
index ce37399..43e5728 100644
--- a/tests/data/test525
+++ b/tests/data/test525
@@ -26,9 +26,9 @@
FTP PORT upload using multi interface
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER log/upload%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER %LOGDIR/upload%TESTNUMBER
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Moooooooooooo
upload this
</file>
diff --git a/tests/data/test529 b/tests/data/test529
index 141166c..9c2bc50 100644
--- a/tests/data/test529
+++ b/tests/data/test529
@@ -26,9 +26,9 @@
FTP PORT upload using multi interface (weird cleanup function sequence)
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER log/upload%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER %LOGDIR/upload%TESTNUMBER
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Moooooooooooo
upload this
</file>
diff --git a/tests/data/test53 b/tests/data/test53
index e3b9ec9..d5997f5 100644
--- a/tests/data/test53
+++ b/tests/data/test53
@@ -29,13 +29,16 @@
HTTP, junk session cookies
</name>
<command>
-%HOSTIP:%HTTPPORT/want/%TESTNUMBER -b log/injar%TESTNUMBER -j
+%HOSTIP:%HTTPPORT/want/%TESTNUMBER -b %LOGDIR/injar%TESTNUMBER -j
</command>
-<file name="log/injar%TESTNUMBER">
+<file name="%LOGDIR/injar%TESTNUMBER">
%HOSTIP FALSE / FALSE 2139150993 mooo indeed
%HOSTIP FALSE / FALSE 0 moo1 indeed
%HOSTIP FALSE / FALSE 1 moo2 indeed
</file>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
diff --git a/tests/data/test531 b/tests/data/test531
index 17ccf68..3463613 100644
--- a/tests/data/test531
+++ b/tests/data/test531
@@ -29,9 +29,9 @@
FTP PORT upload using multi interface and get 425 response
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER log/upload%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER %LOGDIR/upload%TESTNUMBER
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Moooooooooooo
don't upload this
</file>
diff --git a/tests/data/test541 b/tests/data/test541
index 2dc75f8..fbcfeb4 100644
--- a/tests/data/test541
+++ b/tests/data/test541
@@ -23,9 +23,9 @@
FTP upload and upload same file again without rewind
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER log/upload%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER %LOGDIR/upload%TESTNUMBER
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Contents
of
a file
diff --git a/tests/data/test554 b/tests/data/test554
index 8488be6..cee6164 100644
--- a/tests/data/test554
+++ b/tests/data/test554
@@ -38,6 +38,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test558 b/tests/data/test558
index 6df7988..06b7728 100644
--- a/tests/data/test558
+++ b/tests/data/test558
@@ -35,7 +35,7 @@
#
# Verify data after the test has been "shot"
<verify>
-<file name="log/memdump">
+<file name="%LOGDIR/memdump">
MEM easy.c: malloc()
MEM lib%TESTNUMBER.c: malloc()
MEM lib%TESTNUMBER.c: free()
diff --git a/tests/data/test566 b/tests/data/test566
index 09144f5..1fc3968 100644
--- a/tests/data/test566
+++ b/tests/data/test566
@@ -37,14 +37,14 @@
HTTP GET with CURLINFO_CONTENT_LENGTH_DOWNLOAD and 0 bytes transfer
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER log/ip%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/ip%TESTNUMBER
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
-<file name="log/ip%TESTNUMBER">
+<file name="%LOGDIR/ip%TESTNUMBER">
CL 0
</file>
<protocol>
diff --git a/tests/data/test568 b/tests/data/test568
index 7dd23ca..700fd44 100644
--- a/tests/data/test568
+++ b/tests/data/test568
@@ -58,10 +58,10 @@
RTSP Announce (PUT and POST style) test
</name>
<command>
-rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER
+rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER %LOGDIR/file%TESTNUMBER.txt
</command>
# file written before test command runs
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
v=0
o=mhandley 2890844526 2890845468 IN IP4 126.16.64.4
s=SDP Seminar
diff --git a/tests/data/test569 b/tests/data/test569
index 043c244..b70e908 100644
--- a/tests/data/test569
+++ b/tests/data/test569
@@ -66,7 +66,7 @@
RTSP Session ID parsing
</name>
<command>
-rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER log/idfile%TESTNUMBER.txt
+rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER %LOGDIR/idfile%TESTNUMBER.txt
</command>
</client>
@@ -100,7 +100,7 @@
Session: A
</protocol>
-<file name="log/idfile%TESTNUMBER.txt">
+<file name="%LOGDIR/idfile%TESTNUMBER.txt">
Got Session ID: [00.+1-am-aSe55ion_id\$yes-i-am\$]
Got Session ID: [\$extraspaces]
Got Session ID: [A]
diff --git a/tests/data/test57 b/tests/data/test57
index f379d74..70b219d 100644
--- a/tests/data/test57
+++ b/tests/data/test57
@@ -26,7 +26,7 @@
HTTP content-type with spaces in
</name>
<command>
--w "%{content_type}\n" http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o log/out%TESTNUMBER
+-w "%{content_type}\n" http://%HOSTIP:%HTTPPORT/%TESTNUMBER -o %LOGDIR/out%TESTNUMBER
</command>
</client>
diff --git a/tests/data/test571 b/tests/data/test571
index 3cc1b98..bae97d4 100644
--- a/tests/data/test571
+++ b/tests/data/test571
@@ -19,6 +19,7 @@
Server: RTSPD/libcurl-test
Session: asdf
CSeq: 1
+Transport: RTP/AVP/TCP;unicast;interleaved=0-1
</data1>
@@ -54,6 +55,7 @@
rtp: part 2 channel 0 size 196
rtp: part 2 channel 0 size 124
rtp: part 2 channel 0 size 824
+rtp: part 2 channel 0 size 18 size_err -6
rtp: part 3 channel 1 size 10
rtp: part 3 channel 0 size 50
rtp: part 4 channel 0 size 798
@@ -62,6 +64,12 @@
rtp: part 4 channel 0 size 2048
rtp: part 4 channel 0 size 85
rtp: part 4 channel 1 size 24
+rtp: part 4 channel 0 size 17 size_err -4
+rtp: part 4 channel 0 size 33
+rtp: part 4 channel 0 size 127
+rtp: part 4 channel 1 size 24 size_err 11
+rtp: part 4 channel 0 size 37
+rtp: part 4 channel 0 size 63
</servercmd>
</reply>
@@ -78,7 +86,7 @@
RTSP RTP Interleaving Test
</name>
<command>
-rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER log/protofile%TESTNUMBER.txt
+rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER %LOGDIR/protofile%TESTNUMBER.txt
</command>
</client>
@@ -89,6 +97,7 @@
RTP: message size 196, channel 0
RTP: message size 124, channel 0
RTP: message size 824, channel 0
+RTP: message size 12, channel 0
RTP: message size 10, channel 1
RTP: message size 50, channel 0
RTP: message size 798, channel 0
@@ -97,9 +106,15 @@
RTP: message size 2048, channel 0
RTP: message size 85, channel 0
RTP: message size 24, channel 1
+RTP: message size 13, channel 0
+RTP: message size 33, channel 0
+RTP: message size 127, channel 0
+RTP: message size 35, channel 1
+RTP PAYLOAD END CORRUPTED (11), [$]
+RTP: message size 63, channel 0
</stdout>
-<file name="log/protofile%TESTNUMBER.txt">
+<file name="%LOGDIR/protofile%TESTNUMBER.txt">
$99
</file>
</verify>
diff --git a/tests/data/test572 b/tests/data/test572
index 0a47055..4ac86bc 100644
--- a/tests/data/test572
+++ b/tests/data/test572
@@ -73,10 +73,10 @@
RTSP GET_PARAMETER (Put/Heartbeat/Post)
</name>
<command>
-rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER
+rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER %LOGDIR/file%TESTNUMBER.txt
</command>
# file written before test command runs
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
scale
speed
</file>
diff --git a/tests/data/test578 b/tests/data/test578
index 2ff8a1f..9bce581 100644
--- a/tests/data/test578
+++ b/tests/data/test578
@@ -38,14 +38,14 @@
HTTP POST lower than MAX_INITIAL_POST_SIZE with progress callback
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER log/ip%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/ip%TESTNUMBER
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
-<file name="log/ip%TESTNUMBER">
+<file name="%LOGDIR/ip%TESTNUMBER">
PASSED, UL data matched data size
</file>
</verify>
diff --git a/tests/data/test579 b/tests/data/test579
index e4b072b..3a532d8 100644
--- a/tests/data/test579
+++ b/tests/data/test579
@@ -68,14 +68,14 @@
small chunked HTTP POSTs with digest auth. and progress callback
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER log/ip%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/ip%TESTNUMBER
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
-<file name="log/ip%TESTNUMBER">
+<file name="%LOGDIR/ip%TESTNUMBER">
Progress callback called with UL 0 out of 0
Progress callback called with UL 8 out of 0
Progress callback called with UL 16 out of 0
diff --git a/tests/data/test58 b/tests/data/test58
index 01d7189..e68cca9 100644
--- a/tests/data/test58
+++ b/tests/data/test58
@@ -26,9 +26,9 @@
HTTP PUT from file with weird letters
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/ -T log/%TESTNUMBERte[]st.txt -g
+http://%HOSTIP:%HTTPPORT/we/want/ -T %LOGDIR/%TESTNUMBERte[]st.txt -g
</command>
-<file name="log/%TESTNUMBERte[]st.txt">
+<file name="%LOGDIR/%TESTNUMBERte[]st.txt">
a few bytes
</file>
</client>
@@ -36,12 +36,11 @@
# Verify data after the test has been "shot"
<verify>
<protocol>
-PUT /we/want/%TESTNUMBERte%5B%5Dst.txt HTTP/1.1
+PUT /we/want/%TESTNUMBERte%5b%5dst.txt HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 12
-Expect: 100-continue
a few bytes
</protocol>
diff --git a/tests/data/test582 b/tests/data/test582
index ddf17e3..f626d0b 100644
--- a/tests/data/test582
+++ b/tests/data/test582
@@ -24,9 +24,9 @@
SFTP upload using multi interface
</name>
<command>
-Sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/upload%TESTNUMBER.txt %PWD/log/file%TESTNUMBER.txt %USER:
+Sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/upload%TESTNUMBER.txt %PWD/%LOGDIR/file%TESTNUMBER.txt %USER: %LOGDIR/server/curl_client_key.pub %LOGDIR/server/curl_client_key
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Moooooooooooo
upload this
</file>
@@ -41,7 +41,7 @@
</strip>
<protocol>
</protocol>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Moooooooooooo
upload this
</file>
diff --git a/tests/data/test583 b/tests/data/test583
index 029cdac..51e435c 100644
--- a/tests/data/test583
+++ b/tests/data/test583
@@ -29,7 +29,7 @@
# name resolve will cause it to return rather quickly and thus we could trigger
# the problem we're looking to verify.
<command>
-sftp://localhost:%SSHPORT%SSH_PWD/log/upload%TESTNUMBER.txt %USER:
+sftp://localhost:%SSHPORT%SSH_PWD/%LOGDIR/upload%TESTNUMBER.txt %USER: %LOGDIR/server/curl_client_key.pub %LOGDIR/server/curl_client_key
</command>
</client>
diff --git a/tests/data/test584 b/tests/data/test584
index fb23444..7a7d249 100644
--- a/tests/data/test584
+++ b/tests/data/test584
@@ -36,6 +36,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test587 b/tests/data/test587
index a40e4bf..6af7d99 100644
--- a/tests/data/test587
+++ b/tests/data/test587
@@ -16,6 +16,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test588 b/tests/data/test588
index 1eb262f..d36bafe 100644
--- a/tests/data/test588
+++ b/tests/data/test588
@@ -35,9 +35,9 @@
FTP PORT upload using multi interface, EPRT doesn't work
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER log/upload%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER %LOGDIR/upload%TESTNUMBER
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Moooooooooooo
upload this
</file>
diff --git a/tests/data/test589 b/tests/data/test589
index 02fe543..beafaa7 100644
--- a/tests/data/test589
+++ b/tests/data/test589
@@ -22,6 +22,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -31,7 +34,7 @@
</tool>
<name>
-make a HTTP MIME POST set to NULL
+make an HTTP MIME POST set to NULL
</name>
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER
diff --git a/tests/data/test591 b/tests/data/test591
index 843ddb3..5286601 100644
--- a/tests/data/test591
+++ b/tests/data/test591
@@ -37,9 +37,9 @@
FTP multi PORT and 425 on upload
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER %FTPTIME2 log/upload%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER %FTPTIME2 %LOGDIR/upload%TESTNUMBER
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Moooooooooooo for %TESTNUMBER
upload this
</file>
diff --git a/tests/data/test592 b/tests/data/test592
index fc9f15d..e3a9147 100644
--- a/tests/data/test592
+++ b/tests/data/test592
@@ -37,9 +37,9 @@
FTP multi PORT and 421 on upload
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER %FTPTIME2 log/upload%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER %FTPTIME2 %LOGDIR/upload%TESTNUMBER
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Moooooooooooo for %TESTNUMBER
upload this
</file>
diff --git a/tests/data/test593 b/tests/data/test593
index 47c1d94..53a884a 100644
--- a/tests/data/test593
+++ b/tests/data/test593
@@ -37,9 +37,9 @@
FTP multi PORT upload, no data conn and no transient neg. reply
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER %FTPTIME2 log/upload%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER %FTPTIME2 %LOGDIR/upload%TESTNUMBER
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Moooooooooooo for %TESTNUMBER
upload this
</file>
diff --git a/tests/data/test594 b/tests/data/test594
index 5a46450..dab3506 100644
--- a/tests/data/test594
+++ b/tests/data/test594
@@ -12,6 +12,8 @@
multi
EPRT refused
NODATACONN
+timeout
+FAILURE
</keywords>
</info>
@@ -37,9 +39,9 @@
FTP multi PORT upload, no data conn and no positive prelim. reply
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER %FTPTIME2 log/upload%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/path/%TESTNUMBER %FTPTIME2 %LOGDIR/upload%TESTNUMBER
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Moooooooooooo for %TESTNUMBER
upload this
</file>
diff --git a/tests/data/test595 b/tests/data/test595
index 4d2f62b..f979746 100644
--- a/tests/data/test595
+++ b/tests/data/test595
@@ -36,7 +36,7 @@
verify close callbacks with passive FTP
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER log/ip%TESTNUMBER
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER %LOGDIR/ip%TESTNUMBER
</command>
</client>
diff --git a/tests/data/test596 b/tests/data/test596
index 64bd52b..27d5d84 100644
--- a/tests/data/test596
+++ b/tests/data/test596
@@ -36,7 +36,7 @@
verify close callbacks with active FTP
</name>
<command>
-ftp://%HOSTIP:%FTPPORT/%TESTNUMBER log/ip%TESTNUMBER activeftp
+ftp://%HOSTIP:%FTPPORT/%TESTNUMBER %LOGDIR/ip%TESTNUMBER activeftp
</command>
</client>
diff --git a/tests/data/test598 b/tests/data/test598
index 5e52315..a000dca 100644
--- a/tests/data/test598
+++ b/tests/data/test598
@@ -58,6 +58,9 @@
<command>
http://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
+<features>
+cookies
+</features>
</client>
#
diff --git a/tests/data/test599 b/tests/data/test599
index 5911b96..9ca266a 100644
--- a/tests/data/test599
+++ b/tests/data/test599
@@ -72,14 +72,14 @@
HTTP GET with progress callback and redirects changing content sizes
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER log/ip%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/ip%TESTNUMBER
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
-<file name="log/ip%TESTNUMBER">
+<file name="%LOGDIR/ip%TESTNUMBER">
CL -1
</file>
</verify>
diff --git a/tests/data/test6 b/tests/data/test6
index d8231cb..6e83125 100644
--- a/tests/data/test6
+++ b/tests/data/test6
@@ -31,6 +31,9 @@
<command>
http://%HOSTIP:%HTTPPORT/we/want/that/page/%TESTNUMBER -b "name=contents;name2=content2" -b name3=content3
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
diff --git a/tests/data/test600 b/tests/data/test600
index 88a6055..d110ad1 100644
--- a/tests/data/test600
+++ b/tests/data/test600
@@ -24,9 +24,9 @@
SFTP retrieval
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test601 b/tests/data/test601
index cadeeaf..73428de 100644
--- a/tests/data/test601
+++ b/tests/data/test601
@@ -24,9 +24,9 @@
SCP retrieval
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test602 b/tests/data/test602
index 56d2747..2c89659 100644
--- a/tests/data/test602
+++ b/tests/data/test602
@@ -21,9 +21,9 @@
SFTP put
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/upload.%TESTNUMBER --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -T %LOGDIR/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/upload.%TESTNUMBER --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh upload test
</file>
diff --git a/tests/data/test603 b/tests/data/test603
index b873f15..7aa20a9 100644
--- a/tests/data/test603
+++ b/tests/data/test603
@@ -21,9 +21,9 @@
SCP upload
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file%TESTNUMBER.txt scp://%HOSTIP:%SSHPORT%SSH_PWD/log/upload.%TESTNUMBER --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -T %LOGDIR/file%TESTNUMBER.txt scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/upload.%TESTNUMBER --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh upload test
</file>
diff --git a/tests/data/test604 b/tests/data/test604
index f503e66..14d7933 100644
--- a/tests/data/test604
+++ b/tests/data/test604
@@ -16,7 +16,7 @@
SFTP retrieval of nonexistent file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure
</command>
</client>
diff --git a/tests/data/test605 b/tests/data/test605
index 29555fa..5c9a266 100644
--- a/tests/data/test605
+++ b/tests/data/test605
@@ -16,7 +16,7 @@
SCP retrieval of nonexistent file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure
</command>
</client>
diff --git a/tests/data/test606 b/tests/data/test606
index c790bd6..9276411 100644
--- a/tests/data/test606
+++ b/tests/data/test606
@@ -16,7 +16,7 @@
SFTP invalid user login
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u not-a-valid-user: sftp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u not-a-valid-user: sftp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure
</command>
</client>
diff --git a/tests/data/test607 b/tests/data/test607
index 8c13e58..317f56b 100644
--- a/tests/data/test607
+++ b/tests/data/test607
@@ -16,7 +16,7 @@
SCP invalid user login
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u not-a-valid-user: scp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u not-a-valid-user: scp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure
</command>
</client>
diff --git a/tests/data/test608 b/tests/data/test608
index f919e9c..5b0bf19 100644
--- a/tests/data/test608
+++ b/tests/data/test608
@@ -24,14 +24,14 @@
SFTP post-quote rename
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-rename %PWD/log/file%TESTNUMBER.txt %PWD/log/file%TESTNUMBER-renamed.txt" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -Q "-rename %PWD/%LOGDIR/file%TESTNUMBER.txt %PWD/%LOGDIR/file%TESTNUMBER-renamed.txt" sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
# Verify that the file was renamed properly, then rename the file back to what
# it was so the verify section works and the file can be cleaned up.
<postcheck>
-perl %SRCDIR/libtest/test610.pl gone %PWD/log/file%TESTNUMBER.txt move %PWD/log/file%TESTNUMBER-renamed.txt %PWD/log/file%TESTNUMBER.txt
+perl %SRCDIR/libtest/test610.pl gone %PWD/%LOGDIR/file%TESTNUMBER.txt move %PWD/%LOGDIR/file%TESTNUMBER-renamed.txt %PWD/%LOGDIR/file%TESTNUMBER.txt
</postcheck>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test file for rename test
</file>
</client>
@@ -39,7 +39,7 @@
#
# Verify data after the test has been "shot"
<verify>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test file for rename test
</file>
<valgrind>
diff --git a/tests/data/test609 b/tests/data/test609
index 66057d2..631aa62 100644
--- a/tests/data/test609
+++ b/tests/data/test609
@@ -25,9 +25,9 @@
SFTP post-quote mkdir failure
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-mkdir %PWD/log/file%TESTNUMBER.txt" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -Q "-mkdir %PWD/%LOGDIR/file%TESTNUMBER.txt" sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test file for mkdir test
</file>
</client>
diff --git a/tests/data/test61 b/tests/data/test61
index 6d98ba7..b1f53b1 100644
--- a/tests/data/test61
+++ b/tests/data/test61
@@ -45,8 +45,11 @@
TZ=GMT
</setenv>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -c log/jar%TESTNUMBER.txt -H "Host: www.host.foo.com"
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -c %LOGDIR/jar%TESTNUMBER.txt -H "Host: www.host.foo.com"
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
@@ -58,7 +61,7 @@
Accept: */*
</protocol>
-<file name="log/jar%TESTNUMBER.txt" mode="text">
+<file name="%LOGDIR/jar%TESTNUMBER.txt" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test610 b/tests/data/test610
index d9eb2e6..b3599a2 100644
--- a/tests/data/test610
+++ b/tests/data/test610
@@ -21,18 +21,18 @@
sftp
</server>
<precheck>
-perl %SRCDIR/libtest/test%TESTNUMBER.pl mkdir %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test%TESTNUMBER.pl mkdir %PWD/%LOGDIR/test%TESTNUMBER.dir
</precheck>
<name>
SFTP post-quote rmdir
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-rmdir %PWD/log/test%TESTNUMBER.dir" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -Q "-rmdir %PWD/%LOGDIR/test%TESTNUMBER.dir" sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
<postcheck>
-perl %SRCDIR/libtest/test%TESTNUMBER.pl gone %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test%TESTNUMBER.pl gone %PWD/%LOGDIR/test%TESTNUMBER.dir
</postcheck>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Dummy test file for rmdir test
</file>
</client>
diff --git a/tests/data/test611 b/tests/data/test611
index ee2a185..fd9f42f 100644
--- a/tests/data/test611
+++ b/tests/data/test611
@@ -21,18 +21,18 @@
sftp
</server>
<precheck>
-perl %SRCDIR/libtest/test610.pl mkdir %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test610.pl mkdir %PWD/%LOGDIR/test%TESTNUMBER.dir
</precheck>
<name>
SFTP post-quote rename
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-rename %PWD/log/test%TESTNUMBER.dir %PWD/log/test%TESTNUMBER.new" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -Q "-rename %PWD/%LOGDIR/test%TESTNUMBER.dir %PWD/%LOGDIR/test%TESTNUMBER.new" sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
<postcheck>
-perl %SRCDIR/libtest/test610.pl rmdir %PWD/log/test%TESTNUMBER.new
+perl %SRCDIR/libtest/test610.pl rmdir %PWD/%LOGDIR/test%TESTNUMBER.new
</postcheck>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Dummy test file for rename test
</file>
</client>
diff --git a/tests/data/test612 b/tests/data/test612
index 1d6fade..37ffc5c 100644
--- a/tests/data/test612
+++ b/tests/data/test612
@@ -24,12 +24,12 @@
SFTP post-quote remove file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file%TESTNUMBER.txt -Q "-rm %PWD/log/file%TESTNUMBER.txt" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/upload.%TESTNUMBER --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -T %LOGDIR/file%TESTNUMBER.txt -Q "-rm %PWD/%LOGDIR/file%TESTNUMBER.txt" sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/upload.%TESTNUMBER --insecure
</command>
<postcheck>
-perl %SRCDIR/libtest/test610.pl gone %PWD/log/test%TESTNUMBER.txt
+perl %SRCDIR/libtest/test610.pl gone %PWD/%LOGDIR/test%TESTNUMBER.txt
</postcheck>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Dummy test file for remove test
</file>
</client>
diff --git a/tests/data/test613 b/tests/data/test613
index d02e3bb..8a57ec6 100644
--- a/tests/data/test613
+++ b/tests/data/test613
@@ -23,16 +23,16 @@
sftp
</server>
<precheck>
-perl %SRCDIR/libtest/test%TESTNUMBER.pl prepare %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test%TESTNUMBER.pl prepare %PWD/%LOGDIR/test%TESTNUMBER.dir
</precheck>
<name>
SFTP directory retrieval
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test%TESTNUMBER.dir/ --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/test%TESTNUMBER.dir/ --insecure
</command>
<postcheck>
-perl %SRCDIR/libtest/test%TESTNUMBER.pl postprocess %PWD/log/test%TESTNUMBER.dir %PWD/log/curl%TESTNUMBER.out
+perl %SRCDIR/libtest/test%TESTNUMBER.pl postprocess %PWD/%LOGDIR/test%TESTNUMBER.dir %PWD/%LOGDIR/curl%TESTNUMBER.out
</postcheck>
</client>
diff --git a/tests/data/test614 b/tests/data/test614
index c0af263..d7b45a4 100644
--- a/tests/data/test614
+++ b/tests/data/test614
@@ -24,16 +24,16 @@
sftp
</server>
<precheck>
-perl %SRCDIR/libtest/test613.pl prepare %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test613.pl prepare %PWD/%LOGDIR/test%TESTNUMBER.dir
</precheck>
<name>
SFTP pre-quote chmod
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "chmod 444 %PWD/log/test%TESTNUMBER.dir/plainfile.txt" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test%TESTNUMBER.dir/ --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -Q "chmod 444 %PWD/%LOGDIR/test%TESTNUMBER.dir/plainfile.txt" sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/test%TESTNUMBER.dir/ --insecure
</command>
<postcheck>
-perl %SRCDIR/libtest/test613.pl postprocess %PWD/log/test%TESTNUMBER.dir %PWD/log/curl%TESTNUMBER.out
+perl %SRCDIR/libtest/test613.pl postprocess %PWD/%LOGDIR/test%TESTNUMBER.dir %PWD/%LOGDIR/curl%TESTNUMBER.out
</postcheck>
</client>
diff --git a/tests/data/test615 b/tests/data/test615
index 09a825b..d2ed914 100644
--- a/tests/data/test615
+++ b/tests/data/test615
@@ -14,18 +14,18 @@
sftp
</server>
<precheck>
-perl %SRCDIR/libtest/test613.pl prepare %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test613.pl prepare %PWD/%LOGDIR/test%TESTNUMBER.dir
</precheck>
<name>
SFTP put remote failure
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test%TESTNUMBER.dir/rofile.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -T %LOGDIR/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/test%TESTNUMBER.dir/rofile.txt --insecure
</command>
<postcheck>
-perl %SRCDIR/libtest/test613.pl postprocess %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test613.pl postprocess %PWD/%LOGDIR/test%TESTNUMBER.dir
</postcheck>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh upload test
</file>
diff --git a/tests/data/test616 b/tests/data/test616
index ec03c31..570f1fa 100644
--- a/tests/data/test616
+++ b/tests/data/test616
@@ -23,9 +23,9 @@
SFTP retrieval of empty file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
</file>
</client>
diff --git a/tests/data/test617 b/tests/data/test617
index 3c067e3..05c2989 100644
--- a/tests/data/test617
+++ b/tests/data/test617
@@ -23,9 +23,9 @@
SCP retrieval of empty file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
</file>
</client>
diff --git a/tests/data/test618 b/tests/data/test618
index f5e2c7b..1ffe464 100644
--- a/tests/data/test618
+++ b/tests/data/test618
@@ -15,9 +15,9 @@
SFTP retrieval of two files
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test619 b/tests/data/test619
index 0f86d8a..15309a2 100644
--- a/tests/data/test619
+++ b/tests/data/test619
@@ -15,9 +15,9 @@
SCP retrieval of two files
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test62 b/tests/data/test62
index 92396d9..0484e8c 100644
--- a/tests/data/test62
+++ b/tests/data/test62
@@ -29,9 +29,9 @@
HTTP, send cookies when using custom Host:
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER?hoge=fuga -b log/jar%TESTNUMBER.txt -H "Host: www.host.foo.com"
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER?hoge=fuga -b %LOGDIR/jar%TESTNUMBER.txt -H "Host: www.host.foo.com"
</command>
-<file name="log/jar%TESTNUMBER.txt">
+<file name="%LOGDIR/jar%TESTNUMBER.txt">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
@@ -42,6 +42,9 @@
.foo.com TRUE /moo TRUE 0 test3 maybe
</file>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
diff --git a/tests/data/test620 b/tests/data/test620
index fea44ac..2dd3587 100644
--- a/tests/data/test620
+++ b/tests/data/test620
@@ -16,9 +16,9 @@
SFTP retrieval of missing file followed by good file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/not-a-valid-file-moooo sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/not-a-valid-file-moooo sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test621 b/tests/data/test621
index 368baf6..0c65b13 100644
--- a/tests/data/test621
+++ b/tests/data/test621
@@ -16,9 +16,9 @@
SCP retrieval of missing file followed by good file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/not-a-valid-file-moooo scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/not-a-valid-file-moooo scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test622 b/tests/data/test622
index c4f8508..530bd22 100644
--- a/tests/data/test622
+++ b/tests/data/test622
@@ -22,9 +22,9 @@
SFTP put failure
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/nonexistent-directory/nonexistent-file --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -T %LOGDIR/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/nonexistent-directory/nonexistent-file --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh upload test
</file>
diff --git a/tests/data/test623 b/tests/data/test623
index d1afb40..794a251 100644
--- a/tests/data/test623
+++ b/tests/data/test623
@@ -22,9 +22,9 @@
SCP upload failure
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file%TESTNUMBER.txt scp://%HOSTIP:%SSHPORT%SSH_PWD/log/nonexistent-directory/nonexistent-file --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -T %LOGDIR/file%TESTNUMBER.txt scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/nonexistent-directory/nonexistent-file --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh upload test
</file>
diff --git a/tests/data/test624 b/tests/data/test624
index 8daa935..fa7225d 100644
--- a/tests/data/test624
+++ b/tests/data/test624
@@ -22,12 +22,12 @@
SFTP put with --ftp-create-dirs
</name>
<command>
---ftp-create-dirs --key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test%TESTNUMBER.dir/upload.%TESTNUMBER --insecure
+--ftp-create-dirs --key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -T %LOGDIR/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/test%TESTNUMBER.dir/upload.%TESTNUMBER --insecure
</command>
<postcheck>
-perl %SRCDIR/libtest/test610.pl move %PWD/log/test%TESTNUMBER.dir/upload.%TESTNUMBER %PWD/log/upload.%TESTNUMBER rmdir %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test610.pl move %PWD/%LOGDIR/test%TESTNUMBER.dir/upload.%TESTNUMBER %PWD/%LOGDIR/upload.%TESTNUMBER rmdir %PWD/%LOGDIR/test%TESTNUMBER.dir
</postcheck>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh upload test
</file>
diff --git a/tests/data/test625 b/tests/data/test625
index e6f0d77..6ca9f4e 100644
--- a/tests/data/test625
+++ b/tests/data/test625
@@ -22,12 +22,12 @@
SFTP put with --ftp-create-dirs twice
</name>
<command>
---ftp-create-dirs --key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test%TESTNUMBER.a/upload.%TESTNUMBER -T log/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test%TESTNUMBER.b/upload.%TESTNUMBER --insecure
+--ftp-create-dirs --key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -T %LOGDIR/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/test%TESTNUMBER.a/upload.%TESTNUMBER -T %LOGDIR/file%TESTNUMBER.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/test%TESTNUMBER.b/upload.%TESTNUMBER --insecure
</command>
<postcheck>
-perl %SRCDIR/libtest/test610.pl move %PWD/log/test%TESTNUMBER.a/upload.%TESTNUMBER %PWD/log/upload.%TESTNUMBER rmdir %PWD/log/test%TESTNUMBER.a rm %PWD/log/test%TESTNUMBER.b/upload.%TESTNUMBER rmdir %PWD/log/test%TESTNUMBER.b
+perl %SRCDIR/libtest/test610.pl move %PWD/%LOGDIR/test%TESTNUMBER.a/upload.%TESTNUMBER %PWD/%LOGDIR/upload.%TESTNUMBER rmdir %PWD/%LOGDIR/test%TESTNUMBER.a rm %PWD/%LOGDIR/test%TESTNUMBER.b/upload.%TESTNUMBER rmdir %PWD/%LOGDIR/test%TESTNUMBER.b
</postcheck>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh upload test
</file>
diff --git a/tests/data/test626 b/tests/data/test626
index 0580f53..87b7944 100644
--- a/tests/data/test626
+++ b/tests/data/test626
@@ -22,9 +22,9 @@
SFTP invalid quote command
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "invalid-command foo bar" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -Q "invalid-command foo bar" sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test file for rename test
</file>
</client>
diff --git a/tests/data/test627 b/tests/data/test627
index 60b830e..98b563f 100644
--- a/tests/data/test627
+++ b/tests/data/test627
@@ -24,12 +24,12 @@
SFTP quote remove file with NOBODY
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -I -Q "rm %PWD/log/file%TESTNUMBER.txt" sftp://%HOSTIP:%SSHPORT --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -I -Q "rm %PWD/%LOGDIR/file%TESTNUMBER.txt" sftp://%HOSTIP:%SSHPORT --insecure
</command>
<postcheck>
-perl %SRCDIR/libtest/test610.pl gone %PWD/log/test%TESTNUMBER.txt
+perl %SRCDIR/libtest/test610.pl gone %PWD/%LOGDIR/test%TESTNUMBER.txt
</postcheck>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Dummy test file for remove test
</file>
</client>
diff --git a/tests/data/test630 b/tests/data/test630
index f678528..0aed489 100644
--- a/tests/data/test630
+++ b/tests/data/test630
@@ -17,7 +17,7 @@
SFTP incorrect host key
</name>
<command>
---hostpubmd5 00000000000000000000000000000000 --key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/irrelevant-file --insecure
+--hostpubmd5 00000000000000000000000000000000 --key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/irrelevant-file --insecure
</command>
</client>
diff --git a/tests/data/test631 b/tests/data/test631
index 720f371..4e06307 100644
--- a/tests/data/test631
+++ b/tests/data/test631
@@ -17,7 +17,7 @@
SCP incorrect host key
</name>
<command>
---hostpubmd5 00000000000000000000000000000000 --key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/irrelevant-file --insecure
+--hostpubmd5 00000000000000000000000000000000 --key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/irrelevant-file --insecure
</command>
</client>
diff --git a/tests/data/test632 b/tests/data/test632
index 70cfe51..8e3a913 100644
--- a/tests/data/test632
+++ b/tests/data/test632
@@ -20,7 +20,7 @@
SFTP syntactically invalid host key
</name>
<command>
---hostpubmd5 00 --key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%NOLISTENPORT%SSH_PWD/log/irrelevant-file --insecure
+--hostpubmd5 00 --key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%NOLISTENPORT%SSH_PWD/%LOGDIR/irrelevant-file --insecure
</command>
</client>
diff --git a/tests/data/test633 b/tests/data/test633
index f9ad869..df3403c 100644
--- a/tests/data/test633
+++ b/tests/data/test633
@@ -24,9 +24,9 @@
SFTP retrieval with byte range
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt -r 5-9 --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt -r 5-9 --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test634 b/tests/data/test634
index 9cf9320..3ba7fc6 100644
--- a/tests/data/test634
+++ b/tests/data/test634
@@ -25,9 +25,9 @@
SFTP retrieval with byte range past end of file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt -r 5-99 --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt -r 5-99 --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test635 b/tests/data/test635
index 5974ee8..5cdf342 100644
--- a/tests/data/test635
+++ b/tests/data/test635
@@ -24,9 +24,9 @@
SFTP retrieval with byte range relative to end of file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt -r -9 --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt -r -9 --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test636 b/tests/data/test636
index 6bce35b..8afa222 100644
--- a/tests/data/test636
+++ b/tests/data/test636
@@ -25,9 +25,9 @@
SFTP retrieval with X- byte range
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt -r 5- --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt -r 5- --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test637 b/tests/data/test637
index 5425067..77d1ed9 100644
--- a/tests/data/test637
+++ b/tests/data/test637
@@ -23,9 +23,9 @@
SFTP retrieval with invalid X- range
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt -r 99- --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt -r 99- --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test638 b/tests/data/test638
index 85d5909..10b1b4f 100644
--- a/tests/data/test638
+++ b/tests/data/test638
@@ -23,18 +23,18 @@
sftp
</server>
<precheck>
-perl %SRCDIR/libtest/test610.pl mkdir %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test610.pl mkdir %PWD/%LOGDIR/test%TESTNUMBER.dir
</precheck>
<name>
SFTP post-quote rename * asterisk accept-fail
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-*rename %PWD/log/test%TESTNUMBER.dir %PWD/log/test%TESTNUMBER.new" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -Q "-*rename %PWD/%LOGDIR/test%TESTNUMBER.dir %PWD/%LOGDIR/test%TESTNUMBER.new" sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
<postcheck>
-perl %SRCDIR/libtest/test610.pl rmdir %PWD/log/test%TESTNUMBER.new
+perl %SRCDIR/libtest/test610.pl rmdir %PWD/%LOGDIR/test%TESTNUMBER.new
</postcheck>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Dummy test file for rename test
</file>
</client>
diff --git a/tests/data/test639 b/tests/data/test639
index e63cdf6..3c6f50b 100644
--- a/tests/data/test639
+++ b/tests/data/test639
@@ -23,18 +23,18 @@
sftp
</server>
<precheck>
-perl %SRCDIR/libtest/test610.pl mkdir %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test610.pl mkdir %PWD/%LOGDIR/test%TESTNUMBER.dir
</precheck>
<name>
SFTP post-quote rename * asterisk accept-fail
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-*rename %PWD/log/test%TESTNUMBER-not-exists-dir %PWD/log/test%TESTNUMBER.new" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: -Q "-*rename %PWD/%LOGDIR/test%TESTNUMBER-not-exists-dir %PWD/%LOGDIR/test%TESTNUMBER.new" sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
<postcheck>
-perl %SRCDIR/libtest/test610.pl rmdir %PWD/log/test%TESTNUMBER.dir
+perl %SRCDIR/libtest/test610.pl rmdir %PWD/%LOGDIR/test%TESTNUMBER.dir
</postcheck>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Dummy test file for rename test
</file>
</client>
diff --git a/tests/data/test640 b/tests/data/test640
index 2046dab..816dfd5 100644
--- a/tests/data/test640
+++ b/tests/data/test640
@@ -23,9 +23,9 @@
SFTP --head retrieval
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure --head
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure --head
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test641 b/tests/data/test641
index df1788a..3487c90 100644
--- a/tests/data/test641
+++ b/tests/data/test641
@@ -23,9 +23,9 @@
SCP --head retrieval
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure --head
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure --head
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test642 b/tests/data/test642
index 4fa5282..f63bbc6 100644
--- a/tests/data/test642
+++ b/tests/data/test642
@@ -24,9 +24,9 @@
SFTP retrieval
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: --compressed-ssh sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt --insecure
+--key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: --compressed-ssh sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt --insecure
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
Test data
for ssh test
</file>
diff --git a/tests/data/test643 b/tests/data/test643
index 65bb990..ca6c541 100644
--- a/tests/data/test643
+++ b/tests/data/test643
@@ -39,6 +39,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test644 b/tests/data/test644
new file mode 100644
index 0000000..fc67075
--- /dev/null
+++ b/tests/data/test644
@@ -0,0 +1,85 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+xattr
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 301 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: fake/data
+Funny-head: yesyes
+Location: data/%TESTNUMBER0002.txt?coolsite=yes
+
+-foo-
+</data>
+<data2 nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/real
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data2>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<features>
+debug
+xattr
+</features>
+# simulate the xattr operations
+<setenv>
+CURL_FAKE_XATTR=1
+</setenv>
+<name>
+--xattr with redirect
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --xattr -L -o %LOGDIR/out%TESTNUMBER
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+GET /data/%TESTNUMBER0002.txt?coolsite=yes HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+<stdout mode="text">
+user.mime_type => text/html
+user.xdg.origin.url => http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</stdout>
+</verify>
+</testcase>
diff --git a/tests/data/test645 b/tests/data/test645
index d5ce825..5230972 100644
--- a/tests/data/test645
+++ b/tests/data/test645
@@ -39,6 +39,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test646 b/tests/data/test646
index 4c4297c..ef9191e 100644
--- a/tests/data/test646
+++ b/tests/data/test646
Binary files differ
diff --git a/tests/data/test647 b/tests/data/test647
index a609ad9..1b0e152 100644
--- a/tests/data/test647
+++ b/tests/data/test647
@@ -15,6 +15,9 @@
#
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
imap
</server>
@@ -22,9 +25,9 @@
IMAP APPEND multipart using mime API
</name>
<command>
-imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -F "=(;type=multipart/alternative" -F "= <body>This is the html version</body>;type=text/html" -F "=This is the plain text version" -F "=)" -F "=@log/test%TESTNUMBER.txt" -H "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)" -H "From: Fred Foobar <foobar@example.com>" -H "To: joe@example.com" -H "Message-Id: <B27397-0100000@example.com>" -H "Subject: afternoon meeting" -u user:secret
+imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -F "=(;type=multipart/alternative" -F "= <body>This is the html version</body>;type=text/html" -F "=This is the plain text version" -F "=)" -F "=@%LOGDIR/test%TESTNUMBER.txt" -H "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)" -H "From: Fred Foobar <foobar@example.com>" -H "To: joe@example.com" -H "Message-Id: <B27397-0100000@example.com>" -H "Subject: afternoon meeting" -u user:secret
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
This is an attached file.
It may contain any type of data.
diff --git a/tests/data/test648 b/tests/data/test648
index 3683530..3403e21 100644
--- a/tests/data/test648
+++ b/tests/data/test648
@@ -14,6 +14,9 @@
#
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
smtp
</server>
@@ -27,9 +30,9 @@
body
</stdin>
<command>
-smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -F '=This is the email inline text with a very long line containing the special character = and that should be split by encoder.;headers=Content-disposition: "inline";encoder=quoted-printable' -F "=@log/test%TESTNUMBER.txt;encoder=base64" -H "From: different" -H "To: another"
+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -F '=This is the email inline text with a very long line containing the special character = and that should be split by encoder.;headers=Content-disposition: "inline";encoder=quoted-printable' -F "=@%LOGDIR/test%TESTNUMBER.txt;encoder=base64" -H "From: different" -H "To: another"
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
This is an attached file.
It may contain any type of data and will be encoded in base64 for transfer.
diff --git a/tests/data/test649 b/tests/data/test649
index 0f759f0..eced79a 100644
--- a/tests/data/test649
+++ b/tests/data/test649
@@ -14,6 +14,9 @@
#
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
smtp
</server>
@@ -27,9 +30,9 @@
body
</stdin>
<command>
-smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -F '=This is valid;encoder=7bit' -F "=@log/test%TESTNUMBER.txt;encoder=7bit" -H "From: different" -H "To: another"
+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -F '=This is valid;encoder=7bit' -F "=@%LOGDIR/test%TESTNUMBER.txt;encoder=7bit" -H "From: different" -H "To: another"
</command>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
This is an attached file (in french: pièce jointe).
It contains at least an 8-bit byte value.
diff --git a/tests/data/test650 b/tests/data/test650
index 0e4c5d3..c1dcd86 100644
--- a/tests/data/test650
+++ b/tests/data/test650
@@ -23,6 +23,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -38,9 +41,9 @@
Some data from stdin
</stdin>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER log/test%TESTNUMBER.filedata
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/test%TESTNUMBER.filedata
</command>
-<file name="log/test%TESTNUMBER.filedata">
+<file name="%LOGDIR/test%TESTNUMBER.filedata">
This is data from a file.
</file>
</client>
diff --git a/tests/data/test651 b/tests/data/test651
index be2cbe4..b58c224 100644
--- a/tests/data/test651
+++ b/tests/data/test651
@@ -23,6 +23,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -38,9 +41,9 @@
Some data from stdin
</stdin>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER log/test%TESTNUMBER.filedata
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/test%TESTNUMBER.filedata
</command>
-<file name="log/test%TESTNUMBER.filedata">
+<file name="%LOGDIR/test%TESTNUMBER.filedata">
This is data from a file.
</file>
</client>
diff --git a/tests/data/test652 b/tests/data/test652
index f4b9972..d3ff7a0 100644
--- a/tests/data/test652
+++ b/tests/data/test652
@@ -14,6 +14,9 @@
#
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
smtp
</server>
diff --git a/tests/data/test653 b/tests/data/test653
index db62c98..fa018be 100644
--- a/tests/data/test653
+++ b/tests/data/test653
@@ -39,6 +39,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test654 b/tests/data/test654
index d8da0da..c71a047 100644
--- a/tests/data/test654
+++ b/tests/data/test654
@@ -39,6 +39,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -51,9 +54,9 @@
HTTP duplicate easy handle with mime data
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/file%TESTNUMBER.txt
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
This is data from a file
</file>
</client>
diff --git a/tests/data/test656 b/tests/data/test656
index fb0f27f..fff647c 100644
--- a/tests/data/test656
+++ b/tests/data/test656
@@ -16,7 +16,7 @@
SFTP retrieval with nonexistent private key file
</name>
<command>
---key DOES_NOT_EXIST --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure --connect-timeout 8
+--key DOES_NOT_EXIST --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure --connect-timeout 8
</command>
</client>
diff --git a/tests/data/test664 b/tests/data/test664
index 69a75df..69404ef 100644
--- a/tests/data/test664
+++ b/tests/data/test664
@@ -24,9 +24,9 @@
SFTP correct host key
</name>
<command>
---hostpubmd5 %SSHSRVMD5 --key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt
+--hostpubmd5 %SSHSRVMD5 --key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
test
</file>
</client>
diff --git a/tests/data/test665 b/tests/data/test665
index aa20bbf..07aea62 100644
--- a/tests/data/test665
+++ b/tests/data/test665
@@ -24,9 +24,9 @@
SCP correct host key
</name>
<command>
---hostpubmd5 %SSHSRVMD5 --key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file%TESTNUMBER.txt
+--hostpubmd5 %SSHSRVMD5 --key %LOGDIR/server/curl_client_key --pubkey %LOGDIR/server/curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/%LOGDIR/file%TESTNUMBER.txt
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
test
</file>
</client>
diff --git a/tests/data/test666 b/tests/data/test666
index d8b3356..14fbe49 100644
--- a/tests/data/test666
+++ b/tests/data/test666
@@ -32,6 +32,9 @@
#
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test667 b/tests/data/test667
index e54e15b..7546453 100644
--- a/tests/data/test667
+++ b/tests/data/test667
@@ -32,6 +32,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test668 b/tests/data/test668
index 0606e37..ab7cbec 100644
--- a/tests/data/test668
+++ b/tests/data/test668
@@ -32,6 +32,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -44,9 +47,9 @@
HTTP mimepost early end of data detection
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/file%TESTNUMBER.txt
</command>
-<file name="log/file%TESTNUMBER.txt">
+<file name="%LOGDIR/file%TESTNUMBER.txt">
This is data from a file
</file>
</client>
diff --git a/tests/data/test669 b/tests/data/test669
index 20c02a6..7f1be86 100644
--- a/tests/data/test669
+++ b/tests/data/test669
@@ -21,6 +21,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test670 b/tests/data/test670
index 4d1056c..b7b5a90 100644
--- a/tests/data/test670
+++ b/tests/data/test670
@@ -32,6 +32,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test671 b/tests/data/test671
index b6550aa..1100382 100644
--- a/tests/data/test671
+++ b/tests/data/test671
@@ -32,6 +32,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test672 b/tests/data/test672
index 43d183e..d7f1ccc 100644
--- a/tests/data/test672
+++ b/tests/data/test672
@@ -32,6 +32,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test673 b/tests/data/test673
index e263810..0fd3f37 100644
--- a/tests/data/test673
+++ b/tests/data/test673
@@ -32,6 +32,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
diff --git a/tests/data/test676 b/tests/data/test676
index a3916e5..6e1fd19 100644
--- a/tests/data/test676
+++ b/tests/data/test676
@@ -44,7 +44,7 @@
# Client-side
<client>
-<file name="log/cookies676">
+<file name="%LOGDIR/cookies%TESTNUMBER">
%HOSTIP TRUE /we/want/ FALSE 2118138987 proven yes
</file>
<server>
@@ -59,8 +59,11 @@
verify setting CURLOPT_COOKIEFILE to NULL again
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER %LOGDIR/cookies676
</command>
+<features>
+cookies
+</features>
</client>
#
diff --git a/tests/data/test679 b/tests/data/test679
index 53b20c6..d435ae0 100644
--- a/tests/data/test679
+++ b/tests/data/test679
@@ -34,9 +34,9 @@
netrc with quoted password
</name>
<command>
---netrc-optional --netrc-file log/netrc%TESTNUMBER http://%HOSTIP:%HTTPPORT/
+--netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER http://%HOSTIP:%HTTPPORT/
</command>
-<file name="log/netrc%TESTNUMBER" >
+<file name="%LOGDIR/netrc%TESTNUMBER" >
machine %HOSTIP login user1 password "with spaces and \"\n\r\t\a"
</file>
</client>
diff --git a/tests/data/test680 b/tests/data/test680
index 23e194d..2cd0d47 100644
--- a/tests/data/test680
+++ b/tests/data/test680
@@ -23,9 +23,9 @@
netrc with quoted password but missing end quote
</name>
<command>
---netrc --netrc-file log/netrc%TESTNUMBER http://user1@http.example/
+--netrc --netrc-file %LOGDIR/netrc%TESTNUMBER http://user1@http.example/
</command>
-<file name="log/netrc%TESTNUMBER" >
+<file name="%LOGDIR/netrc%TESTNUMBER" >
machine %HOSTIP login user1 password "with spaces and \"\n\r\t\a
</file>
</client>
diff --git a/tests/data/test682 b/tests/data/test682
new file mode 100644
index 0000000..0e3a789
--- /dev/null
+++ b/tests/data/test682
@@ -0,0 +1,53 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+netrc
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Fri, 05 Aug 2022 10:09:00 GMT
+Server: test-server/fake
+Content-Type: text/plain
+Content-Length: 6
+Connection: close
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+netrc with multiple logins - pick first
+ </name>
+ <command>
+--netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER http://user1@%HOSTIP:%HTTPPORT/
+</command>
+<file name="%LOGDIR/netrc%TESTNUMBER" >
+machine %HOSTIP login user1 password passwd1
+machine %HOSTIP login user2 password passwd2
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET / HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic %b64[user1:passwd1]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test683 b/tests/data/test683
new file mode 100644
index 0000000..4cbf5f0
--- /dev/null
+++ b/tests/data/test683
@@ -0,0 +1,53 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+netrc
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Fri, 05 Aug 2022 10:09:00 GMT
+Server: test-server/fake
+Content-Type: text/plain
+Content-Length: 6
+Connection: close
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+netrc with multiple logins - pick second
+ </name>
+ <command>
+--netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER http://user2@%HOSTIP:%HTTPPORT/
+</command>
+<file name="%LOGDIR/netrc%TESTNUMBER" >
+machine %HOSTIP login user1 password passwd1
+machine %HOSTIP login user2 password passwd2
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET / HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic %b64[user2:passwd2]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test684 b/tests/data/test684
new file mode 100644
index 0000000..712ee3b
--- /dev/null
+++ b/tests/data/test684
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+netrc
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Fri, 05 Aug 2022 10:09:00 GMT
+Server: test-server/fake
+Content-Type: text/plain
+Content-Length: 6
+Connection: close
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+netrc with no login
+ </name>
+ <command>
+--netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER http://%HOSTIP:%HTTPPORT/
+</command>
+<file name="%LOGDIR/netrc%TESTNUMBER" >
+machine %HOSTIP password 5up3r53cr37
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET / HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic %b64[:5up3r53cr37]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test685 b/tests/data/test685
new file mode 100644
index 0000000..9d64fe7
--- /dev/null
+++ b/tests/data/test685
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+netrc
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Fri, 05 Aug 2022 10:09:00 GMT
+Server: test-server/fake
+Content-Type: text/plain
+Content-Length: 6
+Connection: close
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+netrc with no login - provided user
+ </name>
+ <command>
+--netrc-optional --netrc-file %LOGDIR/netrc%TESTNUMBER http://user@%HOSTIP:%HTTPPORT/
+</command>
+<file name="%LOGDIR/netrc%TESTNUMBER" >
+machine %HOSTIP password 5up3r53cr37
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+</protocol>
+GET / HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic %b64[user:5up3r53cr37]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+
+</verify>
+</testcase>
diff --git a/tests/data/test686 b/tests/data/test686
new file mode 100644
index 0000000..0badad0
--- /dev/null
+++ b/tests/data/test686
@@ -0,0 +1,34 @@
+<testcase>
+<info>
+<keywords>
+errorcode
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+ <name>
+verify return code for missing URL after --next
+ </name>
+ <command>
+htdhdhdtp://localhost --next
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+2
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test7 b/tests/data/test7
index 06df71d..b7487ff 100644
--- a/tests/data/test7
+++ b/tests/data/test7
@@ -32,7 +32,7 @@
HTTP with cookie parser and header recording
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -b none -D log/heads%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -b none -D %LOGDIR/heads%TESTNUMBER.txt
</command>
</client>
@@ -45,7 +45,7 @@
Accept: */*
</protocol>
-<file name="log/heads%TESTNUMBER.txt">
+<file name="%LOGDIR/heads%TESTNUMBER.txt">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
diff --git a/tests/data/test71 b/tests/data/test71
index 7f8b049..a5b6db6 100644
--- a/tests/data/test71
+++ b/tests/data/test71
@@ -21,6 +21,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -30,14 +33,14 @@
<stdin>
-F name=daniel
-F tool=curl
--F file=@log/test%TESTNUMBER.txt
+-F file=@%LOGDIR/test%TESTNUMBER.txt
user-agent = ""
</stdin>
<command>
http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -K -
</command>
# We create this file before the command is invoked!
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo-
This is a moo-
bar
diff --git a/tests/data/test73 b/tests/data/test73
index e211f21..c5c2c009 100644
--- a/tests/data/test73
+++ b/tests/data/test73
@@ -29,8 +29,11 @@
HTTP, receive cookies when using custom Host:, domain using only two dots
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -c log/jar%TESTNUMBER.txt -H "Host: host.NOT_DISCLOSED.se"
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -c %LOGDIR/jar%TESTNUMBER.txt -H "Host: host.NOT_DISCLOSED.se"
</command>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
@@ -42,7 +45,7 @@
Accept: */*
</protocol>
-<file name="log/jar%TESTNUMBER.txt" mode="text">
+<file name="%LOGDIR/jar%TESTNUMBER.txt" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test74 b/tests/data/test74
index 524a70e..a2ecdd9 100644
--- a/tests/data/test74
+++ b/tests/data/test74
@@ -43,7 +43,7 @@
HTTP, urlglob {}-retrieval and -o #[num] usage
</name>
<command option="no-output">
-"http://%HOSTIP:%HTTPPORT/{%TESTNUMBER,%TESTNUMBER0001}" -o "log/dumpit#1.dump"
+"http://%HOSTIP:%HTTPPORT/{%TESTNUMBER,%TESTNUMBER0001}" -o "%LOGDIR/dumpit#1.dump"
</command>
</client>
@@ -62,7 +62,7 @@
Accept: */*
</protocol>
-<file name="log/dumpit%TESTNUMBER0001.dump">
+<file name="%LOGDIR/dumpit%TESTNUMBER0001.dump">
HTTP/1.0 200 OK
Content-Type: text/html
Funny-head: swsclose
diff --git a/tests/data/test75 b/tests/data/test75
index 7bee044..b11295c 100644
--- a/tests/data/test75
+++ b/tests/data/test75
@@ -25,7 +25,7 @@
HTTP, urlglob retrieval with bad range
</name>
<command option="no-output">
-"http://a-site-never-accessed.example.org/[2-1]" -o "log/weee#1.dump" --stderr -
+"http://a-site-never-accessed.example.org/[2-1]" -o "%LOGDIR/weee#1.dump" --stderr -
</command>
</client>
diff --git a/tests/data/test799 b/tests/data/test799
new file mode 100644
index 0000000..9849512
--- /dev/null
+++ b/tests/data/test799
@@ -0,0 +1,53 @@
+<testcase>
+<info>
+<keywords>
+IMAP
+Clear Text
+SASL AUTH +LOGIN
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+AUTH PLAIN
+REPLY LOGIN A002 OK LOGIN completed
+</servercmd>
+<data>
+From: me@somewhere
+To: fake@nowhere
+
+body
+
+--
+ yours sincerely
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+imap
+</server>
+ <name>
+IMAP with --login-options 'AUTH=+LOGIN'
+ </name>
+ <command>
+'imap://%HOSTIP:%IMAPPORT/%TESTNUMBER/;MAILINDEX=1' -u user:secret --login-options AUTH=+LOGIN
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+A001 CAPABILITY
+A002 LOGIN user secret
+A003 SELECT %TESTNUMBER
+A004 FETCH 1 BODY[]
+A005 LOGOUT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test8 b/tests/data/test8
index a8548e6..7d087f3 100644
--- a/tests/data/test8
+++ b/tests/data/test8
@@ -25,11 +25,11 @@
HTTP with cookie parsing from header file
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -b log/heads%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -b %LOGDIR/heads%TESTNUMBER.txt
</command>
# We create this file before the command is invoked!
-<file name="log/heads%TESTNUMBER.txt">
+<file name="%LOGDIR/heads%TESTNUMBER.txt">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -46,11 +46,44 @@
Set-Cookie: nocookie=yes; path=/WE;
Set-Cookie: blexp=yesyes; domain=%HOSTIP; domain=%HOSTIP; expiry=totally bad;
Set-Cookie: partialip=nono; domain=.0.0.1;
+Set-Cookie: cookie1=%hex[%01-junk]hex%
+Set-Cookie: cookie2=%hex[%02-junk]hex%
+Set-Cookie: cookie3=%hex[%03-junk]hex%
+Set-Cookie: cookie4=%hex[%04-junk]hex%
+Set-Cookie: cookie5=%hex[%05-junk]hex%
+Set-Cookie: cookie6=%hex[%06-junk]hex%
+Set-Cookie: cookie7=%hex[%07-junk]hex%
+Set-Cookie: cookie8=%hex[%08-junk]hex%
+Set-Cookie: cookie9=%hex[junk--%09]hex%
+Set-Cookie: cookie11=%hex[%0b-junk]hex%
+Set-Cookie: cookie12=%hex[%0c-junk]hex%
+Set-Cookie: cookie14=%hex[%0e-junk]hex%
+Set-Cookie: cookie15=%hex[%0f-junk]hex%
+Set-Cookie: cookie16=%hex[%10-junk]hex%
+Set-Cookie: cookie17=%hex[%11-junk]hex%
+Set-Cookie: cookie18=%hex[%12-junk]hex%
+Set-Cookie: cookie19=%hex[%13-junk]hex%
+Set-Cookie: cookie20=%hex[%14-junk]hex%
+Set-Cookie: cookie21=%hex[%15-junk]hex%
+Set-Cookie: cookie22=%hex[%16-junk]hex%
+Set-Cookie: cookie23=%hex[%17-junk]hex%
+Set-Cookie: cookie24=%hex[%18-junk]hex%
+Set-Cookie: cookie25=%hex[%19-junk]hex%
+Set-Cookie: cookie26=%hex[%1a-junk]hex%
+Set-Cookie: cookie27=%hex[%1b-junk]hex%
+Set-Cookie: cookie28=%hex[%1c-junk]hex%
+Set-Cookie: cookie29=%hex[%1d-junk]hex%
+Set-Cookie: cookie30=%hex[%1e-junk]hex%
+Set-Cookie: cookie31=%hex[%1f-junk]hex%
+Set-Cookie: cookie31=%hex[%7f-junk]hex%
</file>
<precheck>
perl -e 'if ("%HOSTIP" !~ /\.0\.0\.1$/) {print "Test only works for HOSTIPs ending with .0.0.1"; exit(1)}'
</precheck>
+<features>
+cookies
+</features>
</client>
# Verify data after the test has been "shot"
@@ -60,7 +93,7 @@
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
-Cookie: name with space=is weird but; trailingspace=removed; cookie=perhaps; cookie=yes; foobar=name; blexp=yesyes
+Cookie: name with space=is weird but; trailingspace=removed; cookie=perhaps; cookie=yes; foobar=name; blexp=yesyes; cookie9=junk--
</protocol>
</verify>
diff --git a/tests/data/test805 b/tests/data/test805
index 5ce64a7..07fb97c 100644
--- a/tests/data/test805
+++ b/tests/data/test805
@@ -23,9 +23,9 @@
IMAP APPEND message
</name>
<command>
-imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -u user:secret
+imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER -u user:secret
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
From: Fred Foobar <foobar@example.COM>
Subject: afternoon meeting
diff --git a/tests/data/test853 b/tests/data/test853
index a3b9688..468e078 100644
--- a/tests/data/test853
+++ b/tests/data/test853
@@ -4,6 +4,7 @@
POP3
Clear Text
LIST
+SLOWDOWN
</keywords>
</info>
diff --git a/tests/data/test86 b/tests/data/test86
index 5d4399c..62284e9 100644
--- a/tests/data/test86
+++ b/tests/data/test86
@@ -57,7 +57,7 @@
HTTP, urlglob []-retrieval and -o #[num] usage
</name>
<command option="no-output">
-"http://%HOSTIP:%HTTPPORT/[%TESTNUMBER0001-%TESTNUMBER0003]" -o "log/dumpit#1.dump"
+"http://%HOSTIP:%HTTPPORT/[%TESTNUMBER0001-%TESTNUMBER0003]" -o "%LOGDIR/dumpit#1.dump"
</command>
</client>
@@ -83,7 +83,7 @@
</protocol>
# we check the second file
-<file name="log/dumpit%TESTNUMBER0002.dump">
+<file name="%LOGDIR/dumpit%TESTNUMBER0002.dump">
HTTP/1.0 200 OK
Content-Type: text/html
Funny-head: swsclose
diff --git a/tests/data/test87 b/tests/data/test87
index ff702dc..5cf7de5 100644
--- a/tests/data/test87
+++ b/tests/data/test87
@@ -40,7 +40,7 @@
urlglob with out of range -o #[num] usage
</name>
<command option="no-output">
-"http://%HOSTIP:%HTTPPORT/[%TESTNUMBER0001-%TESTNUMBER0002]" -o "log/dumpit%TESTNUMBER-#2.dump"
+"http://%HOSTIP:%HTTPPORT/[%TESTNUMBER0001-%TESTNUMBER0002]" -o "%LOGDIR/dumpit%TESTNUMBER-#2.dump"
</command>
</client>
@@ -50,7 +50,7 @@
# survives
#
<verify>
-<file name="log/dumpit%TESTNUMBER-#2.dump">
+<file name="%LOGDIR/dumpit%TESTNUMBER-#2.dump">
HTTP/1.1 200 OK
Funny-head: yesyes
Content-Length: 16
diff --git a/tests/data/test88 b/tests/data/test88
index b7c6207..1ca5d88 100644
--- a/tests/data/test88
+++ b/tests/data/test88
@@ -63,9 +63,9 @@
HTTP PUT with Digest authorization
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T log/put%TESTNUMBER -u testuser:testpass --digest
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -T %LOGDIR/put%TESTNUMBER -u testuser:testpass --digest
</command>
-<file name="log/put%TESTNUMBER">
+<file name="%LOGDIR/put%TESTNUMBER">
This is data we upload with PUT
a second line
line three
@@ -88,7 +88,6 @@
User-Agent: curl/%VERSION
Accept: */*
Content-Length: 85
-Expect: 100-continue
This is data we upload with PUT
a second line
diff --git a/tests/data/test897 b/tests/data/test897
index 1a537ea..5c4410c 100644
--- a/tests/data/test897
+++ b/tests/data/test897
@@ -31,7 +31,7 @@
IMAP and envelope meta data after body transfer
</name>
<command>
-'imap://%HOSTIP:%IMAPPORT/%TESTNUMBER/;MAILINDEX=123/;SECTION=1' -u user:secret -D log/head-%TESTNUMBER
+'imap://%HOSTIP:%IMAPPORT/%TESTNUMBER/;MAILINDEX=123/;SECTION=1' -u user:secret -D %LOGDIR/head-%TESTNUMBER
</command>
</client>
@@ -45,7 +45,7 @@
A004 FETCH 123 BODY[1]
A005 LOGOUT
</protocol>
-<file name="log/head-%TESTNUMBER">
+<file name="%LOGDIR/head-%TESTNUMBER">
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
diff --git a/tests/data/test899 b/tests/data/test899
new file mode 100644
index 0000000..d1f1936
--- /dev/null
+++ b/tests/data/test899
@@ -0,0 +1,64 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+Basic
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes" nocheck="yes">
+HTTP/1.1 302 go go go
+Content-Length: 8
+Location: http://user:pass@%HOSTIP:%HTTPPORT/basic-auth/user/%TESTNUMBER0002
+Content-Type: text/html
+Funny-head: yesyes
+
+notreal
+</data>
+<data2 crlf="yes">
+HTTP/1.1 200 OK
+Content-Length: 6
+Content-Type: text/html
+Funny-head: yesyes
+
+final
+</data2>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+URL with credentials redirects to URL with different credentials
+</name>
+<command>
+http://first:secret@%HOSTIP:%HTTPPORT/%TESTNUMBER -L
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic Zmlyc3Q6c2VjcmV0
+User-Agent: curl/%VERSION
+Accept: */*
+
+GET /basic-auth/user/%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic dXNlcjpwYXNz
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test9 b/tests/data/test9
index e3aa2b6..b37accb 100644
--- a/tests/data/test9
+++ b/tests/data/test9
@@ -20,6 +20,9 @@
# Client-side
<client>
+<features>
+Mime
+</features>
<server>
http
</server>
@@ -27,10 +30,10 @@
HTTP RFC1867-type formposting
</name>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F name=daniel -F tool=curl -F file=@log/test%TESTNUMBER.txt
+http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -F name=daniel -F tool=curl -F file=@%LOGDIR/test%TESTNUMBER.txt
</command>
# We create this file before the command is invoked!
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
foo-
This is a moo-
bar
diff --git a/tests/data/test909 b/tests/data/test909
index d50ab81..6fa4b28 100644
--- a/tests/data/test909
+++ b/tests/data/test909
@@ -19,14 +19,14 @@
<name>
SMTP without SIZE support
</name>
-<file name="log/test%TESTNUMBER.eml">
+<file name="%LOGDIR/test%TESTNUMBER.eml">
From: different
To: another
body
</file>
<command>
-smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -T log/test%TESTNUMBER.eml
+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -T %LOGDIR/test%TESTNUMBER.eml
</command>
</client>
diff --git a/tests/data/test912 b/tests/data/test912
index 4a3f6d1..dd34a46 100644
--- a/tests/data/test912
+++ b/tests/data/test912
@@ -23,14 +23,14 @@
<name>
SMTP with SIZE support
</name>
-<file name="log/test%TESTNUMBER.eml">
+<file name="%LOGDIR/test%TESTNUMBER.eml">
From: different
To: another
body
</file>
<command>
-smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -T log/test%TESTNUMBER.eml
+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -T %LOGDIR/test%TESTNUMBER.eml
</command>
</client>
diff --git a/tests/data/test913 b/tests/data/test913
index 9c19eb2..48beac6 100644
--- a/tests/data/test913
+++ b/tests/data/test913
@@ -23,14 +23,14 @@
<name>
SMTP with large message SIZE
</name>
-<file name="log/test%TESTNUMBER.eml">
+<file name="%LOGDIR/test%TESTNUMBER.eml">
From: different
To: another
body
</file>
<command>
-smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -T log/test%TESTNUMBER.eml
+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -T %LOGDIR/test%TESTNUMBER.eml
</command>
</client>
diff --git a/tests/data/test914 b/tests/data/test914
index ab895d2..1843af9 100644
--- a/tests/data/test914
+++ b/tests/data/test914
@@ -22,14 +22,14 @@
<name>
SMTP invalid --mail-from
</name>
-<file name="log/test%TESTNUMBER.eml">
+<file name="%LOGDIR/test%TESTNUMBER.eml">
From: different
To: another
body
</file>
<command>
-smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from invalid -T log/test%TESTNUMBER.eml
+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from invalid -T %LOGDIR/test%TESTNUMBER.eml
</command>
</client>
diff --git a/tests/data/test938 b/tests/data/test938
index ec19998..0137b7a 100644
--- a/tests/data/test938
+++ b/tests/data/test938
@@ -30,11 +30,11 @@
<name>
SMTP multiple connection authentication
</name>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
mail body
</file>
<command>
-smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER001 --mail-rcpt recipient@example.com --mail-from sender@example.com -u user.one:secret -T log/upload%TESTNUMBER -: smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER002 --mail-rcpt recipient@example.com --mail-from sender@example.com -u user.two:secret -T log/upload%TESTNUMBER
+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER001 --mail-rcpt recipient@example.com --mail-from sender@example.com -u user.one:secret -T %LOGDIR/upload%TESTNUMBER -: smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER002 --mail-rcpt recipient@example.com --mail-from sender@example.com -u user.two:secret -T %LOGDIR/upload%TESTNUMBER
</command>
</client>
diff --git a/tests/data/test941 b/tests/data/test941
index f4dc34f..a983837 100644
--- a/tests/data/test941
+++ b/tests/data/test941
@@ -20,7 +20,7 @@
<name>
SMTP with --crlf
</name>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
From: different
To: another
@@ -34,7 +34,7 @@
--crlf option
</file>
<command>
-smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -T log/upload%TESTNUMBER --crlf
+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -T %LOGDIR/upload%TESTNUMBER --crlf
</command>
</client>
diff --git a/tests/data/test96 b/tests/data/test96
index 27044bc..2bf68cc 100644
--- a/tests/data/test96
+++ b/tests/data/test96
@@ -30,7 +30,7 @@
#
# Verify data after the test has been "shot"
<verify>
-<file name="log/memdump">
+<file name="%LOGDIR/memdump">
MEM tool_paramhlp.c
MEM tool_cfgable.c
MEM tool_cfgable.c
diff --git a/tests/data/test963 b/tests/data/test963
index 22b252a..4ddc871 100644
--- a/tests/data/test963
+++ b/tests/data/test963
@@ -29,7 +29,7 @@
perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if (lc(langinfo(CODESET())) ne "utf-8");'
</precheck>
<name>
-SMTP without SMTPUTF8 support (IDN Enabked) - UTF-8 based recipient (host part only)
+SMTP without SMTPUTF8 support (IDN Enabled) - UTF-8 based recipient (host part only)
</name>
<stdin>
From: different
diff --git a/tests/data/test970 b/tests/data/test970
index ee0a3e9..88ab796 100644
--- a/tests/data/test970
+++ b/tests/data/test970
@@ -44,7 +44,7 @@
HTTP GET with JSON output
</name>
<command option="no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --write-out '%{json}' -o log/out%TESTNUMBER
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --write-out '%{json}' -o %LOGDIR/out%TESTNUMBER
</command>
</client>
@@ -59,7 +59,7 @@
</protocol>
<stdout nonewline="yes">
-{"content_type":"text/html","errormsg":null,"exitcode":0,"filename_effective":"log/out%TESTNUMBER","ftp_entry_path":null,"http_code":200,"http_connect":0,"http_version":"1.1","local_ip":"127.0.0.1","local_port":13,"method":"GET","num_connects":1,"num_headers":9,"num_redirects":0,"proxy_ssl_verify_result":0,"redirect_url":null,"referer":null,"remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"response_code":200,"scheme":"HTTP","size_download":445,"size_header":4019,"size_request":4019,"size_upload":0,"speed_download":13,"speed_upload":13,"ssl_verify_result":0,"time_appconnect":0.000013,"time_connect":0.000013,"time_namelookup":0.000013,"time_pretransfer":0.000013,"time_redirect":0.000013,"time_starttransfer":0.000013,"time_total":0.000013,"url":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","url_effective":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","urlnum":0,"curl_version":"curl-unit-test-fake-version"}
+{"certs":"","content_type":"text/html","conn_id":0,"errormsg":null,"exitcode":0,"filename_effective":"%LOGDIR/out%TESTNUMBER","ftp_entry_path":null,"http_code":200,"http_connect":0,"http_version":"1.1","local_ip":"127.0.0.1","local_port":13,"method":"GET","num_certs":0,"num_connects":1,"num_headers":9,"num_redirects":0,"proxy_ssl_verify_result":0,"redirect_url":null,"referer":null,"remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"response_code":200,"scheme":"HTTP","size_download":445,"size_header":4019,"size_request":4019,"size_upload":0,"speed_download":13,"speed_upload":13,"ssl_verify_result":0,"time_appconnect":0.000013,"time_connect":0.000013,"time_namelookup":0.000013,"time_pretransfer":0.000013,"time_redirect":0.000013,"time_starttransfer":0.000013,"time_total":0.000013,"url":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","url.scheme":"http","url.user":null,"url.password":null,"url.options":null,"url.host":"%HOSTIP","url.port":"%HTTPPORT","url.path":"/%TESTNUMBER","url.query":null,"url.fragment":null,"url.zoneid":null,"urle.scheme":"http","urle.user":null,"urle.password":null,"urle.options":null,"urle.host":"%HOSTIP","urle.port":"%HTTPPORT","urle.path":"/%TESTNUMBER","urle.query":null,"urle.fragment":null,"urle.zoneid":null,"url_effective":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","urlnum":0,"xfer_id":0,"curl_version":"curl-unit-test-fake-version"}
</stdout>
</verify>
</testcase>
diff --git a/tests/data/test972 b/tests/data/test972
index 971f1fa..1dc2eca 100644
--- a/tests/data/test972
+++ b/tests/data/test972
@@ -28,9 +28,7 @@
#
# Client-side
<client>
-<precheck>
-/usr/bin/which jsonlint-php >log/%TESTNUMBER-check
-</precheck>
+
<server>
http
</server>
@@ -47,7 +45,7 @@
Verify JSON output
</name>
<command option="no-include">
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -s --write-out '%{json}' -o log/out972 | jsonlint-php -q
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -s --write-out '%{json}\n' -o %LOGDIR/out972
</command>
</client>
@@ -61,5 +59,8 @@
Accept: */*
</protocol>
+<stdout mode="text">
+{"certs":"","content_type":"text/html","conn_id":0,"errormsg":null,"exitcode":0,"filename_effective":"%LOGDIR/out972","ftp_entry_path":null,"http_code":200,"http_connect":0,"http_version":"1.1","local_ip":"%HOSTIP","local_port":13,"method":"GET","num_certs":0,"num_connects":1,"num_headers":9,"num_redirects":0,"proxy_ssl_verify_result":0,"redirect_url":null,"referer":null,"remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"response_code":200,"scheme":"HTTP","size_download":445,"size_header":4019,"size_request":4019,"size_upload":0,"speed_download":13,"speed_upload":13,"ssl_verify_result":0,"time_appconnect":0.000013,"time_connect":0.000013,"time_namelookup":0.000013,"time_pretransfer":0.000013,"time_redirect":0.000013,"time_starttransfer":0.000013,"time_total":0.000013,"url":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","url.scheme":"http","url.user":null,"url.password":null,"url.options":null,"url.host":"%HOSTIP","url.port":"%HTTPPORT","url.path":"/%TESTNUMBER","url.query":null,"url.fragment":null,"url.zoneid":null,"urle.scheme":"http","urle.user":null,"urle.password":null,"urle.options":null,"urle.host":"%HOSTIP","urle.port":"%HTTPPORT","urle.path":"/%TESTNUMBER","urle.query":null,"urle.fragment":null,"urle.zoneid":null,"url_effective":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","urlnum":0,"xfer_id":0,"curl_version":"curl-unit-test-fake-version"}
+</stdout>
</verify>
</testcase>
diff --git a/tests/data/test977 b/tests/data/test977
index cecfd13..145a81b 100644
--- a/tests/data/test977
+++ b/tests/data/test977
@@ -27,6 +27,7 @@
# Client-side
<client>
<features>
+cookies
proxy
</features>
<server>
@@ -36,7 +37,7 @@
URL with trailing dot and receiving a cookie for the TLD with dot
</name>
<command>
--x http://%HOSTIP:%HTTPPORT http://firsthost.me. -c log/cookies%TESTNUMBER
+-x http://%HOSTIP:%HTTPPORT http://firsthost.me. -c %LOGDIR/cookies%TESTNUMBER
</command>
</client>
@@ -51,7 +52,7 @@
Proxy-Connection: Keep-Alive
</protocol>
-<file name="log/cookies%TESTNUMBER" mode="text">
+<file name="%LOGDIR/cookies%TESTNUMBER" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
diff --git a/tests/data/test978 b/tests/data/test978
new file mode 100644
index 0000000..16e5592
--- /dev/null
+++ b/tests/data/test978
@@ -0,0 +1,56 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+--stderr
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+verify that --stderr works for -w's stderr as well
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --stderr %LOGDIR/redir --silent -w '%{stderr}nonsense\n'
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+<file name="%LOGDIR/redir" mode="text">
+nonsense
+</file>
+</verify>
+</testcase>
diff --git a/tests/data/test979 b/tests/data/test979
new file mode 100644
index 0000000..40cc350
--- /dev/null
+++ b/tests/data/test979
@@ -0,0 +1,64 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+Basic
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes" nocheck="yes">
+HTTP/1.1 302 go go go
+Content-Length: 8
+Location: http://%HOSTIP:%HTTPPORT/user/%TESTNUMBER0002
+Content-Type: text/html
+Funny-head: yesyes
+
+notreal
+</data>
+<data2 crlf="yes">
+HTTP/1.1 200 OK
+Content-Length: 6
+Content-Type: text/html
+Funny-head: yesyes
+
+final
+</data2>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+-u with redirect to absolute URL using same origin and auth
+</name>
+<command>
+http://first:secret@%HOSTIP:%HTTPPORT/%TESTNUMBER -L -u smith:doggie
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic c21pdGg6ZG9nZ2ll
+User-Agent: curl/%VERSION
+Accept: */*
+
+GET /user/%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic c21pdGg6ZG9nZ2ll
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test981 b/tests/data/test981
index 2b98ce4..e7941af 100644
--- a/tests/data/test981
+++ b/tests/data/test981
@@ -29,9 +29,9 @@
IMAP STARTTLS pipelined server response
</name>
<command>
-imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -u user:secret --ssl
+imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER -u user:secret --ssl
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
From: Fred Foobar <foobar@example.COM>
Subject: afternoon meeting
diff --git a/tests/data/test983 b/tests/data/test983
index 300ec45..203e40a 100644
--- a/tests/data/test983
+++ b/tests/data/test983
@@ -26,7 +26,7 @@
<name>
FTP STARTTLS pipelined server response
</name>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
data
to
see
@@ -35,7 +35,7 @@
so does it?
</file>
<command>
---ssl --ftp-ssl-control ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt -u user:secret -P %CLIENTIP
+--ssl --ftp-ssl-control ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt -u user:secret -P %CLIENTIP
</command>
</client>
diff --git a/tests/data/test984 b/tests/data/test984
index e573f23..7887b77 100644
--- a/tests/data/test984
+++ b/tests/data/test984
@@ -27,9 +27,9 @@
IMAP require STARTTLS with failing capabilities
</name>
<command>
-imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -u user:secret --ssl-reqd
+imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER -u user:secret --ssl-reqd
</command>
-<file name="log/upload%TESTNUMBER">
+<file name="%LOGDIR/upload%TESTNUMBER">
Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
From: Fred Foobar <foobar@example.COM>
Subject: afternoon meeting
diff --git a/tests/data/test986 b/tests/data/test986
index a709437..ebe12c2 100644
--- a/tests/data/test986
+++ b/tests/data/test986
@@ -26,7 +26,7 @@
<name>
FTP require STARTTLS while preauthenticated
</name>
-<file name="log/test%TESTNUMBER.txt">
+<file name="%LOGDIR/test%TESTNUMBER.txt">
data
to
see
@@ -35,7 +35,7 @@
so does it?
</file>
<command>
---ssl-reqd --ftp-ssl-control ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt -u user:secret
+--ssl-reqd --ftp-ssl-control ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt -u user:secret
</command>
</client>
diff --git a/tests/data/test987 b/tests/data/test987
new file mode 100644
index 0000000..9176748
--- /dev/null
+++ b/tests/data/test987
@@ -0,0 +1,51 @@
+<testcase>
+<info>
+<keywords>
+SMTPS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtps
+</server>
+ <name>
+SMTPS with redundant explicit SSL request
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+-k --ssl-reqd --mail-rcpt recipient@example.com --mail-from sender@example.com -T - smtps://%HOSTIP:%SMTPSPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO %TESTNUMBER
+MAIL FROM:<sender@example.com>
+RCPT TO:<recipient@example.com>
+DATA
+QUIT
+</protocol>
+<upload>
+From: different
+To: another
+
+body
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test988 b/tests/data/test988
new file mode 100644
index 0000000..71c873c
--- /dev/null
+++ b/tests/data/test988
@@ -0,0 +1,48 @@
+<testcase>
+<info>
+<keywords>
+IMAPS
+FETCH
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+From: me@somewhere
+To: fake@nowhere
+
+body
+
+--
+ yours sincerely
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+imaps
+</server>
+ <name>
+IMAPS FETCH with redundant explicit SSL request
+ </name>
+ <command>
+-k --ssl-reqd -u '"user:sec"ret{' 'imaps://%HOSTIP:%IMAPSPORT/%TESTNUMBER/;MAILINDEX=1'
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+A001 CAPABILITY
+A002 LOGIN "\"user" "sec\"ret{"
+A003 SELECT %TESTNUMBER
+A004 FETCH 1 BODY[]
+A005 LOGOUT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test989 b/tests/data/test989
new file mode 100644
index 0000000..2fee9f8
--- /dev/null
+++ b/tests/data/test989
@@ -0,0 +1,48 @@
+<testcase>
+<info>
+<keywords>
+POP3S
+RETR
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+From: me@somewhere
+To: fake@nowhere
+
+body
+
+--
+ yours sincerely
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+pop3s
+</server>
+ <name>
+POP3S RETR with redundant explicit SSL request
+ </name>
+ <command>
+-k --ssl-reqd -u user:secret pop3s://%HOSTIP:%POP3SPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+CAPA
+USER user
+PASS secret
+RETR %TESTNUMBER
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/devtest.pl b/tests/devtest.pl
new file mode 100755
index 0000000..99a25ab
--- /dev/null
+++ b/tests/devtest.pl
@@ -0,0 +1,202 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Fandrich, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+# This script is intended for developers to test some internals of the
+# runtests.pl harness. Don't try to use this unless you know what you're
+# doing!
+
+# An example command-line that starts a test http server for test 11 and waits
+# for the user before stopping it:
+# ./devtest.pl --verbose serverfortest https echo "Started https" protoport https preprocess 11 pause echo Stopping stopservers echo Done
+# curl can connect to the server while it's running like this:
+# curl -vkL https://localhost:<protoport>/11
+
+use strict;
+use warnings;
+use 5.006;
+
+BEGIN {
+ # Define srcdir to the location of the tests source directory. This is
+ # usually set by the Makefile, but for out-of-tree builds with direct
+ # invocation of runtests.pl, it may not be set.
+ if(!defined $ENV{'srcdir'}) {
+ use File::Basename;
+ $ENV{'srcdir'} = dirname(__FILE__);
+ }
+ push(@INC, $ENV{'srcdir'});
+}
+
+use globalconfig;
+use servers qw(
+ initserverconfig
+ protoport
+ serverfortest
+ stopservers
+);
+use runner qw(
+ readtestkeywords
+ singletest_preprocess
+);
+use testutil qw(
+ setlogfunc
+);
+use getpart;
+
+
+#######################################################################
+# logmsg is our general message logging subroutine.
+# This function is currently required to be here by servers.pm
+# This is copied from runtests.pl
+#
+my $uname_release = `uname -r`;
+my $is_wsl = $uname_release =~ /Microsoft$/;
+sub logmsg {
+ for(@_) {
+ my $line = $_;
+ if ($is_wsl) {
+ # use \r\n for WSL shell
+ $line =~ s/\r?\n$/\r\n/g;
+ }
+ print "$line";
+ }
+}
+
+#######################################################################
+# Parse and store the protocols in curl's Protocols: line
+# This is copied from runtests.pl
+#
+sub parseprotocols {
+ my ($line)=@_;
+
+ @protocols = split(' ', lc($line));
+
+ # Generate a "proto-ipv6" version of each protocol to match the
+ # IPv6 <server> name and a "proto-unix" to match the variant which
+ # uses Unix domain sockets. This works even if support isn't
+ # compiled in because the <features> test will fail.
+ push @protocols, map(("$_-ipv6", "$_-unix"), @protocols);
+
+ # 'http-proxy' is used in test cases to do CONNECT through
+ push @protocols, 'http-proxy';
+
+ # 'none' is used in test cases to mean no server
+ push @protocols, 'none';
+}
+
+
+#######################################################################
+# Initialize @protocols from the curl binary under test
+#
+sub init_protocols {
+ for (`$CURL -V 2>/dev/null`) {
+ if(m/^Protocols: (.*)$/) {
+ parseprotocols($1);
+ }
+ }
+}
+
+
+#######################################################################
+# Initialize the test harness to run tests
+#
+sub init_tests {
+ setlogfunc(\&logmsg);
+ init_protocols();
+ initserverconfig();
+}
+
+#######################################################################
+# Main test loop
+
+init_tests();
+
+#***************************************************************************
+# Parse command-line options and commands
+#
+while(@ARGV) {
+ if($ARGV[0] eq "-h") {
+ print "Usage: devtest.pl [--verbose] [command [arg]...]\n";
+ print "command is one of:\n";
+ print " echo X\n";
+ print " pause\n";
+ print " preprocess\n";
+ print " protocols *|X[,Y...]\n";
+ print " protoport X\n";
+ print " serverfortest X[,Y...]\n";
+ print " stopservers\n";
+ print " sleep N\n";
+ exit 0;
+ }
+ elsif($ARGV[0] eq "--verbose") {
+ $verbose = 1;
+ }
+ elsif($ARGV[0] eq "sleep") {
+ shift @ARGV;
+ sleep $ARGV[0];
+ }
+ elsif($ARGV[0] eq "echo") {
+ shift @ARGV;
+ print $ARGV[0] . "\n";
+ }
+ elsif($ARGV[0] eq "pause") {
+ print "Press Enter to continue: ";
+ readline STDIN;
+ }
+ elsif($ARGV[0] eq "protocols") {
+ shift @ARGV;
+ if($ARGV[0] eq "*") {
+ init_protocols();
+ }
+ else {
+ @protocols = split(",", $ARGV[0]);
+ }
+ print "Set " . scalar @protocols . " protocols\n";
+ }
+ elsif($ARGV[0] eq "preprocess") {
+ shift @ARGV;
+ loadtest("${TESTDIR}/test${ARGV[0]}");
+ readtestkeywords();
+ singletest_preprocess($ARGV[0]);
+ }
+ elsif($ARGV[0] eq "protoport") {
+ shift @ARGV;
+ my $port = protoport($ARGV[0]);
+ print "protoport: $port\n";
+ }
+ elsif($ARGV[0] eq "serverfortest") {
+ shift @ARGV;
+ my ($why, $e) = serverfortest(split(/,/, $ARGV[0]));
+ print "serverfortest: $e $why\n";
+ }
+ elsif($ARGV[0] eq "stopservers") {
+ my $err = stopservers();
+ print "stopservers: $err\n";
+ }
+ else {
+ print "Error: Unknown command: $ARGV[0]\n";
+ print "Continuing anyway\n";
+ }
+ shift @ARGV;
+}
diff --git a/tests/dictserver.py b/tests/dictserver.py
index 5e38ffa..0a08522 100755
--- a/tests/dictserver.py
+++ b/tests/dictserver.py
@@ -7,7 +7,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2008 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/tests/directories.pm b/tests/directories.pm
index 641c6af..238f7e0 100644
--- a/tests/directories.pm
+++ b/tests/directories.pm
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -21,7 +21,24 @@
# SPDX-License-Identifier: curl
#
###########################################################################
-%file_chmod1 = (
+
+package directories;
+
+use strict;
+use warnings;
+
+BEGIN {
+ use base qw(Exporter);
+
+ our @EXPORT = qw(
+ ftp_contentlist
+ wildcard_filesize
+ wildcard_getfile
+ );
+}
+
+
+my %file_chmod1 = (
'name' => 'chmod1',
'content' => "This file should have permissions 444\n",
'perm' => 'r--r--r--',
@@ -29,7 +46,7 @@
'dostime' => '01-11-10 10:00AM',
);
-%file_chmod2 = (
+my %file_chmod2 = (
'name' => 'chmod2',
'content' => "This file should have permissions 666\n",
'perm' => 'rw-rw-rw-',
@@ -37,7 +54,7 @@
'dostime' => '02-01-10 08:00AM',
);
-%file_chmod3 = (
+my %file_chmod3 = (
'name' => 'chmod3',
'content' => "This file should have permissions 777\n",
'perm' => 'rwxrwxrwx',
@@ -45,7 +62,7 @@
'dostime' => '02-01-10 08:00AM',
);
-%file_chmod4 = (
+my %file_chmod4 = (
'type' => 'd',
'name' => 'chmod4',
'content' => "This file should have permissions 001\n",
@@ -54,7 +71,7 @@
'dostime' => '05-04-10 04:31AM'
);
-%file_chmod5 = (
+my %file_chmod5 = (
'type' => 'd',
'name' => 'chmod5',
'content' => "This file should have permissions 110\n",
@@ -63,7 +80,7 @@
'dostime' => '05-04-10 04:31AM'
);
-%link_link = (
+my %link_link = (
'type' => 'l',
'name' => 'link -> file.txt',
'size' => '8',
@@ -71,7 +88,7 @@
'time' => 'Jan 6 4:42'
);
-%link_link_absolute = (
+my %link_link_absolute = (
'type' => 'l',
'name' => 'link_absolute -> /data/ftp/file.txt',
'size' => '15',
@@ -79,7 +96,7 @@
'time' => 'Jan 6 4:45'
);
-%dir_dot = (
+my %dir_dot = (
'type' => "d",
'name' => ".",
'hlink' => "4",
@@ -89,7 +106,7 @@
'perm' => "rwxrwxrwx"
);
-%dir_ddot = (
+my %dir_ddot = (
'type' => "d",
'name' => "..",
'hlink' => "4",
@@ -99,7 +116,7 @@
'perm' => "rwxrwxrwx"
);
-%dir_weirddir_txt = (
+my %dir_weirddir_txt = (
'type' => "d",
'name' => "weirddir.txt",
'hlink' => "2",
@@ -109,7 +126,7 @@
'perm' => "rwxr-xrwx"
);
-%dir_UNIX = (
+my %dir_UNIX = (
'type' => "d",
'name' => "UNIX",
'hlink' => "11",
@@ -119,7 +136,7 @@
'perm' => "rwx--x--x"
);
-%dir_DOS = (
+my %dir_DOS = (
'type' => "d",
'name' => "DOS",
'hlink' => "11",
@@ -129,7 +146,7 @@
'perm' => "rwx--x--x"
);
-%dir_dot_NeXT = (
+my %dir_dot_NeXT = (
'type' => "d",
'name' => ".NeXT",
'hlink' => "4",
@@ -139,7 +156,7 @@
'perm' => "rwxrwxrwx"
);
-%file_empty_file_dat = (
+my %file_empty_file_dat = (
'name' => "empty_file.dat",
'content' => "",
'perm' => "rw-r--r--",
@@ -147,7 +164,7 @@
'dostime' => "04-27-10 11:01AM"
);
-%file_file_txt = (
+my %file_file_txt = (
'name' => "file.txt",
'content' => "This is content of file \"file.txt\"\n",
'time' => "Apr 27 11:01",
@@ -155,7 +172,7 @@
'perm' => "rw-r--r--"
);
-%file_someothertext_txt = (
+my %file_someothertext_txt = (
'name' => "someothertext.txt",
'content' => "Some junk ;-) This file does not really exist.\n",
'time' => "Apr 27 11:01",
@@ -163,7 +180,7 @@
'perm' => "rw-r--r--"
);
-%lists = (
+my %lists = (
'/fully_simulated/' => {
'files' => [ \%dir_dot, \%dir_ddot, \%dir_DOS, \%dir_UNIX ],
'eol' => "\r\n",
@@ -188,12 +205,12 @@
}
);
-sub ftp_createcontent($) {
- my (%list) = @_;
+sub ftp_createcontent {
+ my ($list) = $_[0];
- $type = $$list{'type'};
- $eol = $$list{'eol'};
- $list_ref = $$list{'files'};
+ my $type = $$list{'type'};
+ my $eol = $$list{'eol'};
+ my $list_ref = $$list{'files'};
my @diroutput;
my @contentlist;
@@ -206,11 +223,11 @@
my $fuser = $file{'user'} ? sprintf("%15s", $file{'user'}) : "ftp-default";
my $fgroup = $file{'group'} ? sprintf("%15s", $file{'group'}) : "ftp-default";
my $fsize = "";
- if($file{'type'} eq "d") {
+ if(exists($file{'type'}) && $file{'type'} eq "d") {
$fsize = $file{'size'} ? sprintf("%7s", $file{'size'}) : sprintf("%7d", 4096);
}
else {
- $fsize = sprintf("%7d", length $file{'content'});
+ $fsize = sprintf("%7d", exists($file{'content'}) ? length $file{'content'} : 0);
}
my $fhlink = $file{'hlink'} ? sprintf("%4d", $file{'hlink'}) : " 1";
my $ftime = $file{'time'} ? sprintf("%10s", $file{'time'}) : "Jan 9 1933";
@@ -225,7 +242,7 @@
my $line = "";
my $time = $file{'dostime'} ? $file{'dostime'} : "06-25-97 09:12AM";
my $size_or_dir;
- if($file{'type'} =~ /^d$/) {
+ if(exists($file{'type'}) && $file{'type'} =~ /^d$/) {
$size_or_dir = " <DIR> ";
}
else {
@@ -237,9 +254,9 @@
}
}
-sub wildcard_filesize($$) {
+sub wildcard_filesize {
my ($list_type, $file) = @_;
- $list = $lists{$list_type};
+ my $list = $lists{$list_type};
if($list) {
my $files = $list->{'files'};
for(@$files) {
@@ -259,9 +276,10 @@
}
return -1;
}
-sub wildcard_getfile($$) {
+
+sub wildcard_getfile {
my ($list_type, $file) = @_;
- $list = $lists{$list_type};
+ my $list = $lists{$list_type};
if($list) {
my $files = $list->{'files'};
for(@$files) {
@@ -270,7 +288,7 @@
if($f{'content'}) {
return (length $f{'content'}, $f{'content'});
}
- elsif ($f{'type'} ne "d"){
+ elsif (!exists($f{'type'}) or $f{'type'} ne "d"){
return (0, "");
}
else {
@@ -284,6 +302,6 @@
sub ftp_contentlist {
my $listname = $_[0];
- $list = $lists{$listname};
- return ftp_createcontent(\$list);
+ my $list = $lists{$listname};
+ return ftp_createcontent($list);
}
diff --git a/tests/disable-scan.pl b/tests/disable-scan.pl
index b6ca37f..99f5436 100755
--- a/tests/disable-scan.pl
+++ b/tests/disable-scan.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -95,7 +95,7 @@
my $line = 0;
while(<F>) {
$line++;
- if(/^## (CURL_DISABLE_[A-Z_]+)/g) {
+ if(/^## `(CURL_DISABLE_[A-Z_]+)/g) {
my ($sym)=($1);
$docs{$sym} = $line;
}
diff --git a/tests/error-codes.pl b/tests/error-codes.pl
old mode 100644
new mode 100755
index 5d28886..8147ef6
--- a/tests/error-codes.pl
+++ b/tests/error-codes.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -35,8 +35,8 @@
my %docs; # from libcurl-errors.3
sub getdocserrors {
- open(F, "<$root/docs/libcurl/libcurl-errors.3");
- while(<F>) {
+ open(my $f, "<", "$root/docs/libcurl/libcurl-errors.3");
+ while(<$f>) {
if($_ =~ /^.IP \"(CURL[EM]_[^ \t\"]*)/) {
my ($symbol) = ($1);
if($symbol =~ /OBSOLETE/) {
@@ -47,12 +47,12 @@
}
}
}
- close(F);
+ close($f);
}
sub getincludeerrors {
- open(F, "<$root/docs/libcurl/symbols-in-versions");
- while(<F>) {
+ open(my $f, "<", "$root/docs/libcurl/symbols-in-versions");
+ while(<$f>) {
if($_ =~ /^(CURL[EM]_[^ \t]*)[ \t]*([0-9.]+)[ \t]*(.*)/) {
my ($symbol, $added, $rest) = ($1,$2,$3);
if($rest =~ /^([0-9.]+)/) {
@@ -63,7 +63,7 @@
}
}
}
- close(F);
+ close($f);
}
getincludeerrors();
diff --git a/tests/extern-scan.pl b/tests/extern-scan.pl
index ac089f7..7597a55 100755
--- a/tests/extern-scan.pl
+++ b/tests/extern-scan.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -54,6 +54,8 @@
open H, "<$f" || die;
my $first = "";
while(<H>) {
+ s/CURL_DEPRECATED\(.*"\)//;
+ s/ */ /g;
if (/^(^CURL_EXTERN .*)\(/) {
my $decl = $1;
$decl =~ s/\r$//;
@@ -66,7 +68,7 @@
$first = $decl;
}
elsif($first) {
- if (/^(.*)\(/) {
+ if (/^ *(.*)\(/) {
my $decl = $1;
$decl =~ s/\r$//;
$first .= $decl;
diff --git a/tests/ftpserver.pl b/tests/ftpserver.pl
index 422fdc2..35fa384 100755
--- a/tests/ftpserver.pl
+++ b/tests/ftpserver.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -40,27 +40,31 @@
# All socket/network/TCP related stuff is done by the 'sockfilt' program.
#
+use strict;
+use warnings;
+
BEGIN {
push(@INC, $ENV{'srcdir'}) if(defined $ENV{'srcdir'});
push(@INC, ".");
- # sub second timestamping needs Time::HiRes
- eval {
- no warnings "all";
- require Time::HiRes;
- import Time::HiRes qw( gettimeofday );
- }
}
-use strict;
-use warnings;
use IPC::Open2;
use Digest::MD5;
+use File::Basename;
-require "getpart.pm";
-require "ftp.pm";
-require "directories.pm";
+use directories;
+
+use getpart qw(
+ getpartattr
+ getpart
+ loadtest
+ );
+
+use processhelp;
use serverhelp qw(
+ logmsg
+ $logfile
servername_str
server_pidfilename
server_logfilename
@@ -70,10 +74,15 @@
datasockf_logfilename
);
-use sshhelp qw(
+use pathhelp qw(
exe_ext
);
+use globalconfig qw(
+ $SERVERCMD
+ $LOCKDIR
+ );
+
#**********************************************************************
# global vars...
#
@@ -85,9 +94,10 @@
my $srcdir; # directory where ftpserver.pl is located
my $srvrname; # server name for presentation purposes
my $cwd_testno; # test case numbers extracted from CWD command
-my $testno = 0; # test case number (read from ftpserver.cmd)
+my $testno = 0; # test case number (read from server.cmd)
my $path = '.';
my $logdir = $path .'/log';
+my $piddir;
#**********************************************************************
# global vars used for server address and primary listener port
@@ -98,9 +108,9 @@
#**********************************************************************
# global vars used for file names
#
+my $PORTFILE="ftpserver.port"; # server port file name
+my $portfile; # server port file path
my $pidfile; # server pid file name
-my $portfile=".ftpserver.port"; # server port file name
-my $logfile; # server log file name
my $mainsockf_pidfile; # pid file for primary connection sockfilt process
my $mainsockf_logfile; # log file for primary connection sockfilt process
my $datasockf_pidfile; # pid file for secondary connection sockfilt process
@@ -109,7 +119,7 @@
#**********************************************************************
# global vars used for server logs advisor read lock handling
#
-my $SERVERLOGS_LOCK = 'log/serverlogs.lock';
+my $serverlogs_lockfile;
my $serverlogslocked = 0;
#**********************************************************************
@@ -141,6 +151,7 @@
my $datadelay; # set if server should throttle data stream
my $retrweirdo; # set if ftp server should use RETRWEIRDO
my $retrnosize; # set if ftp server should use RETRNOSIZE
+my $retrsize; # set if ftp server should use RETRSIZE
my $pasvbadip; # set if ftp server should use PASVBADIP
my $nosave; # set if ftp server should not save uploaded data
my $nodataconn; # set if ftp srvr doesn't establish or accepts data channel
@@ -195,48 +206,23 @@
sub exit_signal_handler {
my $signame = shift;
# For now, simply mimic old behavior.
- killsockfilters($proto, $ipvnum, $idnum, $verbose);
+ killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose);
unlink($pidfile);
unlink($portfile);
if($serverlogslocked) {
$serverlogslocked = 0;
- clear_advisor_read_lock($SERVERLOGS_LOCK);
+ clear_advisor_read_lock($serverlogs_lockfile);
}
exit;
}
-#**********************************************************************
-# logmsg is general message logging subroutine for our test servers.
-#
-sub logmsg {
- my $now;
- # sub second timestamping needs Time::HiRes
- if($Time::HiRes::VERSION) {
- my ($seconds, $usec) = gettimeofday();
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
- localtime($seconds);
- $now = sprintf("%02d:%02d:%02d.%06d ", $hour, $min, $sec, $usec);
- }
- else {
- my $seconds = time();
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
- localtime($seconds);
- $now = sprintf("%02d:%02d:%02d ", $hour, $min, $sec);
- }
- if(open(LOGFILEFH, ">>$logfile")) {
- print LOGFILEFH $now;
- print LOGFILEFH @_;
- close(LOGFILEFH);
- }
-}
-
sub ftpmsg {
# append to the server.input file
- open(INPUT, ">>log/server$idstr.input") ||
- logmsg "failed to open log/server$idstr.input\n";
+ open(my $input, ">>", "$logdir/server$idstr.input") ||
+ logmsg "failed to open $logdir/server$idstr.input\n";
- print INPUT @_;
- close(INPUT);
+ print $input @_;
+ close($input);
# use this, open->print->close system only to make the file
# open as little as possible, to make the test suite run
@@ -395,12 +381,12 @@
logmsg "Error: $srvrname server, sysread error: $!\n";
logmsg "Exited from sysread_or_die() at $fcaller " .
"line $lcaller. $srvrname server, sysread error: $!\n";
- killsockfilters($proto, $ipvnum, $idnum, $verbose);
+ killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose);
unlink($pidfile);
unlink($portfile);
if($serverlogslocked) {
$serverlogslocked = 0;
- clear_advisor_read_lock($SERVERLOGS_LOCK);
+ clear_advisor_read_lock($serverlogs_lockfile);
}
exit;
}
@@ -410,12 +396,12 @@
logmsg "Error: $srvrname server, read zero\n";
logmsg "Exited from sysread_or_die() at $fcaller " .
"line $lcaller. $srvrname server, read zero\n";
- killsockfilters($proto, $ipvnum, $idnum, $verbose);
+ killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose);
unlink($pidfile);
unlink($portfile);
if($serverlogslocked) {
$serverlogslocked = 0;
- clear_advisor_read_lock($SERVERLOGS_LOCK);
+ clear_advisor_read_lock($serverlogs_lockfile);
}
exit;
}
@@ -439,12 +425,12 @@
if($pong !~ /^PONG/) {
logmsg "Failed sockfilt command: $mainsockfcmd\n";
- killsockfilters($proto, $ipvnum, $idnum, $verbose);
+ killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose);
unlink($pidfile);
unlink($portfile);
if($serverlogslocked) {
$serverlogslocked = 0;
- clear_advisor_read_lock($SERVERLOGS_LOCK);
+ clear_advisor_read_lock($serverlogs_lockfile);
}
die "Failed to start sockfilt!";
}
@@ -910,11 +896,11 @@
sendcontrol "354 Show me the mail\r\n";
my $testno = $smtp_client;
- my $filename = "log/upload.$testno";
+ my $filename = "$logdir/upload.$testno";
logmsg "Store test number $testno in $filename\n";
- open(FILE, ">$filename") ||
+ open(my $file, ">", "$filename") ||
return 0; # failed to open output
my $line;
@@ -935,7 +921,7 @@
read_mainsockf(\$line, $size);
$ulsize += $size;
- print FILE $line if(!$nosave);
+ print $file $line if(!$nosave);
$raw .= $line;
if($raw =~ /(?:^|\x0d\x0a)\x2e\x0d\x0a/) {
@@ -962,10 +948,10 @@
}
if($nosave) {
- print FILE "$ulsize bytes would've been stored here\n";
+ print $file "$ulsize bytes would've been stored here\n";
}
- close(FILE);
+ close($file);
logmsg "received $ulsize bytes upload\n";
@@ -1259,11 +1245,11 @@
sendcontrol "+ Ready for literal data\r\n";
my $testno = $mailbox;
- my $filename = "log/upload.$testno";
+ my $filename = "$logdir/upload.$testno";
logmsg "Store test number $testno in $filename\n";
- open(FILE, ">$filename") ||
+ open(my $file, ">", "$filename") ||
return 0; # failed to open output
my $received = 0;
@@ -1284,7 +1270,7 @@
if($datasize > 0) {
logmsg "> Appending $datasize bytes to file\n";
- print FILE substr($line, 0, $datasize) if(!$nosave);
+ print $file substr($line, 0, $datasize) if(!$nosave);
$line = substr($line, $datasize);
$received += $datasize;
@@ -1308,10 +1294,10 @@
}
if($nosave) {
- print FILE "$size bytes would've been stored here\n";
+ print $file "$size bytes would've been stored here\n";
}
- close(FILE);
+ close($file);
logmsg "received $size bytes upload\n";
@@ -2343,6 +2329,9 @@
if($retrnosize) {
$sz = "size?";
}
+ elsif($retrsize > 0) {
+ $sz = "($retrsize bytes)";
+ }
sendcontrol "150 Binary data connection for $testno () $sz.\r\n";
@@ -2363,7 +2352,7 @@
sub STOR_ftp {
my $testno=$_[0];
- my $filename = "log/upload.$testno";
+ my $filename = "$logdir/upload.$testno";
if($datasockf_conn eq 'no') {
if($nodataconn425) {
@@ -2388,7 +2377,7 @@
sendcontrol "125 Gimme gimme gimme!\r\n";
- open(FILE, ">$filename") ||
+ open(my $file, ">", "$filename") ||
return 0; # failed to open output
my $line;
@@ -2409,7 +2398,7 @@
#print STDERR " GOT: $size bytes\n";
$ulsize += $size;
- print FILE $line if(!$nosave);
+ print $file $line if(!$nosave);
logmsg "> Appending $size bytes to file\n";
}
elsif($line eq "DISC\n") {
@@ -2427,9 +2416,9 @@
}
}
if($nosave) {
- print FILE "$ulsize bytes would've been stored here\n";
+ print $file "$ulsize bytes would've been stored here\n";
}
- close(FILE);
+ close($file);
close_dataconn($disc);
logmsg "received $ulsize bytes upload\n";
if($storeresp) {
@@ -2448,7 +2437,7 @@
# kill previous data connection sockfilt when alive
if($datasockf_runs eq 'yes') {
- killsockfilters($proto, $ipvnum, $idnum, $verbose, 'data');
+ killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data');
logmsg "DATA sockfilt for $datasockf_mode data channel killed\n";
}
datasockf_state('STOPPED');
@@ -2489,7 +2478,7 @@
logmsg "DATA sockfilt unexpected response: $pong\n";
logmsg "DATA sockfilt for passive data channel failed\n";
logmsg "DATA sockfilt killed now\n";
- killsockfilters($proto, $ipvnum, $idnum, $verbose, 'data');
+ killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data');
logmsg "DATA sockfilt not running\n";
datasockf_state('STOPPED');
sendcontrol "500 no free ports!\r\n";
@@ -2528,7 +2517,7 @@
logmsg "DATA sockfilt unknown listener port\n";
logmsg "DATA sockfilt for passive data channel failed\n";
logmsg "DATA sockfilt killed now\n";
- killsockfilters($proto, $ipvnum, $idnum, $verbose, 'data');
+ killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data');
logmsg "DATA sockfilt not running\n";
datasockf_state('STOPPED');
sendcontrol "500 no free ports!\r\n";
@@ -2573,7 +2562,7 @@
local $SIG{ALRM} = sub { die "alarm\n" };
# assume swift operations unless explicitly slow
- alarm ($datadelay?20:10);
+ alarm ($datadelay?20:2);
# Wait for 'CNCT'
my $input;
@@ -2598,7 +2587,7 @@
"on port $pasvport\n";
logmsg "accept failed or connection not even attempted\n";
logmsg "DATA sockfilt killed now\n";
- killsockfilters($proto, $ipvnum, $idnum, $verbose, 'data');
+ killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data');
logmsg "DATA sockfilt not running\n";
datasockf_state('STOPPED');
return;
@@ -2622,7 +2611,7 @@
# kill previous data connection sockfilt when alive
if($datasockf_runs eq 'yes') {
- killsockfilters($proto, $ipvnum, $idnum, $verbose, 'data');
+ killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data');
logmsg "DATA sockfilt for $datasockf_mode data channel killed\n";
}
datasockf_state('STOPPED');
@@ -2703,7 +2692,7 @@
logmsg "DATA sockfilt unexpected response: $pong\n";
logmsg "DATA sockfilt for active data channel failed\n";
logmsg "DATA sockfilt killed now\n";
- killsockfilters($proto, $ipvnum, $idnum, $verbose, 'data');
+ killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data');
logmsg "DATA sockfilt not running\n";
datasockf_state('STOPPED');
# client shall timeout awaiting connection from server
@@ -2795,6 +2784,7 @@
$datadelay = 0; # default is no throttling of the data stream
$retrweirdo = 0; # default is no use of RETRWEIRDO
$retrnosize = 0; # default is no use of RETRNOSIZE
+ $retrsize = 0; # default is no use of RETRSIZE
$pasvbadip = 0; # default is no use of PASVBADIP
$nosave = 0; # default is to actually save uploaded data to file
$nodataconn = 0; # default is to establish or accept data channel
@@ -2810,12 +2800,12 @@
%customcount = (); #
%delayreply = (); #
- open(CUSTOM, "<log/ftpserver.cmd") ||
+ open(my $custom, "<", "$logdir/$SERVERCMD") ||
return 1;
- logmsg "FTPD: Getting commands from log/ftpserver.cmd\n";
+ logmsg "FTPD: Getting commands from $logdir/$SERVERCMD\n";
- while(<CUSTOM>) {
+ while(<$custom>) {
if($_ =~ /REPLY \"([A-Z]+ [A-Za-z0-9+-\/=\*. ]+)\" (.*)/) {
$fulltextreply{$1}=eval "qq{$2}";
logmsg "FTPD: set custom reply for $1\n";
@@ -2862,6 +2852,10 @@
logmsg "FTPD: instructed to use RETRNOSIZE\n";
$retrnosize=1;
}
+ elsif($_ =~ /RETRSIZE (\d+)/) {
+ $retrsize= $1;
+ logmsg "FTPD: instructed to use RETRSIZE = $1\n";
+ }
elsif($_ =~ /PASVBADIP/) {
logmsg "FTPD: instructed to use PASVBADIP\n";
$pasvbadip=1;
@@ -2915,7 +2909,7 @@
logmsg "FTPD: run test case number: $testno\n";
}
}
- close(CUSTOM);
+ close($custom);
}
#----------------------------------------------------------------------
@@ -2936,6 +2930,7 @@
# --pidfile # server pid file
# --portfile # server port file
# --logfile # server log file
+# --logdir # server log directory
# --ipv4 # server IP version 4
# --ipv6 # server IP version 6
# --port # server listener port
@@ -2984,6 +2979,12 @@
shift @ARGV;
}
}
+ elsif($ARGV[0] eq '--logdir') {
+ if($ARGV[1]) {
+ $logdir = $ARGV[1];
+ shift @ARGV;
+ }
+ }
elsif($ARGV[0] eq '--ipv4') {
$ipvnum = 4;
$listenaddr = '127.0.0.1' if($listenaddr eq '::1');
@@ -3021,29 +3022,37 @@
# Initialize command line option dependent variables
#
+if($pidfile) {
+ # Use our pidfile directory to store the other pidfiles
+ $piddir = dirname($pidfile);
+}
+else {
+ # Use the current directory to store all the pidfiles
+ $piddir = $path;
+ $pidfile = server_pidfilename($piddir, $proto, $ipvnum, $idnum);
+}
+if(!$portfile) {
+ $portfile = $piddir . "/" . $PORTFILE;
+}
if(!$srcdir) {
$srcdir = $ENV{'srcdir'} || '.';
}
-if(!$pidfile) {
- $pidfile = "$path/". server_pidfilename($proto, $ipvnum, $idnum);
-}
if(!$logfile) {
$logfile = server_logfilename($logdir, $proto, $ipvnum, $idnum);
}
-$mainsockf_pidfile = "$path/".
- mainsockf_pidfilename($proto, $ipvnum, $idnum);
+$mainsockf_pidfile = mainsockf_pidfilename($piddir, $proto, $ipvnum, $idnum);
$mainsockf_logfile =
mainsockf_logfilename($logdir, $proto, $ipvnum, $idnum);
if($proto eq 'ftp') {
- $datasockf_pidfile = "$path/".
- datasockf_pidfilename($proto, $ipvnum, $idnum);
+ $datasockf_pidfile = datasockf_pidfilename($piddir, $proto, $ipvnum, $idnum);
$datasockf_logfile =
datasockf_logfilename($logdir, $proto, $ipvnum, $idnum);
}
$srvrname = servername_str($proto, $ipvnum, $idnum);
+$serverlogs_lockfile = "$logdir/$LOCKDIR/${srvrname}.lock";
$idstr = "$idnum" if($idnum > 1);
@@ -3057,17 +3066,17 @@
# actual port
if($portfile && !$port) {
my $aport;
- open(P, "<$portfile");
- $aport = <P>;
- close(P);
+ open(my $p, "<", "$portfile");
+ $aport = <$p>;
+ close($p);
$port = 0 + $aport;
}
logmsg sprintf("%s server listens on port IPv${ipvnum}/${port}\n", uc($proto));
-open(PID, ">$pidfile");
-print PID $$."\n";
-close(PID);
+open(my $pid, ">", "$pidfile");
+print $pid $$."\n";
+close($pid);
logmsg("logged pid $$ in $pidfile\n");
@@ -3075,7 +3084,7 @@
# kill previous data connection sockfilt when alive
if($datasockf_runs eq 'yes') {
- killsockfilters($proto, $ipvnum, $idnum, $verbose, 'data');
+ killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose, 'data');
logmsg "DATA sockfilt for $datasockf_mode data channel killed now\n";
}
datasockf_state('STOPPED');
@@ -3095,7 +3104,7 @@
}
logmsg "====> Client connect\n";
- set_advisor_read_lock($SERVERLOGS_LOCK);
+ set_advisor_read_lock($serverlogs_lockfile);
$serverlogslocked = 1;
# flush data:
@@ -3318,15 +3327,15 @@
if($serverlogslocked) {
$serverlogslocked = 0;
- clear_advisor_read_lock($SERVERLOGS_LOCK);
+ clear_advisor_read_lock($serverlogs_lockfile);
}
}
-killsockfilters($proto, $ipvnum, $idnum, $verbose);
+killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose);
unlink($pidfile);
if($serverlogslocked) {
$serverlogslocked = 0;
- clear_advisor_read_lock($SERVERLOGS_LOCK);
+ clear_advisor_read_lock($serverlogs_lockfile);
}
exit;
diff --git a/tests/fuzz/README.md b/tests/fuzz/README.md
deleted file mode 100644
index 34ba7df..0000000
--- a/tests/fuzz/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-<!--
-Copyright (C) 1998 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
-
-SPDX-License-Identifier: curl
--->
-
-Fuzz tests
-==========
-
-The fuzzing tests for curl have been moved to a separate repository:
-
-https://github.com/curl/curl-fuzzer
-
-More information on how to get started with curl fuzz testing can be found there.
diff --git a/tests/getpart.pm b/tests/getpart.pm
index f8cb6ef..ed60fec 100644
--- a/tests/getpart.pm
+++ b/tests/getpart.pm
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -22,15 +22,45 @@
#
###########################################################################
-#use strict;
+package getpart;
-my @xml;
-my $xmlfile;
+use strict;
+use warnings;
+
+BEGIN {
+ use base qw(Exporter);
+
+ our @EXPORT = qw(
+ compareparts
+ fulltest
+ getpart
+ getpartattr
+ loadarray
+ loadtest
+ partexists
+ striparray
+ writearray
+ );
+}
+
+use Memoize;
+use MIME::Base64;
+
+my @xml; # test data file contents
+my $xmlfile; # test data file name
my $warning=0;
my $trace=0;
-use MIME::Base64;
+# Normalize the part function arguments for proper caching. This includes the
+# file name in the arguments since that is an implied parameter that affects the
+# return value. Any error messages will only be displayed the first time, but
+# those are disabled by default anyway, so should never been seen outside
+# development.
+sub normalize_part {
+ push @_, $xmlfile;
+ return join("\t", @_);
+}
sub decode_hex {
my $s = $_;
@@ -41,6 +71,21 @@
return $s;
}
+sub testcaseattr {
+ my %hash;
+ for(@xml) {
+ if(($_ =~ /^ *\<testcase ([^>]*)/)) {
+ my $attr=$1;
+ while($attr =~ s/ *([^=]*)= *(\"([^\"]*)\"|([^\> ]*))//) {
+ my ($var, $cont)=($1, $2);
+ $cont =~ s/^\"(.*)\"$/$1/;
+ $hash{$var}=$cont;
+ }
+ }
+ }
+ return %hash;
+}
+
sub getpartattr {
# if $part is undefined (ie only one argument) then
# return the attributes of the section
@@ -80,6 +125,7 @@
}
return %hash;
}
+memoize('getpartattr', NORMALIZER => 'normalize_part'); # cache each result
sub getpart {
my ($section, $part)=@_;
@@ -158,6 +204,7 @@
}
return @this;
}
+memoize('getpart', NORMALIZER => 'normalize_part'); # cache each result
sub partexists {
my ($section, $part)=@_;
@@ -177,24 +224,27 @@
}
return 0; # does not exist
}
-
-# Return entire document as list of lines
-sub getall {
- return @xml;
-}
+# The code currently never calls this more than once per part per file, so
+# caching a result that will never be used again just slows things down.
+# memoize('partexists', NORMALIZER => 'normalize_part'); # cache each result
sub loadtest {
my ($file)=@_;
- undef @xml;
- $xmlfile = $file;
+ if(defined $xmlfile && $file eq $xmlfile) {
+ # This test is already loaded
+ return
+ }
- if(open(XML, "<$file")) {
- binmode XML; # for crapage systems, use binary
- while(<XML>) {
+ undef @xml;
+ $xmlfile = "";
+
+ if(open(my $xmlh, "<", "$file")) {
+ binmode $xmlh; # for crapage systems, use binary
+ while(<$xmlh>) {
push @xml, $_;
}
- close(XML);
+ close($xmlh);
}
else {
# failure
@@ -203,9 +253,12 @@
}
return 1;
}
+ $xmlfile = $file;
return 0;
}
+
+# Return entire document as list of lines
sub fulltest {
return @xml;
}
@@ -214,12 +267,12 @@
sub savetest {
my ($file)=@_;
- if(open(XML, ">$file")) {
- binmode XML; # for crapage systems, use binary
+ if(open(my $xmlh, ">", "$file")) {
+ binmode $xmlh; # for crapage systems, use binary
for(@xml) {
- print XML $_;
+ print $xmlh $_;
}
- close(XML);
+ close($xmlh);
}
else {
# failure
@@ -278,12 +331,12 @@
sub writearray {
my ($filename, $arrayref)=@_;
- open(TEMP, ">$filename");
- binmode(TEMP,":raw"); # cygwin fix by Kevin Roth
+ open(my $temp, ">", "$filename") || die "Failure writing file";
+ binmode($temp,":raw"); # cygwin fix by Kevin Roth
for(@$arrayref) {
- print TEMP $_;
+ print $temp $_;
}
- close(TEMP);
+ close($temp) || die "Failure writing file";
}
#
@@ -293,52 +346,14 @@
my ($filename)=@_;
my @array;
- open(TEMP, "<$filename");
- while(<TEMP>) {
- push @array, $_;
+ if (open(my $temp, "<", "$filename")) {
+ while(<$temp>) {
+ push @array, $_;
+ }
+ close($temp);
}
- close(TEMP);
return @array;
}
-# Given two array references, this function will store them in two temporary
-# files, run 'diff' on them, store the result and return the diff output!
-
-sub showdiff {
- my ($logdir, $firstref, $secondref)=@_;
-
- my $file1="$logdir/check-generated";
- my $file2="$logdir/check-expected";
-
- open(TEMP, ">$file1");
- for(@$firstref) {
- my $l = $_;
- $l =~ s/\r/[CR]/g;
- $l =~ s/\n/[LF]/g;
- $l =~ s/([^\x20-\x7f])/sprintf "%%%02x", ord $1/eg;
- print TEMP $l;
- print TEMP "\n";
- }
- close(TEMP);
-
- open(TEMP, ">$file2");
- for(@$secondref) {
- my $l = $_;
- $l =~ s/\r/[CR]/g;
- $l =~ s/\n/[LF]/g;
- $l =~ s/([^\x20-\x7f])/sprintf "%%%02x", ord $1/eg;
- print TEMP $l;
- print TEMP "\n";
- }
- close(TEMP);
- my @out = `diff -u $file2 $file1 2>/dev/null`;
-
- if(!$out[0]) {
- @out = `diff -c $file2 $file1 2>/dev/null`;
- }
-
- return @out;
-}
-
1;
diff --git a/tests/globalconfig.pm b/tests/globalconfig.pm
new file mode 100644
index 0000000..5aad483
--- /dev/null
+++ b/tests/globalconfig.pm
@@ -0,0 +1,117 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+# This module contains global variables used in multiple modules in the test
+# harness but not really "owned" by any one.
+
+package globalconfig;
+
+use strict;
+use warnings;
+
+BEGIN {
+ use base qw(Exporter);
+
+ our @EXPORT = qw(
+ $anyway
+ $automakestyle
+ $CURL
+ $CURLVERSION
+ $has_shared
+ $LIBDIR
+ $listonly
+ $LOCKDIR
+ $LOGDIR
+ $memanalyze
+ $MEMDUMP
+ $perl
+ $PIDDIR
+ $proxy_address
+ $PROXYIN
+ $pwd
+ $randseed
+ $run_event_based
+ $SERVERCMD
+ $SERVERIN
+ $srcdir
+ $TESTDIR
+ $torture
+ $valgrind
+ $VCURL
+ $verbose
+ %feature
+ %keywords
+ @protocols
+ );
+}
+use pathhelp qw(exe_ext);
+use Cwd qw(getcwd);
+
+
+#######################################################################
+# global configuration variables
+#
+
+# config variables overridden by command-line options
+our $verbose; # 1 to show verbose test output
+our $torture; # 1 to enable torture testing
+our $proxy_address; # external HTTP proxy address
+our $listonly; # only list the tests
+our $run_event_based; # run curl with --test-event to test the event API
+our $automakestyle; # use automake-like test status output format
+our $anyway; # continue anyway, even if a test fail
+our $CURLVERSION=""; # curl's reported version number
+our $randseed = 0; # random number seed
+
+# paths
+our $pwd = getcwd(); # current working directory
+our $srcdir = $ENV{'srcdir'} || '.'; # root of the test source code
+our $perl="perl -I$srcdir"; # invoke perl like this
+our $LOGDIR="log"; # root of the log directory; this will be different for
+ # each runner in multiprocess mode
+our $LIBDIR="./libtest";
+our $TESTDIR="$srcdir/data";
+our $CURL="../src/curl".exe_ext('TOOL'); # what curl binary to run on the tests
+our $VCURL=$CURL; # what curl binary to use to verify the servers with
+ # VCURL is handy to set to the system one when the one you
+ # just built hangs or crashes and thus prevent verification
+# the path to the script that analyzes the memory debug output file
+our $memanalyze="$perl $srcdir/memanalyze.pl";
+our $valgrind; # path to valgrind, or empty if disabled
+
+# paths in $LOGDIR
+our $LOCKDIR = "lock"; # root of the server directory with lock files
+our $PIDDIR = "server"; # root of the server directory with PID files
+our $SERVERIN="server.input"; # what curl sent the server
+our $PROXYIN="proxy.input"; # what curl sent the proxy
+our $MEMDUMP="memdump"; # file that the memory debugging creates
+our $SERVERCMD="server.cmd"; # copy server instructions here
+
+# other config variables
+our @protocols; # array of lowercase supported protocol servers
+our %feature; # hash of enabled features
+our $has_shared; # built as a shared library
+our %keywords; # hash of keywords from the test spec
+
+1;
diff --git a/tests/httpserver.pl b/tests/http-server.pl
similarity index 74%
rename from tests/httpserver.pl
rename to tests/http-server.pl
index 64573aa..526ec31 100755
--- a/tests/httpserver.pl
+++ b/tests/http-server.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,20 +23,22 @@
#
#***************************************************************************
+use strict;
+use warnings;
+
BEGIN {
push(@INC, $ENV{'srcdir'}) if(defined $ENV{'srcdir'});
push(@INC, ".");
}
-use strict;
-use warnings;
+use File::Basename;
use serverhelp qw(
server_pidfilename
server_logfilename
);
-use sshhelp qw(
+use pathhelp qw(
exe_ext
);
@@ -49,13 +51,16 @@
my $pidfile; # pid file
my $portfile; # port number file
my $logfile; # log file
+my $cmdfile; # command file
my $connect; # IP to connect to on CONNECT
+my $keepalive_secs; # number of seconds to keep idle connections
my $srcdir;
my $gopher = 0;
my $flags = "";
my $path = '.';
my $logdir = $path .'/log';
+my $piddir;
while(@ARGV) {
if($ARGV[0] eq '--pidfile') {
@@ -70,12 +75,24 @@
shift @ARGV;
}
}
+ elsif($ARGV[0] eq '--config') {
+ if($ARGV[1]) {
+ $cmdfile = $ARGV[1];
+ shift @ARGV;
+ }
+ }
elsif($ARGV[0] eq '--logfile') {
if($ARGV[1]) {
$logfile = $ARGV[1];
shift @ARGV;
}
}
+ elsif($ARGV[0] eq '--logdir') {
+ if($ARGV[1]) {
+ $logdir = $ARGV[1];
+ shift @ARGV;
+ }
+ }
elsif($ARGV[0] eq '--srcdir') {
if($ARGV[1]) {
$srcdir = $ARGV[1];
@@ -110,6 +127,12 @@
shift @ARGV;
}
}
+ elsif($ARGV[0] eq '--keepalive') {
+ if($ARGV[1]) {
+ $keepalive_secs = $ARGV[1];
+ shift @ARGV;
+ }
+ }
elsif($ARGV[0] eq '--id') {
if($ARGV[1] =~ /^(\d+)$/) {
$idnum = $1 if($1 > 0);
@@ -120,29 +143,42 @@
$verbose = 1;
}
else {
- print STDERR "\nWarning: httpserver.pl unknown parameter: $ARGV[0]\n";
+ print STDERR "\nWarning: http-server.pl unknown parameter: $ARGV[0]\n";
}
shift @ARGV;
}
-if(!$srcdir) {
- $srcdir = $ENV{'srcdir'} || '.';
+#***************************************************************************
+# Initialize command line option dependent variables
+#
+
+if($pidfile) {
+ # Use our pidfile directory to store the other pidfiles
+ $piddir = dirname($pidfile);
}
-if(!$pidfile) {
- $pidfile = "$path/". server_pidfilename($proto, $ipvnum, $idnum);
+else {
+ # Use the current directory to store all the pidfiles
+ $piddir = $path;
+ $pidfile = server_pidfilename($piddir, $proto, $ipvnum, $idnum);
}
if(!$portfile) {
- $portfile = "$path/". server_portfilename($proto, $ipvnum, $idnum);
+ $portfile = server_portfilename($piddir, $proto, $ipvnum, $idnum);
+}
+if(!$srcdir) {
+ $srcdir = $ENV{'srcdir'} || '.';
}
if(!$logfile) {
$logfile = server_logfilename($logdir, $proto, $ipvnum, $idnum);
}
$flags .= "--pidfile \"$pidfile\" ".
+ "--cmdfile \"$cmdfile\" ".
"--logfile \"$logfile\" ".
+ "--logdir \"$logdir\" ".
"--portfile \"$portfile\" ";
$flags .= "--gopher " if($gopher);
$flags .= "--connect $connect " if($connect);
+$flags .= "--keepalive $keepalive_secs " if($keepalive_secs);
if($ipvnum eq 'unix') {
$flags .= "--unix-socket '$unix_socket' ";
} else {
diff --git a/tests/http/.gitignore b/tests/http/.gitignore
new file mode 100644
index 0000000..3732aac
--- /dev/null
+++ b/tests/http/.gitignore
@@ -0,0 +1,6 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+config.ini
+gen
\ No newline at end of file
diff --git a/tests/fuzz/download_fuzzer.sh b/tests/http/Makefile.am
old mode 100755
new mode 100644
similarity index 77%
copy from tests/fuzz/download_fuzzer.sh
copy to tests/http/Makefile.am
index e9d6be4..cce66da
--- a/tests/fuzz/download_fuzzer.sh
+++ b/tests/http/Makefile.am
@@ -1,4 +1,3 @@
-#!/bin/bash
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
@@ -6,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,8 +22,16 @@
#
###########################################################################
-# If any commands fail, fail the script immediately.
-set -ex
+SUBDIRS = clients
-# Clone the curl-fuzzer repository to the specified directory.
-git clone --depth=1 https://github.com/curl/curl-fuzzer "$1"
+clean-local:
+ rm -rf *.pyc __pycache__
+ rm -rf gen
+
+check: clients
+
+clients:
+ @(cd clients; $(MAKE) check)
+
+checksrc:
+ cd clients && $(MAKE) checksrc
diff --git a/tests/http/README.md b/tests/http/README.md
new file mode 100644
index 0000000..3a4b263
--- /dev/null
+++ b/tests/http/README.md
@@ -0,0 +1,128 @@
+<!--
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+
+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.
+
+# Usage
+
+The test cases and necessary files are in `tests/http`. You can invoke `pytest` from there or from the top level curl checkout and it will find all tests.
+
+```
+curl> pytest
+platform darwin -- Python 3.9.15, pytest-6.2.0, py-1.10.0, pluggy-0.13.1
+rootdir: /Users/sei/projects/curl
+collected 5 items
+
+tests/http/test_01_basic.py .....
+```
+
+Pytest takes arguments. `-v` increases its verbosity and can be used several times. `-k <expr>` 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> 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.
+
+Depending on your setup, some test cases may be skipped and appear as `s` in the output. If you run pytest verbose, it will also give you the reason for skipping.
+
+
+# Prerequisites
+
+You will need:
+
+1. a recent Python, the `cryptography` module and, of course, `pytest`
+2. a 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 will be skipped.
+
+### Configuration
+
+Via curl's `configure` script you may specify:
+
+ * `--with-test-nghttpx=<path-of-nghttpx>` if you have nghttpx to use somewhere outside your `$PATH`.
+ * `--with-test-httpd=<httpd-install-path>` 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.
+
+## 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:
+
+```
+curl> pytest -k "test_02_06 and h2"
+```
+
+Several test cases can be repeated, they all have the `repeat` parameter. To make this work, you have to start `pytest` in the test directory itself (for some unknown reason). Like in:
+
+```
+curl/tests/http> pytest -k "test_02_06 and h2" --repeat=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:
+
+```
+curl/tests/http> pytest -k "test_02_06 and h2" --repeat=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`:
+
+```
+curl/tests/http> pytest -vvv -k "test_02_06 and h2" --repeat=100 --maxfail=1
+```
+
+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.
+
+### Servers
+
+In `conftest.py` 3 "fixtures" are defined that are used by all test cases:
+
+1. `env`: the test environment. It is an instance of class `testenv/env.py:Env`. It holds all information about paths, availability of features (HTTP/3!), port numbers to use, domains and SSL certificates for those.
+2. `httpd`: the Apache httpd instance, configured and started, then stopped at the end of the test suite. It has sites configured for the domains from `env`. It also loads a local module `mod_curltest?` and makes it available in certain locations. (more on mod_curltest below).
+3. `nghttpx`: an instance of nghttpx that provides HTTP/3 support. `nghttpx` proxies those requests to the `httpd` server. In a direct mapping, so you may access all the resources under the same path as with HTTP/2. Only the port number used for HTTP/3 requests will be different.
+
+`pytest` manages these fixture so that they are created once and terminated before exit. This means you can `Ctrl-C` a running pytest and the server will shutdown. Only when you brutally chop its head off, might there be servers 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.
+
+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.
+
+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 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.
+* `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.
+ * `chunkd_delay=duration`: wait `duration` time between writing chunks
+ * `delay=duration`: wait `duration` time to send the response headers
+ * `body_error=(timeout|reset)`: produce an error after the first chunk in the response body
+ * `id=str`: add `str` in the response header `request-id`
+
+`duration` values are integers, optionally followed by a unit. Units are:
+
+ * `d`: days (probably not useful here)
+ * `h`: hours
+ * `mi`: minutes
+ * `s`: seconds (the default)
+ * `ms`: milliseconds
+
+As you can see, `mod_curltest`'s tweak handler allow to simulate many kinds of responses. An example of its use is `test_03_01` where responses are delayed using `chunk_delay`. This gives the response a defined duration and the test uses that to reload `httpd` in the middle of the first request. A graceful reload in httpd lets ongoing requests finish, but will close the connection afterwards and tear down the serving process. The following request need then to open a new connection. This is verified by the test case.
diff --git a/tests/http/clients/.gitignore b/tests/http/clients/.gitignore
new file mode 100644
index 0000000..02084e1
--- /dev/null
+++ b/tests/http/clients/.gitignore
@@ -0,0 +1,8 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+h2-serverpush
+h2-download
+ws-data
+ws-pingpong
\ No newline at end of file
diff --git a/tests/http/clients/Makefile.am b/tests/http/clients/Makefile.am
new file mode 100644
index 0000000..8fdc190
--- /dev/null
+++ b/tests/http/clients/Makefile.am
@@ -0,0 +1,73 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+AUTOMAKE_OPTIONS = foreign nostdinc
+
+
+# Specify our include paths here, and do it relative to $(top_srcdir) and
+# $(top_builddir), to ensure that these paths which belong to the library
+# being currently built and tested are searched before the library which
+# might possibly already be installed in the system.
+#
+# $(top_srcdir)/include is for libcurl's external include files
+
+AM_CPPFLAGS = -I$(top_srcdir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/lib \
+ -DCURL_DISABLE_DEPRECATION
+
+LIBDIR = $(top_builddir)/lib
+
+# Avoid libcurl obsolete stuff
+AM_CPPFLAGS += -DCURL_NO_OLDIES
+
+if USE_CPPFLAG_CURL_STATICLIB
+AM_CPPFLAGS += -DCURL_STATICLIB
+endif
+
+# Prevent LIBS from being used for all link targets
+LIBS = $(BLANK_AT_MAKETIME)
+
+# Dependencies
+if USE_EXPLICIT_LIB_DEPS
+LDADD = $(LIBDIR)/libcurl.la @LIBCURL_LIBS@
+else
+LDADD = $(LIBDIR)/libcurl.la
+endif
+
+# This might hold -Werror
+CFLAGS += @CURL_CFLAG_EXTRAS@
+
+# Makefile.inc provides the check_PROGRAMS and COMPLICATED_EXAMPLES defines
+include Makefile.inc
+
+all: $(check_PROGRAMS)
+
+CHECKSRC = $(CS_$(V))
+CS_0 = @echo " RUN " $@;
+CS_1 =
+CS_ = $(CS_0)
+
+checksrc:
+ $(CHECKSRC)(@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) $(srcdir)/*.c)
diff --git a/tests/fuzz/download_fuzzer.sh b/tests/http/clients/Makefile.inc
old mode 100755
new mode 100644
similarity index 77%
rename from tests/fuzz/download_fuzzer.sh
rename to tests/http/clients/Makefile.inc
index e9d6be4..e0abf0a
--- a/tests/fuzz/download_fuzzer.sh
+++ b/tests/http/clients/Makefile.inc
@@ -1,4 +1,3 @@
-#!/bin/bash
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
@@ -6,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,8 +22,9 @@
#
###########################################################################
-# If any commands fail, fail the script immediately.
-set -ex
-
-# Clone the curl-fuzzer repository to the specified directory.
-git clone --depth=1 https://github.com/curl/curl-fuzzer "$1"
+# These are all libcurl example programs to be test compiled
+check_PROGRAMS = \
+ h2-serverpush \
+ h2-download \
+ ws-data \
+ ws-pingpong
diff --git a/tests/http/clients/h2-download.c b/tests/http/clients/h2-download.c
new file mode 100644
index 0000000..24ccedb
--- /dev/null
+++ b/tests/http/clients/h2-download.c
@@ -0,0 +1,352 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * HTTP/2 server push
+ * </DESC>
+ */
+
+/* curl stuff */
+#include <curl/curl.h>
+#include <curl/mprintf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* somewhat unix-specific */
+#include <sys/time.h>
+#include <unistd.h>
+
+#ifndef CURLPIPE_MULTIPLEX
+#error "too old libcurl, cannot do HTTP/2 server push!"
+#endif
+
+static int verbose = 1;
+
+static
+int my_trace(CURL *handle, curl_infotype type,
+ char *data, size_t size,
+ void *userp)
+{
+ const char *text;
+ (void)handle; /* prevent compiler warning */
+ (void)userp;
+
+ switch(type) {
+ case CURLINFO_TEXT:
+ fprintf(stderr, "== Info: %s", data);
+ /* FALLTHROUGH */
+ default: /* in case a new one is introduced to shock us */
+ return 0;
+
+ case CURLINFO_HEADER_OUT:
+ text = "=> Send header";
+ break;
+ case CURLINFO_DATA_OUT:
+ if(verbose <= 1)
+ return 0;
+ text = "=> Send data";
+ break;
+ case CURLINFO_HEADER_IN:
+ text = "<= Recv header";
+ break;
+ case CURLINFO_DATA_IN:
+ if(verbose <= 1)
+ return 0;
+ text = "<= Recv data";
+ break;
+ }
+
+ fprintf(stderr, "%s, %lu bytes (0x%lx)\n",
+ text, (unsigned long)size, (unsigned long)size);
+ return 0;
+}
+
+struct transfer {
+ int idx;
+ CURL *easy;
+ char filename[128];
+ FILE *out;
+ curl_off_t recv_size;
+ curl_off_t pause_at;
+ int started;
+ int paused;
+ int resumed;
+ int done;
+};
+
+static size_t transfer_count = 1;
+static struct transfer *transfers;
+
+static struct transfer *get_transfer_for_easy(CURL *easy)
+{
+ size_t i;
+ for(i = 0; i < transfer_count; ++i) {
+ if(easy == transfers[i].easy)
+ return &transfers[i];
+ }
+ return NULL;
+}
+
+static size_t my_write_cb(char *buf, size_t nitems, size_t buflen,
+ void *userdata)
+{
+ struct transfer *t = userdata;
+ ssize_t nwritten;
+
+ if(!t->resumed &&
+ t->recv_size < t->pause_at &&
+ ((curl_off_t)(t->recv_size + (nitems * buflen)) >= t->pause_at)) {
+ fprintf(stderr, "[t-%d] PAUSE\n", t->idx);
+ t->paused = 1;
+ return CURL_WRITEFUNC_PAUSE;
+ }
+
+ if(!t->out) {
+ curl_msnprintf(t->filename, sizeof(t->filename)-1, "download_%u.data",
+ t->idx);
+ t->out = fopen(t->filename, "wb");
+ if(!t->out)
+ return 0;
+ }
+
+ nwritten = fwrite(buf, nitems, buflen, t->out);
+ if(nwritten < 0) {
+ fprintf(stderr, "[t-%d] write failure\n", t->idx);
+ return 0;
+ }
+ t->recv_size += nwritten;
+ return (size_t)nwritten;
+}
+
+static int setup(CURL *hnd, const char *url, struct transfer *t)
+{
+ curl_easy_setopt(hnd, CURLOPT_URL, url);
+ curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
+ curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L);
+ curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, 0L);
+
+ curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, my_write_cb);
+ curl_easy_setopt(hnd, CURLOPT_WRITEDATA, t);
+
+ /* please be verbose */
+ if(verbose) {
+ curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_DEBUGFUNCTION, my_trace);
+ }
+
+#if (CURLPIPE_MULTIPLEX > 0)
+ /* wait for pipe connection to confirm */
+ curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
+#endif
+ return 0; /* all is good */
+}
+
+static void usage(const char *msg)
+{
+ if(msg)
+ fprintf(stderr, "%s\n", msg);
+ fprintf(stderr,
+ "usage: [options] url\n"
+ " download a url with following options:\n"
+ " -m number max parallel downloads\n"
+ " -n number total downloads\n"
+ " -p number pause transfer after `number` response bytes\n"
+ );
+}
+
+/*
+ * Download a file over HTTP/2, take care of server push.
+ */
+int main(int argc, char *argv[])
+{
+ CURLM *multi_handle;
+ struct CURLMsg *m;
+ const char *url;
+ size_t i, n, max_parallel = 1;
+ size_t active_transfers;
+ long pause_offset = 0;
+ int abort_paused = 0;
+ struct transfer *t;
+ int ch;
+
+ while((ch = getopt(argc, argv, "ahm:n:P:")) != -1) {
+ switch(ch) {
+ case 'h':
+ usage(NULL);
+ return 2;
+ break;
+ case 'a':
+ abort_paused = 1;
+ break;
+ case 'm':
+ max_parallel = (size_t)strtol(optarg, NULL, 10);
+ break;
+ case 'n':
+ transfer_count = (size_t)strtol(optarg, NULL, 10);
+ break;
+ case 'P':
+ pause_offset = strtol(optarg, NULL, 10);
+ break;
+ default:
+ usage("invalid option");
+ return 1;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if(argc != 1) {
+ usage("not enough arguments");
+ return 2;
+ }
+ url = argv[0];
+
+ transfers = calloc(transfer_count, sizeof(*transfers));
+ if(!transfers) {
+ fprintf(stderr, "error allocating transfer structs\n");
+ return 1;
+ }
+
+ multi_handle = curl_multi_init();
+ curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
+
+ active_transfers = 0;
+ for(i = 0; i < transfer_count; ++i) {
+ t = &transfers[i];
+ t->idx = (int)i;
+ t->pause_at = (curl_off_t)pause_offset * i;
+ }
+
+ n = (max_parallel < transfer_count)? max_parallel : transfer_count;
+ for(i = 0; i < n; ++i) {
+ t = &transfers[i];
+ t->easy = curl_easy_init();
+ if(!t->easy || setup(t->easy, url, t)) {
+ fprintf(stderr, "[t-%d] FAILED setup\n", (int)i);
+ return 1;
+ }
+ curl_multi_add_handle(multi_handle, t->easy);
+ t->started = 1;
+ ++active_transfers;
+ fprintf(stderr, "[t-%d] STARTED\n", t->idx);
+ }
+
+ do {
+ int still_running; /* keep number of running handles */
+ CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
+
+ if(still_running) {
+ /* wait for activity, timeout or "nothing" */
+ mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
+ fprintf(stderr, "curl_multi_poll() -> %d\n", mc);
+ }
+
+ if(mc)
+ break;
+
+ do {
+ int msgq = 0;
+ m = curl_multi_info_read(multi_handle, &msgq);
+ if(m && (m->msg == CURLMSG_DONE)) {
+ CURL *e = m->easy_handle;
+ active_transfers--;
+ curl_multi_remove_handle(multi_handle, e);
+ t = get_transfer_for_easy(e);
+ if(t) {
+ t->done = 1;
+ }
+ else
+ curl_easy_cleanup(e);
+ }
+ else {
+ /* nothing happening, maintenance */
+ if(abort_paused) {
+ /* abort paused transfers */
+ for(i = 0; i < transfer_count; ++i) {
+ t = &transfers[i];
+ if(!t->done && t->paused && t->easy) {
+ curl_multi_remove_handle(multi_handle, t->easy);
+ t->done = 1;
+ active_transfers--;
+ fprintf(stderr, "[t-%d] ABORTED\n", t->idx);
+ }
+ }
+ }
+ else {
+ /* resume one paused transfer */
+ for(i = 0; i < transfer_count; ++i) {
+ t = &transfers[i];
+ if(!t->done && t->paused) {
+ t->resumed = 1;
+ t->paused = 0;
+ curl_easy_pause(t->easy, CURLPAUSE_CONT);
+ fprintf(stderr, "[t-%d] RESUMED\n", t->idx);
+ break;
+ }
+ }
+ }
+
+ while(active_transfers < max_parallel) {
+ for(i = 0; i < transfer_count; ++i) {
+ t = &transfers[i];
+ if(!t->started) {
+ t->easy = curl_easy_init();
+ if(!t->easy || setup(t->easy, url, t)) {
+ fprintf(stderr, "[t-%d] FAILEED setup\n", (int)i);
+ return 1;
+ }
+ curl_multi_add_handle(multi_handle, t->easy);
+ t->started = 1;
+ ++active_transfers;
+ fprintf(stderr, "[t-%d] STARTED\n", t->idx);
+ break;
+ }
+ }
+ /* all started */
+ if(i == transfer_count)
+ break;
+ }
+ }
+ } while(m);
+
+ } while(active_transfers); /* as long as we have transfers going */
+
+ for(i = 0; i < transfer_count; ++i) {
+ t = &transfers[i];
+ if(t->out) {
+ fclose(t->out);
+ t->out = NULL;
+ }
+ if(t->easy) {
+ curl_easy_cleanup(t->easy);
+ t->easy = NULL;
+ }
+ }
+ free(transfers);
+
+ curl_multi_cleanup(multi_handle);
+
+ return 0;
+}
diff --git a/tests/http/clients/h2-serverpush.c b/tests/http/clients/h2-serverpush.c
new file mode 100644
index 0000000..742a67e
--- /dev/null
+++ b/tests/http/clients/h2-serverpush.c
@@ -0,0 +1,272 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * HTTP/2 server push
+ * </DESC>
+ */
+
+/* curl stuff */
+#include <curl/curl.h>
+#include <curl/mprintf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* somewhat unix-specific */
+#include <sys/time.h>
+#include <unistd.h>
+
+#ifndef CURLPIPE_MULTIPLEX
+#error "too old libcurl, cannot do HTTP/2 server push!"
+#endif
+
+static
+void dump(const char *text, 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, "%s, %lu bytes (0x%lx)\n",
+ text, (unsigned long)size, (unsigned long)size);
+
+ for(i = 0; i<size; i += width) {
+
+ fprintf(stderr, "%4.4lx: ", (unsigned long)i);
+
+ if(!nohex) {
+ /* hex not disabled, show it */
+ for(c = 0; c < width; c++)
+ if(i + c < size)
+ fprintf(stderr, "%02x ", ptr[i + c]);
+ else
+ fputs(" ", stderr);
+ }
+
+ for(c = 0; (c < width) && (i + c < size); c++) {
+ /* check for 0D0A; if found, skip past and start a new line of output */
+ if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+ ptr[i + c + 1] == 0x0A) {
+ i += (c + 2 - width);
+ break;
+ }
+ 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 */
+ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+ ptr[i + c + 2] == 0x0A) {
+ i += (c + 3 - width);
+ break;
+ }
+ }
+ fputc('\n', stderr); /* newline */
+ }
+}
+
+static
+int my_trace(CURL *handle, curl_infotype type,
+ char *data, size_t size,
+ void *userp)
+{
+ const char *text;
+ (void)handle; /* prevent compiler warning */
+ (void)userp;
+ switch(type) {
+ case CURLINFO_TEXT:
+ fprintf(stderr, "== Info: %s", data);
+ /* FALLTHROUGH */
+ default: /* in case a new one is introduced to shock us */
+ return 0;
+
+ case CURLINFO_HEADER_OUT:
+ text = "=> Send header";
+ break;
+ case CURLINFO_DATA_OUT:
+ text = "=> Send data";
+ break;
+ case CURLINFO_SSL_DATA_OUT:
+ text = "=> Send SSL data";
+ break;
+ case CURLINFO_HEADER_IN:
+ text = "<= Recv header";
+ break;
+ case CURLINFO_DATA_IN:
+ text = "<= Recv data";
+ break;
+ case CURLINFO_SSL_DATA_IN:
+ text = "<= Recv SSL data";
+ break;
+ }
+
+ dump(text, (unsigned char *)data, size, 1);
+ return 0;
+}
+
+#define OUTPUTFILE "download_0.data"
+
+static int setup(CURL *hnd, const char *url)
+{
+ FILE *out = fopen(OUTPUTFILE, "wb");
+ if(!out)
+ /* failed */
+ return 1;
+
+ curl_easy_setopt(hnd, CURLOPT_URL, url);
+ curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
+ curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L);
+ curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, 0L);
+
+ curl_easy_setopt(hnd, CURLOPT_WRITEDATA, out);
+
+ /* please be verbose */
+ curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_DEBUGFUNCTION, my_trace);
+
+#if (CURLPIPE_MULTIPLEX > 0)
+ /* wait for pipe connection to confirm */
+ curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
+#endif
+ return 0; /* all is good */
+}
+
+/* called when there's an incoming push */
+static int server_push_callback(CURL *parent,
+ CURL *easy,
+ size_t num_headers,
+ struct curl_pushheaders *headers,
+ void *userp)
+{
+ char *headp;
+ size_t i;
+ int *transfers = (int *)userp;
+ char filename[128];
+ FILE *out;
+ static unsigned int count = 0;
+ int rv;
+
+ (void)parent; /* we have no use for this */
+ curl_msnprintf(filename, sizeof(filename)-1, "push%u", count++);
+
+ /* here's a new stream, save it in a new file for each new push */
+ out = fopen(filename, "wb");
+ if(!out) {
+ /* if we cannot save it, deny it */
+ fprintf(stderr, "Failed to create output file for push\n");
+ rv = CURL_PUSH_DENY;
+ goto out;
+ }
+
+ /* write to this file */
+ curl_easy_setopt(easy, CURLOPT_WRITEDATA, out);
+
+ fprintf(stderr, "**** push callback approves stream %u, got %lu headers!\n",
+ count, (unsigned long)num_headers);
+
+ for(i = 0; i<num_headers; i++) {
+ headp = curl_pushheader_bynum(headers, i);
+ fprintf(stderr, "**** header %lu: %s\n", (unsigned long)i, headp);
+ }
+
+ headp = curl_pushheader_byname(headers, ":path");
+ if(headp) {
+ fprintf(stderr, "**** The PATH is %s\n", headp /* skip :path + colon */);
+ }
+
+ (*transfers)++; /* one more */
+ rv = CURL_PUSH_OK;
+
+out:
+ return rv;
+}
+
+
+/*
+ * Download a file over HTTP/2, take care of server push.
+ */
+int main(int argc, char *argv[])
+{
+ CURL *easy;
+ CURLM *multi_handle;
+ int transfers = 1; /* we start with one */
+ struct CURLMsg *m;
+ const char *url;
+
+ if(argc != 2) {
+ fprintf(stderr, "need URL as argument\n");
+ return 2;
+ }
+ url = argv[1];
+
+ multi_handle = curl_multi_init();
+ 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);
+
+ easy = curl_easy_init();
+ if(setup(easy, url)) {
+ fprintf(stderr, "failed\n");
+ return 1;
+ }
+
+ curl_multi_add_handle(multi_handle, easy);
+ do {
+ int still_running; /* keep number of running handles */
+ CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
+
+ if(still_running)
+ /* wait for activity, timeout or "nothing" */
+ mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
+
+ if(mc)
+ break;
+
+ /*
+ * A little caution when doing server push is that libcurl itself has
+ * 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);
+ if(m && (m->msg == CURLMSG_DONE)) {
+ CURL *e = m->easy_handle;
+ transfers--;
+ curl_multi_remove_handle(multi_handle, e);
+ curl_easy_cleanup(e);
+ }
+ } while(m);
+
+ } while(transfers); /* as long as we have transfers going */
+
+ curl_multi_cleanup(multi_handle);
+
+ return 0;
+}
diff --git a/tests/http/clients/ws-data.c b/tests/http/clients/ws-data.c
new file mode 100644
index 0000000..e8665b1
--- /dev/null
+++ b/tests/http/clients/ws-data.c
@@ -0,0 +1,263 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Websockets data echos
+ * </DESC>
+ */
+
+/* curl stuff */
+#include "curl_setup.h"
+#include <curl/curl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* somewhat unix-specific */
+#include <sys/time.h>
+#include <unistd.h>
+
+#ifdef USE_WEBSOCKETS
+
+static
+void dump(const char *text, 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, "%s, %lu bytes (0x%lx)\n",
+ text, (unsigned long)size, (unsigned long)size);
+
+ for(i = 0; i<size; i += width) {
+
+ fprintf(stderr, "%4.4lx: ", (unsigned long)i);
+
+ if(!nohex) {
+ /* hex not disabled, show it */
+ for(c = 0; c < width; c++)
+ if(i + c < size)
+ fprintf(stderr, "%02x ", ptr[i + c]);
+ else
+ fputs(" ", stderr);
+ }
+
+ for(c = 0; (c < width) && (i + c < size); c++) {
+ /* check for 0D0A; if found, skip past and start a new line of output */
+ if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+ ptr[i + c + 1] == 0x0A) {
+ i += (c + 2 - width);
+ break;
+ }
+ 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 */
+ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+ ptr[i + c + 2] == 0x0A) {
+ i += (c + 3 - width);
+ break;
+ }
+ }
+ fputc('\n', stderr); /* newline */
+ }
+}
+
+static CURLcode send_binary(CURL *curl, char *buf, size_t buflen)
+{
+ size_t nwritten;
+ CURLcode result =
+ curl_ws_send(curl, buf, buflen, &nwritten, 0, CURLWS_BINARY);
+ fprintf(stderr, "ws: send_binary(len=%ld) -> %d, %ld\n",
+ (long)buflen, result, (long)nwritten);
+ return result;
+}
+
+static CURLcode recv_binary(CURL *curl, char *exp_data, size_t exp_len)
+{
+ const struct curl_ws_frame *frame;
+ char recvbuf[256];
+ size_t r_offset, nread;
+ CURLcode result;
+
+ fprintf(stderr, "recv_binary: expected payload %ld bytes\n", (long)exp_len);
+ r_offset = 0;
+ while(1) {
+ result = curl_ws_recv(curl, recvbuf, sizeof(recvbuf), &nread, &frame);
+ if(result == CURLE_AGAIN) {
+ fprintf(stderr, "EAGAIN, sleep, try again\n");
+ usleep(100*1000);
+ continue;
+ }
+ fprintf(stderr, "ws: curl_ws_recv(offset=%ld, len=%ld) -> %d, %ld\n",
+ (long)r_offset, (long)sizeof(recvbuf), result, (long)nread);
+ if(result) {
+ return result;
+ }
+ if(!(frame->flags & CURLWS_BINARY)) {
+ fprintf(stderr, "recv_data: wrong frame, got %ld bytes rflags %x\n",
+ (long)nread, frame->flags);
+ return CURLE_RECV_ERROR;
+ }
+ if(frame->offset != (curl_off_t)r_offset) {
+ fprintf(stderr, "recv_data: frame offset, expected %ld, got %ld\n",
+ (long)r_offset, (long)frame->offset);
+ return CURLE_RECV_ERROR;
+ }
+ if(frame->bytesleft != (curl_off_t)(exp_len - r_offset - nread)) {
+ fprintf(stderr, "recv_data: frame bytesleft, expected %ld, got %ld\n",
+ (long)(exp_len - r_offset - nread), (long)frame->bytesleft);
+ return CURLE_RECV_ERROR;
+ }
+ if(r_offset + nread > exp_len) {
+ fprintf(stderr, "recv_data: data length, expected %ld, now at %ld\n",
+ (long)exp_len, (long)(r_offset + nread));
+ return CURLE_RECV_ERROR;
+ }
+ if(memcmp(exp_data + r_offset, recvbuf, nread)) {
+ fprintf(stderr, "recv_data: data differs, offset=%ld, len=%ld\n",
+ (long)r_offset, (long)nread);
+ dump("expected:", (unsigned char *)exp_data + r_offset, nread, 0);
+ dump("received:", (unsigned char *)recvbuf, nread, 0);
+ return CURLE_RECV_ERROR;
+ }
+ r_offset += nread;
+ if(r_offset >= exp_len) {
+ fprintf(stderr, "recv_data: frame complete\n");
+ break;
+ }
+ }
+ return CURLE_OK;
+}
+
+/* just close the connection */
+static void websocket_close(CURL *curl)
+{
+ size_t sent;
+ CURLcode result =
+ curl_ws_send(curl, "", 0, &sent, 0, CURLWS_CLOSE);
+ fprintf(stderr,
+ "ws: curl_ws_send returned %u, sent %u\n", (int)result, (int)sent);
+}
+
+static CURLcode data_echo(CURL *curl, size_t plen_min, size_t plen_max)
+{
+ CURLcode res;
+ size_t len;
+ char *send_buf;
+ size_t i;
+
+ send_buf = calloc(1, plen_max);
+ if(!send_buf)
+ return CURLE_OUT_OF_MEMORY;
+ for(i = 0; i < plen_max; ++i) {
+ send_buf[i] = (char)('0' + ((int)i % 10));
+ }
+
+ for(len = plen_min; len <= plen_max; ++len) {
+ res = send_binary(curl, send_buf, len);
+ if(res)
+ goto out;
+ res = recv_binary(curl, send_buf, len);
+ if(res) {
+ fprintf(stderr, "recv_data(len=%ld) -> %d\n", (long)len, res);
+ goto out;
+ }
+ }
+
+out:
+ if(!res)
+ websocket_close(curl);
+ free(send_buf);
+ return res;
+}
+
+#endif
+
+int main(int argc, char *argv[])
+{
+#ifdef USE_WEBSOCKETS
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+ const char *url;
+ curl_off_t l1, l2;
+ size_t plen_min, plen_max;
+
+
+ if(argc != 4) {
+ fprintf(stderr, "usage: ws-data url minlen maxlen\n");
+ return 2;
+ }
+ url = argv[1];
+ l1 = strtol(argv[2], NULL, 10);
+ if(l1 < 0) {
+ fprintf(stderr, "minlen must be >= 0, got %ld\n", (long)l1);
+ return 2;
+ }
+ l2 = strtol(argv[3], NULL, 10);
+ if(l2 < 0) {
+ fprintf(stderr, "maxlen must be >= 0, got %ld\n", (long)l2);
+ return 2;
+ }
+ plen_min = l1;
+ plen_max = l2;
+ if(plen_max < plen_min) {
+ fprintf(stderr, "maxlen must be >= minlen, got %ld-%ld\n",
+ (long)plen_min, (long)plen_max);
+ return 2;
+ }
+
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+
+ /* use the callback style */
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, "ws-data");
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); /* websocket style */
+ res = curl_easy_perform(curl);
+ fprintf(stderr, "curl_easy_perform() returned %u\n", (int)res);
+ if(res == CURLE_OK)
+ res = data_echo(curl, plen_min, plen_max);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ curl_global_cleanup();
+ return (int)res;
+
+#else /* USE_WEBSOCKETS */
+ (void)argc;
+ (void)argv;
+ fprintf(stderr, "websockets not enabled in libcurl\n");
+ return 1;
+#endif /* !USE_WEBSOCKETS */
+}
diff --git a/tests/http/clients/ws-pingpong.c b/tests/http/clients/ws-pingpong.c
new file mode 100644
index 0000000..a81c090
--- /dev/null
+++ b/tests/http/clients/ws-pingpong.c
@@ -0,0 +1,158 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Websockets pingpong
+ * </DESC>
+ */
+
+/* curl stuff */
+#include "curl_setup.h"
+#include <curl/curl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* somewhat unix-specific */
+#include <sys/time.h>
+#include <unistd.h>
+
+#ifdef USE_WEBSOCKETS
+
+static CURLcode ping(CURL *curl, const char *send_payload)
+{
+ size_t sent;
+ CURLcode result =
+ curl_ws_send(curl, send_payload, strlen(send_payload), &sent, 0,
+ CURLWS_PING);
+ fprintf(stderr,
+ "ws: curl_ws_send returned %u, sent %u\n", (int)result, (int)sent);
+
+ return result;
+}
+
+static CURLcode recv_pong(CURL *curl, const char *exected_payload)
+{
+ size_t rlen;
+ const struct curl_ws_frame *meta;
+ char buffer[256];
+ CURLcode result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
+ if(result) {
+ fprintf(stderr, "ws: curl_ws_recv returned %u, received %ld\n",
+ (int)result, (long)rlen);
+ return result;
+ }
+
+ if(!(meta->flags & CURLWS_PONG)) {
+ fprintf(stderr, "recv_pong: wrong frame, got %d bytes rflags %x\n",
+ (int)rlen, meta->flags);
+ return CURLE_RECV_ERROR;
+ }
+
+ fprintf(stderr, "ws: got PONG back\n");
+ if(rlen == strlen(exected_payload) &&
+ !memcmp(exected_payload, buffer, rlen)) {
+ fprintf(stderr, "ws: got the same payload back\n");
+ return CURLE_OK;
+ }
+ fprintf(stderr, "ws: did NOT get the same payload back\n");
+ return CURLE_RECV_ERROR;
+}
+
+/* just close the connection */
+static void websocket_close(CURL *curl)
+{
+ size_t sent;
+ CURLcode result =
+ curl_ws_send(curl, "", 0, &sent, 0, CURLWS_CLOSE);
+ fprintf(stderr,
+ "ws: curl_ws_send returned %u, sent %u\n", (int)result, (int)sent);
+}
+
+static CURLcode pingpong(CURL *curl, const char *payload)
+{
+ CURLcode res;
+ int i;
+
+ res = ping(curl, payload);
+ if(res)
+ return res;
+ for(i = 0; i < 10; ++i) {
+ fprintf(stderr, "Receive pong\n");
+ res = recv_pong(curl, payload);
+ if(res == CURLE_AGAIN) {
+ usleep(100*1000);
+ continue;
+ }
+ websocket_close(curl);
+ return res;
+ }
+ websocket_close(curl);
+ return CURLE_RECV_ERROR;
+}
+
+#endif
+
+int main(int argc, char *argv[])
+{
+#ifdef USE_WEBSOCKETS
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+ const char *url, *payload;
+
+ if(argc != 3) {
+ fprintf(stderr, "usage: ws-pingpong url payload\n");
+ return 2;
+ }
+ url = argv[1];
+ payload = argv[2];
+
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+
+ /* use the callback style */
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, "ws-pingpong");
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); /* websocket style */
+ res = curl_easy_perform(curl);
+ fprintf(stderr, "curl_easy_perform() returned %u\n", (int)res);
+ if(res == CURLE_OK)
+ res = pingpong(curl, payload);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ curl_global_cleanup();
+ return (int)res;
+
+#else /* USE_WEBSOCKETS */
+ (void)argc;
+ (void)argv;
+ fprintf(stderr, "websockets not enabled in libcurl\n");
+ return 1;
+#endif /* !USE_WEBSOCKETS */
+}
diff --git a/tests/fuzz/download_fuzzer.sh b/tests/http/config.ini.in
old mode 100755
new mode 100644
similarity index 77%
copy from tests/fuzz/download_fuzzer.sh
copy to tests/http/config.ini.in
index e9d6be4..42a9679
--- a/tests/fuzz/download_fuzzer.sh
+++ b/tests/http/config.ini.in
@@ -1,4 +1,4 @@
-#!/bin/bash
+# -*- coding: utf-8 -*-
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -22,9 +22,16 @@
# SPDX-License-Identifier: curl
#
###########################################################################
+#
+[global]
-# If any commands fail, fail the script immediately.
-set -ex
+[httpd]
+apxs = @APXS@
+httpd = @HTTPD@
+apachectl = @APACHECTL@
-# Clone the curl-fuzzer repository to the specified directory.
-git clone --depth=1 https://github.com/curl/curl-fuzzer "$1"
+[nghttpx]
+nghttpx = @HTTPD_NGHTTPX@
+
+[caddy]
+caddy = @CADDY@
diff --git a/tests/http/conftest.py b/tests/http/conftest.py
new file mode 100644
index 0000000..09e52e6
--- /dev/null
+++ b/tests/http/conftest.py
@@ -0,0 +1,87 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import logging
+import os
+import sys
+from typing import Optional
+
+import pytest
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '.'))
+
+from testenv import Env, Nghttpx, Httpd, NghttpxQuic, NghttpxFwd
+
+@pytest.fixture(scope="package")
+def env(pytestconfig) -> Env:
+ env = Env(pytestconfig=pytestconfig)
+ level = logging.DEBUG if env.verbose > 0 else logging.INFO
+ logging.getLogger('').setLevel(level=level)
+ if not env.curl_has_protocol('http'):
+ pytest.skip("curl built without HTTP support")
+ if not env.curl_has_protocol('https'):
+ pytest.skip("curl built without HTTPS support")
+ if env.setup_incomplete():
+ pytest.skip(env.incomplete_reason())
+
+ env.setup()
+ if not env.make_clients():
+ pytest.exit(1)
+ return env
+
+@pytest.fixture(scope="package", autouse=True)
+def log_global_env_facts(record_testsuite_property, env):
+ record_testsuite_property("http-port", env.http_port)
+
+
+@pytest.fixture(scope='package')
+def httpd(env) -> Httpd:
+ httpd = Httpd(env=env)
+ if not httpd.exists():
+ pytest.skip(f'httpd not found: {env.httpd}')
+ httpd.clear_logs()
+ if not httpd.start():
+ pytest.fail(f'failed to start httpd: {env.httpd}')
+ yield httpd
+ httpd.stop()
+
+
+@pytest.fixture(scope='package')
+def nghttpx(env, httpd) -> Optional[Nghttpx]:
+ nghttpx = NghttpxQuic(env=env)
+ if env.have_h3():
+ nghttpx.clear_logs()
+ assert nghttpx.start()
+ yield nghttpx
+ nghttpx.stop()
+
+@pytest.fixture(scope='package')
+def nghttpx_fwd(env, httpd) -> Optional[Nghttpx]:
+ nghttpx = NghttpxFwd(env=env)
+ if env.have_h3():
+ nghttpx.clear_logs()
+ assert nghttpx.start()
+ yield nghttpx
+ nghttpx.stop()
+
diff --git a/tests/fuzz/download_fuzzer.sh b/tests/http/requirements.txt
old mode 100755
new mode 100644
similarity index 77%
copy from tests/fuzz/download_fuzzer.sh
copy to tests/http/requirements.txt
index e9d6be4..efc3de7
--- a/tests/fuzz/download_fuzzer.sh
+++ b/tests/http/requirements.txt
@@ -1,4 +1,4 @@
-#!/bin/bash
+# -*- coding: utf-8 -*-
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -22,9 +22,8 @@
# SPDX-License-Identifier: curl
#
###########################################################################
-
-# If any commands fail, fail the script immediately.
-set -ex
-
-# Clone the curl-fuzzer repository to the specified directory.
-git clone --depth=1 https://github.com/curl/curl-fuzzer "$1"
+#
+pytest
+cryptography
+multipart
+websockets
\ No newline at end of file
diff --git a/tests/http/scorecard.py b/tests/http/scorecard.py
new file mode 100644
index 0000000..fe56f43
--- /dev/null
+++ b/tests/http/scorecard.py
@@ -0,0 +1,596 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import argparse
+import json
+import logging
+import os
+import re
+import sys
+from statistics import mean
+from typing import Dict, Any, Optional, List
+
+from testenv import Env, Httpd, Nghttpx, CurlClient, Caddy, ExecResult
+
+log = logging.getLogger(__name__)
+
+
+class ScoreCardException(Exception):
+ pass
+
+
+class ScoreCard:
+
+ def __init__(self, env: Env,
+ httpd: Optional[Httpd],
+ nghttpx: Optional[Nghttpx],
+ caddy: Optional[Caddy],
+ verbose: int,
+ curl_verbose: int):
+ self.verbose = verbose
+ self.env = env
+ self.httpd = httpd
+ self.nghttpx = nghttpx
+ self.caddy = caddy
+ self._silent_curl = not curl_verbose
+
+ def info(self, msg):
+ if self.verbose > 0:
+ sys.stderr.write(msg)
+ sys.stderr.flush()
+
+ def handshakes(self, proto: str) -> Dict[str, Any]:
+ props = {}
+ sample_size = 5
+ self.info(f'TLS Handshake\n')
+ for authority in [
+ f'{self.env.authority_for(self.env.domain1, proto)}'
+ ]:
+ self.info(' localhost...')
+ c_samples = []
+ hs_samples = []
+ errors = []
+ for i in range(sample_size):
+ curl = CurlClient(env=self.env, silent=self._silent_curl)
+ url = f'https://{authority}/'
+ r = curl.http_download(urls=[url], alpn_proto=proto,
+ no_save=True)
+ if r.exit_code == 0 and len(r.stats) == 1:
+ c_samples.append(r.stats[0]['time_connect'])
+ hs_samples.append(r.stats[0]['time_appconnect'])
+ else:
+ errors.append(f'exit={r.exit_code}')
+ props['localhost'] = {
+ 'ipv4-connect': mean(c_samples),
+ 'ipv4-handshake': mean(hs_samples),
+ 'ipv4-errors': errors,
+ 'ipv6-connect': 0,
+ 'ipv6-handshake': 0,
+ 'ipv6-errors': [],
+ }
+ self.info('ok.\n')
+ for authority in [
+ 'curl.se', 'nghttp2.org',
+ ]:
+ self.info(f' {authority}...')
+ props[authority] = {}
+ for ipv in ['ipv4', 'ipv6']:
+ self.info(f'{ipv}...')
+ c_samples = []
+ hs_samples = []
+ errors = []
+ for i in range(sample_size):
+ curl = CurlClient(env=self.env, silent=self._silent_curl)
+ args = [
+ '--http3-only' if proto == 'h3' else '--http2',
+ f'--{ipv}', f'https://{authority}/'
+ ]
+ r = curl.run_direct(args=args, with_stats=True)
+ if r.exit_code == 0 and len(r.stats) == 1:
+ c_samples.append(r.stats[0]['time_connect'])
+ hs_samples.append(r.stats[0]['time_appconnect'])
+ else:
+ errors.append(f'exit={r.exit_code}')
+ props[authority][f'{ipv}-connect'] = mean(c_samples) \
+ if len(c_samples) else -1
+ props[authority][f'{ipv}-handshake'] = mean(hs_samples) \
+ if len(hs_samples) else -1
+ props[authority][f'{ipv}-errors'] = errors
+ self.info('ok.\n')
+ return props
+
+ def _make_docs_file(self, docs_dir: str, fname: str, fsize: int):
+ fpath = os.path.join(docs_dir, fname)
+ data1k = 1024*'x'
+ flen = 0
+ with open(fpath, 'w') as fd:
+ while flen < fsize:
+ fd.write(data1k)
+ flen += len(data1k)
+ return flen
+
+ def _check_downloads(self, r: ExecResult, count: int):
+ error = ''
+ if r.exit_code != 0:
+ error += f'exit={r.exit_code} '
+ if r.exit_code != 0 or len(r.stats) != count:
+ error += f'stats={len(r.stats)}/{count} '
+ fails = [s for s in r.stats if s['response_code'] != 200]
+ if len(fails) > 0:
+ error += f'{len(fails)} failed'
+ return error if len(error) > 0 else None
+
+ def transfer_single(self, url: str, proto: str, count: int):
+ sample_size = count
+ count = 1
+ samples = []
+ errors = []
+ self.info(f'single...')
+ for i in range(sample_size):
+ curl = CurlClient(env=self.env, silent=self._silent_curl)
+ r = curl.http_download(urls=[url], alpn_proto=proto, no_save=True,
+ with_headers=False)
+ err = self._check_downloads(r, count)
+ if err:
+ errors.append(err)
+ else:
+ total_size = sum([s['size_download'] for s in r.stats])
+ samples.append(total_size / r.duration.total_seconds())
+ return {
+ 'count': count,
+ 'samples': sample_size,
+ 'speed': mean(samples) if len(samples) else -1,
+ 'errors': errors
+ }
+
+ def transfer_serial(self, url: str, proto: str, count: int):
+ sample_size = 1
+ samples = []
+ errors = []
+ url = f'{url}?[0-{count - 1}]'
+ self.info(f'serial...')
+ for i in range(sample_size):
+ curl = CurlClient(env=self.env, silent=self._silent_curl)
+ r = curl.http_download(urls=[url], alpn_proto=proto, no_save=True,
+ with_headers=False)
+ err = self._check_downloads(r, count)
+ if err:
+ errors.append(err)
+ else:
+ total_size = sum([s['size_download'] for s in r.stats])
+ samples.append(total_size / r.duration.total_seconds())
+ return {
+ 'count': count,
+ 'samples': sample_size,
+ 'speed': mean(samples) if len(samples) else -1,
+ 'errors': errors
+ }
+
+ def transfer_parallel(self, url: str, proto: str, count: int):
+ sample_size = 1
+ samples = []
+ errors = []
+ url = f'{url}?[0-{count - 1}]'
+ self.info(f'parallel...')
+ for i in range(sample_size):
+ curl = CurlClient(env=self.env, silent=self._silent_curl)
+ r = curl.http_download(urls=[url], alpn_proto=proto, no_save=True,
+ with_headers=False,
+ extra_args=['--parallel',
+ '--parallel-max', str(count)])
+ err = self._check_downloads(r, count)
+ if err:
+ errors.append(err)
+ else:
+ total_size = sum([s['size_download'] for s in r.stats])
+ samples.append(total_size / r.duration.total_seconds())
+ return {
+ 'count': count,
+ 'samples': sample_size,
+ 'speed': mean(samples) if len(samples) else -1,
+ 'errors': errors
+ }
+
+ def download_url(self, label: str, url: str, proto: str, count: int):
+ self.info(f' {count}x{label}: ')
+ props = {
+ 'single': self.transfer_single(url=url, proto=proto, count=10),
+ 'serial': self.transfer_serial(url=url, proto=proto, count=count),
+ 'parallel': self.transfer_parallel(url=url, proto=proto,
+ count=count),
+ }
+ self.info(f'ok.\n')
+ return props
+
+ def downloads(self, proto: str, count: int,
+ fsizes: List[int]) -> Dict[str, Any]:
+ scores = {}
+ if self.httpd:
+ if proto == 'h3':
+ port = self.env.h3_port
+ via = 'nghttpx'
+ descr = f'port {port}, proxying httpd'
+ else:
+ port = self.env.https_port
+ via = 'httpd'
+ descr = f'port {port}'
+ self.info(f'{via} downloads\n')
+ scores[via] = {
+ 'description': descr,
+ }
+ for fsize in fsizes:
+ label = f'{int(fsize / 1024)}KB' if fsize < 1024*1024 else \
+ f'{int(fsize / (1024 * 1024))}MB'
+ fname = f'score{label}.data'
+ self._make_docs_file(docs_dir=self.httpd.docs_dir,
+ fname=fname, fsize=fsize)
+ url = f'https://{self.env.domain1}:{port}/{fname}'
+ results = self.download_url(label=label, url=url,
+ proto=proto, count=count)
+ scores[via][label] = results
+ if self.caddy:
+ port = self.caddy.port
+ via = 'caddy'
+ descr = f'port {port}'
+ self.info('caddy downloads\n')
+ scores[via] = {
+ 'description': descr,
+ }
+ for fsize in fsizes:
+ label = f'{int(fsize / 1024)}KB' if fsize < 1024*1024 else \
+ f'{int(fsize / (1024 * 1024))}MB'
+ fname = f'score{label}.data'
+ self._make_docs_file(docs_dir=self.caddy.docs_dir,
+ fname=fname, fsize=fsize)
+ url = f'https://{self.env.domain1}:{port}/{fname}'
+ results = self.download_url(label=label, url=url,
+ proto=proto, count=count)
+ scores[via][label] = results
+ return scores
+
+ def do_requests(self, url: str, proto: str, count: int,
+ max_parallel: int = 1):
+ sample_size = 1
+ samples = []
+ errors = []
+ url = f'{url}?[0-{count - 1}]'
+ extra_args = ['--parallel', '--parallel-max', str(max_parallel)] \
+ if max_parallel > 1 else []
+ self.info(f'{max_parallel}...')
+ for i in range(sample_size):
+ curl = CurlClient(env=self.env, silent=self._silent_curl)
+ r = curl.http_download(urls=[url], alpn_proto=proto, no_save=True,
+ with_headers=False,
+ extra_args=extra_args)
+ err = self._check_downloads(r, count)
+ if err:
+ errors.append(err)
+ else:
+ for _ in r.stats:
+ samples.append(count / r.duration.total_seconds())
+ return {
+ 'count': count,
+ 'samples': sample_size,
+ 'speed': mean(samples) if len(samples) else -1,
+ 'errors': errors
+ }
+
+ def requests_url(self, url: str, proto: str, count: int):
+ self.info(f' {url}: ')
+ props = {
+ 'serial': self.do_requests(url=url, proto=proto, count=count),
+ 'par-6': self.do_requests(url=url, proto=proto, count=count,
+ max_parallel=6),
+ 'par-25': self.do_requests(url=url, proto=proto, count=count,
+ max_parallel=25),
+ 'par-50': self.do_requests(url=url, proto=proto, count=count,
+ max_parallel=50),
+ 'par-100': self.do_requests(url=url, proto=proto, count=count,
+ max_parallel=100),
+ }
+ self.info(f'ok.\n')
+ return props
+
+ def requests(self, proto: str) -> Dict[str, Any]:
+ scores = {}
+ if self.httpd:
+ if proto == 'h3':
+ port = self.env.h3_port
+ via = 'nghttpx'
+ descr = f'port {port}, proxying httpd'
+ else:
+ port = self.env.https_port
+ via = 'httpd'
+ descr = f'port {port}'
+ self.info(f'{via} requests\n')
+ self._make_docs_file(docs_dir=self.httpd.docs_dir,
+ fname='reqs10.data', fsize=10*1024)
+ url1 = f'https://{self.env.domain1}:{port}/reqs10.data'
+ scores[via] = {
+ 'description': descr,
+ '10KB': self.requests_url(url=url1, proto=proto, count=10000),
+ }
+ if self.caddy:
+ port = self.caddy.port
+ via = 'caddy'
+ descr = f'port {port}'
+ self.info('caddy requests\n')
+ self._make_docs_file(docs_dir=self.caddy.docs_dir,
+ fname='req10.data', fsize=10 * 1024)
+ url1 = f'https://{self.env.domain1}:{port}/req10.data'
+ scores[via] = {
+ 'description': descr,
+ '10KB': self.requests_url(url=url1, proto=proto, count=5000),
+ }
+ return scores
+
+ def score_proto(self, proto: str,
+ handshakes: bool = True,
+ downloads: Optional[List[int]] = None,
+ download_count: int = 50,
+ requests: bool = True):
+ self.info(f"scoring {proto}\n")
+ p = {}
+ if proto == 'h3':
+ p['name'] = 'h3'
+ if not self.env.have_h3_curl():
+ raise ScoreCardException('curl does not support HTTP/3')
+ for lib in ['ngtcp2', 'quiche', 'msh3']:
+ if self.env.curl_uses_lib(lib):
+ p['implementation'] = lib
+ break
+ elif proto == 'h2':
+ p['name'] = 'h2'
+ if not self.env.have_h2_curl():
+ raise ScoreCardException('curl does not support HTTP/2')
+ for lib in ['nghttp2', 'hyper']:
+ if self.env.curl_uses_lib(lib):
+ p['implementation'] = lib
+ break
+ elif proto == 'h1' or proto == 'http/1.1':
+ proto = 'http/1.1'
+ p['name'] = proto
+ p['implementation'] = 'hyper' if self.env.curl_uses_lib('hyper')\
+ else 'native'
+ else:
+ raise ScoreCardException(f"unknown protocol: {proto}")
+
+ if 'implementation' not in p:
+ raise ScoreCardException(f'did not recognized {p} lib')
+ p['version'] = Env.curl_lib_version(p['implementation'])
+
+ score = {
+ 'curl': self.env.curl_fullname(),
+ 'os': self.env.curl_os(),
+ 'protocol': p,
+ }
+ if handshakes:
+ score['handshakes'] = self.handshakes(proto=proto)
+ if downloads and len(downloads) > 0:
+ score['downloads'] = self.downloads(proto=proto,
+ count=download_count,
+ fsizes=downloads)
+ if requests:
+ score['requests'] = self.requests(proto=proto)
+ self.info("\n")
+ return score
+
+ def fmt_ms(self, tval):
+ return f'{int(tval*1000)} ms' if tval >= 0 else '--'
+
+ def fmt_mb(self, val):
+ return f'{val/(1024*1024):0.000f} MB' if val >= 0 else '--'
+
+ def fmt_mbs(self, val):
+ return f'{val/(1024*1024):0.000f} MB/s' if val >= 0 else '--'
+
+ def fmt_reqs(self, val):
+ return f'{val:0.000f} r/s' if val >= 0 else '--'
+
+ def print_score(self, score):
+ print(f'{score["protocol"]["name"].upper()} in {score["curl"]}')
+ if 'handshakes' in score:
+ print(f'{"Handshakes":<24} {"ipv4":25} {"ipv6":28}')
+ print(f' {"Host":<17} {"Connect":>12} {"Handshake":>12} '
+ f'{"Connect":>12} {"Handshake":>12} {"Errors":<20}')
+ for key, val in score["handshakes"].items():
+ print(f' {key:<17} {self.fmt_ms(val["ipv4-connect"]):>12} '
+ f'{self.fmt_ms(val["ipv4-handshake"]):>12} '
+ f'{self.fmt_ms(val["ipv6-connect"]):>12} '
+ f'{self.fmt_ms(val["ipv6-handshake"]):>12} '
+ f'{"/".join(val["ipv4-errors"] + val["ipv6-errors"]):<20}'
+ )
+ if 'downloads' in score:
+ print('Downloads')
+ print(f' {"Server":<8} {"Size":>8} {"Single":>12} {"Serial":>12}'
+ f' {"Parallel":>12} {"Errors":<20}')
+ skeys = {}
+ for dkey, dval in score["downloads"].items():
+ for k in dval.keys():
+ skeys[k] = True
+ for skey in skeys:
+ for dkey, dval in score["downloads"].items():
+ if skey in dval:
+ sval = dval[skey]
+ if isinstance(sval, str):
+ continue
+ errors = []
+ for key, val in sval.items():
+ if 'errors' in val:
+ errors.extend(val['errors'])
+ print(f' {dkey:<8} {skey:>8} '
+ f'{self.fmt_mbs(sval["single"]["speed"]):>12} '
+ f'{self.fmt_mbs(sval["serial"]["speed"]):>12} '
+ f'{self.fmt_mbs(sval["parallel"]["speed"]):>12} '
+ f' {"/".join(errors):<20}')
+ if 'requests' in score:
+ print('Requests, max in parallel')
+ print(f' {"Server":<8} {"Size":>8} '
+ f'{"1 ":>12} {"6 ":>12} {"25 ":>12} '
+ f'{"50 ":>12} {"100 ":>12} {"Errors":<20}')
+ for dkey, dval in score["requests"].items():
+ for skey, sval in dval.items():
+ if isinstance(sval, str):
+ continue
+ errors = []
+ for key, val in sval.items():
+ if 'errors' in val:
+ errors.extend(val['errors'])
+ line = f' {dkey:<8} {skey:>8} '
+ for k in sval.keys():
+ line += f'{self.fmt_reqs(sval[k]["speed"]):>12} '
+ line += f' {"/".join(errors):<20}'
+ print(line)
+
+
+def parse_size(s):
+ m = re.match(r'(\d+)(mb|kb|gb)?', s, re.IGNORECASE)
+ if m is None:
+ raise Exception(f'unrecognized size: {s}')
+ size = int(m.group(1))
+ if m.group(2).lower() == 'kb':
+ size *= 1024
+ elif m.group(2).lower() == 'mb':
+ size *= 1024 * 1024
+ elif m.group(2).lower() == 'gb':
+ size *= 1024 * 1024 * 1024
+ return size
+
+
+def main():
+ parser = argparse.ArgumentParser(prog='scorecard', description="""
+ Run a range of tests to give a scorecard for a HTTP protocol
+ 'h3' or 'h2' implementation in curl.
+ """)
+ parser.add_argument("-v", "--verbose", action='count', default=1,
+ help="log more output on stderr")
+ parser.add_argument("-j", "--json", action='store_true',
+ default=False, help="print json instead of text")
+ parser.add_argument("-H", "--handshakes", action='store_true',
+ default=False, help="evaluate handshakes only")
+ parser.add_argument("-d", "--downloads", action='store_true',
+ default=False, help="evaluate downloads only")
+ parser.add_argument("--download", action='append', type=str,
+ default=None, help="evaluate download size")
+ parser.add_argument("--download-count", action='store', type=int,
+ default=50, help="perform that many downloads")
+ parser.add_argument("-r", "--requests", action='store_true',
+ default=False, help="evaluate requests only")
+ parser.add_argument("--httpd", action='store_true', default=False,
+ help="evaluate httpd server only")
+ parser.add_argument("--caddy", action='store_true', default=False,
+ help="evaluate caddy server only")
+ parser.add_argument("--curl-verbose", action='store_true',
+ default=False, help="run curl with `-v`")
+ parser.add_argument("protocol", default='h2', nargs='?',
+ help="Name of protocol to score")
+ args = parser.parse_args()
+
+ if args.verbose > 0:
+ console = logging.StreamHandler()
+ console.setLevel(logging.INFO)
+ console.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
+ logging.getLogger('').addHandler(console)
+
+ protocol = args.protocol
+ handshakes = True
+ downloads = [1024*1024, 10*1024*1024, 100*1024*1024]
+ requests = True
+ test_httpd = protocol != 'h3'
+ test_caddy = True
+ if args.handshakes:
+ downloads = None
+ requests = False
+ if args.downloads:
+ handshakes = False
+ requests = False
+ if args.download:
+ downloads = sorted([parse_size(x) for x in args.download])
+ handshakes = False
+ requests = False
+ if args.requests:
+ handshakes = False
+ downloads = None
+ if args.caddy:
+ test_caddy = True
+ test_httpd = False
+ if args.httpd:
+ test_caddy = False
+ test_httpd = True
+
+ rv = 0
+ env = Env()
+ env.setup()
+ env.test_timeout = None
+ httpd = None
+ nghttpx = None
+ caddy = None
+ try:
+ if test_httpd:
+ httpd = Httpd(env=env)
+ assert httpd.exists(), \
+ f'httpd not found: {env.httpd}'
+ httpd.clear_logs()
+ assert httpd.start()
+ if 'h3' == protocol:
+ nghttpx = Nghttpx(env=env)
+ nghttpx.clear_logs()
+ assert nghttpx.start()
+ if test_caddy and env.caddy:
+ caddy = Caddy(env=env)
+ caddy.clear_logs()
+ assert caddy.start()
+
+ card = ScoreCard(env=env, httpd=httpd, nghttpx=nghttpx, caddy=caddy,
+ verbose=args.verbose, curl_verbose=args.curl_verbose)
+ score = card.score_proto(proto=protocol,
+ handshakes=handshakes,
+ downloads=downloads,
+ download_count=args.download_count,
+ requests=requests)
+ if args.json:
+ print(json.JSONEncoder(indent=2).encode(score))
+ else:
+ card.print_score(score)
+
+ except ScoreCardException as ex:
+ sys.stderr.write(f"ERROR: {str(ex)}\n")
+ rv = 1
+ except KeyboardInterrupt:
+ log.warning("aborted")
+ rv = 1
+ finally:
+ if caddy:
+ caddy.stop()
+ if nghttpx:
+ nghttpx.stop(wait_dead=False)
+ if httpd:
+ httpd.stop()
+ sys.exit(rv)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/http/test_01_basic.py b/tests/http/test_01_basic.py
new file mode 100644
index 0000000..30b8700
--- /dev/null
+++ b/tests/http/test_01_basic.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import logging
+import pytest
+
+from testenv import Env
+from testenv import CurlClient
+
+
+log = logging.getLogger(__name__)
+
+
+class TestBasic:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, nghttpx):
+ if env.have_h3():
+ nghttpx.start_if_needed()
+
+ # simple http: GET
+ def test_01_01_http_get(self, env: Env, httpd):
+ curl = CurlClient(env=env)
+ url = f'http://{env.domain1}:{env.http_port}/data.json'
+ r = curl.http_get(url=url)
+ r.check_response(http_status=200)
+ assert r.json['server'] == env.domain1
+
+ # simple https: GET, any http version
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ def test_01_02_https_get(self, env: Env, httpd):
+ curl = CurlClient(env=env)
+ url = f'https://{env.domain1}:{env.https_port}/data.json'
+ r = curl.http_get(url=url)
+ r.check_response(http_status=200)
+ assert r.json['server'] == env.domain1
+
+ # simple https: GET, h2 wanted and got
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ def test_01_03_h2_get(self, env: Env, httpd):
+ curl = CurlClient(env=env)
+ url = f'https://{env.domain1}:{env.https_port}/data.json'
+ r = curl.http_get(url=url, extra_args=['--http2'])
+ r.check_response(http_status=200, protocol='HTTP/2')
+ assert r.json['server'] == env.domain1
+
+ # simple https: GET, h2 unsupported, fallback to h1
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ def test_01_04_h2_unsupported(self, env: Env, httpd):
+ curl = CurlClient(env=env)
+ url = f'https://{env.domain2}:{env.https_port}/data.json'
+ r = curl.http_get(url=url, extra_args=['--http2'])
+ r.check_response(http_status=200, protocol='HTTP/1.1')
+ assert r.json['server'] == env.domain2
+
+ # simple h3: GET, want h3 and get it
+ @pytest.mark.skipif(condition=not Env.have_h3(), reason="h3 not supported")
+ def test_01_05_h3_get(self, env: Env, httpd, nghttpx):
+ curl = CurlClient(env=env)
+ url = f'https://{env.domain1}:{env.h3_port}/data.json'
+ r = curl.http_get(url=url, extra_args=['--http3'])
+ r.check_response(http_status=200, protocol='HTTP/3')
+ assert r.json['server'] == env.domain1
diff --git a/tests/http/test_02_download.py b/tests/http/test_02_download.py
new file mode 100644
index 0000000..684c406
--- /dev/null
+++ b/tests/http/test_02_download.py
@@ -0,0 +1,364 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import difflib
+import filecmp
+import logging
+import os
+from datetime import timedelta
+import pytest
+
+from testenv import Env, CurlClient, LocalClient
+
+
+log = logging.getLogger(__name__)
+
+
+class TestDownload:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, httpd, nghttpx):
+ if env.have_h3():
+ nghttpx.start_if_needed()
+ httpd.clear_extra_configs()
+ httpd.reload()
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, httpd):
+ indir = httpd.docs_dir
+ env.make_data_file(indir=indir, fname="data-10k", fsize=10*1024)
+ env.make_data_file(indir=indir, fname="data-100k", fsize=100*1024)
+ env.make_data_file(indir=indir, fname="data-1m", fsize=1024*1024)
+ env.make_data_file(indir=indir, fname="data-10m", fsize=10*1024*1024)
+ env.make_data_file(indir=indir, fname="data-50m", fsize=50*1024*1024)
+
+ # download 1 file
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_02_01_download_1(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/data.json'
+ r = curl.http_download(urls=[url], alpn_proto=proto)
+ r.check_response(http_status=200)
+
+ # download 2 files
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_02_02_download_2(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-1]'
+ r = curl.http_download(urls=[url], alpn_proto=proto)
+ r.check_response(http_status=200, count=2)
+
+ # download 100 files sequentially
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_02_03_download_100_sequential(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-99]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto)
+ r.check_response(http_status=200, count=100, connect_count=1)
+
+ # download 100 files parallel
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_02_04_download_100_parallel(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ max_parallel = 6 if proto == 'http/1.1' else 50
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-99]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+ '--parallel', '--parallel-max', f'{max_parallel}'
+ ])
+ r.check_response(http_status=200, count=100)
+ if proto == 'http/1.1':
+ # http/1.1 parallel transfers will open multiple connections
+ assert r.total_connects > 1, r.dump_logs()
+ else:
+ # http2 parallel transfers will use one connection (common limit is 100)
+ assert r.total_connects == 1, r.dump_logs()
+
+ # download 500 files sequential
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_02_05_download_500_sequential(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 shaky here")
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-499]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto)
+ r.check_response(http_status=200, count=500)
+ if proto == 'http/1.1':
+ # http/1.1 parallel transfers will open multiple connections
+ assert r.total_connects > 1, r.dump_logs()
+ else:
+ # http2 parallel transfers will use one connection (common limit is 100)
+ assert r.total_connects == 1, r.dump_logs()
+
+ # download 500 files parallel
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_02_06_download_500_parallel(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 500
+ max_parallel = 50
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[000-{count-1}]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+ '--parallel', '--parallel-max', f'{max_parallel}'
+ ])
+ r.check_response(http_status=200, count=count, connect_count=1)
+
+ # download files parallel, check connection reuse/multiplex
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_02_07_download_reuse(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 200
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-{count-1}]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto,
+ with_stats=True, extra_args=[
+ '--parallel', '--parallel-max', '200'
+ ])
+ r.check_response(http_status=200, count=count)
+ # should have used at most 2 connections only (test servers allow 100 req/conn)
+ # it may be just 1 on slow systems where request are answered faster than
+ # curl can exhaust the capacity or if curl runs with address-sanitizer speed
+ assert r.total_connects <= 2, "h2 should use fewer connections here"
+
+ # download files parallel with http/1.1, check connection not reused
+ @pytest.mark.parametrize("proto", ['http/1.1'])
+ def test_02_07b_download_reuse(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ count = 20
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-{count-1}]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto,
+ with_stats=True, extra_args=[
+ '--parallel'
+ ])
+ r.check_response(count=count, http_status=200)
+ # http/1.1 should have used count connections
+ assert r.total_connects == count, "http/1.1 should use this many connections"
+
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_02_08_1MB_serial(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 20
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data-1m?[0-{count-1}]'
+ curl = CurlClient(env=env)
+ r = curl.http_download(urls=[urln], alpn_proto=proto)
+ r.check_response(count=count, http_status=200)
+
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_02_09_1MB_parallel(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 20
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data-1m?[0-{count-1}]'
+ curl = CurlClient(env=env)
+ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+ '--parallel'
+ ])
+ r.check_response(count=count, http_status=200)
+
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_02_10_10MB_serial(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 20
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data-10m?[0-{count-1}]'
+ curl = CurlClient(env=env)
+ r = curl.http_download(urls=[urln], alpn_proto=proto)
+ r.check_response(count=count, http_status=200)
+
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_02_11_10MB_parallel(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 stalls here")
+ count = 20
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data-10m?[0-{count-1}]'
+ curl = CurlClient(env=env)
+ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+ '--parallel'
+ ])
+ r.check_response(count=count, http_status=200)
+
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_02_12_head_serial_https(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 100
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data-10m?[0-{count-1}]'
+ curl = CurlClient(env=env)
+ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+ '--head'
+ ])
+ r.check_response(count=count, http_status=200)
+
+ @pytest.mark.parametrize("proto", ['h2'])
+ def test_02_13_head_serial_h2c(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 100
+ urln = f'http://{env.domain1}:{env.http_port}/data-10m?[0-{count-1}]'
+ curl = CurlClient(env=env)
+ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+ '--head', '--http2-prior-knowledge', '--fail-early'
+ ])
+ r.check_response(count=count, http_status=200)
+
+ def test_02_20_h2_small_frames(self, env: Env, httpd, repeat):
+ # Test case to reproduce content corruption as observed in
+ # https://github.com/curl/curl/issues/10525
+ # To reliably reproduce, we need an Apache httpd that supports
+ # setting smaller frame sizes. This is not released yet, we
+ # test if it works and back out if not.
+ httpd.set_extra_config(env.domain1, lines=[
+ f'H2MaxDataFrameLen 1024',
+ ])
+ assert httpd.stop()
+ if not httpd.start():
+ # no, not supported, bail out
+ httpd.set_extra_config(env.domain1, lines=None)
+ assert httpd.start()
+ pytest.skip(f'H2MaxDataFrameLen not supported')
+ # ok, make 100 downloads with 2 parallel running and they
+ # are expected to stumble into the issue when using `lib/http2.c`
+ # from curl 7.88.0
+ count = 100
+ urln = f'https://{env.authority_for(env.domain1, "h2")}/data-1m?[0-{count-1}]'
+ curl = CurlClient(env=env)
+ r = curl.http_download(urls=[urln], alpn_proto="h2", extra_args=[
+ '--parallel', '--parallel-max', '2'
+ ])
+ r.check_response(count=count, http_status=200)
+ srcfile = os.path.join(httpd.docs_dir, 'data-1m')
+ self.check_downloads(curl, srcfile, count)
+ # restore httpd defaults
+ httpd.set_extra_config(env.domain1, lines=None)
+ assert httpd.stop()
+ assert httpd.start()
+
+ # download via lib client, 1 at a time, pause/resume at different offsets
+ @pytest.mark.parametrize("pause_offset", [0, 10*1024, 100*1023, 640000])
+ def test_02_21_h2_lib_serial(self, env: Env, httpd, nghttpx, pause_offset, repeat):
+ count = 10
+ docname = 'data-10m'
+ url = f'https://localhost:{env.https_port}/{docname}'
+ client = LocalClient(name='h2-download', env=env)
+ if not client.exists():
+ pytest.skip(f'example client not built: {client.name}')
+ r = client.run(args=[
+ '-n', f'{count}', '-P', f'{pause_offset}', url
+ ])
+ r.check_exit_code(0)
+ srcfile = os.path.join(httpd.docs_dir, docname)
+ self.check_downloads(client, srcfile, count)
+
+ # download via lib client, several at a time, pause/resume
+ @pytest.mark.parametrize("pause_offset", [100*1023])
+ def test_02_22_h2_lib_parallel_resume(self, env: Env, httpd, nghttpx, pause_offset, repeat):
+ count = 10
+ max_parallel = 5
+ docname = 'data-10m'
+ url = f'https://localhost:{env.https_port}/{docname}'
+ client = LocalClient(name='h2-download', env=env)
+ if not client.exists():
+ pytest.skip(f'example client not built: {client.name}')
+ r = client.run(args=[
+ '-n', f'{count}', '-m', f'{max_parallel}',
+ '-P', f'{pause_offset}', url
+ ])
+ r.check_exit_code(0)
+ srcfile = os.path.join(httpd.docs_dir, docname)
+ self.check_downloads(client, srcfile, count)
+
+ # download, several at a time, pause and abort paused
+ @pytest.mark.parametrize("pause_offset", [100*1023])
+ def test_02_23_h2_lib_parallel_abort(self, env: Env, httpd, nghttpx, pause_offset, repeat):
+ count = 200
+ max_parallel = 100
+ docname = 'data-10m'
+ url = f'https://localhost:{env.https_port}/{docname}'
+ client = LocalClient(name='h2-download', env=env)
+ if not client.exists():
+ pytest.skip(f'example client not built: {client.name}')
+ r = client.run(args=[
+ '-n', f'{count}', '-m', f'{max_parallel}', '-a',
+ '-P', f'{pause_offset}', url
+ ])
+ r.check_exit_code(0)
+ srcfile = os.path.join(httpd.docs_dir, docname)
+ # downloads should be there, but not necessarily complete
+ self.check_downloads(client, srcfile, count, complete=False)
+
+ # speed limited download
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_02_24_speed_limit(self, env: Env, httpd, nghttpx, proto, repeat):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 1
+ url = f'https://{env.authority_for(env.domain1, proto)}/data-1m'
+ curl = CurlClient(env=env)
+ r = curl.http_download(urls=[url], alpn_proto=proto, extra_args=[
+ '--limit-rate', f'{196 * 1024}'
+ ])
+ r.check_response(count=count, http_status=200)
+ assert r.duration > timedelta(seconds=4), \
+ f'rate limited transfer should take more than 4s, not {r.duration}'
+
+ def check_downloads(self, client, srcfile: str, count: int,
+ complete: bool = True):
+ for i in range(count):
+ dfile = client.download_file(i)
+ assert os.path.exists(dfile)
+ if complete and not filecmp.cmp(srcfile, dfile, shallow=False):
+ diff = "".join(difflib.unified_diff(a=open(srcfile).readlines(),
+ b=open(dfile).readlines(),
+ fromfile=srcfile,
+ tofile=dfile,
+ n=1))
+ assert False, f'download {dfile} differs:\n{diff}'
diff --git a/tests/http/test_03_goaway.py b/tests/http/test_03_goaway.py
new file mode 100644
index 0000000..00fbce9
--- /dev/null
+++ b/tests/http/test_03_goaway.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import logging
+import time
+from datetime import timedelta
+from threading import Thread
+import pytest
+
+from testenv import Env, CurlClient, ExecResult
+
+
+log = logging.getLogger(__name__)
+
+
+class TestGoAway:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, httpd, nghttpx):
+ if env.have_h3():
+ nghttpx.start_if_needed()
+ httpd.clear_extra_configs()
+ httpd.reload()
+
+ # download files sequentially with delay, reload server for GOAWAY
+ def test_03_01_h2_goaway(self, env: Env, httpd, nghttpx, repeat):
+ proto = 'h2'
+ count = 3
+ self.r = None
+ def long_run():
+ curl = CurlClient(env=env)
+ # send 10 chunks of 1024 bytes in a response body with 100ms delay in between
+ urln = f'https://{env.authority_for(env.domain1, proto)}' \
+ f'/curltest/tweak?id=[0-{count - 1}]'\
+ '&chunks=10&chunk_size=1024&chunk_delay=100ms'
+ self.r = curl.http_download(urls=[urln], alpn_proto=proto)
+
+ t = Thread(target=long_run)
+ t.start()
+ # each request will take a second, reload the server in the middle
+ # of the first one.
+ time.sleep(1.5)
+ assert httpd.reload()
+ t.join()
+ r: ExecResult = self.r
+ r.check_response(count=count, http_status=200)
+ # reload will shut down the connection gracefully with GOAWAY
+ # we expect to see a second connection opened afterwards
+ assert r.total_connects == 2
+ for idx, s in enumerate(r.stats):
+ if s['num_connects'] > 0:
+ log.debug(f'request {idx} connected')
+ # this should take `count` seconds to retrieve
+ assert r.duration >= timedelta(seconds=count)
+
+ # download files sequentially with delay, reload server for GOAWAY
+ @pytest.mark.skipif(condition=not Env.have_h3(), reason="h3 not supported")
+ def test_03_02_h3_goaway(self, env: Env, httpd, nghttpx, repeat):
+ proto = 'h3'
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 stalls here")
+ count = 3
+ self.r = None
+ def long_run():
+ curl = CurlClient(env=env)
+ # send 10 chunks of 1024 bytes in a response body with 100ms delay in between
+ urln = f'https://{env.authority_for(env.domain1, proto)}' \
+ f'/curltest/tweak?id=[0-{count - 1}]'\
+ '&chunks=10&chunk_size=1024&chunk_delay=100ms'
+ self.r = curl.http_download(urls=[urln], alpn_proto=proto)
+
+ t = Thread(target=long_run)
+ t.start()
+ # each request will take a second, reload the server in the middle
+ # of the first one.
+ time.sleep(1.5)
+ assert nghttpx.reload(timeout=timedelta(seconds=2))
+ t.join()
+ r: ExecResult = self.r
+ # this should take `count` seconds to retrieve
+ assert r.duration >= timedelta(seconds=count)
+ r.check_response(count=count, http_status=200, connect_count=2)
+ # reload will shut down the connection gracefully with GOAWAY
+ # we expect to see a second connection opened afterwards
+ for idx, s in enumerate(r.stats):
+ if s['num_connects'] > 0:
+ log.debug(f'request {idx} connected')
+
+ # download files sequentially with delay, reload server for GOAWAY
+ def test_03_03_h1_goaway(self, env: Env, httpd, nghttpx, repeat):
+ proto = 'http/1.1'
+ count = 3
+ self.r = None
+ def long_run():
+ curl = CurlClient(env=env)
+ # send 10 chunks of 1024 bytes in a response body with 100ms delay in between
+ urln = f'https://{env.authority_for(env.domain1, proto)}' \
+ f'/curltest/tweak?id=[0-{count - 1}]'\
+ '&chunks=10&chunk_size=1024&chunk_delay=100ms'
+ self.r = curl.http_download(urls=[urln], alpn_proto=proto)
+
+ t = Thread(target=long_run)
+ t.start()
+ # each request will take a second, reload the server in the middle
+ # of the first one.
+ time.sleep(1.5)
+ assert httpd.reload()
+ t.join()
+ r: ExecResult = self.r
+ r.check_response(count=count, http_status=200, connect_count=2)
+ # reload will shut down the connection gracefully with GOAWAY
+ # we expect to see a second connection opened afterwards
+ for idx, s in enumerate(r.stats):
+ if s['num_connects'] > 0:
+ log.debug(f'request {idx} connected')
+ # this should take `count` seconds to retrieve
+ assert r.duration >= timedelta(seconds=count)
+
+
diff --git a/tests/http/test_04_stuttered.py b/tests/http/test_04_stuttered.py
new file mode 100644
index 0000000..2a5f1e2
--- /dev/null
+++ b/tests/http/test_04_stuttered.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import logging
+from typing import Tuple, List, Dict
+import pytest
+
+from testenv import Env, CurlClient
+
+
+log = logging.getLogger(__name__)
+
+
+class TestStuttered:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, httpd, nghttpx):
+ if env.have_h3():
+ nghttpx.start_if_needed()
+ httpd.clear_extra_configs()
+ httpd.reload()
+
+ # download 1 file, check that delayed response works in general
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_04_01_download_1(self, env: Env, httpd, nghttpx, repeat,
+ proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 1
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, proto)}' \
+ f'/curltest/tweak?id=[0-{count - 1}]'\
+ '&chunks=100&chunk_size=100&chunk_delay=10ms'
+ r = curl.http_download(urls=[urln], alpn_proto=proto)
+ r.check_response(count=1, http_status=200)
+
+ # download 50 files in 100 chunks a 100 bytes with 10ms delay between
+ # prepend 100 file requests to warm up connection processing limits
+ # (Apache2 increases # of parallel processed requests after successes)
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_04_02_100_100_10(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 50
+ warmups = 100
+ curl = CurlClient(env=env)
+ url1 = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-{warmups-1}]'
+ urln = f'https://{env.authority_for(env.domain1, proto)}' \
+ f'/curltest/tweak?id=[0-{count-1}]'\
+ '&chunks=100&chunk_size=100&chunk_delay=10ms'
+ r = curl.http_download(urls=[url1, urln], alpn_proto=proto,
+ extra_args=['--parallel'])
+ r.check_response(count=warmups+count, http_status=200)
+ assert r.total_connects == 1
+ t_avg, i_min, t_min, i_max, t_max = self.stats_spread(r.stats[warmups:], 'time_total')
+ if t_max < (5 * t_min) and t_min < 2:
+ log.warning(f'avg time of transfer: {t_avg} [{i_min}={t_min}, {i_max}={t_max}]')
+
+ # download 50 files in 1000 chunks a 10 bytes with 1ms delay between
+ # prepend 100 file requests to warm up connection processing limits
+ # (Apache2 increases # of parallel processed requests after successes)
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_04_03_1000_10_1(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 50
+ warmups = 100
+ curl = CurlClient(env=env)
+ url1 = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-{warmups-1}]'
+ urln = f'https://{env.authority_for(env.domain1, proto)}' \
+ f'/curltest/tweak?id=[0-{count - 1}]'\
+ '&chunks=1000&chunk_size=10&chunk_delay=100us'
+ r = curl.http_download(urls=[url1, urln], alpn_proto=proto,
+ extra_args=['--parallel'])
+ r.check_response(count=warmups+count, http_status=200)
+ assert r.total_connects == 1
+ t_avg, i_min, t_min, i_max, t_max = self.stats_spread(r.stats[warmups:], 'time_total')
+ if t_max < (5 * t_min):
+ log.warning(f'avg time of transfer: {t_avg} [{i_min}={t_min}, {i_max}={t_max}]')
+
+ # download 50 files in 10000 chunks a 1 byte with 10us delay between
+ # prepend 100 file requests to warm up connection processing limits
+ # (Apache2 increases # of parallel processed requests after successes)
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_04_04_1000_10_1(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 50
+ warmups = 100
+ curl = CurlClient(env=env)
+ url1 = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-{warmups-1}]'
+ urln = f'https://{env.authority_for(env.domain1, proto)}' \
+ f'/curltest/tweak?id=[0-{count - 1}]'\
+ '&chunks=10000&chunk_size=1&chunk_delay=50us'
+ r = curl.http_download(urls=[url1, urln], alpn_proto=proto,
+ extra_args=['--parallel'])
+ r.check_response(count=warmups+count, http_status=200)
+ assert r.total_connects == 1
+ t_avg, i_min, t_min, i_max, t_max = self.stats_spread(r.stats[warmups:], 'time_total')
+ if t_max < (5 * t_min):
+ log.warning(f'avg time of transfer: {t_avg} [{i_min}={t_min}, {i_max}={t_max}]')
+
+ def stats_spread(self, stats: List[Dict], key: str) -> Tuple[float, int, float, int, float]:
+ stotals = 0.0
+ s_min = 100.0
+ i_min = -1
+ s_max = 0.0
+ i_max = -1
+ for idx, s in enumerate(stats):
+ val = float(s[key])
+ stotals += val
+ if val > s_max:
+ s_max = val
+ i_max = idx
+ if val < s_min:
+ s_min = val
+ i_min = idx
+ return stotals/len(stats), i_min, s_min, i_max, s_max
diff --git a/tests/http/test_05_errors.py b/tests/http/test_05_errors.py
new file mode 100644
index 0000000..ecace5f
--- /dev/null
+++ b/tests/http/test_05_errors.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import json
+import logging
+from typing import Optional, Tuple, List, Dict
+import pytest
+
+from testenv import Env, CurlClient, ExecResult
+
+
+log = logging.getLogger(__name__)
+
+
+@pytest.mark.skipif(condition=not Env.httpd_is_at_least('2.4.55'),
+ reason=f"httpd version too old for this: {Env.httpd_version()}")
+class TestErrors:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, httpd, nghttpx):
+ if env.have_h3():
+ nghttpx.start_if_needed()
+ httpd.clear_extra_configs()
+ httpd.reload()
+
+ # download 1 file, check that we get CURLE_PARTIAL_FILE
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_05_01_partial_1(self, env: Env, httpd, nghttpx, repeat,
+ proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 stalls here")
+ count = 1
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, proto)}' \
+ f'/curltest/tweak?id=[0-{count - 1}]'\
+ '&chunks=3&chunk_size=16000&body_error=reset'
+ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+ '--retry', '0'
+ ])
+ r.check_exit_code(False)
+ invalid_stats = []
+ for idx, s in enumerate(r.stats):
+ if 'exitcode' not in s or s['exitcode'] not in [18, 56, 92]:
+ invalid_stats.append(f'request {idx} exit with {s["exitcode"]}')
+ assert len(invalid_stats) == 0, f'failed: {invalid_stats}'
+
+ # download files, check that we get CURLE_PARTIAL_FILE for all
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_05_02_partial_20(self, env: Env, httpd, nghttpx, repeat,
+ proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 stalls here")
+ count = 20
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, proto)}' \
+ f'/curltest/tweak?id=[0-{count - 1}]'\
+ '&chunks=5&chunk_size=16000&body_error=reset'
+ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+ '--retry', '0', '--parallel',
+ ])
+ r.check_exit_code(False)
+ assert len(r.stats) == count, f'did not get all stats: {r}'
+ invalid_stats = []
+ for idx, s in enumerate(r.stats):
+ if 'exitcode' not in s or s['exitcode'] not in [18, 55, 56, 92, 95]:
+ invalid_stats.append(f'request {idx} exit with {s["exitcode"]}\n{s}')
+ assert len(invalid_stats) == 0, f'failed: {invalid_stats}'
+
+ # access a resource that, on h2, RST the stream with HTTP_1_1_REQUIRED
+ def test_05_03_required(self, env: Env, httpd, nghttpx, repeat):
+ curl = CurlClient(env=env)
+ proto = 'http/1.1'
+ urln = f'https://{env.authority_for(env.domain1, proto)}/curltest/1_1'
+ r = curl.http_download(urls=[urln], alpn_proto=proto)
+ r.check_exit_code(0)
+ r.check_response(http_status=200, count=1)
+ proto = 'h2'
+ urln = f'https://{env.authority_for(env.domain1, proto)}/curltest/1_1'
+ r = curl.http_download(urls=[urln], alpn_proto=proto)
+ r.check_exit_code(0)
+ r.check_response(http_status=200, count=1)
+ # check that we did a downgrade
+ assert r.stats[0]['http_version'] == '1.1', r.dump_logs()
+
diff --git a/tests/http/test_06_eyeballs.py b/tests/http/test_06_eyeballs.py
new file mode 100644
index 0000000..3eeb079
--- /dev/null
+++ b/tests/http/test_06_eyeballs.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import json
+import logging
+from typing import Optional, Tuple, List, Dict
+import pytest
+
+from testenv import Env, CurlClient, ExecResult
+
+
+log = logging.getLogger(__name__)
+
+
+class TestEyeballs:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, httpd, nghttpx):
+ if env.have_h3():
+ nghttpx.start_if_needed()
+ httpd.clear_extra_configs()
+ httpd.reload()
+
+ # download using only HTTP/3 on working server
+ @pytest.mark.skipif(condition=not Env.have_h3(), reason=f"missing HTTP/3 support")
+ def test_06_01_h3_only(self, env: Env, httpd, nghttpx, repeat):
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, "h3")}/data.json'
+ r = curl.http_download(urls=[urln], extra_args=['--http3-only'])
+ r.check_response(count=1, http_status=200)
+ assert r.stats[0]['http_version'] == '3'
+
+ # download using only HTTP/3 on missing server
+ @pytest.mark.skipif(condition=not Env.have_h3(), reason=f"missing HTTP/3 support")
+ def test_06_02_h3_only(self, env: Env, httpd, nghttpx, repeat):
+ nghttpx.stop_if_running()
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, "h3")}/data.json'
+ r = curl.http_download(urls=[urln], extra_args=['--http3-only'])
+ r.check_response(exitcode=7, http_status=None)
+
+ # download using HTTP/3 on missing server with fallback on h2
+ @pytest.mark.skipif(condition=not Env.have_h3(), reason=f"missing HTTP/3 support")
+ def test_06_03_h3_fallback_h2(self, env: Env, httpd, nghttpx, repeat):
+ nghttpx.stop_if_running()
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, "h3")}/data.json'
+ r = curl.http_download(urls=[urln], extra_args=['--http3'])
+ r.check_response(count=1, http_status=200)
+ assert r.stats[0]['http_version'] == '2'
+
+ # download using HTTP/3 on missing server with fallback on http/1.1
+ @pytest.mark.skipif(condition=not Env.have_h3(), reason=f"missing HTTP/3 support")
+ def test_06_04_h3_fallback_h1(self, env: Env, httpd, nghttpx, repeat):
+ nghttpx.stop_if_running()
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain2, "h3")}/data.json'
+ r = curl.http_download(urls=[urln], extra_args=['--http3'])
+ r.check_response(count=1, http_status=200)
+ assert r.stats[0]['http_version'] == '1.1'
+
+ # make a successful https: transfer and observer the timer stats
+ def test_06_10_stats_success(self, env: Env, httpd, nghttpx, repeat):
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, "h2")}/data.json'
+ r = curl.http_download(urls=[urln])
+ r.check_response(count=1, http_status=200)
+ assert r.stats[0]['time_connect'] > 0.0
+ assert r.stats[0]['time_appconnect'] > 0.0
+
+ # make https: to a hostname that tcp connects, but will not verify
+ def test_06_11_stats_fail_verify(self, env: Env, httpd, nghttpx, repeat):
+ curl = CurlClient(env=env)
+ urln = f'https://not-valid.com:{env.https_port}/data.json'
+ r = curl.http_download(urls=[urln], extra_args=[
+ '--resolve', f'not-valid.com:{env.https_port}:127.0.0.1'
+ ])
+ r.check_response(count=1, http_status=0, exitcode=False)
+ assert r.stats[0]['time_connect'] > 0.0 # was tcp connected
+ assert r.stats[0]['time_appconnect'] == 0 # but not SSL verified
+
+ # make https: to an invalid address
+ def test_06_12_stats_fail_tcp(self, env: Env, httpd, nghttpx, repeat):
+ curl = CurlClient(env=env)
+ urln = f'https://not-valid.com:1/data.json'
+ r = curl.http_download(urls=[urln], extra_args=[
+ '--resolve', f'not-valid.com:{1}:127.0.0.1'
+ ])
+ r.check_response(count=1, http_status=None, exitcode=False)
+ assert r.stats[0]['time_connect'] == 0 # no one should have listened
+ assert r.stats[0]['time_appconnect'] == 0 # did not happen either
+
diff --git a/tests/http/test_07_upload.py b/tests/http/test_07_upload.py
new file mode 100644
index 0000000..84a23b2
--- /dev/null
+++ b/tests/http/test_07_upload.py
@@ -0,0 +1,318 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import difflib
+import filecmp
+import logging
+import os
+import pytest
+
+from testenv import Env, CurlClient
+
+
+log = logging.getLogger(__name__)
+
+
+class TestUpload:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, httpd, nghttpx):
+ if env.have_h3():
+ nghttpx.start_if_needed()
+ env.make_data_file(indir=env.gen_dir, fname="data-100k", fsize=100*1024)
+ env.make_data_file(indir=env.gen_dir, fname="data-10m", fsize=10*1024*1024)
+ httpd.clear_extra_configs()
+ httpd.reload()
+
+ # upload small data, check that this is what was echoed
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_07_01_upload_1_small(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 fails here")
+ data = '0123456789'
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]'
+ r = curl.http_upload(urls=[url], data=data, alpn_proto=proto)
+ r.check_response(count=1, http_status=200)
+ respdata = open(curl.response_file(0)).readlines()
+ assert respdata == [data]
+
+ # upload large data, check that this is what was echoed
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_07_02_upload_1_large(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 fails here")
+ fdata = os.path.join(env.gen_dir, 'data-100k')
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]'
+ r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto)
+ r.check_response(count=1, http_status=200)
+ indata = open(fdata).readlines()
+ respdata = open(curl.response_file(0)).readlines()
+ assert respdata == indata
+
+ # upload data sequentially, check that they were echoed
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_07_10_upload_sequential(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 stalls here")
+ count = 50
+ data = '0123456789'
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-{count-1}]'
+ r = curl.http_upload(urls=[url], data=data, alpn_proto=proto)
+ r.check_response(count=count, http_status=200)
+ for i in range(count):
+ respdata = open(curl.response_file(i)).readlines()
+ assert respdata == [data]
+
+ # upload data parallel, check that they were echoed
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_07_11_upload_parallel(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 stalls here")
+ # limit since we use a separate connection in h1
+ count = 50
+ data = '0123456789'
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-{count-1}]'
+ r = curl.http_upload(urls=[url], data=data, alpn_proto=proto,
+ extra_args=['--parallel'])
+ r.check_response(count=count, http_status=200)
+ for i in range(count):
+ respdata = open(curl.response_file(i)).readlines()
+ assert respdata == [data]
+
+ # upload large data sequentially, check that this is what was echoed
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_07_20_upload_seq_large(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 stalls here")
+ fdata = os.path.join(env.gen_dir, 'data-100k')
+ count = 50
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-{count-1}]'
+ r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto)
+ r.check_response(count=count, http_status=200)
+ indata = open(fdata).readlines()
+ r.check_response(count=count, http_status=200)
+ for i in range(count):
+ respdata = open(curl.response_file(i)).readlines()
+ assert respdata == indata
+
+ # upload very large data sequentially, check that this is what was echoed
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_07_12_upload_seq_large(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 stalls here")
+ fdata = os.path.join(env.gen_dir, 'data-10m')
+ count = 2
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-{count-1}]'
+ r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto)
+ r.check_response(count=count, http_status=200)
+ indata = open(fdata).readlines()
+ for i in range(count):
+ respdata = open(curl.response_file(i)).readlines()
+ assert respdata == indata
+
+ # upload data parallel, check that they were echoed
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_07_20_upload_parallel(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 stalls here")
+ # limit since we use a separate connection in h1
+ count = 50
+ data = '0123456789'
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-{count-1}]'
+ r = curl.http_upload(urls=[url], data=data, alpn_proto=proto,
+ extra_args=['--parallel'])
+ r.check_response(count=count, http_status=200)
+ for i in range(count):
+ respdata = open(curl.response_file(i)).readlines()
+ assert respdata == [data]
+
+ # upload large data parallel, check that this is what was echoed
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_07_21_upload_parallel_large(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 stalls here")
+ fdata = os.path.join(env.gen_dir, 'data-100k')
+ # limit since we use a separate connection in h1
+ count = 50
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-{count-1}]'
+ r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto,
+ extra_args=['--parallel'])
+ r.check_response(count=count, http_status=200)
+ self.check_download(count, fdata, curl)
+
+ # PUT 100k
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_07_30_put_100k(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 fails here")
+ fdata = os.path.join(env.gen_dir, 'data-100k')
+ count = 1
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?id=[0-{count-1}]'
+ r = curl.http_put(urls=[url], fdata=fdata, alpn_proto=proto,
+ extra_args=['--parallel'])
+ r.check_response(count=count, http_status=200)
+ exp_data = [f'{os.path.getsize(fdata)}']
+ r.check_response(count=count, http_status=200)
+ for i in range(count):
+ respdata = open(curl.response_file(i)).readlines()
+ assert respdata == exp_data
+
+ # PUT 10m
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_07_31_put_10m(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 fails here")
+ fdata = os.path.join(env.gen_dir, 'data-10m')
+ count = 1
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?id=[0-{count-1}]&chunk_delay=10ms'
+ r = curl.http_put(urls=[url], fdata=fdata, alpn_proto=proto,
+ extra_args=['--parallel'])
+ r.check_response(count=count, http_status=200)
+ exp_data = [f'{os.path.getsize(fdata)}']
+ r.check_response(count=count, http_status=200)
+ for i in range(count):
+ respdata = open(curl.response_file(i)).readlines()
+ assert respdata == exp_data
+
+ # issue #10591
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_07_32_issue_10591(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 fails here")
+ fdata = os.path.join(env.gen_dir, 'data-10m')
+ count = 1
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?id=[0-{count-1}]'
+ r = curl.http_put(urls=[url], fdata=fdata, alpn_proto=proto)
+ r.check_response(count=count, http_status=200)
+
+ # issue #11157, upload that is 404'ed by server, needs to terminate
+ # correctly and not time out on sending
+ def test_07_33_issue_11157a(self, env: Env, httpd, nghttpx, repeat):
+ proto = 'h2'
+ fdata = os.path.join(env.gen_dir, 'data-10m')
+ # send a POST to our PUT handler which will send immediately a 404 back
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put'
+ curl = CurlClient(env=env)
+ r = curl.run_direct(with_stats=True, args=[
+ '--resolve', f'{env.authority_for(env.domain1, proto)}:127.0.0.1',
+ '--cacert', env.ca.cert_file,
+ '--request', 'POST',
+ '--max-time', '5', '-v',
+ '--url', url,
+ '--form', 'idList=12345678',
+ '--form', 'pos=top',
+ '--form', 'name=mr_test',
+ '--form', f'fileSource=@{fdata};type=application/pdf',
+ ])
+ assert r.exit_code == 0, f'{r}'
+ r.check_stats(1, 404)
+
+ # issue #11157, send upload that is slowly read in
+ def test_07_33_issue_11157b(self, env: Env, httpd, nghttpx, repeat):
+ proto = 'h2'
+ fdata = os.path.join(env.gen_dir, 'data-10m')
+ # tell our test PUT handler to read the upload more slowly, so
+ # that the send buffering and transfer loop needs to wait
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?chunk_delay=2ms'
+ curl = CurlClient(env=env)
+ r = curl.run_direct(with_stats=True, args=[
+ '--resolve', f'{env.authority_for(env.domain1, proto)}:127.0.0.1',
+ '--cacert', env.ca.cert_file,
+ '--request', 'PUT',
+ '--max-time', '10', '-v',
+ '--url', url,
+ '--form', 'idList=12345678',
+ '--form', 'pos=top',
+ '--form', 'name=mr_test',
+ '--form', f'fileSource=@{fdata};type=application/pdf',
+ ])
+ assert r.exit_code == 0, r.dump_logs()
+ r.check_stats(1, 200)
+
+ def test_07_34_issue_11194(self, env: Env, httpd, nghttpx, repeat):
+ proto = 'h2'
+ fdata = os.path.join(env.gen_dir, 'data-10m')
+ # tell our test PUT handler to read the upload more slowly, so
+ # that the send buffering and transfer loop needs to wait
+ fdata = os.path.join(env.gen_dir, 'data-100k')
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put'
+ curl = CurlClient(env=env)
+ r = curl.run_direct(with_stats=True, args=[
+ '--verbose',
+ '--resolve', f'{env.authority_for(env.domain1, proto)}:127.0.0.1',
+ '--cacert', env.ca.cert_file,
+ '--request', 'PUT',
+ '--digest', '--user', 'test:test',
+ '--data-binary', f'@{fdata}'
+ '--url', url,
+ ])
+ assert r.exit_code == 0, r.dump_logs()
+ r.check_stats(1, 200)
+
+ def check_download(self, count, srcfile, curl):
+ for i in range(count):
+ dfile = curl.download_file(i)
+ assert os.path.exists(dfile)
+ if not filecmp.cmp(srcfile, dfile, shallow=False):
+ diff = "".join(difflib.unified_diff(a=open(srcfile).readlines(),
+ b=open(dfile).readlines(),
+ fromfile=srcfile,
+ tofile=dfile,
+ n=1))
+ assert False, f'download {dfile} differs:\n{diff}'
diff --git a/tests/http/test_08_caddy.py b/tests/http/test_08_caddy.py
new file mode 100644
index 0000000..1574192
--- /dev/null
+++ b/tests/http/test_08_caddy.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import logging
+import os
+import pytest
+
+from testenv import Env, CurlClient, Caddy
+
+
+log = logging.getLogger(__name__)
+
+
+@pytest.mark.skipif(condition=not Env.has_caddy(), reason=f"missing caddy")
+@pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+class TestCaddy:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def caddy(self, env):
+ caddy = Caddy(env=env)
+ assert caddy.start()
+ yield caddy
+ caddy.stop()
+
+ def _make_docs_file(self, docs_dir: str, fname: str, fsize: int):
+ fpath = os.path.join(docs_dir, fname)
+ data1k = 1024*'x'
+ flen = 0
+ with open(fpath, 'w') as fd:
+ while flen < fsize:
+ fd.write(data1k)
+ flen += len(data1k)
+ return flen
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, caddy):
+ self._make_docs_file(docs_dir=caddy.docs_dir, fname='data1.data', fsize=1024*1024)
+ self._make_docs_file(docs_dir=caddy.docs_dir, fname='data5.data', fsize=5*1024*1024)
+ self._make_docs_file(docs_dir=caddy.docs_dir, fname='data10.data', fsize=10*1024*1024)
+ self._make_docs_file(docs_dir=caddy.docs_dir, fname='data100.data', fsize=100*1024*1024)
+
+ # download 1 file
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_08_01_download_1(self, env: Env, caddy: Caddy, repeat, proto):
+ if proto == 'h3' and not env.have_h3_curl():
+ pytest.skip("h3 not supported in curl")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 itself crashes")
+ curl = CurlClient(env=env)
+ url = f'https://{env.domain1}:{caddy.port}/data.json'
+ r = curl.http_download(urls=[url], alpn_proto=proto)
+ r.check_response(count=1, http_status=200)
+
+ # download 1MB files sequentially
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_08_02_download_1mb_sequential(self, env: Env, caddy: Caddy,
+ repeat, proto):
+ if proto == 'h3' and not env.have_h3_curl():
+ pytest.skip("h3 not supported in curl")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 itself crashes")
+ count = 50
+ curl = CurlClient(env=env)
+ urln = f'https://{env.domain1}:{caddy.port}/data1.data?[0-{count-1}]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto)
+ r.check_response(count=count, http_status=200, connect_count=1)
+
+ # download 1MB files parallel
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_08_03_download_1mb_parallel(self, env: Env, caddy: Caddy,
+ repeat, proto):
+ if proto == 'h3' and not env.have_h3_curl():
+ pytest.skip("h3 not supported in curl")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 itself crashes")
+ count = 20
+ curl = CurlClient(env=env)
+ urln = f'https://{env.domain1}:{caddy.port}/data1.data?[0-{count-1}]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+ '--parallel'
+ ])
+ r.check_response(count=count, http_status=200)
+ if proto == 'http/1.1':
+ # http/1.1 parallel transfers will open multiple connections
+ assert r.total_connects > 1, r.dump_logs()
+ else:
+ assert r.total_connects == 1, r.dump_logs()
+
+ # download 5MB files sequentially
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_08_04a_download_10mb_sequential(self, env: Env, caddy: Caddy,
+ repeat, proto):
+ if proto == 'h3' and not env.have_h3_curl():
+ pytest.skip("h3 not supported in curl")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 itself crashes")
+ count = 40
+ curl = CurlClient(env=env)
+ urln = f'https://{env.domain1}:{caddy.port}/data5.data?[0-{count-1}]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto)
+ r.check_response(count=count, http_status=200, connect_count=1)
+
+ # download 10MB files sequentially
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_08_04b_download_10mb_sequential(self, env: Env, caddy: Caddy,
+ repeat, proto):
+ if proto == 'h3' and not env.have_h3_curl():
+ pytest.skip("h3 not supported in curl")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 itself crashes")
+ count = 20
+ curl = CurlClient(env=env)
+ urln = f'https://{env.domain1}:{caddy.port}/data10.data?[0-{count-1}]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto)
+ r.check_response(count=count, http_status=200, connect_count=1)
+
+ # download 10MB files parallel
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_08_05_download_1mb_parallel(self, env: Env, caddy: Caddy,
+ repeat, proto):
+ if proto == 'h3' and not env.have_h3_curl():
+ pytest.skip("h3 not supported in curl")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 itself crashes")
+ count = 50
+ curl = CurlClient(env=env)
+ urln = f'https://{env.domain1}:{caddy.port}/data10.data?[0-{count-1}]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+ '--parallel'
+ ])
+ r.check_response(count=count, http_status=200)
+ if proto == 'http/1.1':
+ # http/1.1 parallel transfers will open multiple connections
+ assert r.total_connects > 1, r.dump_logs()
+ else:
+ assert r.total_connects == 1, r.dump_logs()
+
diff --git a/tests/http/test_09_push.py b/tests/http/test_09_push.py
new file mode 100644
index 0000000..92d4a59
--- /dev/null
+++ b/tests/http/test_09_push.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import logging
+import os
+import pytest
+
+from testenv import Env, CurlClient, LocalClient
+
+
+log = logging.getLogger(__name__)
+
+
+class TestPush:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, httpd):
+ push_dir = os.path.join(httpd.docs_dir, 'push')
+ if not os.path.exists(push_dir):
+ os.makedirs(push_dir)
+ env.make_data_file(indir=push_dir, fname="data1", fsize=1*1024)
+ env.make_data_file(indir=push_dir, fname="data2", fsize=1*1024)
+ env.make_data_file(indir=push_dir, fname="data3", fsize=1*1024)
+ httpd.set_extra_config(env.domain1, [
+ f'H2EarlyHints on',
+ f'<Location /push/data1>',
+ f' H2PushResource /push/data2',
+ f'</Location>',
+ f'<Location /push/data2>',
+ f' H2PushResource /push/data1',
+ f' H2PushResource /push/data3',
+ f'</Location>',
+ ])
+ # activate the new config
+ httpd.reload()
+ yield
+ httpd.clear_extra_configs()
+ httpd.reload()
+
+ # download a file that triggers a "103 Early Hints" response
+ def test_09_01_h2_early_hints(self, env: Env, httpd, repeat):
+ curl = CurlClient(env=env)
+ url = f'https://{env.domain1}:{env.https_port}/push/data1'
+ r = curl.http_download(urls=[url], alpn_proto='h2', with_stats=False,
+ with_headers=True)
+ r.check_exit_code(0)
+ assert len(r.responses) == 2, f'{r.responses}'
+ assert r.responses[0]['status'] == 103, f'{r.responses}'
+ assert 'link' in r.responses[0]['header'], f'{r.responses[0]}'
+ assert r.responses[0]['header']['link'] == '</push/data2>; rel=preload', f'{r.responses[0]}'
+
+ def test_09_02_h2_push(self, env: Env, httpd, repeat):
+ # use localhost as we do not have resolve support in local client
+ url = f'https://localhost:{env.https_port}/push/data1'
+ client = LocalClient(name='h2-serverpush', env=env)
+ if not client.exists():
+ pytest.skip(f'example client not built: {client.name}')
+ r = client.run(args=[url])
+ r.check_exit_code(0)
+ assert os.path.exists(client.download_file(0))
+ assert os.path.exists(os.path.join(client.run_dir, 'push0')), r.dump_logs()
diff --git a/tests/http/test_10_proxy.py b/tests/http/test_10_proxy.py
new file mode 100644
index 0000000..9cbf35d
--- /dev/null
+++ b/tests/http/test_10_proxy.py
@@ -0,0 +1,251 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import filecmp
+import logging
+import os
+import re
+import pytest
+
+from testenv import Env, CurlClient, ExecResult
+
+
+log = logging.getLogger(__name__)
+
+
+class TestProxy:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, httpd, nghttpx_fwd):
+ push_dir = os.path.join(httpd.docs_dir, 'push')
+ if not os.path.exists(push_dir):
+ os.makedirs(push_dir)
+ if env.have_nghttpx():
+ nghttpx_fwd.start_if_needed()
+ env.make_data_file(indir=env.gen_dir, fname="data-100k", fsize=100*1024)
+ env.make_data_file(indir=env.gen_dir, fname="data-10m", fsize=10*1024*1024)
+ httpd.clear_extra_configs()
+ httpd.reload()
+
+ def get_tunnel_proto_used(self, r: ExecResult):
+ for l in r.trace_lines:
+ m = re.match(r'.* CONNECT tunnel: (\S+) negotiated$', l)
+ if m:
+ return m.group(1)
+ assert False, f'tunnel protocol not found in:\n{"".join(r.trace_lines)}'
+ return None
+
+ # download via http: proxy (no tunnel)
+ def test_10_01_proxy_http(self, env: Env, httpd, repeat):
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.http_port}/data.json'
+ r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=curl.get_proxy_args(proxys=False))
+ r.check_response(count=1, http_status=200)
+
+ # download via https: proxy (no tunnel)
+ @pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'),
+ reason='curl lacks HTTPS-proxy support')
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ def test_10_02_proxys_down(self, env: Env, httpd, nghttpx_fwd, proto, repeat):
+ if proto == 'h2' and not env.curl_uses_lib('nghttp2'):
+ pytest.skip('only supported with nghttp2')
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.http_port}/data.json'
+ xargs = curl.get_proxy_args(proto=proto)
+ r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=xargs)
+ r.check_response(count=1, http_status=200,
+ protocol='HTTP/2' if proto == 'h2' else 'HTTP/1.1')
+
+ # upload via https: with proto (no tunnel)
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
+ @pytest.mark.parametrize("fname, fcount", [
+ ['data.json', 5],
+ ['data-100k', 5],
+ ['data-1m', 2]
+ ])
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(),
+ reason="no nghttpx available")
+ def test_10_02_proxys_up(self, env: Env, httpd, nghttpx, proto,
+ fname, fcount, repeat):
+ if proto == 'h2' and not env.curl_uses_lib('nghttp2'):
+ pytest.skip('only supported with nghttp2')
+ count = fcount
+ srcfile = os.path.join(httpd.docs_dir, fname)
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.http_port}/curltest/echo?id=[0-{count-1}]'
+ xargs = curl.get_proxy_args(proto=proto)
+ r = curl.http_upload(urls=[url], data=f'@{srcfile}', alpn_proto=proto,
+ extra_args=xargs)
+ r.check_response(count=count, http_status=200,
+ protocol='HTTP/2' if proto == 'h2' else 'HTTP/1.1')
+ indata = open(srcfile).readlines()
+ for i in range(count):
+ respdata = open(curl.response_file(i)).readlines()
+ assert respdata == indata
+
+ # download http: via http: proxytunnel
+ def test_10_03_proxytunnel_http(self, env: Env, httpd, repeat):
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.http_port}/data.json'
+ xargs = curl.get_proxy_args(proxys=False, tunnel=True)
+ r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=xargs)
+ r.check_response(count=1, http_status=200)
+
+ # download http: via https: proxytunnel
+ @pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'),
+ reason='curl lacks HTTPS-proxy support')
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ def test_10_04_proxy_https(self, env: Env, httpd, nghttpx_fwd, repeat):
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.http_port}/data.json'
+ xargs = curl.get_proxy_args(tunnel=True)
+ r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=xargs)
+ r.check_response(count=1, http_status=200)
+
+ # download https: with proto via http: proxytunnel
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ def test_10_05_proxytunnel_http(self, env: Env, httpd, proto, repeat):
+ curl = CurlClient(env=env)
+ url = f'https://localhost:{env.https_port}/data.json'
+ xargs = curl.get_proxy_args(proxys=False, tunnel=True)
+ r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True,
+ with_headers=True,
+ extra_args=xargs)
+ r.check_response(count=1, http_status=200,
+ protocol='HTTP/2' if proto == 'h2' else 'HTTP/1.1')
+
+ # download https: with proto via https: proxytunnel
+ @pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'),
+ reason='curl lacks HTTPS-proxy support')
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
+ @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ def test_10_06_proxytunnel_https(self, env: Env, httpd, nghttpx_fwd, proto, tunnel, repeat):
+ if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
+ pytest.skip('only supported with nghttp2')
+ curl = CurlClient(env=env)
+ url = f'https://localhost:{env.https_port}/data.json?[0-0]'
+ xargs = curl.get_proxy_args(tunnel=True, proto=tunnel)
+ r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True,
+ with_headers=True, extra_args=xargs)
+ r.check_response(count=1, http_status=200,
+ protocol='HTTP/2' if proto == 'h2' else 'HTTP/1.1')
+ assert self.get_tunnel_proto_used(r) == 'HTTP/2' \
+ if tunnel == 'h2' else 'HTTP/1.1'
+ srcfile = os.path.join(httpd.docs_dir, 'data.json')
+ dfile = curl.download_file(0)
+ assert filecmp.cmp(srcfile, dfile, shallow=False)
+
+ # download many https: with proto via https: proxytunnel
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
+ @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
+ @pytest.mark.parametrize("fname, fcount", [
+ ['data.json', 100],
+ ['data-100k', 20],
+ ['data-1m', 5]
+ ])
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ def test_10_07_pts_down_small(self, env: Env, httpd, nghttpx_fwd, proto,
+ tunnel, fname, fcount, repeat):
+ if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
+ pytest.skip('only supported with nghttp2')
+ count = fcount
+ curl = CurlClient(env=env)
+ url = f'https://localhost:{env.https_port}/{fname}?[0-{count-1}]'
+ xargs = curl.get_proxy_args(tunnel=True, proto=tunnel)
+ r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True,
+ with_headers=True, extra_args=xargs)
+ r.check_response(count=count, http_status=200,
+ protocol='HTTP/2' if proto == 'h2' else 'HTTP/1.1')
+ assert self.get_tunnel_proto_used(r) == 'HTTP/2' \
+ if tunnel == 'h2' else 'HTTP/1.1'
+ srcfile = os.path.join(httpd.docs_dir, fname)
+ for i in range(count):
+ dfile = curl.download_file(i)
+ assert filecmp.cmp(srcfile, dfile, shallow=False)
+ assert r.total_connects == 1, r.dump_logs()
+
+ # upload many https: with proto via https: proxytunnel
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
+ @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
+ @pytest.mark.parametrize("fname, fcount", [
+ ['data.json', 50],
+ ['data-100k', 20],
+ ['data-1m', 5]
+ ])
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ def test_10_08_upload_seq_large(self, env: Env, httpd, nghttpx, proto,
+ tunnel, fname, fcount, repeat):
+ if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
+ pytest.skip('only supported with nghttp2')
+ count = fcount
+ srcfile = os.path.join(httpd.docs_dir, fname)
+ curl = CurlClient(env=env)
+ url = f'https://localhost:{env.https_port}/curltest/echo?id=[0-{count-1}]'
+ xargs = curl.get_proxy_args(tunnel=True, proto=tunnel)
+ r = curl.http_upload(urls=[url], data=f'@{srcfile}', alpn_proto=proto,
+ extra_args=xargs)
+ assert self.get_tunnel_proto_used(r) == 'HTTP/2' \
+ if tunnel == 'h2' else 'HTTP/1.1'
+ r.check_response(count=count, http_status=200)
+ indata = open(srcfile).readlines()
+ for i in range(count):
+ respdata = open(curl.response_file(i)).readlines()
+ assert respdata == indata
+ assert r.total_connects == 1, r.dump_logs()
+
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ def test_10_09_reuse_ser(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat):
+ if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
+ pytest.skip('only supported with nghttp2')
+ curl = CurlClient(env=env)
+ url1 = f'https://localhost:{env.https_port}/data.json'
+ url2 = f'http://localhost:{env.http_port}/data.json'
+ xargs = curl.get_proxy_args(tunnel=True, proto=tunnel)
+ r = curl.http_download(urls=[url1, url2], alpn_proto='http/1.1', with_stats=True,
+ with_headers=True, extra_args=xargs)
+ r.check_response(count=2, http_status=200)
+ assert self.get_tunnel_proto_used(r) == 'HTTP/2' \
+ if tunnel == 'h2' else 'HTTP/1.1'
+ if tunnel == 'h2':
+ # TODO: we would like to reuse the first connection for the
+ # second URL, but this is currently not possible
+ # assert r.total_connects == 1
+ assert r.total_connects == 2
+ else:
+ assert r.total_connects == 2
+
diff --git a/tests/http/test_11_unix.py b/tests/http/test_11_unix.py
new file mode 100644
index 0000000..dc2684a
--- /dev/null
+++ b/tests/http/test_11_unix.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import logging
+import os
+import socket
+from threading import Thread
+import pytest
+
+from testenv import Env, CurlClient
+
+
+log = logging.getLogger(__name__)
+
+class UDSFaker:
+
+ def __init__(self, path):
+ self._uds_path = path
+ self._done = False
+
+ @property
+ def path(self):
+ return self._uds_path
+
+ def start(self):
+ def process(self):
+ self._socket.listen(1)
+ self._process()
+
+ try:
+ os.unlink(self._uds_path)
+ except OSError:
+ if os.path.exists(self._uds_path):
+ raise
+ self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ self._socket.bind(self._uds_path)
+ self._thread = Thread(target=process, daemon=True, args=[self])
+ self._thread.start()
+
+ def stop(self):
+ self._done = True
+ self._socket.close()
+
+ def _process(self):
+ while self._done is False:
+ try:
+ c, client_address = self._socket.accept()
+ try:
+ data = c.recv(16)
+ c.sendall("""HTTP/1.1 200 Ok
+Server: UdsFaker
+Content-Type: application/json
+Content-Length: 19
+
+{ "host": "faked" }""".encode())
+ finally:
+ c.close()
+
+ except ConnectionAbortedError:
+ self._done = True
+
+
+class TestUnix:
+
+ @pytest.fixture(scope="class")
+ def uds_faker(self, env: Env) -> UDSFaker:
+ uds_path = os.path.join(env.gen_dir, 'uds_11.sock')
+ faker = UDSFaker(path=uds_path)
+ faker.start()
+ yield faker
+ faker.stop()
+
+ # download http: via unix socket
+ def test_11_01_unix_connect_http(self, env: Env, httpd, uds_faker, repeat):
+ curl = CurlClient(env=env)
+ url = f'http://{env.domain1}:{env.http_port}/data.json'
+ r = curl.http_download(urls=[url], with_stats=True,
+ extra_args=[
+ '--unix-socket', uds_faker.path,
+ ])
+ r.check_response(count=1, http_status=200)
+
+ # download https: via unix socket
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ def test_11_02_unix_connect_http(self, env: Env, httpd, uds_faker, repeat):
+ curl = CurlClient(env=env)
+ url = f'https://{env.domain1}:{env.https_port}/data.json'
+ r = curl.http_download(urls=[url], with_stats=True,
+ extra_args=[
+ '--unix-socket', uds_faker.path,
+ ])
+ r.check_response(exitcode=35, http_status=None)
+
+ # download HTTP/3 via unix socket
+ @pytest.mark.skipif(condition=not Env.have_h3(), reason='h3 not supported')
+ def test_11_03_unix_connect_quic(self, env: Env, httpd, uds_faker, repeat):
+ curl = CurlClient(env=env)
+ url = f'https://{env.domain1}:{env.https_port}/data.json'
+ r = curl.http_download(urls=[url], with_stats=True,
+ alpn_proto='h3',
+ extra_args=[
+ '--unix-socket', uds_faker.path,
+ ])
+ r.check_response(exitcode=96, http_status=None)
diff --git a/tests/http/test_12_reuse.py b/tests/http/test_12_reuse.py
new file mode 100644
index 0000000..83bfadf
--- /dev/null
+++ b/tests/http/test_12_reuse.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import difflib
+import filecmp
+import logging
+import os
+import pytest
+
+from testenv import Env, CurlClient
+
+
+log = logging.getLogger(__name__)
+
+
+@pytest.mark.skipif(condition=Env.curl_uses_lib('bearssl'), reason='BearSSL too slow')
+@pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+class TestReuse:
+
+ # check if HTTP/1.1 handles 'Connection: close' correctly
+ @pytest.mark.parametrize("proto", ['http/1.1'])
+ def test_12_01_h1_conn_close(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ httpd.clear_extra_configs()
+ httpd.set_extra_config('base', [
+ f'MaxKeepAliveRequests 1',
+ ])
+ httpd.reload()
+ count = 100
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-{count-1}]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto)
+ r.check_response(count=count, http_status=200)
+ # Server sends `Connection: close` on every 2nd request, requiring
+ # a new connection
+ delta = 5
+ assert (count/2 - delta) < r.total_connects < (count/2 + delta)
+
+ @pytest.mark.parametrize("proto", ['http/1.1'])
+ def test_12_02_h1_conn_timeout(self, env: Env,
+ httpd, nghttpx, repeat, proto):
+ httpd.clear_extra_configs()
+ httpd.set_extra_config('base', [
+ f'KeepAliveTimeout 1',
+ ])
+ httpd.reload()
+ count = 5
+ curl = CurlClient(env=env)
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-{count-1}]'
+ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+ '--rate', '30/m',
+ ])
+ r.check_response(count=count, http_status=200)
+ # Connections time out on server before we send another request,
+ assert r.total_connects == count
diff --git a/tests/http/test_13_proxy_auth.py b/tests/http/test_13_proxy_auth.py
new file mode 100644
index 0000000..3468017
--- /dev/null
+++ b/tests/http/test_13_proxy_auth.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import filecmp
+import logging
+import os
+import re
+import time
+import pytest
+
+from testenv import Env, CurlClient, ExecResult
+
+
+log = logging.getLogger(__name__)
+
+
+@pytest.mark.skipif(condition=Env.setup_incomplete(),
+ reason=f"missing: {Env.incomplete_reason()}")
+class TestProxyAuth:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, httpd, nghttpx_fwd):
+ if env.have_nghttpx():
+ nghttpx_fwd.start_if_needed()
+ httpd.clear_extra_configs()
+ httpd.set_proxy_auth(True)
+ httpd.reload()
+ yield
+ httpd.set_proxy_auth(False)
+ httpd.reload()
+
+ def get_tunnel_proto_used(self, r: ExecResult):
+ for line in r.trace_lines:
+ m = re.match(r'.* CONNECT tunnel: (\S+) negotiated$', line)
+ if m:
+ return m.group(1)
+ assert False, f'tunnel protocol not found in:\n{"".join(r.trace_lines)}'
+ return None
+
+ # download via http: proxy (no tunnel), no auth
+ def test_13_01_proxy_no_auth(self, env: Env, httpd, repeat):
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.http_port}/data.json'
+ r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=curl.get_proxy_args(proxys=False))
+ r.check_response(count=1, http_status=407)
+
+ # download via http: proxy (no tunnel), auth
+ def test_13_02_proxy_auth(self, env: Env, httpd, repeat):
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.http_port}/data.json'
+ xargs = curl.get_proxy_args(proxys=False)
+ xargs.extend(['--proxy-user', 'proxy:proxy'])
+ r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=xargs)
+ r.check_response(count=1, http_status=200)
+
+ @pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'),
+ reason='curl lacks HTTPS-proxy support')
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ def test_13_03_proxys_no_auth(self, env: Env, httpd, nghttpx_fwd, repeat):
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.http_port}/data.json'
+ xargs = curl.get_proxy_args(proxys=True)
+ r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=xargs)
+ r.check_response(count=1, http_status=407)
+
+ @pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'),
+ reason='curl lacks HTTPS-proxy support')
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ def test_13_04_proxys_auth(self, env: Env, httpd, nghttpx_fwd, repeat):
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.http_port}/data.json'
+ xargs = curl.get_proxy_args(proxys=True)
+ xargs.extend(['--proxy-user', 'proxy:proxy'])
+ r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=xargs)
+ r.check_response(count=1, http_status=200)
+
+ def test_13_05_tunnel_http_no_auth(self, env: Env, httpd, repeat):
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.http_port}/data.json'
+ xargs = curl.get_proxy_args(proxys=False, tunnel=True)
+ r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=xargs)
+ # expect "COULD_NOT_CONNECT"
+ r.check_response(exitcode=56, http_status=None)
+
+ def test_13_06_tunnel_http_auth(self, env: Env, httpd, repeat):
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.http_port}/data.json'
+ xargs = curl.get_proxy_args(proxys=False, tunnel=True)
+ xargs.extend(['--proxy-user', 'proxy:proxy'])
+ r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=xargs)
+ r.check_response(count=1, http_status=200)
+
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ @pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'),
+ reason='curl lacks HTTPS-proxy support')
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
+ @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
+ def test_13_07_tunnels_no_auth(self, env: Env, httpd, proto, tunnel, repeat):
+ if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
+ pytest.skip('only supported with nghttp2')
+ curl = CurlClient(env=env)
+ url = f'https://localhost:{env.https_port}/data.json'
+ xargs = curl.get_proxy_args(proxys=True, tunnel=True, proto=tunnel)
+ r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True,
+ with_headers=True, with_trace=True,
+ extra_args=xargs)
+ # expect "COULD_NOT_CONNECT"
+ r.check_response(exitcode=56, http_status=None)
+ assert self.get_tunnel_proto_used(r) == 'HTTP/2' \
+ if tunnel == 'h2' else 'HTTP/1.1'
+
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ @pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'),
+ reason='curl lacks HTTPS-proxy support')
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
+ @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
+ def test_13_08_tunnels_auth(self, env: Env, httpd, proto, tunnel, repeat):
+ if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
+ pytest.skip('only supported with nghttp2')
+ curl = CurlClient(env=env)
+ url = f'https://localhost:{env.https_port}/data.json'
+ xargs = curl.get_proxy_args(proxys=True, tunnel=True, proto=tunnel)
+ xargs.extend(['--proxy-user', 'proxy:proxy'])
+ r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True,
+ with_headers=True, with_trace=True,
+ extra_args=xargs)
+ r.check_response(count=1, http_status=200,
+ protocol='HTTP/2' if proto == 'h2' else 'HTTP/1.1')
+ assert self.get_tunnel_proto_used(r) == 'HTTP/2' \
+ if tunnel == 'h2' else 'HTTP/1.1'
+
diff --git a/tests/http/test_14_auth.py b/tests/http/test_14_auth.py
new file mode 100644
index 0000000..d962ced
--- /dev/null
+++ b/tests/http/test_14_auth.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import difflib
+import filecmp
+import logging
+import os
+import pytest
+
+from testenv import Env, CurlClient, LocalClient
+
+
+log = logging.getLogger(__name__)
+
+
+class TestAuth:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, httpd, nghttpx):
+ if env.have_h3():
+ nghttpx.start_if_needed()
+ env.make_data_file(indir=env.gen_dir, fname="data-10m", fsize=10*1024*1024)
+ httpd.clear_extra_configs()
+ httpd.reload()
+
+ # download 1 file, not authenticated
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_14_01_digest_get_noauth(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/restricted/digest/data.json'
+ r = curl.http_download(urls=[url], alpn_proto=proto)
+ r.check_response(http_status=401)
+
+ # download 1 file, authenticated
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_14_02_digest_get_auth(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/restricted/digest/data.json'
+ r = curl.http_download(urls=[url], alpn_proto=proto, extra_args=[
+ '--digest', '--user', 'test:test'
+ ])
+ r.check_response(http_status=200)
+
+ # PUT data, authenticated
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_14_03_digest_put_auth(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ data='0123456789'
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/restricted/digest/data.json'
+ r = curl.http_upload(urls=[url], data=data, alpn_proto=proto, extra_args=[
+ '--digest', '--user', 'test:test'
+ ])
+ r.check_response(http_status=200)
+
+ # PUT data, digest auth large pw
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_14_04_digest_large_pw(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ data='0123456789'
+ password = 'x' * 65535
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/restricted/digest/data.json'
+ r = curl.http_upload(urls=[url], data=data, alpn_proto=proto, extra_args=[
+ '--digest', '--user', f'test:{password}'
+ ])
+ # digest does not submit the password, but a hash of it, so all
+ # works and, since the pw is not correct, we get a 401
+ r.check_response(http_status=401)
+
+ # PUT data, basic auth large pw
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_14_05_basic_large_pw(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ # just large enought that nghttp2 will submit
+ password = 'x' * (47 * 1024)
+ fdata = os.path.join(env.gen_dir, 'data-10m')
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/restricted/digest/data.json'
+ r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto, extra_args=[
+ '--basic', '--user', f'test:{password}'
+ ])
+ # but apache denies on length limit
+ r.check_response(http_status=431)
+
+ # PUT data, basic auth with very large pw
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_14_06_basic_very_large_pw(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ data='0123456789'
+ password = 'x' * (64 * 1024)
+ fdata = os.path.join(env.gen_dir, 'data-10m')
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/restricted/digest/data.json'
+ r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto, extra_args=[
+ '--basic', '--user', f'test:{password}'
+ ])
+ # request was never sent
+ r.check_response(exitcode=55, http_status=0)
diff --git a/tests/http/test_20_websockets.py b/tests/http/test_20_websockets.py
new file mode 100644
index 0000000..4e70dce
--- /dev/null
+++ b/tests/http/test_20_websockets.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import logging
+import os
+import shutil
+import subprocess
+import time
+from datetime import datetime, timedelta
+import pytest
+
+from testenv import Env, CurlClient, LocalClient
+
+
+log = logging.getLogger(__name__)
+
+
+@pytest.mark.skipif(condition=not Env.curl_has_protocol('ws'),
+ reason='curl lacks ws protocol support')
+class TestWebsockets:
+
+ def check_alive(self, env, timeout=5):
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.ws_port}/'
+ end = datetime.now() + timedelta(seconds=timeout)
+ while datetime.now() < end:
+ r = curl.http_download(urls=[url])
+ if r.exit_code == 0:
+ return True
+ time.sleep(.1)
+ return False
+
+ def _mkpath(self, path):
+ if not os.path.exists(path):
+ return os.makedirs(path)
+
+ def _rmrf(self, path):
+ if os.path.exists(path):
+ return shutil.rmtree(path)
+
+ @pytest.fixture(autouse=True, scope='class')
+ def ws_echo(self, env):
+ run_dir = os.path.join(env.gen_dir, 'ws-echo-server')
+ err_file = os.path.join(run_dir, 'stderr')
+ self._rmrf(run_dir)
+ self._mkpath(run_dir)
+
+ with open(err_file, 'w') as cerr:
+ cmd = os.path.join(env.project_dir,
+ 'tests/http/testenv/ws_echo_server.py')
+ args = [cmd, '--port', str(env.ws_port)]
+ p = subprocess.Popen(args=args, cwd=run_dir, stderr=cerr,
+ stdout=cerr)
+ assert self.check_alive(env)
+ yield
+ p.terminate()
+
+ def test_20_01_basic(self, env: Env, ws_echo, repeat):
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.ws_port}/'
+ r = curl.http_download(urls=[url])
+ r.check_response(http_status=426)
+
+ def test_20_02_pingpong_small(self, env: Env, ws_echo, repeat):
+ payload = 125 * "x"
+ client = LocalClient(env=env, name='ws-pingpong')
+ if not client.exists():
+ pytest.skip(f'example client not built: {client.name}')
+ url = f'ws://localhost:{env.ws_port}/'
+ r = client.run(args=[url, payload])
+ r.check_exit_code(0)
+
+ # the python websocket server does not like 'large' control frames
+ def test_20_03_pingpong_too_large(self, env: Env, ws_echo, repeat):
+ payload = 127 * "x"
+ client = LocalClient(env=env, name='ws-pingpong')
+ if not client.exists():
+ pytest.skip(f'example client not built: {client.name}')
+ url = f'ws://localhost:{env.ws_port}/'
+ r = client.run(args=[url, payload])
+ r.check_exit_code(56)
+
+ # the python websocket server does not like 'large' control frames
+ def test_20_04_data_small(self, env: Env, ws_echo, repeat):
+ client = LocalClient(env=env, name='ws-data')
+ if not client.exists():
+ pytest.skip(f'example client not built: {client.name}')
+ url = f'ws://localhost:{env.ws_port}/'
+ r = client.run(args=[url, str(0), str(10)])
+ r.check_exit_code(0)
+
+ # the python websocket server does not like 'large' control frames
+ def test_20_05_data_med(self, env: Env, ws_echo, repeat):
+ client = LocalClient(env=env, name='ws-data')
+ if not client.exists():
+ pytest.skip(f'example client not built: {client.name}')
+ url = f'ws://localhost:{env.ws_port}/'
+ r = client.run(args=[url, str(120), str(130)])
+ r.check_exit_code(0)
+
+ # the python websocket server does not like 'large' control frames
+ def test_20_06_data_large(self, env: Env, ws_echo, repeat):
+ client = LocalClient(env=env, name='ws-data')
+ if not client.exists():
+ pytest.skip(f'example client not built: {client.name}')
+ url = f'ws://localhost:{env.ws_port}/'
+ r = client.run(args=[url, str(65535 - 5), str(65535 + 5)])
+ r.check_exit_code(0)
diff --git a/lib/makefile.amiga b/tests/http/testenv/__init__.py
similarity index 63%
rename from lib/makefile.amiga
rename to tests/http/testenv/__init__.py
index b09fee9..2195634 100644
--- a/lib/makefile.amiga
+++ b/tests/http/testenv/__init__.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
@@ -5,7 +7,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -22,23 +24,15 @@
#
###########################################################################
#
-# libcurl Makefile for AmigaOS ...
-#
+import pytest
+pytest.register_assert_rewrite("testenv.env", "testenv.curl", "testenv.caddy",
+ "testenv.httpd", "testenv.nghttpx")
-# change the follow to where you have the AmiTCP SDK v4.3 includes:
-
-ATCPSDKI= /GG/netinclude
-
-
-CC = m68k-amigaos-gcc
-CFLAGS = -I$(ATCPSDKI) -m68020-60 -O2 -msoft-float -noixemul -g -I. -I../include -W -Wall
-
-include Makefile.inc
-OBJS = $(CSOURCES:.c=.o)
-
-all: $(OBJS)
- ar cru libcurl.a $(OBJS)
- ranlib libcurl.a
-
-install:
- $(INSTALL) -c ./libcurl.a /lib/libcurl.a
+from .env import Env
+from .certs import TestCA, Credentials
+from .caddy import Caddy
+from .httpd import Httpd
+from .curl import CurlClient, ExecResult
+from .client import LocalClient
+from .nghttpx import Nghttpx
+from .nghttpx import Nghttpx, NghttpxQuic, NghttpxFwd
diff --git a/tests/http/testenv/caddy.py b/tests/http/testenv/caddy.py
new file mode 100644
index 0000000..ea1343a
--- /dev/null
+++ b/tests/http/testenv/caddy.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import logging
+import os
+import subprocess
+import time
+from datetime import timedelta, datetime
+from json import JSONEncoder
+
+from .curl import CurlClient
+from .env import Env
+
+
+log = logging.getLogger(__name__)
+
+
+class Caddy:
+
+ def __init__(self, env: Env):
+ self.env = env
+ self._caddy = os.environ['CADDY'] if 'CADDY' in os.environ else env.caddy
+ self._caddy_dir = os.path.join(env.gen_dir, 'caddy')
+ self._docs_dir = os.path.join(self._caddy_dir, 'docs')
+ self._conf_file = os.path.join(self._caddy_dir, 'Caddyfile')
+ self._error_log = os.path.join(self._caddy_dir, 'caddy.log')
+ self._tmp_dir = os.path.join(self._caddy_dir, 'tmp')
+ self._process = None
+ self._rmf(self._error_log)
+
+ @property
+ def docs_dir(self):
+ return self._docs_dir
+
+ @property
+ def port(self) -> str:
+ return self.env.caddy_https_port
+
+ def clear_logs(self):
+ self._rmf(self._error_log)
+
+ def is_running(self):
+ if self._process:
+ self._process.poll()
+ return self._process.returncode is None
+ return False
+
+ def start_if_needed(self):
+ if not self.is_running():
+ return self.start()
+ return True
+
+ def start(self, wait_live=True):
+ self._mkpath(self._tmp_dir)
+ if self._process:
+ self.stop()
+ self._write_config()
+ args = [
+ self._caddy, 'run'
+ ]
+ caddyerr = open(self._error_log, 'a')
+ self._process = subprocess.Popen(args=args, cwd=self._caddy_dir, stderr=caddyerr)
+ if self._process.returncode is not None:
+ return False
+ return not wait_live or self.wait_live(timeout=timedelta(seconds=5))
+
+ def stop_if_running(self):
+ if self.is_running():
+ return self.stop()
+ return True
+
+ def stop(self, wait_dead=True):
+ self._mkpath(self._tmp_dir)
+ if self._process:
+ self._process.terminate()
+ self._process.wait(timeout=2)
+ self._process = None
+ return not wait_dead or self.wait_dead(timeout=timedelta(seconds=5))
+ return True
+
+ def restart(self):
+ self.stop()
+ return self.start()
+
+ def wait_dead(self, timeout: timedelta):
+ curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
+ try_until = datetime.now() + timeout
+ while datetime.now() < try_until:
+ check_url = f'https://{self.env.domain1}:{self.port}/'
+ r = curl.http_get(url=check_url)
+ if r.exit_code != 0:
+ return True
+ log.debug(f'waiting for caddy to stop responding: {r}')
+ time.sleep(.1)
+ log.debug(f"Server still responding after {timeout}")
+ return False
+
+ def wait_live(self, timeout: timedelta):
+ curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
+ try_until = datetime.now() + timeout
+ while datetime.now() < try_until:
+ check_url = f'https://{self.env.domain1}:{self.port}/'
+ r = curl.http_get(url=check_url)
+ if r.exit_code == 0:
+ return True
+ time.sleep(.1)
+ log.error(f"Caddy still not responding after {timeout}")
+ return False
+
+ def _rmf(self, path):
+ if os.path.exists(path):
+ return os.remove(path)
+
+ def _mkpath(self, path):
+ if not os.path.exists(path):
+ return os.makedirs(path)
+
+ def _write_config(self):
+ domain1 = self.env.domain1
+ creds1 = self.env.get_credentials(domain1)
+ self._mkpath(self._docs_dir)
+ self._mkpath(self._tmp_dir)
+ with open(os.path.join(self._docs_dir, 'data.json'), 'w') as fd:
+ data = {
+ 'server': f'{domain1}',
+ }
+ fd.write(JSONEncoder().encode(data))
+ with open(self._conf_file, 'w') as fd:
+ conf = [ # base server config
+ f'{{',
+ f' http_port {self.env.caddy_http_port}',
+ f' https_port {self.env.caddy_https_port}',
+ f' servers :{self.env.caddy_https_port} {{',
+ f' protocols h3 h2 h1',
+ f' }}',
+ f'}}',
+ f'{domain1}:{self.env.caddy_https_port} {{',
+ f' file_server * {{',
+ f' root {self._docs_dir}',
+ f' }}',
+ f' tls {creds1.cert_file} {creds1.pkey_file}',
+ f'}}',
+ ]
+ fd.write("\n".join(conf))
diff --git a/tests/http/testenv/certs.py b/tests/http/testenv/certs.py
new file mode 100644
index 0000000..f575a74
--- /dev/null
+++ b/tests/http/testenv/certs.py
@@ -0,0 +1,528 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import os
+import re
+from datetime import timedelta, datetime
+from typing import List, Any, Optional
+
+from cryptography import x509
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.asymmetric import ec, rsa
+from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey
+from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
+from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption, load_pem_private_key
+from cryptography.x509 import ExtendedKeyUsageOID, NameOID
+
+
+EC_SUPPORTED = {}
+EC_SUPPORTED.update([(curve.name.upper(), curve) for curve in [
+ ec.SECP192R1,
+ ec.SECP224R1,
+ ec.SECP256R1,
+ ec.SECP384R1,
+]])
+
+
+def _private_key(key_type):
+ if isinstance(key_type, str):
+ key_type = key_type.upper()
+ m = re.match(r'^(RSA)?(\d+)$', key_type)
+ if m:
+ key_type = int(m.group(2))
+
+ if isinstance(key_type, int):
+ return rsa.generate_private_key(
+ public_exponent=65537,
+ key_size=key_type,
+ backend=default_backend()
+ )
+ if not isinstance(key_type, ec.EllipticCurve) and key_type in EC_SUPPORTED:
+ key_type = EC_SUPPORTED[key_type]
+ return ec.generate_private_key(
+ curve=key_type,
+ backend=default_backend()
+ )
+
+
+class CertificateSpec:
+
+ def __init__(self, name: Optional[str] = None,
+ domains: Optional[List[str]] = None,
+ email: Optional[str] = None,
+ key_type: Optional[str] = None,
+ single_file: bool = False,
+ valid_from: timedelta = timedelta(days=-1),
+ valid_to: timedelta = timedelta(days=89),
+ client: bool = False,
+ sub_specs: Optional[List['CertificateSpec']] = None):
+ self._name = name
+ self.domains = domains
+ self.client = client
+ self.email = email
+ self.key_type = key_type
+ self.single_file = single_file
+ self.valid_from = valid_from
+ self.valid_to = valid_to
+ self.sub_specs = sub_specs
+
+ @property
+ def name(self) -> Optional[str]:
+ if self._name:
+ return self._name
+ elif self.domains:
+ return self.domains[0]
+ return None
+
+ @property
+ def type(self) -> Optional[str]:
+ if self.domains and len(self.domains):
+ return "server"
+ elif self.client:
+ return "client"
+ elif self.name:
+ return "ca"
+ return None
+
+
+class Credentials:
+
+ def __init__(self,
+ name: str,
+ cert: Any,
+ pkey: Any,
+ issuer: Optional['Credentials'] = None):
+ self._name = name
+ self._cert = cert
+ self._pkey = pkey
+ self._issuer = issuer
+ self._cert_file = None
+ self._pkey_file = None
+ self._store = None
+
+ @property
+ def name(self) -> str:
+ return self._name
+
+ @property
+ def subject(self) -> x509.Name:
+ return self._cert.subject
+
+ @property
+ def key_type(self):
+ if isinstance(self._pkey, RSAPrivateKey):
+ return f"rsa{self._pkey.key_size}"
+ elif isinstance(self._pkey, EllipticCurvePrivateKey):
+ return f"{self._pkey.curve.name}"
+ else:
+ raise Exception(f"unknown key type: {self._pkey}")
+
+ @property
+ def private_key(self) -> Any:
+ return self._pkey
+
+ @property
+ def certificate(self) -> Any:
+ return self._cert
+
+ @property
+ def cert_pem(self) -> bytes:
+ return self._cert.public_bytes(Encoding.PEM)
+
+ @property
+ def pkey_pem(self) -> bytes:
+ return self._pkey.private_bytes(
+ Encoding.PEM,
+ PrivateFormat.TraditionalOpenSSL if self.key_type.startswith('rsa') else PrivateFormat.PKCS8,
+ NoEncryption())
+
+ @property
+ def issuer(self) -> Optional['Credentials']:
+ return self._issuer
+
+ def set_store(self, store: 'CertStore'):
+ self._store = store
+
+ def set_files(self, cert_file: str, pkey_file: Optional[str] = None,
+ combined_file: Optional[str] = None):
+ self._cert_file = cert_file
+ self._pkey_file = pkey_file
+ self._combined_file = combined_file
+
+ @property
+ def cert_file(self) -> str:
+ return self._cert_file
+
+ @property
+ def pkey_file(self) -> Optional[str]:
+ return self._pkey_file
+
+ @property
+ def combined_file(self) -> Optional[str]:
+ return self._combined_file
+
+ def get_first(self, name) -> Optional['Credentials']:
+ creds = self._store.get_credentials_for_name(name) if self._store else []
+ return creds[0] if len(creds) else None
+
+ def get_credentials_for_name(self, name) -> List['Credentials']:
+ return self._store.get_credentials_for_name(name) if self._store else []
+
+ def issue_certs(self, specs: List[CertificateSpec],
+ chain: Optional[List['Credentials']] = None) -> List['Credentials']:
+ return [self.issue_cert(spec=spec, chain=chain) for spec in specs]
+
+ def issue_cert(self, spec: CertificateSpec,
+ chain: Optional[List['Credentials']] = None) -> 'Credentials':
+ key_type = spec.key_type if spec.key_type else self.key_type
+ creds = None
+ if self._store:
+ creds = self._store.load_credentials(
+ name=spec.name, key_type=key_type, single_file=spec.single_file, issuer=self)
+ if creds is None:
+ creds = TestCA.create_credentials(spec=spec, issuer=self, key_type=key_type,
+ valid_from=spec.valid_from, valid_to=spec.valid_to)
+ if self._store:
+ self._store.save(creds, single_file=spec.single_file)
+ if spec.type == "ca":
+ self._store.save_chain(creds, "ca", with_root=True)
+
+ if spec.sub_specs:
+ if self._store:
+ sub_store = CertStore(fpath=os.path.join(self._store.path, creds.name))
+ creds.set_store(sub_store)
+ subchain = chain.copy() if chain else []
+ subchain.append(self)
+ creds.issue_certs(spec.sub_specs, chain=subchain)
+ return creds
+
+
+class CertStore:
+
+ def __init__(self, fpath: str):
+ self._store_dir = fpath
+ if not os.path.exists(self._store_dir):
+ os.makedirs(self._store_dir)
+ self._creds_by_name = {}
+
+ @property
+ def path(self) -> str:
+ return self._store_dir
+
+ def save(self, creds: Credentials, name: Optional[str] = None,
+ chain: Optional[List[Credentials]] = None,
+ single_file: bool = False) -> None:
+ name = name if name is not None else creds.name
+ cert_file = self.get_cert_file(name=name, key_type=creds.key_type)
+ pkey_file = self.get_pkey_file(name=name, key_type=creds.key_type)
+ comb_file = self.get_combined_file(name=name, key_type=creds.key_type)
+ if single_file:
+ pkey_file = None
+ with open(cert_file, "wb") as fd:
+ fd.write(creds.cert_pem)
+ if chain:
+ for c in chain:
+ fd.write(c.cert_pem)
+ if pkey_file is None:
+ fd.write(creds.pkey_pem)
+ if pkey_file is not None:
+ with open(pkey_file, "wb") as fd:
+ fd.write(creds.pkey_pem)
+ with open(comb_file, "wb") as fd:
+ fd.write(creds.cert_pem)
+ if chain:
+ for c in chain:
+ fd.write(c.cert_pem)
+ fd.write(creds.pkey_pem)
+ creds.set_files(cert_file, pkey_file, comb_file)
+ self._add_credentials(name, creds)
+
+ def save_chain(self, creds: Credentials, infix: str, with_root=False):
+ name = creds.name
+ chain = [creds]
+ while creds.issuer is not None:
+ creds = creds.issuer
+ chain.append(creds)
+ if not with_root and len(chain) > 1:
+ chain = chain[:-1]
+ chain_file = os.path.join(self._store_dir, f'{name}-{infix}.pem')
+ with open(chain_file, "wb") as fd:
+ for c in chain:
+ fd.write(c.cert_pem)
+
+ def _add_credentials(self, name: str, creds: Credentials):
+ if name not in self._creds_by_name:
+ self._creds_by_name[name] = []
+ self._creds_by_name[name].append(creds)
+
+ def get_credentials_for_name(self, name) -> List[Credentials]:
+ return self._creds_by_name[name] if name in self._creds_by_name else []
+
+ def get_cert_file(self, name: str, key_type=None) -> str:
+ key_infix = ".{0}".format(key_type) if key_type is not None else ""
+ return os.path.join(self._store_dir, f'{name}{key_infix}.cert.pem')
+
+ def get_pkey_file(self, name: str, key_type=None) -> str:
+ key_infix = ".{0}".format(key_type) if key_type is not None else ""
+ return os.path.join(self._store_dir, f'{name}{key_infix}.pkey.pem')
+
+ def get_combined_file(self, name: str, key_type=None) -> str:
+ return os.path.join(self._store_dir, f'{name}.pem')
+
+ def load_pem_cert(self, fpath: str) -> x509.Certificate:
+ with open(fpath) as fd:
+ return x509.load_pem_x509_certificate("".join(fd.readlines()).encode())
+
+ def load_pem_pkey(self, fpath: str):
+ with open(fpath) as fd:
+ return load_pem_private_key("".join(fd.readlines()).encode(), password=None)
+
+ def load_credentials(self, name: str, key_type=None,
+ single_file: bool = False,
+ issuer: Optional[Credentials] = None):
+ cert_file = self.get_cert_file(name=name, key_type=key_type)
+ pkey_file = cert_file if single_file else self.get_pkey_file(name=name, key_type=key_type)
+ comb_file = self.get_combined_file(name=name, key_type=key_type)
+ if os.path.isfile(cert_file) and os.path.isfile(pkey_file):
+ cert = self.load_pem_cert(cert_file)
+ pkey = self.load_pem_pkey(pkey_file)
+ creds = Credentials(name=name, cert=cert, pkey=pkey, issuer=issuer)
+ creds.set_store(self)
+ creds.set_files(cert_file, pkey_file, comb_file)
+ self._add_credentials(name, creds)
+ return creds
+ return None
+
+
+class TestCA:
+
+ @classmethod
+ def create_root(cls, name: str, store_dir: str, key_type: str = "rsa2048") -> Credentials:
+ store = CertStore(fpath=store_dir)
+ creds = store.load_credentials(name="ca", key_type=key_type, issuer=None)
+ if creds is None:
+ creds = TestCA._make_ca_credentials(name=name, key_type=key_type)
+ store.save(creds, name="ca")
+ creds.set_store(store)
+ return creds
+
+ @staticmethod
+ def create_credentials(spec: CertificateSpec, issuer: Credentials, key_type: Any,
+ valid_from: timedelta = timedelta(days=-1),
+ valid_to: timedelta = timedelta(days=89),
+ ) -> Credentials:
+ """Create a certificate signed by this CA for the given domains.
+ :returns: the certificate and private key PEM file paths
+ """
+ if spec.domains and len(spec.domains):
+ creds = TestCA._make_server_credentials(name=spec.name, domains=spec.domains,
+ issuer=issuer, valid_from=valid_from,
+ valid_to=valid_to, key_type=key_type)
+ elif spec.client:
+ creds = TestCA._make_client_credentials(name=spec.name, issuer=issuer,
+ email=spec.email, valid_from=valid_from,
+ valid_to=valid_to, key_type=key_type)
+ elif spec.name:
+ creds = TestCA._make_ca_credentials(name=spec.name, issuer=issuer,
+ valid_from=valid_from, valid_to=valid_to,
+ key_type=key_type)
+ else:
+ raise Exception(f"unrecognized certificate specification: {spec}")
+ return creds
+
+ @staticmethod
+ def _make_x509_name(org_name: str = None, common_name: str = None, parent: x509.Name = None) -> x509.Name:
+ name_pieces = []
+ if org_name:
+ oid = NameOID.ORGANIZATIONAL_UNIT_NAME if parent else NameOID.ORGANIZATION_NAME
+ name_pieces.append(x509.NameAttribute(oid, org_name))
+ elif common_name:
+ name_pieces.append(x509.NameAttribute(NameOID.COMMON_NAME, common_name))
+ if parent:
+ name_pieces.extend([rdn for rdn in parent])
+ return x509.Name(name_pieces)
+
+ @staticmethod
+ def _make_csr(
+ subject: x509.Name,
+ pkey: Any,
+ issuer_subject: Optional[Credentials],
+ valid_from_delta: timedelta = None,
+ valid_until_delta: timedelta = None
+ ):
+ pubkey = pkey.public_key()
+ issuer_subject = issuer_subject if issuer_subject is not None else subject
+
+ valid_from = datetime.now()
+ if valid_until_delta is not None:
+ valid_from += valid_from_delta
+ valid_until = datetime.now()
+ if valid_until_delta is not None:
+ valid_until += valid_until_delta
+
+ return (
+ x509.CertificateBuilder()
+ .subject_name(subject)
+ .issuer_name(issuer_subject)
+ .public_key(pubkey)
+ .not_valid_before(valid_from)
+ .not_valid_after(valid_until)
+ .serial_number(x509.random_serial_number())
+ .add_extension(
+ x509.SubjectKeyIdentifier.from_public_key(pubkey),
+ critical=False,
+ )
+ )
+
+ @staticmethod
+ def _add_ca_usages(csr: Any) -> Any:
+ return csr.add_extension(
+ x509.BasicConstraints(ca=True, path_length=9),
+ critical=True,
+ ).add_extension(
+ x509.KeyUsage(
+ digital_signature=True,
+ content_commitment=False,
+ key_encipherment=False,
+ data_encipherment=False,
+ key_agreement=False,
+ key_cert_sign=True,
+ crl_sign=True,
+ encipher_only=False,
+ decipher_only=False),
+ critical=True
+ ).add_extension(
+ x509.ExtendedKeyUsage([
+ ExtendedKeyUsageOID.CLIENT_AUTH,
+ ExtendedKeyUsageOID.SERVER_AUTH,
+ ExtendedKeyUsageOID.CODE_SIGNING,
+ ]),
+ critical=True
+ )
+
+ @staticmethod
+ def _add_leaf_usages(csr: Any, domains: List[str], issuer: Credentials) -> Any:
+ return csr.add_extension(
+ x509.BasicConstraints(ca=False, path_length=None),
+ critical=True,
+ ).add_extension(
+ x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
+ issuer.certificate.extensions.get_extension_for_class(
+ x509.SubjectKeyIdentifier).value),
+ critical=False
+ ).add_extension(
+ x509.SubjectAlternativeName([x509.DNSName(domain) for domain in domains]),
+ critical=True,
+ ).add_extension(
+ x509.ExtendedKeyUsage([
+ ExtendedKeyUsageOID.SERVER_AUTH,
+ ]),
+ critical=False
+ )
+
+ @staticmethod
+ def _add_client_usages(csr: Any, issuer: Credentials, rfc82name: str = None) -> Any:
+ cert = csr.add_extension(
+ x509.BasicConstraints(ca=False, path_length=None),
+ critical=True,
+ ).add_extension(
+ x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
+ issuer.certificate.extensions.get_extension_for_class(
+ x509.SubjectKeyIdentifier).value),
+ critical=False
+ )
+ if rfc82name:
+ cert.add_extension(
+ x509.SubjectAlternativeName([x509.RFC822Name(rfc82name)]),
+ critical=True,
+ )
+ cert.add_extension(
+ x509.ExtendedKeyUsage([
+ ExtendedKeyUsageOID.CLIENT_AUTH,
+ ]),
+ critical=True
+ )
+ return cert
+
+ @staticmethod
+ def _make_ca_credentials(name, key_type: Any,
+ issuer: Credentials = None,
+ valid_from: timedelta = timedelta(days=-1),
+ valid_to: timedelta = timedelta(days=89),
+ ) -> Credentials:
+ pkey = _private_key(key_type=key_type)
+ if issuer is not None:
+ issuer_subject = issuer.certificate.subject
+ issuer_key = issuer.private_key
+ else:
+ issuer_subject = None
+ issuer_key = pkey
+ subject = TestCA._make_x509_name(org_name=name, parent=issuer.subject if issuer else None)
+ csr = TestCA._make_csr(subject=subject,
+ issuer_subject=issuer_subject, pkey=pkey,
+ valid_from_delta=valid_from, valid_until_delta=valid_to)
+ csr = TestCA._add_ca_usages(csr)
+ cert = csr.sign(private_key=issuer_key,
+ algorithm=hashes.SHA256(),
+ backend=default_backend())
+ return Credentials(name=name, cert=cert, pkey=pkey, issuer=issuer)
+
+ @staticmethod
+ def _make_server_credentials(name: str, domains: List[str], issuer: Credentials,
+ key_type: Any,
+ valid_from: timedelta = timedelta(days=-1),
+ valid_to: timedelta = timedelta(days=89),
+ ) -> Credentials:
+ name = name
+ pkey = _private_key(key_type=key_type)
+ subject = TestCA._make_x509_name(common_name=name, parent=issuer.subject)
+ csr = TestCA._make_csr(subject=subject,
+ issuer_subject=issuer.certificate.subject, pkey=pkey,
+ valid_from_delta=valid_from, valid_until_delta=valid_to)
+ csr = TestCA._add_leaf_usages(csr, domains=domains, issuer=issuer)
+ cert = csr.sign(private_key=issuer.private_key,
+ algorithm=hashes.SHA256(),
+ backend=default_backend())
+ return Credentials(name=name, cert=cert, pkey=pkey, issuer=issuer)
+
+ @staticmethod
+ def _make_client_credentials(name: str,
+ issuer: Credentials, email: Optional[str],
+ key_type: Any,
+ valid_from: timedelta = timedelta(days=-1),
+ valid_to: timedelta = timedelta(days=89),
+ ) -> Credentials:
+ pkey = _private_key(key_type=key_type)
+ subject = TestCA._make_x509_name(common_name=name, parent=issuer.subject)
+ csr = TestCA._make_csr(subject=subject,
+ issuer_subject=issuer.certificate.subject, pkey=pkey,
+ valid_from_delta=valid_from, valid_until_delta=valid_to)
+ csr = TestCA._add_client_usages(csr, issuer=issuer, rfc82name=email)
+ cert = csr.sign(private_key=issuer.private_key,
+ algorithm=hashes.SHA256(),
+ backend=default_backend())
+ return Credentials(name=name, cert=cert, pkey=pkey, issuer=issuer)
diff --git a/tests/http/testenv/client.py b/tests/http/testenv/client.py
new file mode 100644
index 0000000..3b7ea0f
--- /dev/null
+++ b/tests/http/testenv/client.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import pytest
+import json
+import logging
+import os
+import re
+import shutil
+import subprocess
+from datetime import timedelta, datetime
+from typing import List, Optional, Dict, Union
+from urllib.parse import urlparse
+
+from . import ExecResult
+from .env import Env
+
+
+log = logging.getLogger(__name__)
+
+
+class LocalClient:
+
+ def __init__(self, name: str, env: Env, run_dir: Optional[str] = None,
+ timeout: Optional[float] = None):
+ self.name = name
+ self.path = os.path.join(env.project_dir, f'tests/http/clients/{name}')
+ self.env = env
+ self._timeout = timeout if timeout else env.test_timeout
+ self._curl = os.environ['CURL'] if 'CURL' in os.environ else env.curl
+ self._run_dir = run_dir if run_dir else os.path.join(env.gen_dir, name)
+ self._stdoutfile = f'{self._run_dir}/stdout'
+ self._stderrfile = f'{self._run_dir}/stderr'
+ self._rmrf(self._run_dir)
+ self._mkpath(self._run_dir)
+
+ @property
+ def run_dir(self) -> str:
+ return self._run_dir
+
+ def exists(self) -> bool:
+ return os.path.exists(self.path)
+
+ def download_file(self, i: int) -> str:
+ return os.path.join(self._run_dir, f'download_{i}.data')
+
+ def _rmf(self, path):
+ if os.path.exists(path):
+ return os.remove(path)
+
+ def _rmrf(self, path):
+ if os.path.exists(path):
+ return shutil.rmtree(path)
+
+ def _mkpath(self, path):
+ if not os.path.exists(path):
+ return os.makedirs(path)
+
+ def run(self, args):
+ self._rmf(self._stdoutfile)
+ self._rmf(self._stderrfile)
+ start = datetime.now()
+ exception = None
+ myargs = [self.path]
+ myargs.extend(args)
+ try:
+ with open(self._stdoutfile, 'w') as cout:
+ with open(self._stderrfile, 'w') as cerr:
+ p = subprocess.run(myargs, stderr=cerr, stdout=cout,
+ cwd=self._run_dir, shell=False,
+ input=None,
+ timeout=self._timeout)
+ exitcode = p.returncode
+ except subprocess.TimeoutExpired:
+ log.warning(f'Timeout after {self._timeout}s: {args}')
+ exitcode = -1
+ exception = 'TimeoutExpired'
+ coutput = open(self._stdoutfile).readlines()
+ cerrput = open(self._stderrfile).readlines()
+ return ExecResult(args=myargs, exit_code=exitcode, exception=exception,
+ stdout=coutput, stderr=cerrput,
+ duration=datetime.now() - start)
diff --git a/tests/http/testenv/curl.py b/tests/http/testenv/curl.py
new file mode 100644
index 0000000..54622b5
--- /dev/null
+++ b/tests/http/testenv/curl.py
@@ -0,0 +1,577 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import pytest
+import json
+import logging
+import os
+import re
+import shutil
+import subprocess
+from datetime import timedelta, datetime
+from typing import List, Optional, Dict, Union
+from urllib.parse import urlparse
+
+from .env import Env
+
+
+log = logging.getLogger(__name__)
+
+
+class ExecResult:
+
+ def __init__(self, args: List[str], exit_code: int,
+ stdout: List[str], stderr: List[str],
+ trace: Optional[List[str]] = None,
+ duration: Optional[timedelta] = None,
+ with_stats: bool = False,
+ exception: Optional[str] = None):
+ self._args = args
+ self._exit_code = exit_code
+ self._exception = exception
+ self._stdout = stdout
+ self._stderr = stderr
+ self._trace = trace
+ self._duration = duration if duration is not None else timedelta()
+ self._response = None
+ self._responses = []
+ self._results = {}
+ self._assets = []
+ self._stats = []
+ self._json_out = None
+ self._with_stats = with_stats
+ if with_stats:
+ self._parse_stats()
+ else:
+ # noinspection PyBroadException
+ try:
+ out = ''.join(self._stdout)
+ self._json_out = json.loads(out)
+ except:
+ pass
+
+ def __repr__(self):
+ return f"ExecResult[code={self.exit_code}, exception={self._exception}, "\
+ f"args={self._args}, stdout={self._stdout}, stderr={self._stderr}]"
+
+ def _parse_stats(self):
+ self._stats = []
+ for l in self._stdout:
+ try:
+ self._stats.append(json.loads(l))
+ except:
+ log.error(f'not a JSON stat: {l}')
+ break
+
+ @property
+ def exit_code(self) -> int:
+ return self._exit_code
+
+ @property
+ def args(self) -> List[str]:
+ return self._args
+
+ @property
+ def outraw(self) -> bytes:
+ return ''.join(self._stdout).encode()
+
+ @property
+ def stdout(self) -> str:
+ return ''.join(self._stdout)
+
+ @property
+ def json(self) -> Optional[Dict]:
+ """Output as JSON dictionary or None if not parseable."""
+ return self._json_out
+
+ @property
+ def stderr(self) -> str:
+ return ''.join(self._stderr)
+
+ @property
+ def trace_lines(self) -> List[str]:
+ return self._trace if self._trace else self._stderr
+
+ @property
+ def duration(self) -> timedelta:
+ return self._duration
+
+ @property
+ def response(self) -> Optional[Dict]:
+ return self._response
+
+ @property
+ def responses(self) -> List[Dict]:
+ return self._responses
+
+ @property
+ def results(self) -> Dict:
+ return self._results
+
+ @property
+ def assets(self) -> List:
+ return self._assets
+
+ @property
+ def with_stats(self) -> bool:
+ return self._with_stats
+
+ @property
+ def stats(self) -> List:
+ return self._stats
+
+ @property
+ def total_connects(self) -> Optional[int]:
+ if len(self.stats):
+ n = 0
+ for stat in self.stats:
+ n += stat['num_connects']
+ return n
+ return None
+
+ def add_response(self, resp: Dict):
+ self._response = resp
+ self._responses.append(resp)
+
+ def add_results(self, results: Dict):
+ self._results.update(results)
+ if 'response' in results:
+ self.add_response(results['response'])
+
+ def add_assets(self, assets: List):
+ self._assets.extend(assets)
+
+ def check_exit_code(self, code: Union[int, bool]):
+ if code is True:
+ assert self.exit_code == 0, f'expected exit code {code}, '\
+ f'got {self.exit_code}\n{self.dump_logs()}'
+ elif code is False:
+ assert self.exit_code != 0, f'expected exit code {code}, '\
+ f'got {self.exit_code}\n{self.dump_logs()}'
+ else:
+ assert self.exit_code == code, f'expected exit code {code}, '\
+ f'got {self.exit_code}\n{self.dump_logs()}'
+
+ def check_response(self, http_status: Optional[int] = 200,
+ count: Optional[int] = 1,
+ protocol: Optional[str] = None,
+ exitcode: Optional[int] = 0,
+ connect_count: Optional[int] = None):
+ if exitcode:
+ self.check_exit_code(exitcode)
+ if self.with_stats and isinstance(exitcode, int):
+ for idx, x in enumerate(self.stats):
+ if 'exitcode' in x:
+ assert int(x['exitcode']) == exitcode, \
+ f'response #{idx} exitcode: expected {exitcode}, '\
+ f'got {x["exitcode"]}\n{self.dump_logs()}'
+
+ if self.with_stats:
+ assert len(self.stats) == count, \
+ f'response count: expected {count}, ' \
+ f'got {len(self.stats)}\n{self.dump_logs()}'
+ else:
+ assert len(self.responses) == count, \
+ f'response count: expected {count}, ' \
+ f'got {len(self.responses)}\n{self.dump_logs()}'
+ if http_status is not None:
+ if self.with_stats:
+ for idx, x in enumerate(self.stats):
+ assert 'http_code' in x, \
+ f'response #{idx} reports no http_code\n{self.dump_logs()}'
+ assert x['http_code'] == http_status, \
+ f'response #{idx} http_code: expected {http_status}, '\
+ f'got {x["http_code"]}\n{self.dump_logs()}'
+ else:
+ for idx, x in enumerate(self.responses):
+ assert x['status'] == http_status, \
+ f'response #{idx} status: expected {http_status},'\
+ f'got {x["status"]}\n{self.dump_logs()}'
+ if protocol is not None:
+ if self.with_stats:
+ http_version = None
+ if protocol == 'HTTP/1.1':
+ http_version = '1.1'
+ elif protocol == 'HTTP/2':
+ http_version = '2'
+ elif protocol == 'HTTP/3':
+ http_version = '3'
+ if http_version is not None:
+ for idx, x in enumerate(self.stats):
+ assert x['http_version'] == http_version, \
+ f'response #{idx} protocol: expected http/{http_version},' \
+ f'got version {x["http_version"]}\n{self.dump_logs()}'
+ else:
+ for idx, x in enumerate(self.responses):
+ assert x['protocol'] == protocol, \
+ f'response #{idx} protocol: expected {protocol},'\
+ f'got {x["protocol"]}\n{self.dump_logs()}'
+ if connect_count is not None:
+ assert self.total_connects == connect_count, \
+ f'expected {connect_count}, but {self.total_connects} '\
+ f'were made\n{self.dump_logs()}'
+
+ def check_stats(self, count: int, http_status: Optional[int] = None,
+ exitcode: Optional[int] = None):
+ if exitcode is None:
+ self.check_exit_code(0)
+ assert len(self.stats) == count, \
+ f'stats count: expected {count}, got {len(self.stats)}\n{self.dump_logs()}'
+ if http_status is not None:
+ for idx, x in enumerate(self.stats):
+ assert 'http_code' in x, \
+ f'status #{idx} reports no http_code\n{self.dump_logs()}'
+ assert x['http_code'] == http_status, \
+ f'status #{idx} http_code: expected {http_status}, '\
+ f'got {x["http_code"]}\n{self.dump_logs()}'
+ if exitcode is not None:
+ for idx, x in enumerate(self.stats):
+ if 'exitcode' in x:
+ assert x['exitcode'] == 0, \
+ f'status #{idx} exitcode: expected {exitcode}, '\
+ f'got {x["exitcode"]}\n{self.dump_logs()}'
+
+ def dump_logs(self):
+ lines = []
+ lines.append('>>--stdout ----------------------------------------------\n')
+ lines.extend(self._stdout)
+ if self._trace:
+ lines.append('>>--trace ----------------------------------------------\n')
+ lines.extend(self._trace)
+ else:
+ lines.append('>>--stderr ----------------------------------------------\n')
+ lines.extend(self._stderr)
+ lines.append('<<-------------------------------------------------------\n')
+ return ''.join(lines)
+
+
+class CurlClient:
+
+ ALPN_ARG = {
+ 'http/0.9': '--http0.9',
+ 'http/1.0': '--http1.0',
+ 'http/1.1': '--http1.1',
+ 'h2': '--http2',
+ 'h2c': '--http2',
+ 'h3': '--http3-only',
+ }
+
+ def __init__(self, env: Env, run_dir: Optional[str] = None,
+ timeout: Optional[float] = None, silent: bool = False):
+ self.env = env
+ self._timeout = timeout if timeout else env.test_timeout
+ self._curl = os.environ['CURL'] if 'CURL' in os.environ else env.curl
+ self._run_dir = run_dir if run_dir else os.path.join(env.gen_dir, 'curl')
+ self._stdoutfile = f'{self._run_dir}/curl.stdout'
+ self._stderrfile = f'{self._run_dir}/curl.stderr'
+ self._headerfile = f'{self._run_dir}/curl.headers'
+ self._tracefile = f'{self._run_dir}/curl.trace'
+ self._log_path = f'{self._run_dir}/curl.log'
+ self._silent = silent
+ self._rmrf(self._run_dir)
+ self._mkpath(self._run_dir)
+
+ @property
+ def run_dir(self) -> str:
+ return self._run_dir
+
+ def download_file(self, i: int) -> str:
+ return os.path.join(self.run_dir, f'download_{i}.data')
+
+ @property
+ def trace_file(self) -> str:
+ return self._tracefile
+
+ def _rmf(self, path):
+ if os.path.exists(path):
+ return os.remove(path)
+
+ def _rmrf(self, path):
+ if os.path.exists(path):
+ return shutil.rmtree(path)
+
+ def _mkpath(self, path):
+ if not os.path.exists(path):
+ return os.makedirs(path)
+
+ def get_proxy_args(self, proto: str = 'http/1.1',
+ proxys: bool = True, tunnel: bool = False):
+ if proxys:
+ pport = self.env.pts_port(proto) if tunnel else self.env.proxys_port
+ xargs = [
+ '--proxy', f'https://{self.env.proxy_domain}:{pport}/',
+ '--resolve', f'{self.env.proxy_domain}:{pport}:127.0.0.1',
+ '--proxy-cacert', self.env.ca.cert_file,
+ ]
+ if proto == 'h2':
+ xargs.append('--proxy-http2')
+ else:
+ xargs = [
+ '--proxy', f'http://{self.env.proxy_domain}:{self.env.proxy_port}/',
+ '--resolve', f'{self.env.proxy_domain}:{self.env.proxy_port}:127.0.0.1',
+ ]
+ if tunnel:
+ xargs.append('--proxytunnel')
+ return xargs
+
+ def http_get(self, url: str, extra_args: Optional[List[str]] = None):
+ return self._raw(url, options=extra_args, with_stats=False)
+
+ def http_download(self, urls: List[str],
+ alpn_proto: Optional[str] = None,
+ with_stats: bool = True,
+ with_headers: bool = False,
+ no_save: bool = False,
+ with_trace: bool = False,
+ extra_args: List[str] = None):
+ if extra_args is None:
+ extra_args = []
+ if no_save:
+ extra_args.extend([
+ '-o', '/dev/null',
+ ])
+ else:
+ extra_args.extend([
+ '-o', 'download_#1.data',
+ ])
+ # remove any existing ones
+ for i in range(100):
+ self._rmf(self.download_file(i))
+ if with_stats:
+ extra_args.extend([
+ '-w', '%{json}\\n'
+ ])
+ return self._raw(urls, alpn_proto=alpn_proto, options=extra_args,
+ with_stats=with_stats,
+ with_headers=with_headers,
+ with_trace=with_trace)
+
+ def http_upload(self, urls: List[str], data: str,
+ alpn_proto: Optional[str] = None,
+ with_stats: bool = True,
+ with_headers: bool = False,
+ with_trace: bool = False,
+ extra_args: Optional[List[str]] = None):
+ if extra_args is None:
+ extra_args = []
+ extra_args.extend([
+ '--data-binary', data, '-o', 'download_#1.data',
+ ])
+ if with_stats:
+ extra_args.extend([
+ '-w', '%{json}\\n'
+ ])
+ return self._raw(urls, alpn_proto=alpn_proto, options=extra_args,
+ with_stats=with_stats,
+ with_headers=with_headers,
+ with_trace=with_trace)
+
+ def http_put(self, urls: List[str], data=None, fdata=None,
+ alpn_proto: Optional[str] = None,
+ with_stats: bool = True,
+ with_headers: bool = False,
+ with_trace: bool = False,
+ extra_args: Optional[List[str]] = None):
+ if extra_args is None:
+ extra_args = []
+ if fdata is not None:
+ extra_args.extend(['-T', fdata])
+ elif data is not None:
+ extra_args.extend(['-T', '-'])
+ extra_args.extend([
+ '-o', 'download_#1.data',
+ ])
+ if with_stats:
+ extra_args.extend([
+ '-w', '%{json}\\n'
+ ])
+ return self._raw(urls, intext=data,
+ alpn_proto=alpn_proto, options=extra_args,
+ with_stats=with_stats,
+ with_headers=with_headers,
+ with_trace=with_trace)
+
+ def response_file(self, idx: int):
+ return os.path.join(self._run_dir, f'download_{idx}.data')
+
+ def run_direct(self, args, with_stats: bool = False):
+ my_args = [self._curl]
+ if with_stats:
+ my_args.extend([
+ '-w', '%{json}\\n'
+ ])
+ my_args.extend([
+ '-o', 'download.data',
+ ])
+ my_args.extend(args)
+ return self._run(args=my_args, with_stats=with_stats)
+
+ def _run(self, args, intext='', with_stats: bool = False):
+ self._rmf(self._stdoutfile)
+ self._rmf(self._stderrfile)
+ self._rmf(self._headerfile)
+ self._rmf(self._tracefile)
+ start = datetime.now()
+ exception = None
+ try:
+ with open(self._stdoutfile, 'w') as cout:
+ with open(self._stderrfile, 'w') as cerr:
+ p = subprocess.run(args, stderr=cerr, stdout=cout,
+ cwd=self._run_dir, shell=False,
+ input=intext.encode() if intext else None,
+ timeout=self._timeout)
+ exitcode = p.returncode
+ except subprocess.TimeoutExpired:
+ log.warning(f'Timeout after {self._timeout}s: {args}')
+ exitcode = -1
+ exception = 'TimeoutExpired'
+ coutput = open(self._stdoutfile).readlines()
+ cerrput = open(self._stderrfile).readlines()
+ ctrace = None
+ if os.path.exists(self._tracefile):
+ ctrace = open(self._tracefile).readlines()
+ return ExecResult(args=args, exit_code=exitcode, exception=exception,
+ stdout=coutput, stderr=cerrput, trace=ctrace,
+ duration=datetime.now() - start,
+ with_stats=with_stats)
+
+ def _raw(self, urls, intext='', timeout=None, options=None, insecure=False,
+ alpn_proto: Optional[str] = None,
+ force_resolve=True,
+ with_stats=False,
+ with_headers=True,
+ with_trace=False):
+ args = self._complete_args(
+ urls=urls, timeout=timeout, options=options, insecure=insecure,
+ alpn_proto=alpn_proto, force_resolve=force_resolve,
+ with_headers=with_headers, with_trace=with_trace)
+ r = self._run(args, intext=intext, with_stats=with_stats)
+ if r.exit_code == 0 and with_headers:
+ self._parse_headerfile(self._headerfile, r=r)
+ if r.json:
+ r.response["json"] = r.json
+ return r
+
+ def _complete_args(self, urls, timeout=None, options=None,
+ insecure=False, force_resolve=True,
+ alpn_proto: Optional[str] = None,
+ with_headers: bool = True,
+ with_trace: bool = False):
+ if not isinstance(urls, list):
+ urls = [urls]
+
+ args = [self._curl, "-s", "--path-as-is", '--trace-time', '--trace-ids']
+ if with_headers:
+ args.extend(["-D", self._headerfile])
+ if with_trace or self.env.verbose > 2:
+ args.extend(['--trace', self._tracefile])
+ elif self.env.verbose > 1:
+ args.extend(['--trace-ascii', self._tracefile])
+ elif not self._silent:
+ args.extend(['-v'])
+
+ for url in urls:
+ u = urlparse(urls[0])
+ if alpn_proto is not None:
+ if alpn_proto not in self.ALPN_ARG:
+ raise Exception(f'unknown ALPN protocol: "{alpn_proto}"')
+ args.append(self.ALPN_ARG[alpn_proto])
+
+ if u.scheme == 'http':
+ pass
+ elif insecure:
+ args.append('--insecure')
+ elif options and "--cacert" in options:
+ pass
+ elif u.hostname:
+ args.extend(["--cacert", self.env.ca.cert_file])
+
+ if force_resolve and u.hostname and u.hostname != 'localhost' \
+ and not re.match(r'^(\d+|\[|:).*', u.hostname):
+ port = u.port if u.port else 443
+ args.extend(["--resolve", f"{u.hostname}:{port}:127.0.0.1"])
+ if timeout is not None and int(timeout) > 0:
+ args.extend(["--connect-timeout", str(int(timeout))])
+ if options:
+ args.extend(options)
+ args.append(url)
+ return args
+
+ def _parse_headerfile(self, headerfile: str, r: ExecResult = None) -> ExecResult:
+ lines = open(headerfile).readlines()
+ if r is None:
+ r = ExecResult(args=[], exit_code=0, stdout=[], stderr=[])
+
+ response = None
+
+ def fin_response(resp):
+ if resp:
+ r.add_response(resp)
+
+ expected = ['status']
+ for line in lines:
+ line = line.strip()
+ if re.match(r'^$', line):
+ if 'trailer' in expected:
+ # end of trailers
+ fin_response(response)
+ response = None
+ expected = ['status']
+ elif 'header' in expected:
+ # end of header, another status or trailers might follow
+ expected = ['status', 'trailer']
+ else:
+ assert False, f"unexpected line: '{line}'"
+ continue
+ if 'status' in expected:
+ # log.debug("reading 1st response line: %s", line)
+ m = re.match(r'^(\S+) (\d+)( .*)?$', line)
+ if m:
+ fin_response(response)
+ response = {
+ "protocol": m.group(1),
+ "status": int(m.group(2)),
+ "description": m.group(3),
+ "header": {},
+ "trailer": {},
+ "body": r.outraw
+ }
+ expected = ['header']
+ continue
+ if 'trailer' in expected:
+ m = re.match(r'^([^:]+):\s*(.*)$', line)
+ if m:
+ response['trailer'][m.group(1).lower()] = m.group(2)
+ continue
+ if 'header' in expected:
+ m = re.match(r'^([^:]+):\s*(.*)$', line)
+ if m:
+ response['header'][m.group(1).lower()] = m.group(2)
+ continue
+ assert False, f"unexpected line: '{line}, expected: {expected}'"
+
+ fin_response(response)
+ return r
diff --git a/tests/http/testenv/env.py b/tests/http/testenv/env.py
new file mode 100644
index 0000000..b2ed4e6
--- /dev/null
+++ b/tests/http/testenv/env.py
@@ -0,0 +1,472 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import logging
+import os
+import re
+import socket
+import subprocess
+import sys
+from configparser import ConfigParser, ExtendedInterpolation
+from typing import Optional
+
+import pytest
+
+from .certs import CertificateSpec, TestCA, Credentials
+from .ports import alloc_ports
+
+
+log = logging.getLogger(__name__)
+
+
+def init_config_from(conf_path):
+ if os.path.isfile(conf_path):
+ config = ConfigParser(interpolation=ExtendedInterpolation())
+ config.read(conf_path)
+ return config
+ return None
+
+
+TESTS_HTTPD_PATH = os.path.dirname(os.path.dirname(__file__))
+DEF_CONFIG = init_config_from(os.path.join(TESTS_HTTPD_PATH, 'config.ini'))
+
+TOP_PATH = os.path.dirname(os.path.dirname(TESTS_HTTPD_PATH))
+CURL = os.path.join(TOP_PATH, 'src/curl')
+
+
+class EnvConfig:
+
+ def __init__(self):
+ self.tests_dir = TESTS_HTTPD_PATH
+ self.gen_dir = os.path.join(self.tests_dir, 'gen')
+ self.project_dir = os.path.dirname(os.path.dirname(self.tests_dir))
+ self.config = DEF_CONFIG
+ # check cur and its features
+ self.curl = CURL
+ if 'CURL' in os.environ:
+ self.curl = os.environ['CURL']
+ self.curl_props = {
+ 'version': None,
+ 'os': None,
+ 'fullname': None,
+ 'features': [],
+ 'protocols': [],
+ 'libs': [],
+ 'lib_versions': [],
+ }
+ self.curl_protos = []
+ p = subprocess.run(args=[self.curl, '-V'],
+ capture_output=True, text=True)
+ if p.returncode != 0:
+ assert False, f'{self.curl} -V failed with exit code: {p.returncode}'
+ for l in p.stdout.splitlines(keepends=False):
+ if l.startswith('curl '):
+ m = re.match(r'^curl (?P<version>\S+) (?P<os>\S+) (?P<libs>.*)$', l)
+ if m:
+ self.curl_props['fullname'] = m.group(0)
+ self.curl_props['version'] = m.group('version')
+ self.curl_props['os'] = m.group('os')
+ self.curl_props['lib_versions'] = [
+ lib.lower() for lib in m.group('libs').split(' ')
+ ]
+ self.curl_props['libs'] = [
+ re.sub(r'/.*', '', lib) for lib in self.curl_props['lib_versions']
+ ]
+ if l.startswith('Features: '):
+ self.curl_props['features'] = [
+ feat.lower() for feat in l[10:].split(' ')
+ ]
+ if l.startswith('Protocols: '):
+ self.curl_props['protocols'] = [
+ prot.lower() for prot in l[11:].split(' ')
+ ]
+
+ self.ports = alloc_ports(port_specs={
+ 'http': socket.SOCK_STREAM,
+ 'https': socket.SOCK_STREAM,
+ 'proxy': socket.SOCK_STREAM,
+ 'proxys': socket.SOCK_STREAM,
+ 'h2proxys': socket.SOCK_STREAM,
+ 'caddy': socket.SOCK_STREAM,
+ 'caddys': socket.SOCK_STREAM,
+ 'ws': socket.SOCK_STREAM,
+ })
+ self.httpd = self.config['httpd']['httpd']
+ self.apachectl = self.config['httpd']['apachectl']
+ self.apxs = self.config['httpd']['apxs']
+ if len(self.apxs) == 0:
+ self.apxs = None
+ self._httpd_version = None
+
+ self.examples_pem = {
+ 'key': 'xxx',
+ 'cert': 'xxx',
+ }
+ self.htdocs_dir = os.path.join(self.gen_dir, 'htdocs')
+ self.tld = 'http.curl.se'
+ self.domain1 = f"one.{self.tld}"
+ self.domain2 = f"two.{self.tld}"
+ self.proxy_domain = f"proxy.{self.tld}"
+ self.cert_specs = [
+ CertificateSpec(domains=[self.domain1, 'localhost'], key_type='rsa2048'),
+ CertificateSpec(domains=[self.domain2], key_type='rsa2048'),
+ CertificateSpec(domains=[self.proxy_domain], key_type='rsa2048'),
+ CertificateSpec(name="clientsX", sub_specs=[
+ CertificateSpec(name="user1", client=True),
+ ]),
+ ]
+
+ self.nghttpx = self.config['nghttpx']['nghttpx']
+ if len(self.nghttpx.strip()) == 0:
+ self.nghttpx = None
+ self._nghttpx_version = None
+ self.nghttpx_with_h3 = False
+ if self.nghttpx is not None:
+ p = subprocess.run(args=[self.nghttpx, '-v'],
+ capture_output=True, text=True)
+ if p.returncode != 0:
+ # not a working nghttpx
+ self.nghttpx = None
+ else:
+ self._nghttpx_version = re.sub(r'^nghttpx\s*', '', p.stdout.strip())
+ self.nghttpx_with_h3 = re.match(r'.* nghttp3/.*', p.stdout.strip()) is not None
+ log.debug(f'nghttpx -v: {p.stdout}')
+
+ self.caddy = self.config['caddy']['caddy']
+ self._caddy_version = None
+ if len(self.caddy.strip()) == 0:
+ self.caddy = None
+ if self.caddy is not None:
+ try:
+ p = subprocess.run(args=[self.caddy, 'version'],
+ capture_output=True, text=True)
+ if p.returncode != 0:
+ # not a working caddy
+ self.caddy = None
+ self._caddy_version = re.sub(r' .*', '', p.stdout.strip())
+ except:
+ self.caddy = None
+
+ @property
+ def httpd_version(self):
+ if self._httpd_version is None and self.apxs is not None:
+ try:
+ p = subprocess.run(args=[self.apxs, '-q', 'HTTPD_VERSION'],
+ capture_output=True, text=True)
+ if p.returncode != 0:
+ log.error(f'{self.apxs} failed to query HTTPD_VERSION: {p}')
+ else:
+ self._httpd_version = p.stdout.strip()
+ except Exception as e:
+ log.error(f'{self.apxs} failed to run: {e}')
+ return self._httpd_version
+
+ def _versiontuple(self, v):
+ v = re.sub(r'(\d+\.\d+(\.\d+)?)(-\S+)?', r'\1', v)
+ return tuple(map(int, v.split('.')))
+
+ def httpd_is_at_least(self, minv):
+ if self.httpd_version is None:
+ return False
+ hv = self._versiontuple(self.httpd_version)
+ return hv >= self._versiontuple(minv)
+
+ def is_complete(self) -> bool:
+ return os.path.isfile(self.httpd) and \
+ os.path.isfile(self.apachectl) and \
+ self.apxs is not None and \
+ os.path.isfile(self.apxs)
+
+ def get_incomplete_reason(self) -> Optional[str]:
+ if self.httpd is None or len(self.httpd.strip()) == 0:
+ return f'httpd not configured, see `--with-test-httpd=<path>`'
+ if not os.path.isfile(self.httpd):
+ return f'httpd ({self.httpd}) not found'
+ if not os.path.isfile(self.apachectl):
+ return f'apachectl ({self.apachectl}) not found'
+ if self.apxs is None:
+ return f"command apxs not found (commonly provided in apache2-dev)"
+ if not os.path.isfile(self.apxs):
+ return f"apxs ({self.apxs}) not found"
+ return None
+
+ @property
+ def nghttpx_version(self):
+ return self._nghttpx_version
+
+ @property
+ def caddy_version(self):
+ return self._caddy_version
+
+
+class Env:
+
+ CONFIG = EnvConfig()
+
+ @staticmethod
+ def setup_incomplete() -> bool:
+ return not Env.CONFIG.is_complete()
+
+ @staticmethod
+ def incomplete_reason() -> Optional[str]:
+ return Env.CONFIG.get_incomplete_reason()
+
+ @staticmethod
+ def have_nghttpx() -> bool:
+ return Env.CONFIG.nghttpx is not None
+
+ @staticmethod
+ def have_h3_server() -> bool:
+ return Env.CONFIG.nghttpx_with_h3
+
+ @staticmethod
+ def have_ssl_curl() -> bool:
+ return 'ssl' in Env.CONFIG.curl_props['features']
+
+ @staticmethod
+ def have_h2_curl() -> bool:
+ return 'http2' in Env.CONFIG.curl_props['features']
+
+ @staticmethod
+ def have_h3_curl() -> bool:
+ return 'http3' in Env.CONFIG.curl_props['features']
+
+ @staticmethod
+ def curl_uses_lib(libname: str) -> bool:
+ return libname.lower() in Env.CONFIG.curl_props['libs']
+
+ @staticmethod
+ def curl_has_feature(feature: str) -> bool:
+ return feature.lower() in Env.CONFIG.curl_props['features']
+
+ @staticmethod
+ def curl_has_protocol(protocol: str) -> bool:
+ return protocol.lower() in Env.CONFIG.curl_props['protocols']
+
+ @staticmethod
+ def curl_lib_version(libname: str) -> str:
+ prefix = f'{libname.lower()}/'
+ for lversion in Env.CONFIG.curl_props['lib_versions']:
+ if lversion.startswith(prefix):
+ return lversion[len(prefix):]
+ return 'unknown'
+
+ @staticmethod
+ def curl_os() -> str:
+ return Env.CONFIG.curl_props['os']
+
+ @staticmethod
+ def curl_fullname() -> str:
+ return Env.CONFIG.curl_props['fullname']
+
+ @staticmethod
+ def curl_version() -> str:
+ return Env.CONFIG.curl_props['version']
+
+ @staticmethod
+ def have_h3() -> bool:
+ return Env.have_h3_curl() and Env.have_h3_server()
+
+ @staticmethod
+ def httpd_version() -> str:
+ return Env.CONFIG.httpd_version
+
+ @staticmethod
+ def nghttpx_version() -> str:
+ return Env.CONFIG.nghttpx_version
+
+ @staticmethod
+ def caddy_version() -> str:
+ return Env.CONFIG.caddy_version
+
+ @staticmethod
+ def httpd_is_at_least(minv) -> bool:
+ return Env.CONFIG.httpd_is_at_least(minv)
+
+ @staticmethod
+ def has_caddy() -> bool:
+ return Env.CONFIG.caddy is not None
+
+ def __init__(self, pytestconfig=None):
+ self._verbose = pytestconfig.option.verbose \
+ if pytestconfig is not None else 0
+ self._ca = None
+ self._test_timeout = 300.0 if self._verbose > 1 else 60.0 # seconds
+
+ def issue_certs(self):
+ if self._ca is None:
+ ca_dir = os.path.join(self.CONFIG.gen_dir, 'ca')
+ self._ca = TestCA.create_root(name=self.CONFIG.tld,
+ store_dir=ca_dir,
+ key_type="rsa2048")
+ self._ca.issue_certs(self.CONFIG.cert_specs)
+
+ def setup(self):
+ os.makedirs(self.gen_dir, exist_ok=True)
+ os.makedirs(self.htdocs_dir, exist_ok=True)
+ self.issue_certs()
+
+ def get_credentials(self, domain) -> Optional[Credentials]:
+ creds = self.ca.get_credentials_for_name(domain)
+ if len(creds) > 0:
+ return creds[0]
+ return None
+
+ @property
+ def verbose(self) -> int:
+ return self._verbose
+
+ @property
+ def test_timeout(self) -> Optional[float]:
+ return self._test_timeout
+
+ @test_timeout.setter
+ def test_timeout(self, val: Optional[float]):
+ self._test_timeout = val
+
+ @property
+ def gen_dir(self) -> str:
+ return self.CONFIG.gen_dir
+
+ @property
+ def project_dir(self) -> str:
+ return self.CONFIG.project_dir
+
+ @property
+ def ca(self):
+ return self._ca
+
+ @property
+ def htdocs_dir(self) -> str:
+ return self.CONFIG.htdocs_dir
+
+ @property
+ def domain1(self) -> str:
+ return self.CONFIG.domain1
+
+ @property
+ def domain2(self) -> str:
+ return self.CONFIG.domain2
+
+ @property
+ def proxy_domain(self) -> str:
+ return self.CONFIG.proxy_domain
+
+ @property
+ def http_port(self) -> int:
+ return self.CONFIG.ports['http']
+
+ @property
+ def https_port(self) -> int:
+ return self.CONFIG.ports['https']
+
+ @property
+ def h3_port(self) -> int:
+ return self.https_port
+
+ @property
+ def proxy_port(self) -> int:
+ return self.CONFIG.ports['proxy']
+
+ @property
+ def proxys_port(self) -> int:
+ return self.CONFIG.ports['proxys']
+
+ @property
+ def h2proxys_port(self) -> int:
+ return self.CONFIG.ports['h2proxys']
+
+ def pts_port(self, proto: str = 'http/1.1') -> int:
+ # proxy tunnel port
+ return self.CONFIG.ports['h2proxys' if proto == 'h2' else 'proxys']
+
+ @property
+ def caddy(self) -> str:
+ return self.CONFIG.caddy
+
+ @property
+ def caddy_https_port(self) -> int:
+ return self.CONFIG.ports['caddys']
+
+ @property
+ def caddy_http_port(self) -> int:
+ return self.CONFIG.ports['caddy']
+
+ @property
+ def ws_port(self) -> int:
+ return self.CONFIG.ports['ws']
+
+ @property
+ def curl(self) -> str:
+ return self.CONFIG.curl
+
+ @property
+ def httpd(self) -> str:
+ return self.CONFIG.httpd
+
+ @property
+ def apachectl(self) -> str:
+ return self.CONFIG.apachectl
+
+ @property
+ def apxs(self) -> str:
+ return self.CONFIG.apxs
+
+ @property
+ def nghttpx(self) -> Optional[str]:
+ return self.CONFIG.nghttpx
+
+ def authority_for(self, domain: str, alpn_proto: Optional[str] = None):
+ if alpn_proto is None or \
+ alpn_proto in ['h2', 'http/1.1', 'http/1.0', 'http/0.9']:
+ return f'{domain}:{self.https_port}'
+ if alpn_proto in ['h3']:
+ return f'{domain}:{self.h3_port}'
+ return f'{domain}:{self.http_port}'
+
+ def make_data_file(self, indir: str, fname: str, fsize: int) -> str:
+ fpath = os.path.join(indir, fname)
+ s10 = "0123456789"
+ s = (101 * s10) + s10[0:3]
+ with open(fpath, 'w') as fd:
+ for i in range(int(fsize / 1024)):
+ fd.write(f"{i:09d}-{s}\n")
+ remain = int(fsize % 1024)
+ if remain != 0:
+ i = int(fsize / 1024) + 1
+ s = f"{i:09d}-{s}\n"
+ fd.write(s[0:remain])
+ return fpath
+
+ def make_clients(self):
+ client_dir = os.path.join(self.project_dir, 'tests/http/clients')
+ p = subprocess.run(['make'], capture_output=True, text=True,
+ cwd=client_dir)
+ if p.returncode != 0:
+ pytest.exit(f"`make`in {client_dir} failed:\n{p.stderr}")
+ return False
+ return True
+
diff --git a/tests/http/testenv/httpd.py b/tests/http/testenv/httpd.py
new file mode 100644
index 0000000..4db1845
--- /dev/null
+++ b/tests/http/testenv/httpd.py
@@ -0,0 +1,411 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import inspect
+import logging
+import os
+import subprocess
+from datetime import timedelta, datetime
+from json import JSONEncoder
+import time
+from typing import List, Union, Optional
+
+from .curl import CurlClient, ExecResult
+from .env import Env
+
+
+log = logging.getLogger(__name__)
+
+
+class Httpd:
+
+ MODULES = [
+ 'log_config', 'logio', 'unixd', 'version', 'watchdog',
+ 'authn_core', 'authn_file',
+ 'authz_user', 'authz_core', 'authz_host',
+ 'auth_basic', 'auth_digest',
+ 'env', 'filter', 'headers', 'mime',
+ 'rewrite', 'http2', 'ssl', 'proxy', 'proxy_http', 'proxy_connect',
+ 'mpm_event',
+ ]
+ COMMON_MODULES_DIRS = [
+ '/usr/lib/apache2/modules', # debian
+ '/usr/libexec/apache2/', # macos
+ ]
+
+ MOD_CURLTEST = None
+
+ def __init__(self, env: Env, proxy_auth: bool = False):
+ self.env = env
+ self._cmd = env.apachectl
+ self._apache_dir = os.path.join(env.gen_dir, 'apache')
+ self._run_dir = os.path.join(self._apache_dir, 'run')
+ self._lock_dir = os.path.join(self._apache_dir, 'locks')
+ self._docs_dir = os.path.join(self._apache_dir, 'docs')
+ self._conf_dir = os.path.join(self._apache_dir, 'conf')
+ self._conf_file = os.path.join(self._conf_dir, 'test.conf')
+ self._logs_dir = os.path.join(self._apache_dir, 'logs')
+ self._error_log = os.path.join(self._logs_dir, 'error_log')
+ self._tmp_dir = os.path.join(self._apache_dir, 'tmp')
+ self._basic_passwords = os.path.join(self._conf_dir, 'basic.passwords')
+ self._digest_passwords = os.path.join(self._conf_dir, 'digest.passwords')
+ self._mods_dir = None
+ self._auth_digest = True
+ self._proxy_auth_basic = proxy_auth
+ self._extra_configs = {}
+ assert env.apxs
+ p = subprocess.run(args=[env.apxs, '-q', 'libexecdir'],
+ capture_output=True, text=True)
+ if p.returncode != 0:
+ raise Exception(f'{env.apxs} failed to query libexecdir: {p}')
+ self._mods_dir = p.stdout.strip()
+ if self._mods_dir is None:
+ raise Exception(f'apache modules dir cannot be found')
+ if not os.path.exists(self._mods_dir):
+ raise Exception(f'apache modules dir does not exist: {self._mods_dir}')
+ self._process = None
+ self._rmf(self._error_log)
+ self._init_curltest()
+
+ @property
+ def docs_dir(self):
+ return self._docs_dir
+
+ def clear_logs(self):
+ self._rmf(self._error_log)
+
+ def exists(self):
+ return os.path.exists(self._cmd)
+
+ def set_extra_config(self, domain: str, lines: Optional[Union[str, List[str]]]):
+ if lines is None:
+ self._extra_configs.pop(domain, None)
+ else:
+ self._extra_configs[domain] = lines
+
+ def clear_extra_configs(self):
+ self._extra_configs = {}
+
+ def set_proxy_auth(self, active: bool):
+ self._proxy_auth_basic = active
+
+ def _run(self, args, intext=''):
+ env = {}
+ for key, val in os.environ.items():
+ env[key] = val
+ env['APACHE_RUN_DIR'] = self._run_dir
+ env['APACHE_RUN_USER'] = os.environ['USER']
+ env['APACHE_LOCK_DIR'] = self._lock_dir
+ env['APACHE_CONFDIR'] = self._apache_dir
+ p = subprocess.run(args, stderr=subprocess.PIPE, stdout=subprocess.PIPE,
+ cwd=self.env.gen_dir,
+ input=intext.encode() if intext else None,
+ env=env)
+ start = datetime.now()
+ return ExecResult(args=args, exit_code=p.returncode,
+ stdout=p.stdout.decode().splitlines(),
+ stderr=p.stderr.decode().splitlines(),
+ duration=datetime.now() - start)
+
+ def _apachectl(self, cmd: str):
+ args = [self.env.apachectl,
+ "-d", self._apache_dir,
+ "-f", self._conf_file,
+ "-k", cmd]
+ return self._run(args=args)
+
+ def start(self):
+ if self._process:
+ self.stop()
+ self._write_config()
+ with open(self._error_log, 'a') as fd:
+ fd.write('start of server\n')
+ with open(os.path.join(self._apache_dir, 'xxx'), 'a') as fd:
+ fd.write('start of server\n')
+ r = self._apachectl('start')
+ if r.exit_code != 0:
+ log.error(f'failed to start httpd: {r}')
+ return False
+ return self.wait_live(timeout=timedelta(seconds=5))
+
+ def stop(self):
+ r = self._apachectl('stop')
+ if r.exit_code == 0:
+ return self.wait_dead(timeout=timedelta(seconds=5))
+ log.fatal(f'stopping httpd failed: {r}')
+ return r.exit_code == 0
+
+ def restart(self):
+ self.stop()
+ return self.start()
+
+ def reload(self):
+ self._write_config()
+ r = self._apachectl("graceful")
+ if r.exit_code != 0:
+ log.error(f'failed to reload httpd: {r}')
+ return self.wait_live(timeout=timedelta(seconds=5))
+
+ def wait_dead(self, timeout: timedelta):
+ curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
+ try_until = datetime.now() + timeout
+ while datetime.now() < try_until:
+ r = curl.http_get(url=f'http://{self.env.domain1}:{self.env.http_port}/')
+ if r.exit_code != 0:
+ return True
+ time.sleep(.1)
+ log.debug(f"Server still responding after {timeout}")
+ return False
+
+ def wait_live(self, timeout: timedelta):
+ curl = CurlClient(env=self.env, run_dir=self._tmp_dir,
+ timeout=timeout.total_seconds())
+ try_until = datetime.now() + timeout
+ while datetime.now() < try_until:
+ r = curl.http_get(url=f'http://{self.env.domain1}:{self.env.http_port}/')
+ if r.exit_code == 0:
+ return True
+ time.sleep(.1)
+ log.debug(f"Server still not responding after {timeout}")
+ return False
+
+ def _rmf(self, path):
+ if os.path.exists(path):
+ return os.remove(path)
+
+ def _mkpath(self, path):
+ if not os.path.exists(path):
+ return os.makedirs(path)
+
+ def _write_config(self):
+ domain1 = self.env.domain1
+ creds1 = self.env.get_credentials(domain1)
+ domain2 = self.env.domain2
+ creds2 = self.env.get_credentials(domain2)
+ proxy_domain = self.env.proxy_domain
+ proxy_creds = self.env.get_credentials(proxy_domain)
+ self._mkpath(self._conf_dir)
+ self._mkpath(self._logs_dir)
+ self._mkpath(self._tmp_dir)
+ self._mkpath(os.path.join(self._docs_dir, 'two'))
+ with open(os.path.join(self._docs_dir, 'data.json'), 'w') as fd:
+ data = {
+ 'server': f'{domain1}',
+ }
+ fd.write(JSONEncoder().encode(data))
+ with open(os.path.join(self._docs_dir, 'two/data.json'), 'w') as fd:
+ data = {
+ 'server': f'{domain2}',
+ }
+ fd.write(JSONEncoder().encode(data))
+ if self._proxy_auth_basic:
+ with open(self._basic_passwords, 'w') as fd:
+ fd.write('proxy:$apr1$FQfeInbs$WQZbODJlVg60j0ogEIlTW/\n')
+ if self._auth_digest:
+ with open(self._digest_passwords, 'w') as fd:
+ fd.write('test:restricted area:57123e269fd73d71ae0656594e938e2f\n')
+ self._mkpath(os.path.join(self.docs_dir, 'restricted/digest'))
+ with open(os.path.join(self.docs_dir, 'restricted/digest/data.json'), 'w') as fd:
+ fd.write('{"area":"digest"}\n')
+ with open(self._conf_file, 'w') as fd:
+ for m in self.MODULES:
+ if os.path.exists(os.path.join(self._mods_dir, f'mod_{m}.so')):
+ fd.write(f'LoadModule {m}_module "{self._mods_dir}/mod_{m}.so"\n')
+ if Httpd.MOD_CURLTEST is not None:
+ fd.write(f'LoadModule curltest_module \"{Httpd.MOD_CURLTEST}\"\n')
+ conf = [ # base server config
+ f'ServerRoot "{self._apache_dir}"',
+ f'DefaultRuntimeDir logs',
+ f'PidFile httpd.pid',
+ f'ErrorLog {self._error_log}',
+ f'LogLevel {self._get_log_level()}',
+ f'H2MinWorkers 16',
+ f'H2MaxWorkers 128',
+ f'H2Direct on',
+ f'Listen {self.env.http_port}',
+ f'Listen {self.env.https_port}',
+ f'Listen {self.env.proxy_port}',
+ f'Listen {self.env.proxys_port}',
+ f'TypesConfig "{self._conf_dir}/mime.types',
+ ]
+ if 'base' in self._extra_configs:
+ conf.extend(self._extra_configs['base'])
+ conf.extend([ # plain http host for domain1
+ f'<VirtualHost *:{self.env.http_port}>',
+ f' ServerName {domain1}',
+ f' ServerAlias localhost',
+ f' DocumentRoot "{self._docs_dir}"',
+ f' Protocols h2c http/1.1',
+ ])
+ conf.extend(self._curltest_conf(domain1))
+ conf.extend([
+ f'</VirtualHost>',
+ f'',
+ ])
+ conf.extend([ # https host for domain1, h1 + h2
+ f'<VirtualHost *:{self.env.https_port}>',
+ f' ServerName {domain1}',
+ f' ServerAlias localhost',
+ f' Protocols h2 http/1.1',
+ f' SSLEngine on',
+ f' SSLCertificateFile {creds1.cert_file}',
+ f' SSLCertificateKeyFile {creds1.pkey_file}',
+ f' DocumentRoot "{self._docs_dir}"',
+ ])
+ conf.extend(self._curltest_conf(domain1))
+ if domain1 in self._extra_configs:
+ conf.extend(self._extra_configs[domain1])
+ conf.extend([
+ f'</VirtualHost>',
+ f'',
+ ])
+ conf.extend([ # https host for domain2, no h2
+ f'<VirtualHost *:{self.env.https_port}>',
+ f' ServerName {domain2}',
+ f' Protocols http/1.1',
+ f' SSLEngine on',
+ f' SSLCertificateFile {creds2.cert_file}',
+ f' SSLCertificateKeyFile {creds2.pkey_file}',
+ f' DocumentRoot "{self._docs_dir}/two"',
+ ])
+ conf.extend(self._curltest_conf(domain2))
+ if domain2 in self._extra_configs:
+ conf.extend(self._extra_configs[domain2])
+ conf.extend([
+ f'</VirtualHost>',
+ f'',
+ ])
+ conf.extend([ # http forward proxy
+ f'<VirtualHost *:{self.env.proxy_port}>',
+ f' ServerName {proxy_domain}',
+ f' Protocols h2c http/1.1',
+ f' ProxyRequests On',
+ f' H2ProxyRequests On',
+ f' ProxyVia On',
+ f' AllowCONNECT {self.env.http_port} {self.env.https_port}',
+ ])
+ conf.extend(self._get_proxy_conf())
+ conf.extend([
+ f'</VirtualHost>',
+ f'',
+ ])
+ conf.extend([ # https forward proxy
+ f'<VirtualHost *:{self.env.proxys_port}>',
+ f' ServerName {proxy_domain}',
+ f' Protocols h2 http/1.1',
+ f' SSLEngine on',
+ f' SSLCertificateFile {proxy_creds.cert_file}',
+ f' SSLCertificateKeyFile {proxy_creds.pkey_file}',
+ f' ProxyRequests On',
+ f' H2ProxyRequests On',
+ f' ProxyVia On',
+ f' AllowCONNECT {self.env.http_port} {self.env.https_port}',
+ ])
+ conf.extend(self._get_proxy_conf())
+ conf.extend([
+ f'</VirtualHost>',
+ f'',
+ ])
+
+ fd.write("\n".join(conf))
+ with open(os.path.join(self._conf_dir, 'mime.types'), 'w') as fd:
+ fd.write("\n".join([
+ 'text/html html',
+ 'application/json json',
+ ''
+ ]))
+
+ def _get_proxy_conf(self):
+ if self._proxy_auth_basic:
+ return [
+ f' <Proxy "*">',
+ f' AuthType Basic',
+ f' AuthName "Restricted Proxy"',
+ f' AuthBasicProvider file',
+ f' AuthUserFile "{self._basic_passwords}"',
+ f' Require user proxy',
+ f' </Proxy>',
+ ]
+ else:
+ return [
+ f' <Proxy "*">',
+ f' Require ip 127.0.0.1',
+ f' </Proxy>',
+ ]
+
+ def _get_log_level(self):
+ if self.env.verbose > 3:
+ return 'trace2'
+ if self.env.verbose > 2:
+ return 'trace1'
+ if self.env.verbose > 1:
+ return 'debug'
+ return 'info'
+
+ def _curltest_conf(self, servername) -> List[str]:
+ lines = []
+ if Httpd.MOD_CURLTEST is not None:
+ lines.extend([
+ f' <Location /curltest/echo>',
+ f' SetHandler curltest-echo',
+ f' </Location>',
+ f' <Location /curltest/put>',
+ f' SetHandler curltest-put',
+ f' </Location>',
+ f' <Location /curltest/tweak>',
+ f' SetHandler curltest-tweak',
+ f' </Location>',
+ f' <Location /curltest/1_1>',
+ f' SetHandler curltest-1_1-required',
+ f' </Location>',
+ ])
+ if self._auth_digest:
+ lines.extend([
+ f' <Directory {self.docs_dir}/restricted/digest>',
+ f' AuthType Digest',
+ f' AuthName "restricted area"',
+ f' AuthDigestDomain "https://{servername}"',
+ f' AuthBasicProvider file',
+ f' AuthUserFile "{self._digest_passwords}"',
+ f' Require valid-user',
+ f' </Directory>',
+
+ ])
+ return lines
+
+ def _init_curltest(self):
+ if Httpd.MOD_CURLTEST is not None:
+ return
+ local_dir = os.path.dirname(inspect.getfile(Httpd))
+ p = subprocess.run([self.env.apxs, '-c', 'mod_curltest.c'],
+ capture_output=True,
+ cwd=os.path.join(local_dir, 'mod_curltest'))
+ rv = p.returncode
+ if rv != 0:
+ log.error(f"compiling mod_curltest failed: {p.stderr}")
+ raise Exception(f"compiling mod_curltest failed: {p.stderr}")
+ Httpd.MOD_CURLTEST = os.path.join(
+ local_dir, 'mod_curltest/.libs/mod_curltest.so')
diff --git a/tests/http/testenv/mod_curltest/.gitignore b/tests/http/testenv/mod_curltest/.gitignore
new file mode 100644
index 0000000..0618663
--- /dev/null
+++ b/tests/http/testenv/mod_curltest/.gitignore
@@ -0,0 +1,5 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+*.slo
\ No newline at end of file
diff --git a/tests/http/testenv/mod_curltest/mod_curltest.c b/tests/http/testenv/mod_curltest/mod_curltest.c
new file mode 100644
index 0000000..30fb765
--- /dev/null
+++ b/tests/http/testenv/mod_curltest/mod_curltest.c
@@ -0,0 +1,583 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 <apr_optional.h>
+#include <apr_optional_hooks.h>
+#include <apr_strings.h>
+#include <apr_cstr.h>
+#include <apr_time.h>
+#include <apr_want.h>
+
+#include <httpd.h>
+#include <http_protocol.h>
+#include <http_request.h>
+#include <http_log.h>
+
+static void curltest_hooks(apr_pool_t *pool);
+static int curltest_echo_handler(request_rec *r);
+static int curltest_put_handler(request_rec *r);
+static int curltest_tweak_handler(request_rec *r);
+static int curltest_1_1_required(request_rec *r);
+
+AP_DECLARE_MODULE(curltest) = {
+ STANDARD20_MODULE_STUFF,
+ NULL, /* func to create per dir config */
+ NULL, /* func to merge per dir config */
+ NULL, /* func to create per server config */
+ NULL, /* func to merge per server config */
+ NULL, /* command handlers */
+ curltest_hooks,
+#if defined(AP_MODULE_FLAG_NONE)
+ AP_MODULE_FLAG_ALWAYS_MERGE
+#endif
+};
+
+static int curltest_post_config(apr_pool_t *p, apr_pool_t *plog,
+ apr_pool_t *ptemp, server_rec *s)
+{
+ void *data = NULL;
+ const char *key = "mod_curltest_init_counter";
+
+ (void)plog;(void)ptemp;
+
+ apr_pool_userdata_get(&data, key, s->process->pool);
+ if(!data) {
+ /* dry run */
+ apr_pool_userdata_set((const void *)1, key,
+ apr_pool_cleanup_null, s->process->pool);
+ return APR_SUCCESS;
+ }
+
+ /* mess with the overall server here */
+
+ return APR_SUCCESS;
+}
+
+static void curltest_hooks(apr_pool_t *pool)
+{
+ ap_log_perror(APLOG_MARK, APLOG_TRACE1, 0, pool, "installing hooks");
+
+ /* Run once after configuration is set, but before mpm children initialize.
+ */
+ ap_hook_post_config(curltest_post_config, NULL, NULL, APR_HOOK_MIDDLE);
+
+ /* curl test handlers */
+ ap_hook_handler(curltest_echo_handler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_handler(curltest_put_handler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_handler(curltest_tweak_handler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_handler(curltest_1_1_required, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+#define SECS_PER_HOUR (60*60)
+#define SECS_PER_DAY (24*SECS_PER_HOUR)
+
+static apr_status_t duration_parse(apr_interval_time_t *ptimeout, const char *value,
+ const char *def_unit)
+{
+ char *endp;
+ apr_int64_t n;
+
+ n = apr_strtoi64(value, &endp, 10);
+ if(errno) {
+ return errno;
+ }
+ if(!endp || !*endp) {
+ if (!def_unit) def_unit = "s";
+ }
+ else if(endp == value) {
+ return APR_EINVAL;
+ }
+ else {
+ def_unit = endp;
+ }
+
+ switch(*def_unit) {
+ case 'D':
+ case 'd':
+ *ptimeout = apr_time_from_sec(n * SECS_PER_DAY);
+ break;
+ case 's':
+ case 'S':
+ *ptimeout = (apr_interval_time_t) apr_time_from_sec(n);
+ break;
+ case 'h':
+ case 'H':
+ /* Time is in hours */
+ *ptimeout = (apr_interval_time_t) apr_time_from_sec(n * SECS_PER_HOUR);
+ break;
+ case 'm':
+ case 'M':
+ switch(*(++def_unit)) {
+ /* Time is in milliseconds */
+ case 's':
+ case 'S':
+ *ptimeout = (apr_interval_time_t) n * 1000;
+ break;
+ /* Time is in minutes */
+ case 'i':
+ case 'I':
+ *ptimeout = (apr_interval_time_t) apr_time_from_sec(n * 60);
+ break;
+ default:
+ return APR_EGENERAL;
+ }
+ break;
+ case 'u':
+ case 'U':
+ switch(*(++def_unit)) {
+ /* Time is in microseconds */
+ case 's':
+ case 'S':
+ *ptimeout = (apr_interval_time_t) n;
+ break;
+ default:
+ return APR_EGENERAL;
+ }
+ break;
+ default:
+ return APR_EGENERAL;
+ }
+ return APR_SUCCESS;
+}
+
+static int status_from_str(const char *s, apr_status_t *pstatus)
+{
+ if(!strcmp("timeout", s)) {
+ *pstatus = APR_TIMEUP;
+ return 1;
+ }
+ else if(!strcmp("reset", s)) {
+ *pstatus = APR_ECONNRESET;
+ return 1;
+ }
+ return 0;
+}
+
+static int curltest_echo_handler(request_rec *r)
+{
+ conn_rec *c = r->connection;
+ apr_bucket_brigade *bb;
+ apr_bucket *b;
+ apr_status_t rv;
+ char buffer[8192];
+ const char *ct;
+ long l;
+
+ if(strcmp(r->handler, "curltest-echo")) {
+ return DECLINED;
+ }
+ if(r->method_number != M_GET && r->method_number != M_POST) {
+ return DECLINED;
+ }
+
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "echo_handler: processing");
+ r->status = 200;
+ r->clength = -1;
+ r->chunked = 1;
+ apr_table_unset(r->headers_out, "Content-Length");
+ /* Discourage content-encodings */
+ apr_table_unset(r->headers_out, "Content-Encoding");
+ apr_table_setn(r->subprocess_env, "no-brotli", "1");
+ apr_table_setn(r->subprocess_env, "no-gzip", "1");
+
+ ct = apr_table_get(r->headers_in, "content-type");
+ ap_set_content_type(r, ct? ct : "application/octet-stream");
+
+ bb = apr_brigade_create(r->pool, c->bucket_alloc);
+ /* copy any request body into the response */
+ if((rv = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK))) goto cleanup;
+ if(ap_should_client_block(r)) {
+ while(0 < (l = ap_get_client_block(r, &buffer[0], sizeof(buffer)))) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "echo_handler: copying %ld bytes from request body", l);
+ rv = apr_brigade_write(bb, NULL, NULL, buffer, l);
+ if (APR_SUCCESS != rv) goto cleanup;
+ rv = ap_pass_brigade(r->output_filters, bb);
+ if (APR_SUCCESS != rv) goto cleanup;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "echo_handler: passed %ld bytes from request body", l);
+ }
+ }
+ /* we are done */
+ b = apr_bucket_eos_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "echo_handler: request read");
+
+ if(r->trailers_in && !apr_is_empty_table(r->trailers_in)) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
+ "echo_handler: seeing incoming trailers");
+ apr_table_setn(r->trailers_out, "h2test-trailers-in",
+ apr_itoa(r->pool, 1));
+ }
+
+ rv = ap_pass_brigade(r->output_filters, bb);
+
+cleanup:
+ if(rv == APR_SUCCESS ||
+ r->status != HTTP_OK ||
+ c->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, r, "echo_handler: done");
+ return OK;
+ }
+ else {
+ /* no way to know what type of error occurred */
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, r, "echo_handler failed");
+ return AP_FILTER_ERROR;
+ }
+ return DECLINED;
+}
+
+static int curltest_tweak_handler(request_rec *r)
+{
+ conn_rec *c = r->connection;
+ apr_bucket_brigade *bb;
+ apr_bucket *b;
+ apr_status_t rv;
+ char buffer[16*1024];
+ int i, chunks = 3, error_bucket = 1;
+ size_t chunk_size = sizeof(buffer);
+ const char *request_id = "none";
+ apr_time_t delay = 0, chunk_delay = 0;
+ apr_array_header_t *args = NULL;
+ int http_status = 200;
+ apr_status_t error = APR_SUCCESS, body_error = APR_SUCCESS;
+
+ if(strcmp(r->handler, "curltest-tweak")) {
+ return DECLINED;
+ }
+ if(r->method_number != M_GET && r->method_number != M_POST) {
+ return DECLINED;
+ }
+
+ if(r->args) {
+ args = apr_cstr_split(r->args, "&", 1, r->pool);
+ for(i = 0; i < args->nelts; ++i) {
+ char *s, *val, *arg = APR_ARRAY_IDX(args, i, char*);
+ s = strchr(arg, '=');
+ if(s) {
+ *s = '\0';
+ val = s + 1;
+ if(!strcmp("status", arg)) {
+ http_status = (int)apr_atoi64(val);
+ if(http_status > 0) {
+ continue;
+ }
+ }
+ else if(!strcmp("chunks", arg)) {
+ chunks = (int)apr_atoi64(val);
+ if(chunks >= 0) {
+ continue;
+ }
+ }
+ else if(!strcmp("chunk_size", arg)) {
+ chunk_size = (int)apr_atoi64(val);
+ if(chunk_size >= 0) {
+ if(chunk_size > sizeof(buffer)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "chunk_size %zu too large", chunk_size);
+ ap_die(HTTP_BAD_REQUEST, r);
+ return OK;
+ }
+ continue;
+ }
+ }
+ else if(!strcmp("id", arg)) {
+ /* just an id for repeated requests with curl's url globbing */
+ request_id = val;
+ continue;
+ }
+ else if(!strcmp("error", arg)) {
+ if(status_from_str(val, &error)) {
+ continue;
+ }
+ }
+ else if(!strcmp("error_bucket", arg)) {
+ error_bucket = (int)apr_atoi64(val);
+ if(error_bucket >= 0) {
+ continue;
+ }
+ }
+ else if(!strcmp("body_error", arg)) {
+ if(status_from_str(val, &body_error)) {
+ continue;
+ }
+ }
+ else if(!strcmp("delay", arg)) {
+ rv = duration_parse(&delay, val, "s");
+ if(APR_SUCCESS == rv) {
+ continue;
+ }
+ }
+ else if(!strcmp("chunk_delay", arg)) {
+ rv = duration_parse(&chunk_delay, val, "s");
+ if(APR_SUCCESS == rv) {
+ continue;
+ }
+ }
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "query parameter not "
+ "understood: '%s' in %s",
+ arg, r->args);
+ ap_die(HTTP_BAD_REQUEST, r);
+ return OK;
+ }
+ }
+
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "error_handler: processing "
+ "request, %s", r->args? r->args : "(no args)");
+ r->status = http_status;
+ r->clength = -1;
+ r->chunked = 1;
+ apr_table_setn(r->headers_out, "request-id", request_id);
+ apr_table_unset(r->headers_out, "Content-Length");
+ /* Discourage content-encodings */
+ apr_table_unset(r->headers_out, "Content-Encoding");
+ apr_table_setn(r->subprocess_env, "no-brotli", "1");
+ apr_table_setn(r->subprocess_env, "no-gzip", "1");
+
+ ap_set_content_type(r, "application/octet-stream");
+ bb = apr_brigade_create(r->pool, c->bucket_alloc);
+
+ if(delay) {
+ apr_sleep(delay);
+ }
+ if(error != APR_SUCCESS) {
+ return ap_map_http_request_error(error, HTTP_BAD_REQUEST);
+ }
+ /* flush response */
+ b = apr_bucket_flush_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ rv = ap_pass_brigade(r->output_filters, bb);
+ if (APR_SUCCESS != rv) goto cleanup;
+
+ memset(buffer, 'X', sizeof(buffer));
+ for(i = 0; i < chunks; ++i) {
+ if(chunk_delay) {
+ apr_sleep(chunk_delay);
+ }
+ rv = apr_brigade_write(bb, NULL, NULL, buffer, chunk_size);
+ if(APR_SUCCESS != rv) goto cleanup;
+ rv = ap_pass_brigade(r->output_filters, bb);
+ if(APR_SUCCESS != rv) goto cleanup;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "error_handler: passed %lu bytes as response body",
+ (unsigned long)chunk_size);
+ if(body_error != APR_SUCCESS) {
+ rv = body_error;
+ goto cleanup;
+ }
+ }
+ /* we are done */
+ b = apr_bucket_eos_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ rv = ap_pass_brigade(r->output_filters, bb);
+ apr_brigade_cleanup(bb);
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, r,
+ "error_handler: response passed");
+
+cleanup:
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, r,
+ "error_handler: request cleanup, r->status=%d, aborted=%d",
+ r->status, c->aborted);
+ if(rv == APR_SUCCESS) {
+ return OK;
+ }
+ if(error_bucket) {
+ http_status = ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
+ b = ap_bucket_error_create(http_status, NULL, r->pool, c->bucket_alloc);
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, r,
+ "error_handler: passing error bucket, status=%d",
+ http_status);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ ap_pass_brigade(r->output_filters, bb);
+ }
+ return AP_FILTER_ERROR;
+}
+
+static int curltest_put_handler(request_rec *r)
+{
+ conn_rec *c = r->connection;
+ apr_bucket_brigade *bb;
+ apr_bucket *b;
+ apr_status_t rv;
+ char buffer[16*1024];
+ const char *ct;
+ apr_off_t rbody_len = 0;
+ const char *request_id = "none";
+ apr_time_t chunk_delay = 0;
+ apr_array_header_t *args = NULL;
+ long l;
+ int i;
+
+ if(strcmp(r->handler, "curltest-put")) {
+ return DECLINED;
+ }
+ if(r->method_number != M_PUT) {
+ return DECLINED;
+ }
+
+ if(r->args) {
+ args = apr_cstr_split(r->args, "&", 1, r->pool);
+ for(i = 0; i < args->nelts; ++i) {
+ char *s, *val, *arg = APR_ARRAY_IDX(args, i, char*);
+ s = strchr(arg, '=');
+ if(s) {
+ *s = '\0';
+ val = s + 1;
+ if(!strcmp("id", arg)) {
+ /* just an id for repeated requests with curl's url globbing */
+ request_id = val;
+ continue;
+ }
+ else if(!strcmp("chunk_delay", arg)) {
+ rv = duration_parse(&chunk_delay, val, "s");
+ if(APR_SUCCESS == rv) {
+ continue;
+ }
+ }
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "query parameter not "
+ "understood: '%s' in %s",
+ arg, r->args);
+ ap_die(HTTP_BAD_REQUEST, r);
+ return OK;
+ }
+ }
+
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "put_handler: processing");
+ r->status = 200;
+ r->clength = -1;
+ r->chunked = 1;
+ apr_table_unset(r->headers_out, "Content-Length");
+ /* Discourage content-encodings */
+ apr_table_unset(r->headers_out, "Content-Encoding");
+ apr_table_setn(r->subprocess_env, "no-brotli", "1");
+ apr_table_setn(r->subprocess_env, "no-gzip", "1");
+
+ ct = apr_table_get(r->headers_in, "content-type");
+ ap_set_content_type(r, ct? ct : "text/plain");
+
+ bb = apr_brigade_create(r->pool, c->bucket_alloc);
+ /* copy any request body into the response */
+ if((rv = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK))) goto cleanup;
+ if(ap_should_client_block(r)) {
+ while(0 < (l = ap_get_client_block(r, &buffer[0], sizeof(buffer)))) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "put_handler: read %ld bytes from request body", l);
+ if(chunk_delay) {
+ apr_sleep(chunk_delay);
+ }
+ rbody_len += l;
+ }
+ }
+ /* we are done */
+ rv = apr_brigade_printf(bb, NULL, NULL, "%"APR_OFF_T_FMT, rbody_len);
+ if(APR_SUCCESS != rv) goto cleanup;
+ b = apr_bucket_eos_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "put_handler: request read");
+
+ rv = ap_pass_brigade(r->output_filters, bb);
+
+cleanup:
+ if(rv == APR_SUCCESS
+ || r->status != HTTP_OK
+ || c->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, r, "put_handler: done");
+ return OK;
+ }
+ else {
+ /* no way to know what type of error occurred */
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, r, "put_handler failed");
+ return AP_FILTER_ERROR;
+ }
+ return DECLINED;
+}
+
+static int curltest_1_1_required(request_rec *r)
+{
+ conn_rec *c = r->connection;
+ apr_bucket_brigade *bb;
+ apr_bucket *b;
+ apr_status_t rv;
+ char buffer[16*1024];
+ const char *ct;
+ const char *request_id = "none";
+ apr_time_t chunk_delay = 0;
+ apr_array_header_t *args = NULL;
+ long l;
+ int i;
+
+ if(strcmp(r->handler, "curltest-1_1-required")) {
+ return DECLINED;
+ }
+
+ if (HTTP_VERSION_MAJOR(r->proto_num) > 1) {
+ apr_table_setn(r->notes, "ssl-renegotiate-forbidden", "1");
+ ap_die(HTTP_FORBIDDEN, r);
+ return OK;
+ }
+
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "1_1_handler: processing");
+ r->status = 200;
+ r->clength = -1;
+ r->chunked = 1;
+ apr_table_unset(r->headers_out, "Content-Length");
+ /* Discourage content-encodings */
+ apr_table_unset(r->headers_out, "Content-Encoding");
+ apr_table_setn(r->subprocess_env, "no-brotli", "1");
+ apr_table_setn(r->subprocess_env, "no-gzip", "1");
+
+ ct = apr_table_get(r->headers_in, "content-type");
+ ap_set_content_type(r, ct? ct : "text/plain");
+
+ bb = apr_brigade_create(r->pool, c->bucket_alloc);
+ /* flush response */
+ b = apr_bucket_flush_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ rv = ap_pass_brigade(r->output_filters, bb);
+ if (APR_SUCCESS != rv) goto cleanup;
+
+ /* we are done */
+ rv = apr_brigade_printf(bb, NULL, NULL, "well done!");
+ if(APR_SUCCESS != rv) goto cleanup;
+ b = apr_bucket_eos_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "1_1_handler: request read");
+
+ rv = ap_pass_brigade(r->output_filters, bb);
+
+cleanup:
+ if(rv == APR_SUCCESS
+ || r->status != HTTP_OK
+ || c->aborted) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, r, "1_1_handler: done");
+ return OK;
+ }
+ else {
+ /* no way to know what type of error occurred */
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, rv, r, "1_1_handler failed");
+ return AP_FILTER_ERROR;
+ }
+ return DECLINED;
+}
diff --git a/tests/http/testenv/nghttpx.py b/tests/http/testenv/nghttpx.py
new file mode 100644
index 0000000..234b31c
--- /dev/null
+++ b/tests/http/testenv/nghttpx.py
@@ -0,0 +1,259 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import logging
+import os
+import signal
+import subprocess
+import time
+from typing import Optional
+from datetime import datetime, timedelta
+
+from .env import Env
+from .curl import CurlClient
+
+
+log = logging.getLogger(__name__)
+
+
+class Nghttpx:
+
+ def __init__(self, env: Env, port: int, name: str):
+ self.env = env
+ self._name = name
+ self._port = port
+ self._cmd = env.nghttpx
+ self._run_dir = os.path.join(env.gen_dir, name)
+ self._pid_file = os.path.join(self._run_dir, 'nghttpx.pid')
+ self._conf_file = os.path.join(self._run_dir, 'nghttpx.conf')
+ self._error_log = os.path.join(self._run_dir, 'nghttpx.log')
+ self._stderr = os.path.join(self._run_dir, 'nghttpx.stderr')
+ self._tmp_dir = os.path.join(self._run_dir, 'tmp')
+ self._process = None
+ self._process: Optional[subprocess.Popen] = None
+ self._rmf(self._pid_file)
+ self._rmf(self._error_log)
+ self._mkpath(self._run_dir)
+ self._write_config()
+
+ def exists(self):
+ return os.path.exists(self._cmd)
+
+ def clear_logs(self):
+ self._rmf(self._error_log)
+ self._rmf(self._stderr)
+
+ def is_running(self):
+ if self._process:
+ self._process.poll()
+ return self._process.returncode is None
+ return False
+
+ def start_if_needed(self):
+ if not self.is_running():
+ return self.start()
+ return True
+
+ def start(self, wait_live=True):
+ pass
+
+ def stop_if_running(self):
+ if self.is_running():
+ return self.stop()
+ return True
+
+ def stop(self, wait_dead=True):
+ self._mkpath(self._tmp_dir)
+ if self._process:
+ self._process.terminate()
+ self._process.wait(timeout=2)
+ self._process = None
+ return not wait_dead or self.wait_dead(timeout=timedelta(seconds=5))
+ return True
+
+ def restart(self):
+ self.stop()
+ return self.start()
+
+ def reload(self, timeout: timedelta):
+ if self._process:
+ running = self._process
+ self._process = None
+ os.kill(running.pid, signal.SIGQUIT)
+ end_wait = datetime.now() + timeout
+ if not self.start(wait_live=False):
+ self._process = running
+ return False
+ while datetime.now() < end_wait:
+ try:
+ log.debug(f'waiting for nghttpx({running.pid}) to exit.')
+ running.wait(2)
+ log.debug(f'nghttpx({running.pid}) terminated -> {running.returncode}')
+ break
+ except subprocess.TimeoutExpired:
+ log.warning(f'nghttpx({running.pid}), not shut down yet.')
+ os.kill(running.pid, signal.SIGQUIT)
+ if datetime.now() >= end_wait:
+ log.error(f'nghttpx({running.pid}), terminate forcefully.')
+ os.kill(running.pid, signal.SIGKILL)
+ running.terminate()
+ running.wait(1)
+ return self.wait_live(timeout=timedelta(seconds=5))
+ return False
+
+ def wait_dead(self, timeout: timedelta):
+ curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
+ try_until = datetime.now() + timeout
+ while datetime.now() < try_until:
+ check_url = f'https://{self.env.domain1}:{self._port}/'
+ r = curl.http_get(url=check_url, extra_args=['--http3-only'])
+ if r.exit_code != 0:
+ return True
+ log.debug(f'waiting for nghttpx to stop responding: {r}')
+ time.sleep(.1)
+ log.debug(f"Server still responding after {timeout}")
+ return False
+
+ def wait_live(self, timeout: timedelta):
+ curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
+ try_until = datetime.now() + timeout
+ while datetime.now() < try_until:
+ check_url = f'https://{self.env.domain1}:{self._port}/'
+ r = curl.http_get(url=check_url, extra_args=[
+ '--http3-only', '--trace', 'curl.trace', '--trace-time'
+ ])
+ if r.exit_code == 0:
+ return True
+ log.debug(f'waiting for nghttpx to become responsive: {r}')
+ time.sleep(.1)
+ log.error(f"Server still not responding after {timeout}")
+ return False
+
+ def _rmf(self, path):
+ if os.path.exists(path):
+ return os.remove(path)
+
+ def _mkpath(self, path):
+ if not os.path.exists(path):
+ return os.makedirs(path)
+
+ def _write_config(self):
+ with open(self._conf_file, 'w') as fd:
+ fd.write(f'# nghttpx test config'),
+ fd.write("\n".join([
+ '# do we need something here?'
+ ]))
+
+
+class NghttpxQuic(Nghttpx):
+
+ def __init__(self, env: Env):
+ super().__init__(env=env, name='nghttpx-quic', port=env.h3_port)
+
+ def start(self, wait_live=True):
+ self._mkpath(self._tmp_dir)
+ if self._process:
+ self.stop()
+ args = [
+ self._cmd,
+ f'--frontend=*,{self.env.h3_port};quic',
+ f'--backend=127.0.0.1,{self.env.https_port};{self.env.domain1};sni={self.env.domain1};proto=h2;tls',
+ f'--backend=127.0.0.1,{self.env.http_port}',
+ f'--log-level=INFO',
+ f'--pid-file={self._pid_file}',
+ f'--errorlog-file={self._error_log}',
+ f'--conf={self._conf_file}',
+ f'--cacert={self.env.ca.cert_file}',
+ self.env.get_credentials(self.env.domain1).pkey_file,
+ self.env.get_credentials(self.env.domain1).cert_file,
+ f'--frontend-http3-window-size=1M',
+ f'--frontend-http3-max-window-size=10M',
+ f'--frontend-http3-connection-window-size=10M',
+ f'--frontend-http3-max-connection-window-size=100M',
+ ]
+ ngerr = open(self._stderr, 'a')
+ self._process = subprocess.Popen(args=args, stderr=ngerr)
+ if self._process.returncode is not None:
+ return False
+ return not wait_live or self.wait_live(timeout=timedelta(seconds=5))
+
+
+class NghttpxFwd(Nghttpx):
+
+ def __init__(self, env: Env):
+ super().__init__(env=env, name='nghttpx-fwd', port=env.h2proxys_port)
+
+ def start(self, wait_live=True):
+ self._mkpath(self._tmp_dir)
+ if self._process:
+ self.stop()
+ args = [
+ self._cmd,
+ f'--http2-proxy',
+ f'--frontend=*,{self.env.h2proxys_port}',
+ f'--backend=127.0.0.1,{self.env.proxy_port}',
+ f'--log-level=INFO',
+ f'--pid-file={self._pid_file}',
+ f'--errorlog-file={self._error_log}',
+ f'--conf={self._conf_file}',
+ f'--cacert={self.env.ca.cert_file}',
+ self.env.get_credentials(self.env.proxy_domain).pkey_file,
+ self.env.get_credentials(self.env.proxy_domain).cert_file,
+ ]
+ ngerr = open(self._stderr, 'a')
+ self._process = subprocess.Popen(args=args, stderr=ngerr)
+ if self._process.returncode is not None:
+ return False
+ return not wait_live or self.wait_live(timeout=timedelta(seconds=5))
+
+ def wait_dead(self, timeout: timedelta):
+ curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
+ try_until = datetime.now() + timeout
+ while datetime.now() < try_until:
+ check_url = f'https://{self.env.proxy_domain}:{self.env.h2proxys_port}/'
+ r = curl.http_get(url=check_url)
+ if r.exit_code != 0:
+ return True
+ log.debug(f'waiting for nghttpx-fwd to stop responding: {r}')
+ time.sleep(.1)
+ log.debug(f"Server still responding after {timeout}")
+ return False
+
+ def wait_live(self, timeout: timedelta):
+ curl = CurlClient(env=self.env, run_dir=self._tmp_dir)
+ try_until = datetime.now() + timeout
+ while datetime.now() < try_until:
+ check_url = f'https://{self.env.proxy_domain}:{self.env.h2proxys_port}/'
+ r = curl.http_get(url=check_url, extra_args=[
+ '--trace', 'curl.trace', '--trace-time'
+ ])
+ if r.exit_code == 0:
+ return True
+ log.debug(f'waiting for nghttpx-fwd to become responsive: {r}')
+ time.sleep(.1)
+ log.error(f"Server still not responding after {timeout}")
+ return False
+
diff --git a/lib/makefile.amiga b/tests/http/testenv/ports.py
similarity index 61%
copy from lib/makefile.amiga
copy to tests/http/testenv/ports.py
index b09fee9..b7e8d97 100644
--- a/lib/makefile.amiga
+++ b/tests/http/testenv/ports.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
@@ -5,7 +7,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -22,23 +24,26 @@
#
###########################################################################
#
-# libcurl Makefile for AmigaOS ...
-#
+import logging
+import socket
+from typing import Dict
-# change the follow to where you have the AmiTCP SDK v4.3 includes:
-
-ATCPSDKI= /GG/netinclude
+log = logging.getLogger(__name__)
-CC = m68k-amigaos-gcc
-CFLAGS = -I$(ATCPSDKI) -m68020-60 -O2 -msoft-float -noixemul -g -I. -I../include -W -Wall
+def alloc_ports(port_specs: Dict[str, int]) -> Dict[str, int]:
+ ports = {}
+ socks = []
+ for name, ptype in port_specs.items():
+ try:
+ s = socket.socket(type=ptype)
+ s.bind(('', 0))
+ ports[name] = s.getsockname()[1]
+ socks.append(s)
+ except Exception as e:
+ raise e
+ for s in socks:
+ s.close()
+ return ports
-include Makefile.inc
-OBJS = $(CSOURCES:.c=.o)
-all: $(OBJS)
- ar cru libcurl.a $(OBJS)
- ranlib libcurl.a
-
-install:
- $(INSTALL) -c ./libcurl.a /lib/libcurl.a
diff --git a/tests/http/testenv/ws_echo_server.py b/tests/http/testenv/ws_echo_server.py
new file mode 100755
index 0000000..d13f757
--- /dev/null
+++ b/tests/http/testenv/ws_echo_server.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+import argparse
+import asyncio
+import logging
+from asyncio import IncompleteReadError
+
+from websockets import server
+from websockets.exceptions import ConnectionClosedError
+
+
+async def echo(websocket):
+ try:
+ async for message in websocket:
+ await websocket.send(message)
+ except ConnectionClosedError:
+ pass
+
+
+async def run_server(port):
+ async with server.serve(echo, "localhost", port):
+ await asyncio.Future() # run forever
+
+
+def main():
+ parser = argparse.ArgumentParser(prog='scorecard', description="""
+ Run a websocket echo server.
+ """)
+ parser.add_argument("--port", type=int,
+ default=9876, help="port to listen on")
+ args = parser.parse_args()
+
+ logging.basicConfig(
+ format="%(asctime)s %(message)s",
+ level=logging.DEBUG,
+ )
+
+ asyncio.run(run_server(args.port))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/http2-server.pl b/tests/http2-server.pl
index 09ada66..52c5284 100755
--- a/tests/http2-server.pl
+++ b/tests/http2-server.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2016 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -25,12 +25,19 @@
# This script invokes nghttpx properly to have it serve HTTP/2 for us.
# nghttpx runs as a proxy in front of our "actual" HTTP/1 server.
+use Cwd;
+use Cwd 'abs_path';
+use File::Basename;
-my $pidfile = "log/nghttpx.pid";
-my $logfile = "log/http2.log";
+my $logdir = "log";
+my $pidfile = "$logdir/nghttpx.pid";
+my $logfile = "$logdir/http2.log";
my $nghttpx = "nghttpx";
my $listenport = 9015;
+my $listenport2 = 9016;
my $connect = "127.0.0.1,8990";
+my $conf = "nghttpx.conf";
+my $cert = "Server-localhost-sv";
#***************************************************************************
# Process command line options
@@ -57,6 +64,12 @@
shift @ARGV;
}
}
+ elsif($ARGV[0] eq '--port2') {
+ if($ARGV[1]) {
+ $listenport2 = $ARGV[1];
+ shift @ARGV;
+ }
+ }
elsif($ARGV[0] eq '--connect') {
if($ARGV[1]) {
$connect = $ARGV[1];
@@ -70,16 +83,37 @@
shift @ARGV;
}
}
+ elsif($ARGV[0] eq '--logdir') {
+ if($ARGV[1]) {
+ $logdir = $ARGV[1];
+ shift @ARGV;
+ }
+ }
+ elsif($ARGV[0] eq '--conf') {
+ if($ARGV[1]) {
+ $conf = $ARGV[1];
+ shift @ARGV;
+ }
+ }
else {
print STDERR "\nWarning: http2-server.pl unknown parameter: $ARGV[0]\n";
}
shift @ARGV;
}
+my $srcdir = dirname(__FILE__);
+$certfile = "$srcdir/certs/$cert.pem";
+$keyfile = "$srcdir/certs/$cert.key";
+$certfile = abs_path($certfile);
+$keyfile = abs_path($keyfile);
+
my $cmdline="$nghttpx --backend=$connect ".
"--frontend=\"*,$listenport;no-tls\" ".
+ "--frontend=\"*,$listenport2\" ".
"--log-level=INFO ".
"--pid-file=$pidfile ".
- "--errorlog-file=$logfile";
+ "--conf=$conf ".
+ "--errorlog-file=$logfile ".
+ "$keyfile $certfile";
print "RUN: $cmdline\n" if($verbose);
system("$cmdline 2>/dev/null");
diff --git a/tests/http3-server.pl b/tests/http3-server.pl
new file mode 100755
index 0000000..7e5f243
--- /dev/null
+++ b/tests/http3-server.pl
@@ -0,0 +1,118 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+#***************************************************************************
+
+# This script invokes nghttpx properly to have it serve HTTP/3 for us.
+# nghttpx runs as a proxy in front of our "actual" HTTP/1 server.
+
+use Cwd;
+use Cwd 'abs_path';
+use File::Basename;
+
+my $logdir = "log";
+my $pidfile = "$logdir/nghttpx.pid";
+my $logfile = "$logdir/http3.log";
+my $nghttpx = "nghttpx";
+my $listenport = 9015;
+my $connect = "127.0.0.1,8990";
+my $cert = "Server-localhost-sv";
+my $conf = "nghttpx.conf";
+
+#***************************************************************************
+# Process command line options
+#
+while(@ARGV) {
+ if($ARGV[0] eq '--verbose') {
+ $verbose = 1;
+ }
+ elsif($ARGV[0] eq '--pidfile') {
+ if($ARGV[1]) {
+ $pidfile = $ARGV[1];
+ shift @ARGV;
+ }
+ }
+ elsif($ARGV[0] eq '--nghttpx') {
+ if($ARGV[1]) {
+ $nghttpx = $ARGV[1];
+ shift @ARGV;
+ }
+ }
+ elsif($ARGV[0] eq '--port') {
+ if($ARGV[1]) {
+ $listenport = $ARGV[1];
+ shift @ARGV;
+ }
+ }
+ elsif($ARGV[0] eq '--connect') {
+ if($ARGV[1]) {
+ $connect = $ARGV[1];
+ $connect =~ s/:/,/;
+ shift @ARGV;
+ }
+ }
+ elsif($ARGV[0] eq '--cert') {
+ if($ARGV[1]) {
+ $cert = $ARGV[1];
+ shift @ARGV;
+ }
+ }
+ elsif($ARGV[0] eq '--logfile') {
+ if($ARGV[1]) {
+ $logfile = $ARGV[1];
+ shift @ARGV;
+ }
+ }
+ elsif($ARGV[0] eq '--logdir') {
+ if($ARGV[1]) {
+ $logdir = $ARGV[1];
+ shift @ARGV;
+ }
+ }
+ elsif($ARGV[0] eq '--conf') {
+ if($ARGV[1]) {
+ $conf = $ARGV[1];
+ shift @ARGV;
+ }
+ }
+ else {
+ print STDERR "\nWarning: http3-server.pl unknown parameter: $ARGV[0]\n";
+ }
+ shift @ARGV;
+}
+
+my $srcdir = dirname(__FILE__);
+$certfile = "$srcdir/certs/$cert.pem";
+$keyfile = "$srcdir/certs/$cert.key";
+$certfile = abs_path($certfile);
+$keyfile = abs_path($keyfile);
+
+my $cmdline="$nghttpx --http2-proxy --backend=$connect ".
+ "--frontend=\"*,$listenport;quic\" ".
+ "--log-level=INFO ".
+ "--pid-file=$pidfile ".
+ "--errorlog-file=$logfile ".
+ "--conf=$conf ".
+ "$keyfile $certfile";
+print "RUN: $cmdline\n" if($verbose);
+system("$cmdline 2>/dev/null");
diff --git a/tests/keywords.pl b/tests/keywords.pl
deleted file mode 100755
index 88d521e..0000000
--- a/tests/keywords.pl
+++ /dev/null
@@ -1,155 +0,0 @@
-#!/usr/bin/env perl
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-
-use strict;
-
-push(@INC, $ENV{'srcdir'}) if(defined $ENV{'srcdir'});
-push(@INC, ".");
-
-require "getpart.pm"; # array functions
-
-my $srcdir = $ENV{'srcdir'} || '.';
-my $TESTDIR="$srcdir/data";
-
-# Get all commands and find out their test numbers
-opendir(DIR, $TESTDIR) || die "can't opendir $TESTDIR: $!";
-my @cmds = grep { /^test([0-9]+)$/ && -f "$TESTDIR/$_" } readdir(DIR);
-closedir DIR;
-
-my $TESTCASES; # start with no test cases
-
-# cut off everything but the digits
-for(@cmds) {
- $_ =~ s/[a-z\/\.]*//g;
-}
-# the numbers from low to high
-for(sort { $a <=> $b } @cmds) {
- $TESTCASES .= " $_";
-}
-
-my $t;
-
-my %k; # keyword count
-my %t; # keyword to test case mapping
-my @miss; # test cases without keywords set
-
-my $count;
-
-my %errors;
-
-for $t (split(/ /, $TESTCASES)) {
- if(loadtest("${TESTDIR}/test${t}")) {
- # bad case
- next;
- }
-
- my @ec = getpart("verify", "errorcode");
- if($ec[0]) {
- # count number of check error codes
- $errors{ 0 + $ec[0] } ++;
- }
-
-
- my @what = getpart("info", "keywords");
-
- if(!$what[0]) {
- push @miss, $t;
- next;
- }
-
- for(@what) {
- chomp;
- #print "Test $t: $_\n";
- $k{$_}++;
- $t{$_} .= "$t ";
- }
-
-
-
-
-
-
-
-
- $count++;
-}
-
-sub show {
- my ($list)=@_;
- my @a = split(" ", $list);
- my $ret;
-
- my $c;
- my @l = sort {rand(100) - 50} @a;
- my @ll;
-
- for(1 .. 11) {
- my $v = shift @l;
- if($v) {
- push @ll, $v;
- }
- }
-
- for (sort {$a <=> $b} @ll) {
- if($c++ == 10) {
- $ret .= "...";
- last;
- }
- $ret .= "$_ ";
- }
- return $ret;
-}
-
-# sort alphabetically
-my @mtest = reverse sort { lc($b) cmp lc($a) } keys %k;
-
-print <<TOP
-<table><tr><th>Num</th><th>Keyword</th><th>Test Cases</th></tr>
-TOP
- ;
-for $t (@mtest) {
- printf "<tr><td>%d</td><td>$t</td><td>%s</td></tr>\n", $k{$t},
- show($t{$t});
-}
-printf "</table><p> $count out of %d tests (%d lack keywords)\n",
- scalar(@miss) + $count,
- scalar(@miss);
-
-for(@miss) {
- print "$_ ";
-}
-
-print "\n";
-
-printf "<p> %d different error codes tested for:<br>\n",
- scalar(keys %errors);
-
-# numerically on amount, or alphebetically if same amount
-my @etest = sort { $a <=> $b} keys %errors;
-
-for(@etest) {
- print "$_ ";
-}
-print "\n";
diff --git a/tests/libtest/.gitignore b/tests/libtest/.gitignore
index 122a94e..9541d16 100644
--- a/tests/libtest/.gitignore
+++ b/tests/libtest/.gitignore
@@ -1,10 +1,9 @@
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
-chkdecimalpoint
chkhostname
-lib[123][0-9][0-9][0-9]
+lib[1234][0-9][0-9][0-9]
lib[56][0-9][0-9]
lib1521.c
libauthretry
diff --git a/tests/libtest/CMakeLists.txt b/tests/libtest/CMakeLists.txt
index e547c6a..2579cef 100644
--- a/tests/libtest/CMakeLists.txt
+++ b/tests/libtest/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -24,6 +24,12 @@
set(TARGET_LABEL_PREFIX "Test ")
function(setup_test TEST_NAME) # ARGN are the files in the test
+
+ if(NOT BUILD_SHARED_LIBS)
+ # These are part of the libcurl static lib. Do not compile/link them again.
+ list(REMOVE_ITEM ARGN ${WARNLESS} ${MULTIBYTE} ${TIMEDIFF})
+ endif()
+
add_executable(${TEST_NAME} EXCLUDE_FROM_ALL ${ARGN})
add_dependencies(testdeps ${TEST_NAME})
string(TOUPPER ${TEST_NAME} UPPER_TEST_NAME)
@@ -80,6 +86,3 @@
"${CMAKE_CURRENT_SOURCE_DIR}/mk-lib1521.pl"
"${CURL_SOURCE_DIR}/include/curl/curl.h"
VERBATIM)
-
-set_property(TARGET chkdecimalpoint
- APPEND PROPERTY COMPILE_DEFINITIONS "CURLX_NO_MEMORY_CALLBACKS;CURL_STATICLIB")
diff --git a/tests/libtest/Makefile.am b/tests/libtest/Makefile.am
index 4a22f52..9ee6916 100644
--- a/tests/libtest/Makefile.am
+++ b/tests/libtest/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
index dbd5a60..648536e 100644
--- a/tests/libtest/Makefile.inc
+++ b/tests/libtest/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -34,11 +34,11 @@
MULTIBYTE = ../../lib/curl_multibyte.c ../../lib/curl_multibyte.h
# these files are used in every single test program below
-SUPPORTFILES = ../../lib/timediff.c ../../lib/timediff.h first.c test.h
+TIMEDIFF = ../../lib/timediff.c ../../lib/timediff.h
+SUPPORTFILES = $(TIMEDIFF) first.c test.h
# These are all libcurl test programs
-noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \
- chkdecimalpoint libprereq \
+noinst_PROGRAMS = chkhostname libauthretry libntlmconnect libprereq \
lib500 lib501 lib502 lib503 lib504 lib505 lib506 lib507 lib508 lib509 \
lib510 lib511 lib512 lib513 lib514 lib515 lib516 lib517 lib518 lib519 \
lib520 lib521 lib523 lib524 lib525 lib526 lib527 lib529 lib530 lib532 \
@@ -52,6 +52,7 @@
lib659 lib661 lib666 lib667 lib668 \
lib670 lib671 lib672 lib673 lib674 lib676 lib677 lib678 \
lib1156 \
+ lib1301 \
lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1507 lib1508 \
lib1509 lib1510 lib1511 lib1512 lib1513 lib1514 lib1515 lib1517 \
lib1518 lib1520 lib1521 lib1522 lib1523 \
@@ -60,115 +61,89 @@
lib1540 lib1542 lib1543 \
lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 lib1556 lib1557 \
lib1558 lib1559 lib1560 lib1564 lib1565 lib1567 lib1568 lib1569 \
- lib1591 lib1592 lib1593 lib1594 lib1596 \
- lib1905 lib1906 lib1907 lib1908 lib1910 lib1911 lib1912 lib1913 \
+ lib1591 lib1592 lib1593 lib1594 lib1596 lib1597 \
+ \
+ lib1662 \
+ \
+ lib1903 lib1905 lib1906 lib1907 lib1908 lib1910 lib1911 lib1912 lib1913 \
lib1915 lib1916 lib1917 lib1918 lib1919 \
lib1933 lib1934 lib1935 lib1936 lib1937 lib1938 lib1939 lib1940 \
- lib1945 lib1946 \
- lib3010 lib3025 lib3026
-
-chkdecimalpoint_SOURCES = chkdecimalpoint.c ../../lib/mprintf.c \
- ../../lib/curl_ctype.c ../../lib/dynbuf.c ../../lib/strdup.c
-chkdecimalpoint_LDADD =
-chkdecimalpoint_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB \
- -DCURLX_NO_MEMORY_CALLBACKS -DBUILDING_LIBCURL
+ lib1945 lib1946 lib1947 lib1948 lib1955 lib1956 lib1957 lib1958 lib1959 \
+ lib1960 \
+ lib1970 lib1971 lib1972 lib1973 lib1974 lib1975 \
+ lib2301 lib2302 lib2304 lib2305 lib2306 \
+ lib2402 lib2404 \
+ lib2502 \
+ lib3010 lib3025 lib3026 lib3027 \
+ lib3100 lib3101
chkhostname_SOURCES = chkhostname.c ../../lib/curl_gethostname.c
chkhostname_LDADD = @CURL_NETWORK_LIBS@
chkhostname_DEPENDENCIES =
-chkhostname_CPPFLAGS = $(AM_CPPFLAGS)
libntlmconnect_SOURCES = libntlmconnect.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
libntlmconnect_LDADD = $(TESTUTIL_LIBS)
-libntlmconnect_CPPFLAGS = $(AM_CPPFLAGS)
libauthretry_SOURCES = libauthretry.c $(SUPPORTFILES)
-libauthretry_CPPFLAGS = $(AM_CPPFLAGS)
libprereq_SOURCES = libprereq.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
libprereq_LDADD = $(TESTUTIL_LIBS)
-libprereq_CPPFLAGS = $(AM_CPPFLAGS)
lib500_SOURCES = lib500.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(MULTIBYTE)
lib500_LDADD = $(TESTUTIL_LIBS)
-lib500_CPPFLAGS = $(AM_CPPFLAGS)
lib501_SOURCES = lib501.c $(SUPPORTFILES)
-lib501_CPPFLAGS = $(AM_CPPFLAGS)
lib502_SOURCES = lib502.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib502_LDADD = $(TESTUTIL_LIBS)
-lib502_CPPFLAGS = $(AM_CPPFLAGS)
lib503_SOURCES = lib503.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib503_LDADD = $(TESTUTIL_LIBS)
-lib503_CPPFLAGS = $(AM_CPPFLAGS)
lib504_SOURCES = lib504.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib504_LDADD = $(TESTUTIL_LIBS)
-lib504_CPPFLAGS = $(AM_CPPFLAGS)
lib505_SOURCES = lib505.c $(SUPPORTFILES) $(MULTIBYTE)
-lib505_CPPFLAGS = $(AM_CPPFLAGS)
lib506_SOURCES = lib506.c $(SUPPORTFILES)
-lib506_CPPFLAGS = $(AM_CPPFLAGS)
lib507_SOURCES = lib507.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib507_LDADD = $(TESTUTIL_LIBS)
-lib507_CPPFLAGS = $(AM_CPPFLAGS)
lib508_SOURCES = lib508.c $(SUPPORTFILES)
-lib508_CPPFLAGS = $(AM_CPPFLAGS)
lib509_SOURCES = lib509.c $(SUPPORTFILES)
-lib509_CPPFLAGS = $(AM_CPPFLAGS)
lib510_SOURCES = lib510.c $(SUPPORTFILES)
-lib510_CPPFLAGS = $(AM_CPPFLAGS)
lib511_SOURCES = lib511.c $(SUPPORTFILES)
-lib511_CPPFLAGS = $(AM_CPPFLAGS)
lib512_SOURCES = lib512.c $(SUPPORTFILES)
-lib512_CPPFLAGS = $(AM_CPPFLAGS)
lib513_SOURCES = lib513.c $(SUPPORTFILES)
-lib513_CPPFLAGS = $(AM_CPPFLAGS)
lib514_SOURCES = lib514.c $(SUPPORTFILES)
-lib514_CPPFLAGS = $(AM_CPPFLAGS)
lib515_SOURCES = lib515.c $(SUPPORTFILES)
-lib515_CPPFLAGS = $(AM_CPPFLAGS)
lib516_SOURCES = lib516.c $(SUPPORTFILES)
-lib516_CPPFLAGS = $(AM_CPPFLAGS)
lib517_SOURCES = lib517.c $(SUPPORTFILES)
-lib517_CPPFLAGS = $(AM_CPPFLAGS)
lib518_SOURCES = lib518.c $(SUPPORTFILES) $(WARNLESS) $(MULTIBYTE)
-lib518_CPPFLAGS = $(AM_CPPFLAGS)
lib519_SOURCES = lib519.c $(SUPPORTFILES)
-lib519_CPPFLAGS = $(AM_CPPFLAGS)
lib520_SOURCES = lib520.c $(SUPPORTFILES)
-lib520_CPPFLAGS = $(AM_CPPFLAGS)
lib521_SOURCES = lib521.c $(SUPPORTFILES)
-lib521_CPPFLAGS = $(AM_CPPFLAGS)
lib523_SOURCES = lib523.c $(SUPPORTFILES)
-lib523_CPPFLAGS = $(AM_CPPFLAGS)
lib524_SOURCES = lib524.c $(SUPPORTFILES)
-lib524_CPPFLAGS = $(AM_CPPFLAGS)
lib525_SOURCES = lib525.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib525_LDADD = $(TESTUTIL_LIBS)
-lib525_CPPFLAGS = $(AM_CPPFLAGS)
lib526_SOURCES = lib526.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib526_LDADD = $(TESTUTIL_LIBS)
@@ -184,7 +159,6 @@
lib530_SOURCES = lib530.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib530_LDADD = $(TESTUTIL_LIBS)
-lib530_CPPFLAGS = $(AM_CPPFLAGS)
lib532_SOURCES = lib526.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib532_LDADD = $(TESTUTIL_LIBS)
@@ -192,128 +166,92 @@
lib533_SOURCES = lib533.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib533_LDADD = $(TESTUTIL_LIBS)
-lib533_CPPFLAGS = $(AM_CPPFLAGS)
lib537_SOURCES = lib537.c $(SUPPORTFILES) $(WARNLESS) $(MULTIBYTE)
-lib537_CPPFLAGS = $(AM_CPPFLAGS)
lib539_SOURCES = lib539.c $(SUPPORTFILES)
-lib539_CPPFLAGS = $(AM_CPPFLAGS)
lib540_SOURCES = lib540.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib540_LDADD = $(TESTUTIL_LIBS)
-lib540_CPPFLAGS = $(AM_CPPFLAGS)
lib541_SOURCES = lib541.c $(SUPPORTFILES) $(MULTIBYTE)
-lib541_CPPFLAGS = $(AM_CPPFLAGS)
lib542_SOURCES = lib542.c $(SUPPORTFILES)
-lib542_CPPFLAGS = $(AM_CPPFLAGS)
lib543_SOURCES = lib543.c $(SUPPORTFILES)
-lib543_CPPFLAGS = $(AM_CPPFLAGS)
lib544_SOURCES = lib544.c $(SUPPORTFILES)
-lib544_CPPFLAGS = $(AM_CPPFLAGS)
lib545_SOURCES = lib544.c $(SUPPORTFILES)
lib545_CPPFLAGS = $(AM_CPPFLAGS) -DLIB545
lib547_SOURCES = lib547.c $(SUPPORTFILES)
-lib547_CPPFLAGS = $(AM_CPPFLAGS)
lib548_SOURCES = lib547.c $(SUPPORTFILES)
lib548_CPPFLAGS = $(AM_CPPFLAGS) -DLIB548
lib549_SOURCES = lib549.c $(SUPPORTFILES)
-lib549_CPPFLAGS = $(AM_CPPFLAGS)
lib552_SOURCES = lib552.c $(SUPPORTFILES) $(WARNLESS)
-lib552_CPPFLAGS = $(AM_CPPFLAGS)
lib553_SOURCES = lib553.c $(SUPPORTFILES)
-lib553_CPPFLAGS = $(AM_CPPFLAGS)
lib554_SOURCES = lib554.c $(SUPPORTFILES)
-lib554_CPPFLAGS = $(AM_CPPFLAGS)
lib555_SOURCES = lib555.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib555_LDADD = $(TESTUTIL_LIBS)
-lib555_CPPFLAGS = $(AM_CPPFLAGS)
lib556_SOURCES = lib556.c $(SUPPORTFILES) $(WARNLESS)
-lib556_CPPFLAGS = $(AM_CPPFLAGS)
lib557_SOURCES = lib557.c $(SUPPORTFILES)
-lib557_CPPFLAGS = $(AM_CPPFLAGS)
lib558_SOURCES = lib558.c $(SUPPORTFILES)
-lib558_CPPFLAGS = $(AM_CPPFLAGS)
lib559_SOURCES = lib559.c $(SUPPORTFILES)
-lib559_CPPFLAGS = $(AM_CPPFLAGS)
lib560_SOURCES = lib560.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib560_LDADD = $(TESTUTIL_LIBS)
-lib560_CPPFLAGS = $(AM_CPPFLAGS)
lib562_SOURCES = lib562.c $(SUPPORTFILES)
-lib562_CPPFLAGS = $(AM_CPPFLAGS)
lib564_SOURCES = lib564.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib564_LDADD = $(TESTUTIL_LIBS)
-lib564_CPPFLAGS = $(AM_CPPFLAGS)
lib565_SOURCES = lib510.c $(SUPPORTFILES)
lib565_CPPFLAGS = $(AM_CPPFLAGS) -DLIB565
lib566_SOURCES = lib566.c $(SUPPORTFILES) $(MULTIBYTE)
-lib566_CPPFLAGS = $(AM_CPPFLAGS)
lib567_SOURCES = lib567.c $(SUPPORTFILES)
-lib567_CPPFLAGS = $(AM_CPPFLAGS)
lib568_SOURCES = lib568.c $(SUPPORTFILES) $(MULTIBYTE)
-lib568_CPPFLAGS = $(AM_CPPFLAGS)
lib569_SOURCES = lib569.c $(SUPPORTFILES) $(MULTIBYTE)
-lib569_CPPFLAGS = $(AM_CPPFLAGS)
lib570_SOURCES = lib570.c $(SUPPORTFILES)
-lib570_CPPFLAGS = $(AM_CPPFLAGS)
lib571_SOURCES = lib571.c $(SUPPORTFILES) $(WARNLESS) $(MULTIBYTE)
-lib571_CPPFLAGS = $(AM_CPPFLAGS)
lib572_SOURCES = lib572.c $(SUPPORTFILES) $(MULTIBYTE)
-lib572_CPPFLAGS = $(AM_CPPFLAGS)
lib573_SOURCES = lib573.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(TSTTRACE)
lib573_LDADD = $(TESTUTIL_LIBS)
-lib573_CPPFLAGS = $(AM_CPPFLAGS)
lib574_SOURCES = lib574.c $(SUPPORTFILES)
-lib574_CPPFLAGS = $(AM_CPPFLAGS)
lib575_SOURCES = lib575.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib575_LDADD = $(TESTUTIL_LIBS)
-lib575_CPPFLAGS = $(AM_CPPFLAGS)
lib576_SOURCES = lib576.c $(SUPPORTFILES)
-lib576_CPPFLAGS = $(AM_CPPFLAGS)
lib578_SOURCES = lib578.c $(SUPPORTFILES) $(MULTIBYTE)
-lib578_CPPFLAGS = $(AM_CPPFLAGS)
lib579_SOURCES = lib579.c $(SUPPORTFILES) $(MULTIBYTE)
-lib579_CPPFLAGS = $(AM_CPPFLAGS)
lib582_SOURCES = lib582.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib582_LDADD = $(TESTUTIL_LIBS)
-lib582_CPPFLAGS = $(AM_CPPFLAGS)
lib583_SOURCES = lib583.c $(SUPPORTFILES)
-lib583_CPPFLAGS = $(AM_CPPFLAGS)
lib584_SOURCES = lib589.c $(SUPPORTFILES)
lib584_CPPFLAGS = $(AM_CPPFLAGS) -DLIB584
@@ -323,76 +261,56 @@
lib585_CPPFLAGS = $(AM_CPPFLAGS) -DLIB585
lib586_SOURCES = lib586.c $(SUPPORTFILES)
-lib586_CPPFLAGS = $(AM_CPPFLAGS)
lib587_SOURCES = lib554.c $(SUPPORTFILES)
lib587_CPPFLAGS = $(AM_CPPFLAGS) -DLIB587
lib589_SOURCES = lib589.c $(SUPPORTFILES)
-lib589_CPPFLAGS = $(AM_CPPFLAGS)
lib590_SOURCES = lib590.c $(SUPPORTFILES)
-lib590_CPPFLAGS = $(AM_CPPFLAGS)
lib591_SOURCES = lib591.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib591_LDADD = $(TESTUTIL_LIBS)
-lib591_CPPFLAGS = $(AM_CPPFLAGS)
lib597_SOURCES = lib597.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib597_LDADD = $(TESTUTIL_LIBS)
-lib597_CPPFLAGS = $(AM_CPPFLAGS)
lib598_SOURCES = lib598.c $(SUPPORTFILES)
-lib598_CPPFLAGS = $(AM_CPPFLAGS)
lib599_SOURCES = lib599.c $(SUPPORTFILES) $(MULTIBYTE)
-lib599_CPPFLAGS = $(AM_CPPFLAGS)
lib643_SOURCES = lib643.c $(SUPPORTFILES)
-lib643_CPPFLAGS = $(AM_CPPFLAGS)
lib645_SOURCES = lib643.c $(SUPPORTFILES)
lib645_CPPFLAGS = $(AM_CPPFLAGS) -DLIB645
lib650_SOURCES = lib650.c $(SUPPORTFILES)
-lib650_CPPFLAGS = $(AM_CPPFLAGS)
lib651_SOURCES = lib651.c $(SUPPORTFILES)
-lib651_CPPFLAGS = $(AM_CPPFLAGS)
lib652_SOURCES = lib652.c $(SUPPORTFILES)
-lib652_CPPFLAGS = $(AM_CPPFLAGS)
lib653_SOURCES = lib653.c $(SUPPORTFILES)
-lib653_CPPFLAGS = $(AM_CPPFLAGS)
lib654_SOURCES = lib654.c $(SUPPORTFILES)
-lib654_CPPFLAGS = $(AM_CPPFLAGS)
lib655_SOURCES = lib655.c $(SUPPORTFILES)
-lib655_CPPFLAGS = $(AM_CPPFLAGS)
lib658_SOURCES = lib658.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib658_LDADD = $(TESTUTIL_LIBS)
-lib658_CPPFLAGS = $(AM_CPPFLAGS)
lib659_SOURCES = lib659.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib659_LDADD = $(TESTUTIL_LIBS)
-lib659_CPPFLAGS = $(AM_CPPFLAGS)
lib661_SOURCES = lib661.c $(SUPPORTFILES)
-lib661_CPPFLAGS = $(AM_CPPFLAGS)
lib666_SOURCES = lib666.c $(SUPPORTFILES)
-lib666_CPPFLAGS = $(AM_CPPFLAGS)
lib667_SOURCES = lib667.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib667_LDADD = $(TESTUTIL_LIBS)
-lib667_CPPFLAGS = $(AM_CPPFLAGS)
lib668_SOURCES = lib668.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib668_LDADD = $(TESTUTIL_LIBS)
-lib668_CPPFLAGS = $(AM_CPPFLAGS)
lib670_SOURCES = lib670.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib670_LDADD = $(TESTUTIL_LIBS)
@@ -408,31 +326,27 @@
lib673_SOURCES = lib670.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib673_LDADD = $(TESTUTIL_LIBS)
-lib673_CPPFLAGS = $(AM_CPPFLAGS) -DLIB673
lib674_SOURCES = lib674.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib674_LDADD = $(TESTUTIL_LIBS)
-lib674_CPPFLAGS = $(AM_CPPFLAGS)
lib676_SOURCES = lib676.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib676_LDADD = $(TESTUTIL_LIBS)
-lib676_CPPFLAGS = $(AM_CPPFLAGS)
lib677_SOURCES = lib677.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib677_LDADD = $(TESTUTIL_LIBS)
-lib677_CPPFLAGS = $(AM_CPPFLAGS)
lib678_SOURCES = lib678.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib678_LDADD = $(TESTUTIL_LIBS)
-lib678_CPPFLAGS = $(AM_CPPFLAGS)
+
+lib1301_SOURCES = lib1301.c $(SUPPORTFILES) $(TESTUTIL)
+lib1301_LDADD = $(TESTUTIL_LIBS)
lib1500_SOURCES = lib1500.c $(SUPPORTFILES) $(TESTUTIL)
lib1500_LDADD = $(TESTUTIL_LIBS)
-lib1500_CPPFLAGS = $(AM_CPPFLAGS)
lib1501_SOURCES = lib1501.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1501_LDADD = $(TESTUTIL_LIBS)
-lib1501_CPPFLAGS = $(AM_CPPFLAGS)
lib1502_SOURCES = lib1502.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1502_LDADD = $(TESTUTIL_LIBS)
@@ -452,122 +366,92 @@
lib1506_SOURCES = lib1506.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1506_LDADD = $(TESTUTIL_LIBS)
-lib1506_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1506
lib1156_SOURCES = lib1156.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1156_LDADD = $(TESTUTIL_LIBS)
-lib1156_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1156
lib1507_SOURCES = lib1507.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1507_LDADD = $(TESTUTIL_LIBS)
-lib1507_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1507
lib1508_SOURCES = lib1508.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1508_LDADD = $(TESTUTIL_LIBS)
-lib1508_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1508
lib1509_SOURCES = lib1509.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1509_LDADD = $(TESTUTIL_LIBS)
-lib1509_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1509
lib1510_SOURCES = lib1510.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1510_LDADD = $(TESTUTIL_LIBS)
-lib1510_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1510
lib1511_SOURCES = lib1511.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1511_LDADD = $(TESTUTIL_LIBS)
-lib1511_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1511
lib1512_SOURCES = lib1512.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1512_LDADD = $(TESTUTIL_LIBS)
-lib1512_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1512
lib1513_SOURCES = lib1513.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1513_LDADD = $(TESTUTIL_LIBS)
-lib1513_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1513
lib1514_SOURCES = lib1514.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1514_LDADD = $(TESTUTIL_LIBS)
-lib1514_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1514
lib1515_SOURCES = lib1515.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1515_LDADD = $(TESTUTIL_LIBS)
-lib1515_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1515
lib1517_SOURCES = lib1517.c $(SUPPORTFILES)
-lib1517_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1517
lib1518_SOURCES = lib1518.c $(SUPPORTFILES)
-lib1518_CPPFLAGS = $(AM_CPPFLAGS)
lib1520_SOURCES = lib1520.c $(SUPPORTFILES)
-lib1520_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1520
nodist_lib1521_SOURCES = lib1521.c $(SUPPORTFILES)
lib1521_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)
lib1522_SOURCES = lib1522.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE)
lib1522_LDADD = $(TESTUTIL_LIBS)
-lib1522_CPPFLAGS = $(AM_CPPFLAGS)
lib1523_SOURCES = lib1523.c $(SUPPORTFILES)
-lib1523_CPPFLAGS = $(AM_CPPFLAGS)
lib1525_SOURCES = lib1525.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1525_LDADD = $(TESTUTIL_LIBS)
-lib1525_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1525
lib1526_SOURCES = lib1526.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1526_LDADD = $(TESTUTIL_LIBS)
-lib1526_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1526
lib1527_SOURCES = lib1527.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1527_LDADD = $(TESTUTIL_LIBS)
-lib1527_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1527
lib1528_SOURCES = lib1528.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1528_LDADD = $(TESTUTIL_LIBS)
-lib1528_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1528
lib1529_SOURCES = lib1529.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1529_LDADD = $(TESTUTIL_LIBS)
-lib1529_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1529
lib1530_SOURCES = lib1530.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1530_LDADD = $(TESTUTIL_LIBS)
-lib1530_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1530
lib1531_SOURCES = lib1531.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1531_LDADD = $(TESTUTIL_LIBS)
-lib1531_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1531
lib1532_SOURCES = lib1532.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1532_LDADD = $(TESTUTIL_LIBS)
-lib1532_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1532
lib1533_SOURCES = lib1533.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1533_LDADD = $(TESTUTIL_LIBS)
-lib1533_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1533
lib1534_SOURCES = lib1534.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1534_LDADD = $(TESTUTIL_LIBS)
-lib1534_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1534
lib1535_SOURCES = lib1535.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1535_LDADD = $(TESTUTIL_LIBS)
-lib1535_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1535
lib1536_SOURCES = lib1536.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1536_LDADD = $(TESTUTIL_LIBS)
-lib1536_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1536
lib1537_SOURCES = lib1537.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1537_LDADD = $(TESTUTIL_LIBS)
-lib1537_CPPFLAGS = $(AM_CPPFLAGS)
lib1538_SOURCES = lib1538.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1538_LDADD = $(TESTUTIL_LIBS)
-lib1538_CPPFLAGS = $(AM_CPPFLAGS)
lib1539_SOURCES = lib1514.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1539_LDADD = $(TESTUTIL_LIBS)
@@ -575,43 +459,33 @@
lib1540_SOURCES = lib1540.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1540_LDADD = $(TESTUTIL_LIBS)
-lib1540_CPPFLAGS = $(AM_CPPFLAGS)
lib1542_SOURCES = lib1542.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(WARNLESS)
lib1542_LDADD = $(TESTUTIL_LIBS)
-lib1542_CPPFLAGS = $(AM_CPPFLAGS)
lib1543_SOURCES = lib1518.c $(SUPPORTFILES)
lib1543_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1543
lib1550_SOURCES = lib1550.c $(SUPPORTFILES)
-lib1550_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1517
lib1551_SOURCES = lib1551.c $(SUPPORTFILES)
-lib1551_CPPFLAGS = $(AM_CPPFLAGS)
lib1552_SOURCES = lib1552.c $(SUPPORTFILES) $(TESTUTIL)
lib1552_LDADD = $(TESTUTIL_LIBS)
-lib1552_CPPFLAGS = $(AM_CPPFLAGS)
lib1553_SOURCES = lib1553.c $(SUPPORTFILES) $(TESTUTIL)
lib1553_LDADD = $(TESTUTIL_LIBS)
-lib1553_CPPFLAGS = $(AM_CPPFLAGS)
lib1554_SOURCES = lib1554.c $(SUPPORTFILES)
-lib1554_CPPFLAGS = $(AM_CPPFLAGS)
lib1555_SOURCES = lib1555.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1555_LDADD = $(TESTUTIL_LIBS)
-lib1555_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1555
lib1556_SOURCES = lib1556.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1556_LDADD = $(TESTUTIL_LIBS)
-lib1556_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1556
lib1557_SOURCES = lib1557.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1557_LDADD = $(TESTUTIL_LIBS)
-lib1557_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1557
lib1558_SOURCES = lib1558.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1558_LDADD = $(TESTUTIL_LIBS)
@@ -624,28 +498,21 @@
lib1564_SOURCES = lib1564.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1564_LDADD = $(TESTUTIL_LIBS)
-lib1564_CPPFLAGS = $(AM_CPPFLAGS)
lib1565_SOURCES = lib1565.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1565_LDADD = $(TESTUTIL_LIBS)
-lib1565_CPPFLAGS = $(AM_CPPFLAGS)
lib1567_SOURCES = lib1567.c $(SUPPORTFILES)
-lib1567_CPPFLAGS = $(AM_CPPFLAGS)
lib1568_SOURCES = lib1568.c $(SUPPORTFILES)
-lib1568_CPPFLAGS = $(AM_CPPFLAGS)
lib1569_SOURCES = lib1569.c $(SUPPORTFILES)
-lib1569_CPPFLAGS = $(AM_CPPFLAGS)
lib1591_SOURCES = lib1591.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1591_LDADD = $(TESTUTIL_LIBS)
-lib1591_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1591
lib1592_SOURCES = lib1592.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1592_LDADD = $(TESTUTIL_LIBS)
-lib1592_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1592
lib1593_SOURCES = lib1593.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1593_LDADD = $(TESTUTIL_LIBS)
@@ -657,102 +524,163 @@
lib1596_LDADD = $(TESTUTIL_LIBS)
lib1596_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1596
+lib1597_SOURCES = lib1597.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1597_LDADD = $(TESTUTIL_LIBS)
+
+lib1662_SOURCES = lib1662.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1662_LDADD = $(TESTUTIL_LIBS)
+
+lib1903_SOURCES = lib1903.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1903_LDADD = $(TESTUTIL_LIBS)
+
lib1905_SOURCES = lib1905.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1905_LDADD = $(TESTUTIL_LIBS)
-lib1905_CPPFLAGS = $(AM_CPPFLAGS)
lib1906_SOURCES = lib1906.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1906_LDADD = $(TESTUTIL_LIBS)
-lib1906_CPPFLAGS = $(AM_CPPFLAGS)
lib1907_SOURCES = lib1907.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1907_LDADD = $(TESTUTIL_LIBS)
-lib1907_CPPFLAGS = $(AM_CPPFLAGS)
lib1908_SOURCES = lib1908.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1908_LDADD = $(TESTUTIL_LIBS)
-lib1908_CPPFLAGS = $(AM_CPPFLAGS)
lib1910_SOURCES = lib1910.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1910_LDADD = $(TESTUTIL_LIBS)
-lib1910_CPPFLAGS = $(AM_CPPFLAGS)
lib1911_SOURCES = lib1911.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1911_LDADD = $(TESTUTIL_LIBS)
-lib1911_CPPFLAGS = $(AM_CPPFLAGS)
lib1912_SOURCES = lib1912.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1912_LDADD = $(TESTUTIL_LIBS)
-lib1912_CPPFLAGS = $(AM_CPPFLAGS)
lib1913_SOURCES = lib1913.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1913_LDADD = $(TESTUTIL_LIBS)
-lib1913_CPPFLAGS = $(AM_CPPFLAGS)
lib1915_SOURCES = lib1915.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1915_LDADD = $(TESTUTIL_LIBS)
-lib1915_CPPFLAGS = $(AM_CPPFLAGS)
lib1916_SOURCES = lib1916.c $(SUPPORTFILES) $(WARNLESS)
-lib1916_CPPFLAGS = $(AM_CPPFLAGS)
lib1917_SOURCES = lib1916.c $(SUPPORTFILES) $(WARNLESS)
lib1917_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1917
lib1918_SOURCES = lib1918.c $(SUPPORTFILES) $(WARNLESS)
-lib1918_CPPFLAGS = $(AM_CPPFLAGS)
lib1919_SOURCES = lib1919.c $(SUPPORTFILES) $(WARNLESS)
-lib1919_CPPFLAGS = $(AM_CPPFLAGS)
lib1933_SOURCES = lib1933.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1933_LDADD = $(TESTUTIL_LIBS)
-lib1933_CPPFLAGS = $(AM_CPPFLAGS)
lib1934_SOURCES = lib1934.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1934_LDADD = $(TESTUTIL_LIBS)
-lib1934_CPPFLAGS = $(AM_CPPFLAGS)
lib1935_SOURCES = lib1935.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1935_LDADD = $(TESTUTIL_LIBS)
-lib1935_CPPFLAGS = $(AM_CPPFLAGS)
lib1936_SOURCES = lib1936.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1936_LDADD = $(TESTUTIL_LIBS)
-lib1936_CPPFLAGS = $(AM_CPPFLAGS)
lib1937_SOURCES = lib1937.c $(SUPPORTFILES)
lib1937_LDADD = $(TESTUTIL_LIBS)
-lib1937_CPPFLAGS = $(AM_CPPFLAGS)
lib1938_SOURCES = lib1938.c $(SUPPORTFILES)
lib1938_LDADD = $(TESTUTIL_LIBS)
-lib1938_CPPFLAGS = $(AM_CPPFLAGS)
lib1939_SOURCES = lib1939.c $(SUPPORTFILES)
lib1939_LDADD = $(TESTUTIL_LIBS)
-lib1939_CPPFLAGS = $(AM_CPPFLAGS)
lib1940_SOURCES = lib1940.c $(SUPPORTFILES)
lib1940_LDADD = $(TESTUTIL_LIBS)
-lib1940_CPPFLAGS = $(AM_CPPFLAGS)
lib1945_SOURCES = lib1945.c $(SUPPORTFILES)
lib1945_LDADD = $(TESTUTIL_LIBS)
-lib1945_CPPFLAGS = $(AM_CPPFLAGS)
lib1946_SOURCES = lib1940.c $(SUPPORTFILES)
lib1946_LDADD = $(TESTUTIL_LIBS)
lib1946_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1946
+lib1947_SOURCES = lib1947.c $(SUPPORTFILES)
+lib1947_LDADD = $(TESTUTIL_LIBS)
+
+lib1948_SOURCES = lib1948.c $(SUPPORTFILES)
+lib1948_LDADD = $(TESTUTIL_LIBS)
+
+lib1955_SOURCES = lib1955.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1955_LDADD = $(TESTUTIL_LIBS)
+
+lib1956_SOURCES = lib1956.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1956_LDADD = $(TESTUTIL_LIBS)
+
+lib1957_SOURCES = lib1957.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1957_LDADD = $(TESTUTIL_LIBS)
+
+lib1958_SOURCES = lib1958.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1958_LDADD = $(TESTUTIL_LIBS)
+
+lib1959_SOURCES = lib1959.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1959_LDADD = $(TESTUTIL_LIBS)
+
+lib1960_SOURCES = lib1960.c $(SUPPORTFILES)
+lib1960_LDADD = $(TESTUTIL_LIBS)
+
+lib1970_SOURCES = lib1970.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1970_LDADD = $(TESTUTIL_LIBS)
+
+lib1971_SOURCES = lib1971.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1971_LDADD = $(TESTUTIL_LIBS)
+
+lib1972_SOURCES = lib1972.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1972_LDADD = $(TESTUTIL_LIBS)
+
+lib1973_SOURCES = lib1973.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1973_LDADD = $(TESTUTIL_LIBS)
+
+lib1974_SOURCES = lib1974.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1974_LDADD = $(TESTUTIL_LIBS)
+
+lib1975_SOURCES = lib1975.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1975_LDADD = $(TESTUTIL_LIBS)
+
+lib2301_SOURCES = lib2301.c $(SUPPORTFILES)
+lib2301_LDADD = $(TESTUTIL_LIBS)
+
+lib2302_SOURCES = lib2302.c $(SUPPORTFILES)
+lib2302_LDADD = $(TESTUTIL_LIBS)
+
+lib2304_SOURCES = lib2304.c $(SUPPORTFILES)
+lib2304_LDADD = $(TESTUTIL_LIBS)
+
+lib2305_SOURCES = lib2305.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(MULTIBYTE)
+lib2305_LDADD = $(TESTUTIL_LIBS)
+
+lib2306_SOURCES = lib2306.c $(SUPPORTFILES)
+lib2306_LDADD = $(TESTUTIL_LIBS)
+
+lib2402_SOURCES = lib2402.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib2402_LDADD = $(TESTUTIL_LIBS)
+
+lib2404_SOURCES = lib2404.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib2404_LDADD = $(TESTUTIL_LIBS)
+
+lib2502_SOURCES = lib2502.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib2502_LDADD = $(TESTUTIL_LIBS)
+
lib3010_SOURCES = lib3010.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib3010_LDADD = $(TESTUTIL_LIBS)
-lib3010_CPPFLAGS = $(AM_CPPFLAGS)
lib3025_SOURCES = lib3025.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib3025_LDADD = $(TESTUTIL_LIBS)
-lib3025_CPPFLAGS = $(AM_CPPFLAGS)
lib3026_SOURCES = lib3026.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib3026_LDADD = $(TESTUTIL_LIBS)
-lib3026_CPPFLAGS = $(AM_CPPFLAGS)
+
+lib3027_SOURCES = lib3027.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib3027_LDADD = $(TESTUTIL_LIBS)
+
+lib3100_SOURCES = lib3100.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib3100_LDADD = $(TESTUTIL_LIBS)
+
+lib3101_SOURCES = lib3101.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib3101_LDADD = $(TESTUTIL_LIBS)
+
diff --git a/tests/libtest/chkhostname.c b/tests/libtest/chkhostname.c
index 04716f9..e49da13 100644
--- a/tests/libtest/chkhostname.c
+++ b/tests/libtest/chkhostname.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/first.c b/tests/libtest/first.c
index 5edb49b..334ccd9 100644
--- a/tests/libtest/first.c
+++ b/tests/libtest/first.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -85,9 +85,7 @@
struct timeval tv_test_start; /* for test timing */
-#ifdef UNITTESTS
int unitfail; /* for unittests */
-#endif
#ifdef CURLDEBUG
static void memory_tracking_init(void)
@@ -190,5 +188,7 @@
_flushall();
#endif
- return result;
+ /* Regular program status codes are limited to 0..127 and 126 and 127 have
+ * special meanings by the shell, so limit a normal return code to 125 */
+ return result <= 125 ? result : 125;
}
diff --git a/tests/libtest/lib1156.c b/tests/libtest/lib1156.c
index 23e3d94..84a5d48 100644
--- a/tests/libtest/lib1156.c
+++ b/tests/libtest/lib1156.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -123,13 +123,13 @@
}
return 0;
- test_cleanup:
+test_cleanup:
return 1;
}
/* for debugging: */
-/*#define SINGLETEST 9*/
+/* #define SINGLETEST 9 */
int test(char *URL)
{
@@ -164,7 +164,7 @@
printf("%d\n", status);
return status;
- test_cleanup:
+test_cleanup:
curl_easy_cleanup(curl);
curl_global_cleanup();
diff --git a/tests/libtest/lib1301.c b/tests/libtest/lib1301.c
new file mode 100644
index 0000000..f63b94c
--- /dev/null
+++ b/tests/libtest/lib1301.c
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#define fail_unless(expr, msg) \
+ do { \
+ if(!(expr)) { \
+ fprintf(stderr, "%s:%d Assertion '%s' failed: %s\n", \
+ __FILE__, __LINE__, #expr, msg); \
+ return 1; \
+ } \
+ } while(0)
+
+int test(char *URL)
+{
+ int rc;
+ (void)URL;
+
+ rc = curl_strequal("iii", "III");
+ fail_unless(rc != 0, "return code should be non-zero");
+
+ rc = curl_strequal("iiia", "III");
+ fail_unless(rc == 0, "return code should be zero");
+
+ rc = curl_strequal("iii", "IIIa");
+ fail_unless(rc == 0, "return code should be zero");
+
+ rc = curl_strequal("iiiA", "IIIa");
+ fail_unless(rc != 0, "return code should be non-zero");
+
+ rc = curl_strnequal("iii", "III", 3);
+ fail_unless(rc != 0, "return code should be non-zero");
+
+ rc = curl_strnequal("iiiABC", "IIIcba", 3);
+ fail_unless(rc != 0, "return code should be non-zero");
+
+ rc = curl_strnequal("ii", "II", 3);
+ fail_unless(rc != 0, "return code should be non-zero");
+
+ return 0;
+}
diff --git a/tests/libtest/lib1500.c b/tests/libtest/lib1500.c
index 9e009a3..3f237a0 100644
--- a/tests/libtest/lib1500.c
+++ b/tests/libtest/lib1500.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1501.c b/tests/libtest/lib1501.c
index 1deb2fd..a4816c7 100644
--- a/tests/libtest/lib1501.c
+++ b/tests/libtest/lib1501.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1502.c b/tests/libtest/lib1502.c
index 2b5ba9e..2e2415b 100644
--- a/tests/libtest/lib1502.c
+++ b/tests/libtest/lib1502.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1506.c b/tests/libtest/lib1506.c
index 1acb7bc..a1a72b2 100644
--- a/tests/libtest/lib1506.c
+++ b/tests/libtest/lib1506.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2022, Linus Nielsen Feltzing <linus@haxx.se>
+ * Copyright (C) Linus Nielsen Feltzing <linus@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1507.c b/tests/libtest/lib1507.c
index 0783486..d23e0b1 100644
--- a/tests/libtest/lib1507.c
+++ b/tests/libtest/lib1507.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1508.c b/tests/libtest/lib1508.c
index 732e10d..9810391 100644
--- a/tests/libtest/lib1508.c
+++ b/tests/libtest/lib1508.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2022, Linus Nielsen Feltzing <linus@haxx.se>
+ * Copyright (C) Linus Nielsen Feltzing <linus@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1509.c b/tests/libtest/lib1509.c
index e64f3a3..2277e6c 100644
--- a/tests/libtest/lib1509.c
+++ b/tests/libtest/lib1509.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1510.c b/tests/libtest/lib1510.c
index 130400a..7b0e12c 100644
--- a/tests/libtest/lib1510.c
+++ b/tests/libtest/lib1510.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2022, Linus Nielsen Feltzing <linus@haxx.se>
+ * Copyright (C) Linus Nielsen Feltzing <linus@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1511.c b/tests/libtest/lib1511.c
index 26d3084..d093a5b 100644
--- a/tests/libtest/lib1511.c
+++ b/tests/libtest/lib1511.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1512.c b/tests/libtest/lib1512.c
index d88dd1c..2ca0fe6 100644
--- a/tests/libtest/lib1512.c
+++ b/tests/libtest/lib1512.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2022, Linus Nielsen Feltzing <linus@haxx.se>
+ * Copyright (C) Linus Nielsen Feltzing <linus@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -71,7 +71,9 @@
/* include headers */
easy_setopt(curl[i], CURLOPT_HEADER, 1L);
- easy_setopt(curl[i], CURLOPT_DNS_USE_GLOBAL_CACHE, 1L);
+ CURL_IGNORE_DEPRECATION(
+ easy_setopt(curl[i], CURLOPT_DNS_USE_GLOBAL_CACHE, 1L);
+ )
}
/* make the first one populate the GLOBAL cache */
diff --git a/tests/libtest/lib1513.c b/tests/libtest/lib1513.c
index 04e1ecc..19c23c0 100644
--- a/tests/libtest/lib1513.c
+++ b/tests/libtest/lib1513.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -59,8 +59,10 @@
easy_setopt(curl, CURLOPT_URL, URL);
easy_setopt(curl, CURLOPT_TIMEOUT, (long)7);
easy_setopt(curl, CURLOPT_NOSIGNAL, (long)1);
- easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressKiller);
- easy_setopt(curl, CURLOPT_PROGRESSDATA, NULL);
+ CURL_IGNORE_DEPRECATION(
+ easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressKiller);
+ easy_setopt(curl, CURLOPT_PROGRESSDATA, NULL);
+ )
easy_setopt(curl, CURLOPT_NOPROGRESS, (long)0);
res = curl_easy_perform(curl);
diff --git a/tests/libtest/lib1514.c b/tests/libtest/lib1514.c
index a235003..6582b59 100644
--- a/tests/libtest/lib1514.c
+++ b/tests/libtest/lib1514.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1515.c b/tests/libtest/lib1515.c
index 6690af4..d210ed3 100644
--- a/tests/libtest/lib1515.c
+++ b/tests/libtest/lib1515.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,10 +37,6 @@
#define DNS_TIMEOUT 1
-#if defined(WIN32) || defined(_WIN32)
-#define sleep(sec) Sleep ((sec)*1000)
-#endif
-
static int debug_callback(CURL *curl, curl_infotype info, char *msg,
size_t len, void *ptr)
{
diff --git a/tests/libtest/lib1517.c b/tests/libtest/lib1517.c
index 85e027a..706b556 100644
--- a/tests/libtest/lib1517.c
+++ b/tests/libtest/lib1517.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -60,6 +60,16 @@
struct WriteThis pooh;
+ if(!strcmp(URL, "check")) {
+#if (defined(WIN32) || defined(__CYGWIN__))
+ printf("Windows TCP does not deliver response data but reports "
+ "CONNABORTED\n");
+ return 1; /* skip since test will fail on Windows without workaround */
+#else
+ return 0; /* sure, run this! */
+#endif
+ }
+
pooh.readptr = data;
pooh.sizeleft = strlen(data);
diff --git a/tests/libtest/lib1518.c b/tests/libtest/lib1518.c
index 42a6db7..9805a22 100644
--- a/tests/libtest/lib1518.c
+++ b/tests/libtest/lib1518.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1520.c b/tests/libtest/lib1520.c
index 248620b..5b6c3dc 100644
--- a/tests/libtest/lib1520.c
+++ b/tests/libtest/lib1520.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2022, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1522.c b/tests/libtest/lib1522.c
index fa4c0c8..8699597 100644
--- a/tests/libtest/lib1522.c
+++ b/tests/libtest/lib1522.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -92,7 +92,7 @@
else {
printf("curl_easy_perform() failed. e = %d\n", code);
}
- test_cleanup:
+test_cleanup:
curl_slist_free_all(pHeaderList);
curl_easy_cleanup(curl);
curl_global_cleanup();
diff --git a/tests/libtest/lib1523.c b/tests/libtest/lib1523.c
index 2e359a0..3da471f 100644
--- a/tests/libtest/lib1523.c
+++ b/tests/libtest/lib1523.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -77,7 +77,7 @@
if(ret != CURLE_OPERATION_TIMEDOUT)
fprintf(stderr, "error %d: %s\n", ret, buffer);
else
- ret = 0;
+ ret = CURLE_OK;
printf("End: %d\n", time(NULL));
curl_easy_cleanup(hnd);
diff --git a/tests/libtest/lib1525.c b/tests/libtest/lib1525.c
index 44c52ff..591eb41 100644
--- a/tests/libtest/lib1525.c
+++ b/tests/libtest/lib1525.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 1998, Vijay Panghal, <vpanghal@maginatics.com>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Vijay Panghal, <vpanghal@maginatics.com>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -50,7 +50,7 @@
{
CURL *curl = NULL;
CURLcode res = CURLE_FAILED_INIT;
- /* http and proxy header list*/
+ /* http and proxy header list */
struct curl_slist *hhl = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
diff --git a/tests/libtest/lib1526.c b/tests/libtest/lib1526.c
index d9f11f5..c11e536 100644
--- a/tests/libtest/lib1526.c
+++ b/tests/libtest/lib1526.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Vijay Panghal, <vpanghal@maginatics.com>, et al.
+ * Copyright (C) Vijay Panghal, <vpanghal@maginatics.com>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,7 +48,7 @@
{
CURL *curl = NULL;
CURLcode res = CURLE_FAILED_INIT;
- /* http and proxy header list*/
+ /* http and proxy header list */
struct curl_slist *hhl = NULL, *phl = NULL, *tmp = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
diff --git a/tests/libtest/lib1527.c b/tests/libtest/lib1527.c
index 6f4d7fe..e598705 100644
--- a/tests/libtest/lib1527.c
+++ b/tests/libtest/lib1527.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Vijay Panghal, <vpanghal@maginatics.com>, et al.
+ * Copyright (C) Vijay Panghal, <vpanghal@maginatics.com>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -49,7 +49,7 @@
{
CURL *curl = NULL;
CURLcode res = CURLE_FAILED_INIT;
- /* http header list*/
+ /* http header list */
struct curl_slist *hhl = NULL, *tmp = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
diff --git a/tests/libtest/lib1528.c b/tests/libtest/lib1528.c
index 3401f65..ae23604 100644
--- a/tests/libtest/lib1528.c
+++ b/tests/libtest/lib1528.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,7 +30,7 @@
{
CURL *curl = NULL;
CURLcode res = CURLE_FAILED_INIT;
- /* http header list*/
+ /* http header list */
struct curl_slist *hhl = NULL;
struct curl_slist *phl = NULL;
diff --git a/tests/libtest/lib1529.c b/tests/libtest/lib1529.c
index b2fa29a..5b0f990 100644
--- a/tests/libtest/lib1529.c
+++ b/tests/libtest/lib1529.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1530.c b/tests/libtest/lib1530.c
index 39b2042..e459492 100644
--- a/tests/libtest/lib1530.c
+++ b/tests/libtest/lib1530.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1531.c b/tests/libtest/lib1531.c
index c5cc548..7034001 100644
--- a/tests/libtest/lib1531.c
+++ b/tests/libtest/lib1531.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1532.c b/tests/libtest/lib1532.c
index 8906ce7..a3ac709 100644
--- a/tests/libtest/lib1532.c
+++ b/tests/libtest/lib1532.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
{
CURL *curl;
long httpcode;
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
@@ -78,5 +78,5 @@
test_cleanup:
curl_easy_cleanup(curl);
curl_global_cleanup();
- return res;
+ return (int)res;
}
diff --git a/tests/libtest/lib1533.c b/tests/libtest/lib1533.c
index ed6b1fa..555fb96 100644
--- a/tests/libtest/lib1533.c
+++ b/tests/libtest/lib1533.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -131,7 +131,7 @@
{
struct cb_data data;
CURL *curl = NULL;
- CURLcode res = CURLE_FAILED_INIT;
+ int res = TEST_ERR_FAILURE;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib1534.c b/tests/libtest/lib1534.c
index 53a155c..620e383 100644
--- a/tests/libtest/lib1534.c
+++ b/tests/libtest/lib1534.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
{
CURL *curl, *dupe = NULL;
long filetime;
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
@@ -127,5 +127,5 @@
curl_easy_cleanup(curl);
curl_easy_cleanup(dupe);
curl_global_cleanup();
- return res;
+ return (int)res;
}
diff --git a/tests/libtest/lib1535.c b/tests/libtest/lib1535.c
index 5c2e8ca..6edf887 100644
--- a/tests/libtest/lib1535.c
+++ b/tests/libtest/lib1535.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
{
CURL *curl, *dupe = NULL;
long protocol;
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
@@ -40,7 +40,9 @@
/* Test that protocol is properly initialized on curl_easy_init.
*/
- res = curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+ CURL_IGNORE_DEPRECATION(
+ res = curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+ )
if(res) {
fprintf(stderr, "%s:%d curl_easy_getinfo() failed with code %d (%s)\n",
__FILE__, __LINE__, res, curl_easy_strerror(res));
@@ -65,7 +67,9 @@
/* Test that a protocol is properly set after receiving an HTTP resource.
*/
- res = curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+ CURL_IGNORE_DEPRECATION(
+ res = curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+ )
if(res) {
fprintf(stderr, "%s:%d curl_easy_getinfo() failed with code %d (%s)\n",
__FILE__, __LINE__, res, curl_easy_strerror(res));
@@ -90,7 +94,9 @@
goto test_cleanup;
}
- res = curl_easy_getinfo(dupe, CURLINFO_PROTOCOL, &protocol);
+ CURL_IGNORE_DEPRECATION(
+ res = curl_easy_getinfo(dupe, CURLINFO_PROTOCOL, &protocol);
+ )
if(res) {
fprintf(stderr, "%s:%d curl_easy_getinfo() failed with code %d (%s)\n",
__FILE__, __LINE__, res, curl_easy_strerror(res));
@@ -109,7 +115,9 @@
curl_easy_reset(curl);
- res = curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+ CURL_IGNORE_DEPRECATION(
+ res = curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+ )
if(res) {
fprintf(stderr, "%s:%d curl_easy_getinfo() failed with code %d (%s)\n",
__FILE__, __LINE__, res, curl_easy_strerror(res));
@@ -126,5 +134,5 @@
curl_easy_cleanup(curl);
curl_easy_cleanup(dupe);
curl_global_cleanup();
- return res;
+ return (int)res;
}
diff --git a/tests/libtest/lib1536.c b/tests/libtest/lib1536.c
index a9a57ba..9ba7ec1 100644
--- a/tests/libtest/lib1536.c
+++ b/tests/libtest/lib1536.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
{
CURL *curl, *dupe = NULL;
char *scheme;
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
@@ -127,5 +127,5 @@
curl_easy_cleanup(curl);
curl_easy_cleanup(dupe);
curl_global_cleanup();
- return res;
+ return (int)res;
}
diff --git a/tests/libtest/lib1537.c b/tests/libtest/lib1537.c
index 30f7be2..21252fb 100644
--- a/tests/libtest/lib1537.c
+++ b/tests/libtest/lib1537.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1538.c b/tests/libtest/lib1538.c
index 494a4e9..cd9e3f6 100644
--- a/tests/libtest/lib1538.c
+++ b/tests/libtest/lib1538.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1540.c b/tests/libtest/lib1540.c
index 0f74931..8ea82a2 100644
--- a/tests/libtest/lib1540.c
+++ b/tests/libtest/lib1540.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1541.c b/tests/libtest/lib1541.c
index 01343aa..7146288 100644
--- a/tests/libtest/lib1541.c
+++ b/tests/libtest/lib1541.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1542.c b/tests/libtest/lib1542.c
index 19c46b5..2570ea3 100644
--- a/tests/libtest/lib1542.c
+++ b/tests/libtest/lib1542.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,10 +36,6 @@
#include "warnless.h"
#include "memdebug.h"
-#if defined(WIN32) || defined(_WIN32)
-#define sleep(sec) Sleep ((sec)*1000)
-#endif
-
int test(char *URL)
{
CURL *easy = NULL;
@@ -84,5 +80,5 @@
curl_easy_cleanup(easy);
curl_global_cleanup();
- return (int)res;
+ return res;
}
diff --git a/tests/libtest/lib1550.c b/tests/libtest/lib1550.c
index c35e293..4c34be8 100644
--- a/tests/libtest/lib1550.c
+++ b/tests/libtest/lib1550.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1551.c b/tests/libtest/lib1551.c
index aabb92a..f693cb1 100644
--- a/tests/libtest/lib1551.c
+++ b/tests/libtest/lib1551.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1552.c b/tests/libtest/lib1552.c
index acab9cd..c48d640 100644
--- a/tests/libtest/lib1552.c
+++ b/tests/libtest/lib1552.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1553.c b/tests/libtest/lib1553.c
index 01003c5..8bf1568 100644
--- a/tests/libtest/lib1553.c
+++ b/tests/libtest/lib1553.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1554.c b/tests/libtest/lib1554.c
index 021cdc9..b0e94b8 100644
--- a/tests/libtest/lib1554.c
+++ b/tests/libtest/lib1554.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1555.c b/tests/libtest/lib1555.c
index 25a9086..1ff6f28 100644
--- a/tests/libtest/lib1555.c
+++ b/tests/libtest/lib1555.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@
double ultotal,
double ulnow)
{
- CURLcode res = 0;
+ CURLcode res = CURLE_OK;
char buffer[256];
size_t n = 0;
(void)arg;
@@ -64,8 +64,10 @@
easy_setopt(curl, CURLOPT_URL, URL);
easy_setopt(curl, CURLOPT_TIMEOUT, (long)7);
easy_setopt(curl, CURLOPT_NOSIGNAL, (long)1);
- easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressCallback);
- easy_setopt(curl, CURLOPT_PROGRESSDATA, NULL);
+ CURL_IGNORE_DEPRECATION(
+ easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressCallback);
+ easy_setopt(curl, CURLOPT_PROGRESSDATA, NULL);
+ )
easy_setopt(curl, CURLOPT_NOPROGRESS, (long)0);
res = curl_easy_perform(curl);
diff --git a/tests/libtest/lib1556.c b/tests/libtest/lib1556.c
index b59a0db..6f8a214 100644
--- a/tests/libtest/lib1556.c
+++ b/tests/libtest/lib1556.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1557.c b/tests/libtest/lib1557.c
index 6828d78..2fa34ad 100644
--- a/tests/libtest/lib1557.c
+++ b/tests/libtest/lib1557.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1558.c b/tests/libtest/lib1558.c
index 7ee61c5..d64b598 100644
--- a/tests/libtest/lib1558.c
+++ b/tests/libtest/lib1558.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,7 +29,7 @@
int test(char *URL)
{
- CURLcode res = 0;
+ CURLcode res = CURLE_OK;
CURL *curl = NULL;
long protocol = 0;
@@ -44,7 +44,9 @@
goto test_cleanup;
}
- res = curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+ CURL_IGNORE_DEPRECATION(
+ res = curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+ )
if(res) {
fprintf(stderr, "curl_easy_getinfo() returned %d (%s)\n",
res, curl_easy_strerror(res));
diff --git a/tests/libtest/lib1559.c b/tests/libtest/lib1559.c
index 83b1193..402fee3 100644
--- a/tests/libtest/lib1559.c
+++ b/tests/libtest/lib1559.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,7 +30,7 @@
#define EXCESSIVE 10*1000*1000
int test(char *URL)
{
- CURLcode res = 0;
+ CURLcode res = CURLE_OK;
CURL *curl = NULL;
char *longurl = malloc(EXCESSIVE);
CURLU *u;
diff --git a/tests/libtest/lib1560.c b/tests/libtest/lib1560.c
index e5dd688..0eca0fd 100644
--- a/tests/libtest/lib1560.c
+++ b/tests/libtest/lib1560.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,6 +31,9 @@
*/
#include "test.h"
+#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
+#define USE_IDN
+#endif
#include "testutil.h"
#include "warnless.h"
@@ -60,7 +63,7 @@
{CURLUPART_PATH, "path"},
{CURLUPART_QUERY, "query"},
{CURLUPART_FRAGMENT, "fragment"},
- {0, NULL}
+ {CURLUPART_URL, NULL}
};
memset(buf, 0, sizeof(buf));
@@ -105,6 +108,16 @@
CURLUcode pcode; /* for updating parts */
};
+struct setgetcase {
+ const char *in;
+ const char *set;
+ const char *out;
+ unsigned int urlflags; /* for setting the URL */
+ unsigned int setflags; /* for updating parts */
+ unsigned int getflags; /* for getting parts */
+ CURLUcode pcode; /* for updating parts */
+};
+
struct testcase {
const char *in;
const char *out;
@@ -138,18 +151,123 @@
};
static const struct testcase get_parts_list[] ={
+ {"1h://example.net", "", 0, 0, CURLUE_BAD_SCHEME},
+ {"..://example.net", "", 0, 0, CURLUE_BAD_SCHEME},
+ {"-ht://example.net", "", 0, 0, CURLUE_BAD_SCHEME},
+ {"+ftp://example.net", "", 0, 0, CURLUE_BAD_SCHEME},
+ {"hej.hej://example.net",
+ "hej.hej | [11] | [12] | [13] | example.net | [15] | / | [16] | [17]",
+ CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
+ {"ht-tp://example.net",
+ "ht-tp | [11] | [12] | [13] | example.net | [15] | / | [16] | [17]",
+ CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
+ {"ftp+more://example.net",
+ "ftp+more | [11] | [12] | [13] | example.net | [15] | / | [16] | [17]",
+ CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
+ {"f1337://example.net",
+ "f1337 | [11] | [12] | [13] | example.net | [15] | / | [16] | [17]",
+ CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
+ {"https://user@example.net?hello# space ",
+ "https | user | [12] | [13] | example.net | [15] | / | hello | %20space%20",
+ CURLU_ALLOW_SPACE|CURLU_URLENCODE, 0, CURLUE_OK},
+ {"https://test%test", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://example.com%252f%40@example.net",
+ "https | example.com%2f@ | [12] | [13] | example.net | [15] | / "
+ "| [16] | [17]",
+ 0, CURLU_URLDECODE, CURLUE_OK },
+#ifdef USE_IDN
+ {"https://räksmörgås.se",
+ "https | [11] | [12] | [13] | xn--rksmrgs-5wao1o.se | "
+ "[15] | / | [16] | [17]", 0, CURLU_PUNYCODE, CURLUE_OK},
+#else
+ {"https://räksmörgås.se",
+ "https | [11] | [12] | [13] | [30] | [15] | / | [16] | [17]",
+ 0, CURLU_PUNYCODE, CURLUE_OK},
+#endif
+ /* https://ℂᵤⓇℒ。𝐒🄴 */
+ {"https://"
+ "%e2%84%82%e1%b5%a4%e2%93%87%e2%84%92%e3%80%82%f0%9d%90%92%f0%9f%84%b4",
+ "https | [11] | [12] | [13] | ℂᵤⓇℒ。𝐒🄴 | [15] |"
+ " / | [16] | [17]",
+ 0, 0, CURLUE_OK},
+ {"https://"
+ "%e2%84%82%e1%b5%a4%e2%93%87%e2%84%92%e3%80%82%f0%9d%90%92%f0%9f%84%b4",
+ "https | [11] | [12] | [13] | "
+ "%e2%84%82%e1%b5%a4%e2%93%87%e2%84%92%e3%80%82%f0%9d%90%92%f0%9f%84%b4 "
+ "| [15] | / | [16] | [17]",
+ 0, CURLU_URLENCODE, CURLUE_OK},
+ {"https://"
+ "\xe2\x84\x82\xe1\xb5\xa4\xe2\x93\x87\xe2\x84\x92"
+ "\xe3\x80\x82\xf0\x9d\x90\x92\xf0\x9f\x84\xb4",
+ "https | [11] | [12] | [13] | "
+ "%e2%84%82%e1%b5%a4%e2%93%87%e2%84%92%e3%80%82%f0%9d%90%92%f0%9f%84%b4 "
+ "| [15] | / | [16] | [17]",
+ 0, CURLU_URLENCODE, CURLUE_OK},
+ {"https://user@example.net?he l lo",
+ "https | user | [12] | [13] | example.net | [15] | / | he+l+lo | [17]",
+ CURLU_ALLOW_SPACE, CURLU_URLENCODE, CURLUE_OK},
+ {"https://user@example.net?he l lo",
+ "https | user | [12] | [13] | example.net | [15] | / | he l lo | [17]",
+ CURLU_ALLOW_SPACE, 0, CURLUE_OK},
+ {"https://exam{}[]ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam{ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam}ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam]ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam\\ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam$ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam'ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam\"ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam^ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam`ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam*ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam<ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam>ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam=ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://exam;ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://example,net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://example&net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://example+net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://example(net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://example)net", "", 0, 0, CURLUE_BAD_HOSTNAME},
+ {"https://example.net/}",
+ "https | [11] | [12] | [13] | example.net | [15] | /} | [16] | [17]",
+ 0, 0, CURLUE_OK},
+
+ /* blank user is blank */
+ {"https://:password@example.net",
+ "https | | password | [13] | example.net | [15] | / | [16] | [17]",
+ 0, 0, CURLUE_OK},
+ /* blank user + blank password */
+ {"https://:@example.net",
+ "https | | | [13] | example.net | [15] | / | [16] | [17]",
+ 0, 0, CURLUE_OK},
+ /* user-only (no password) */
+ {"https://user@example.net",
+ "https | user | [12] | [13] | example.net | [15] | / | [16] | [17]",
+ 0, 0, CURLUE_OK},
+#ifdef USE_WEBSOCKETS
+ {"ws://example.com/color/?green",
+ "ws | [11] | [12] | [13] | example.com | [15] | /color/ | green |"
+ " [17]",
+ CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
+ {"wss://example.com/color/?green",
+ "wss | [11] | [12] | [13] | example.com | [15] | /color/ | green |"
+ " [17]",
+ CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
+#endif
+
{"https://user:password@example.net/get?this=and#but frag then", "",
- CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_FRAGMENT},
+ CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
{"https://user:password@example.net/get?this=and what", "",
- CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_QUERY},
+ CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
{"https://user:password@example.net/ge t?this=and-what", "",
- CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PATH},
+ CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
{"https://user:pass word@example.net/get?this=and-what", "",
- CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PASSWORD},
+ CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
{"https://u ser:password@example.net/get?this=and-what", "",
- CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_USER},
+ CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
{"imap://user:pass;opt ion@server/path", "",
- CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_LOGIN},
+ CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
/* no space allowed in scheme */
{"htt ps://user:password@example.net/get?this=and-what", "",
CURLU_NON_SUPPORT_SCHEME|CURLU_ALLOW_SPACE, 0, CURLUE_BAD_SCHEME},
@@ -237,7 +355,7 @@
CURLU_DEFAULT_SCHEME, 0, CURLUE_NO_HOST},
{"boing:80",
"https | [11] | [12] | [13] | boing | 80 | / | [16] | [17]",
- CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
+ CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME, 0, CURLUE_OK},
{"http://[fd00:a41::50]:8080",
"http | [11] | [12] | [13] | [fd00:a41::50] | 8080 | / | [16] | [17]",
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
@@ -311,9 +429,9 @@
"https | [11] | [12] | [13] | 127abc.com | [15] | / | [16] | [17]",
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
{"https:// example.com?check", "",
- CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_HOSTNAME},
+ CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
{"https://e x a m p l e.com?check", "",
- CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_HOSTNAME},
+ CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
{"https://example.com?check",
"https | [11] | [12] | [13] | example.com | [15] | / | check | [17]",
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
@@ -382,6 +500,44 @@
};
static const struct urltestcase get_url_list[] = {
+ {"https://1.0x1000000", "https://1.0x1000000/", 0, 0, CURLUE_OK},
+ {"https://0x7f.1", "https://127.0.0.1/", 0, 0, CURLUE_OK},
+ {"https://1.2.3.256.com", "https://1.2.3.256.com/", 0, 0, CURLUE_OK},
+ {"https://10.com", "https://10.com/", 0, 0, CURLUE_OK},
+ {"https://1.2.com", "https://1.2.com/", 0, 0, CURLUE_OK},
+ {"https://1.2.3.com", "https://1.2.3.com/", 0, 0, CURLUE_OK},
+ {"https://1.2.com.99", "https://1.2.com.99/", 0, 0, CURLUE_OK},
+ {"https://[fe80::0000:20c:29ff:fe9c:409b]:80/moo",
+ "https://[fe80::20c:29ff:fe9c:409b]:80/moo",
+ 0, 0, CURLUE_OK},
+ {"https://[fe80::020c:29ff:fe9c:409b]:80/moo",
+ "https://[fe80::20c:29ff:fe9c:409b]:80/moo",
+ 0, 0, CURLUE_OK},
+ {"https://[fe80:0000:0000:0000:020c:29ff:fe9c:409b]:80/moo",
+ "https://[fe80::20c:29ff:fe9c:409b]:80/moo",
+ 0, 0, CURLUE_OK},
+ {"https://[fe80:0:0:0:409b::]:80/moo",
+ "https://[fe80::409b:0:0:0]:80/moo",
+ 0, 0, CURLUE_OK},
+ {"https://[::%25fakeit];80/moo",
+ "",
+ 0, 0, CURLUE_BAD_PORT_NUMBER},
+ {"https://[fe80::20c:29ff:fe9c:409b]-80/moo",
+ "",
+ 0, 0, CURLUE_BAD_PORT_NUMBER},
+#ifdef USE_IDN
+ {"https://räksmörgås.se/path?q#frag",
+ "https://xn--rksmrgs-5wao1o.se/path?q#frag", 0, CURLU_PUNYCODE, CURLUE_OK},
+#endif
+ /* unsupported schemes with no guessing enabled */
+ {"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIEhUTUw+PG1ldGEgY",
+ "", 0, 0, CURLUE_UNSUPPORTED_SCHEME},
+ {"d:anything-really", "", 0, 0, CURLUE_UNSUPPORTED_SCHEME},
+ {"about:config", "", 0, 0, CURLUE_UNSUPPORTED_SCHEME},
+ {"example://foo", "", 0, 0, CURLUE_UNSUPPORTED_SCHEME},
+ {"mailto:infobot@example.com?body=send%20current-issue", "", 0, 0,
+ CURLUE_UNSUPPORTED_SCHEME},
+ {"about:80", "https://about:80/", CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
/* percent encoded host names */
{"http://example.com%40127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
{"http://example.com%21127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
@@ -390,34 +546,34 @@
{"http://example.com%3a127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
{"http://example.com%09127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
{"http://example.com%2F127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
- {"https://%this", "https://%25this/", 0, 0, CURLUE_OK},
- {"https://h%c", "https://h%25c/", 0, 0, CURLUE_OK},
- {"https://%%%%%%", "https://%25%25%25%25%25%25/", 0, 0, CURLUE_OK},
{"https://%41", "https://A/", 0, 0, CURLUE_OK},
{"https://%20", "", 0, 0, CURLUE_BAD_HOSTNAME},
{"https://%41%0d", "", 0, 0, CURLUE_BAD_HOSTNAME},
- {"https://%25", "https://%25/", 0, 0, CURLUE_OK},
+ {"https://%25", "", 0, 0, CURLUE_BAD_HOSTNAME},
{"https://_%c0_", "https://_\xC0_/", 0, 0, CURLUE_OK},
{"https://_%c0_", "https://_%C0_/", 0, CURLU_URLENCODE, CURLUE_OK},
/* IPv4 trickeries */
{"https://16843009", "https://1.1.1.1/", 0, 0, CURLUE_OK},
- {"https://0x7f.1", "https://127.0.0.1/", 0, 0, CURLUE_OK},
{"https://0177.1", "https://127.0.0.1/", 0, 0, CURLUE_OK},
{"https://0111.02.0x3", "https://73.2.0.3/", 0, 0, CURLUE_OK},
+ {"https://0111.02.0x3.", "https://0111.02.0x3./", 0, 0, CURLUE_OK},
+ {"https://0111.02.030", "https://73.2.0.24/", 0, 0, CURLUE_OK},
+ {"https://0111.02.030.", "https://0111.02.030./", 0, 0, CURLUE_OK},
{"https://0xff.0xff.0377.255", "https://255.255.255.255/", 0, 0, CURLUE_OK},
{"https://1.0xffffff", "https://1.255.255.255/", 0, 0, CURLUE_OK},
/* IPv4 numerical overflows or syntax errors will not normalize */
- {"https://+127.0.0.1", "https://+127.0.0.1/", 0, 0, CURLUE_OK},
- {"https://+127.0.0.1", "https://%2B127.0.0.1/", 0, CURLU_URLENCODE,
+ {"https://a127.0.0.1", "https://a127.0.0.1/", 0, 0, CURLUE_OK},
+ {"https://\xff.127.0.0.1", "https://%FF.127.0.0.1/", 0, CURLU_URLENCODE,
CURLUE_OK},
{"https://127.-0.0.1", "https://127.-0.0.1/", 0, 0, CURLUE_OK},
- {"https://127.0. 1", "https://127.0.0.1/", 0, 0, CURLUE_BAD_HOSTNAME},
- {"https://1.0x1000000", "https://1.0x1000000/", 0, 0, CURLUE_OK},
+ {"https://127.0. 1", "https://127.0.0.1/", 0, 0, CURLUE_MALFORMED_INPUT},
{"https://1.2.3.256", "https://1.2.3.256/", 0, 0, CURLUE_OK},
+ {"https://1.2.3.256.", "https://1.2.3.256./", 0, 0, CURLUE_OK},
{"https://1.2.3.4.5", "https://1.2.3.4.5/", 0, 0, CURLUE_OK},
{"https://1.2.0x100.3", "https://1.2.0x100.3/", 0, 0, CURLUE_OK},
{"https://4294967296", "https://4294967296/", 0, 0, CURLUE_OK},
+ {"https://123host", "https://123host/", 0, 0, CURLUE_OK},
/* 40 bytes scheme is the max allowed */
{"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA://hostname/path",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa://hostname/path",
@@ -462,36 +618,63 @@
{"example.com/path/html",
"http://example.com/path/html",
CURLU_GUESS_SCHEME, 0, CURLUE_OK},
+ {"smtp.com/path/html",
+ "smtp://smtp.com/path/html",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK},
+ {"dict.com/path/html",
+ "dict://dict.com/path/html",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK},
+ {"pop3.com/path/html",
+ "pop3://pop3.com/path/html",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK},
+ {"ldap.com/path/html",
+ "ldap://ldap.com/path/html",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK},
+ {"imap.com/path/html",
+ "imap://imap.com/path/html",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK},
+ {"ftp.com/path/html",
+ "ftp://ftp.com/path/html",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK},
+ {"smtp/path/html",
+ "http://smtp/path/html",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK},
+ {"dict/path/html",
+ "http://dict/path/html",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK},
+ {"pop3/path/html",
+ "http://pop3/path/html",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK},
+ {"ldap/path/html",
+ "http://ldap/path/html",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK},
+ {"imap/path/html",
+ "http://imap/path/html",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK},
+ {"ftp/path/html",
+ "http://ftp/path/html",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK},
{"HTTP://test/", "http://test/", 0, 0, CURLUE_OK},
{"http://HO0_-st..~./", "http://HO0_-st..~./", 0, 0, CURLUE_OK},
- {"http:/@example.com: 123/", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
- {"http:/@example.com:123 /", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
+ {"http:/@example.com: 123/", "", 0, 0, CURLUE_MALFORMED_INPUT},
+ {"http:/@example.com:123 /", "", 0, 0, CURLUE_MALFORMED_INPUT},
{"http:/@example.com:123a/", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
- {"http://host/file\r", "", 0, 0, CURLUE_BAD_PATH},
- {"http://host/file\n\x03", "", 0, 0, CURLUE_BAD_PATH},
+ {"http://host/file\r", "", 0, 0, CURLUE_MALFORMED_INPUT},
+ {"http://host/file\n\x03", "", 0, 0, CURLUE_MALFORMED_INPUT},
{"htt\x02://host/file", "",
- CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_BAD_SCHEME},
- {" http://host/file", "", 0, 0, CURLUE_BAD_SCHEME},
+ CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
+ {" http://host/file", "", 0, 0, CURLUE_MALFORMED_INPUT},
/* here the password ends at the semicolon and options is 'word' */
{"imap://user:pass;word@host/file",
"imap://user:pass;word@host/file",
0, 0, CURLUE_OK},
/* here the password has the semicolon */
{"http://user:pass;word@host/file",
- "http://user:pass;word@host/file",
- 0, 0, CURLUE_OK},
- {"file:///file.txt#moo",
- "file:///file.txt#moo",
- 0, 0, CURLUE_OK},
- {"file:////file.txt",
- "file:////file.txt",
- 0, 0, CURLUE_OK},
- {"file:///file.txt",
- "file:///file.txt",
- 0, 0, CURLUE_OK},
- {"file:./",
- "file://",
- 0, 0, CURLUE_BAD_SCHEME},
+ "http://user:pass;word@host/file", 0, 0, CURLUE_OK},
+ {"file:///file.txt#moo", "file:///file.txt#moo", 0, 0, CURLUE_OK},
+ {"file:////file.txt", "file:////file.txt", 0, 0, CURLUE_OK},
+ {"file:///file.txt", "file:///file.txt", 0, 0, CURLUE_OK},
+ {"file:./", "file://", 0, 0, CURLUE_OK},
{"http://example.com/hello/../here",
"http://example.com/hello/../here",
CURLU_PATH_AS_IS, 0, CURLUE_OK},
@@ -508,7 +691,7 @@
"",
CURLU_DISALLOW_USER, 0, CURLUE_USER_NOT_ALLOWED},
{"http:/@example.com:123",
- "http://example.com:123/",
+ "http://@example.com:123/",
0, 0, CURLUE_OK},
{"http:/:password@example.com",
"http://:password@example.com/",
@@ -558,25 +741,101 @@
{"custom-scheme://host?expected=test-still-good",
"custom-scheme://host/?expected=test-still-good",
CURLU_NON_SUPPORT_SCHEME | CURLU_NO_AUTHORITY, 0, CURLUE_OK},
- {NULL, NULL, 0, 0, 0}
+ {NULL, NULL, 0, 0, CURLUE_OK}
};
-static int checkurl(const char *url, const char *out)
+static int checkurl(const char *org, const char *url, const char *out)
{
if(strcmp(out, url)) {
- fprintf(stderr, "Wanted: %s\nGot : %s\n",
- out, url);
+ fprintf(stderr,
+ "Org: %s\n"
+ "Wanted: %s\n"
+ "Got : %s\n",
+ org, out, url);
return 1;
}
return 0;
}
+/* 1. Set the URL
+ 2. Set components
+ 3. Extract all components (not URL)
+*/
+static const struct setgetcase setget_parts_list[] = {
+ {"https://example.com",
+ "path=get,",
+ "https | [11] | [12] | [13] | example.com | [15] | /get | [16] | [17]",
+ 0, 0, 0, CURLUE_OK},
+ {"https://example.com",
+ "path=/get,",
+ "https | [11] | [12] | [13] | example.com | [15] | /get | [16] | [17]",
+ 0, 0, 0, CURLUE_OK},
+ {"https://example.com",
+ "path=g e t,",
+ "https | [11] | [12] | [13] | example.com | [15] | /g%20e%20t | "
+ "[16] | [17]",
+ 0, CURLU_URLENCODE, 0, CURLUE_OK},
+ {NULL, NULL, NULL, 0, 0, 0, CURLUE_OK}
+};
+
/* !checksrc! disable SPACEBEFORECOMMA 1 */
static const struct setcase set_parts_list[] = {
+ {"https://example.com",
+ "path=get,",
+ "https://example.com/get",
+ 0, 0, CURLUE_OK, CURLUE_OK},
{"https://example.com/",
- "host=++,", /* '++' there's no automatic URL decode when settin this
+ "scheme=ftp+-.123,",
+ "ftp+-.123://example.com/",
+ 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
+ {"https://example.com/",
+ "scheme=1234,",
+ "https://example.com/",
+ 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
+ {"https://example.com/",
+ "scheme=1http,",
+ "https://example.com/",
+ 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
+ {"https://example.com/",
+ "scheme=-ftp,",
+ "https://example.com/",
+ 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
+ {"https://example.com/",
+ "scheme=+ftp,",
+ "https://example.com/",
+ 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
+ {"https://example.com/",
+ "scheme=.ftp,",
+ "https://example.com/",
+ 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
+ {"https://example.com/",
+ "host=example.com%2fmoo,",
+ "",
+ 0, /* get */
+ 0, /* set */
+ CURLUE_OK, CURLUE_BAD_HOSTNAME},
+ {"https://example.com/",
+ "host=http://fake,",
+ "",
+ 0, /* get */
+ 0, /* set */
+ CURLUE_OK, CURLUE_BAD_HOSTNAME},
+ {"https://example.com/",
+ "host=test%,",
+ "",
+ 0, /* get */
+ 0, /* set */
+ CURLUE_OK, CURLUE_BAD_HOSTNAME},
+ {"https://example.com/",
+ "host=te st,",
+ "",
+ 0, /* get */
+ 0, /* set */
+ CURLUE_OK, CURLUE_BAD_HOSTNAME},
+ {"https://example.com/",
+ "host=0xff,", /* '++' there's no automatic URL decode when settin this
part */
- "https://++/",
+ "https://0xff/",
0, /* get */
0, /* set */
CURLUE_OK, CURLUE_OK},
@@ -589,6 +848,11 @@
CURLUE_OK, CURLUE_OK},
{"https://example.com/",
+ /* Set a bad scheme *including* :// */
+ "scheme=https://,",
+ "https://example.com/",
+ 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
+ {"https://example.com/",
/* Set a 41 bytes scheme. That's too long so the old scheme remains set. */
"scheme=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc,",
"https://example.com/",
@@ -722,7 +986,7 @@
CURLU_NON_SUPPORT_SCHEME, CURLU_NON_SUPPORT_SCHEME | CURLU_NO_AUTHORITY,
CURLUE_OK, CURLUE_OK},
- {NULL, NULL, NULL, 0, 0, 0, 0}
+ {NULL, NULL, NULL, 0, 0, CURLUE_OK, CURLUE_OK}
};
static CURLUPart part2id(char *part)
@@ -797,35 +1061,51 @@
}
static const struct redircase set_url_list[] = {
+ {"http://example.com/please/../gimme/%TESTNUMBER?foobar#hello",
+ "http://example.net/there/it/is/../../tes t case=/%TESTNUMBER0002? yes no",
+ "http://example.net/there/tes%20t%20case=/%TESTNUMBER0002?+yes+no",
+ 0, CURLU_URLENCODE|CURLU_ALLOW_SPACE, CURLUE_OK},
+ {"http://local.test?redirect=http://local.test:80?-321",
+ "http://local.test:80?-123",
+ "http://local.test:80/?-123",
+ 0, CURLU_URLENCODE|CURLU_ALLOW_SPACE, CURLUE_OK},
+ {"http://local.test?redirect=http://local.test:80?-321",
+ "http://local.test:80?-123",
+ "http://local.test:80/?-123",
+ 0, 0, CURLUE_OK},
{"http://example.org/static/favicon/wikipedia.ico",
"//fake.example.com/licenses/by-sa/3.0/",
"http://fake.example.com/licenses/by-sa/3.0/",
- 0, 0, 0},
+ 0, 0, CURLUE_OK},
{"https://example.org/static/favicon/wikipedia.ico",
"//fake.example.com/licenses/by-sa/3.0/",
"https://fake.example.com/licenses/by-sa/3.0/",
- 0, 0, 0},
+ 0, 0, CURLUE_OK},
{"file://localhost/path?query#frag",
"foo#another",
"file:///foo#another",
- 0, 0, 0},
+ 0, 0, CURLUE_OK},
{"http://example.com/path?query#frag",
"https://two.example.com/bradnew",
"https://two.example.com/bradnew",
- 0, 0, 0},
+ 0, 0, CURLUE_OK},
{"http://example.com/path?query#frag",
"../../newpage#foo",
"http://example.com/newpage#foo",
- 0, 0, 0},
+ 0, 0, CURLUE_OK},
{"http://user:foo@example.com/path?query#frag",
"../../newpage",
"http://user:foo@example.com/newpage",
- 0, 0, 0},
+ 0, 0, CURLUE_OK},
{"http://user:foo@example.com/path?query#frag",
"../newpage",
"http://user:foo@example.com/newpage",
- 0, 0, 0},
- {NULL, NULL, NULL, 0, 0, 0}
+ 0, 0, CURLUE_OK},
+ {"http://user:foo@example.com/path?query#frag",
+ "http://?hi",
+ "http:///?hi",
+ 0, CURLU_NO_AUTHORITY, CURLUE_OK},
+ {NULL, NULL, NULL, 0, 0, CURLUE_OK}
};
static int set_url(void)
@@ -858,7 +1138,7 @@
error++;
}
else {
- if(checkurl(url, set_url_list[i].out)) {
+ if(checkurl(set_url_list[i].in, url, set_url_list[i].out)) {
error++;
}
}
@@ -875,6 +1155,54 @@
return error;
}
+/* 1. Set a URL
+ 2. Set one or more parts
+ 3. Extract and compare all parts - not the URL
+*/
+static int setget_parts(void)
+{
+ int i;
+ int error = 0;
+
+ for(i = 0; setget_parts_list[i].set && !error; i++) {
+ CURLUcode rc;
+ CURLU *urlp = curl_url();
+ if(!urlp) {
+ error++;
+ break;
+ }
+ if(setget_parts_list[i].in)
+ rc = curl_url_set(urlp, CURLUPART_URL, setget_parts_list[i].in,
+ setget_parts_list[i].urlflags);
+ else
+ rc = CURLUE_OK;
+ if(!rc) {
+ char *url = NULL;
+ CURLUcode uc = updateurl(urlp, setget_parts_list[i].set,
+ setget_parts_list[i].setflags);
+
+ if(uc != setget_parts_list[i].pcode) {
+ fprintf(stderr, "updateurl\nin: %s\nreturned %d (expected %d)\n",
+ setget_parts_list[i].set, (int)uc, setget_parts_list[i].pcode);
+ error++;
+ }
+ if(!uc) {
+ if(checkparts(urlp, setget_parts_list[i].set, setget_parts_list[i].out,
+ setget_parts_list[i].getflags))
+ error++; /* add */
+ }
+ curl_free(url);
+ }
+ else if(rc != CURLUE_OK) {
+ fprintf(stderr, "Set parts\nin: %s\nreturned %d (expected %d)\n",
+ setget_parts_list[i].in, (int)rc, 0);
+ error++;
+ }
+ curl_url_cleanup(urlp);
+ }
+ return error;
+}
+
static int set_parts(void)
{
int i;
@@ -911,7 +1239,7 @@
__FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
error++;
}
- else if(checkurl(url, set_parts_list[i].out)) {
+ else if(checkurl(set_parts_list[i].in, url, set_parts_list[i].out)) {
error++;
}
}
@@ -951,13 +1279,13 @@
error++;
}
else {
- if(checkurl(url, get_url_list[i].out)) {
+ if(checkurl(get_url_list[i].in, url, get_url_list[i].out)) {
error++;
}
}
curl_free(url);
}
- else if(rc != get_url_list[i].ucode) {
+ if(rc != get_url_list[i].ucode) {
fprintf(stderr, "Get URL\nin: %s\nreturned %d (expected %d)\n",
get_url_list[i].in, (int)rc, get_url_list[i].ucode);
error++;
@@ -1012,7 +1340,7 @@
0, 0, CURLUE_OK},
{"HTTP://test/?size=2#f", "name=joe", "http://test/?size=2&name=joe#f",
0, 0, CURLUE_OK},
- {NULL, NULL, NULL, 0, 0, 0}
+ {NULL, NULL, NULL, 0, 0, CURLUE_OK}
};
static int append(void)
@@ -1054,7 +1382,7 @@
error++;
}
else {
- if(checkurl(url, append_list[i].out)) {
+ if(checkurl(append_list[i].in, url, append_list[i].out)) {
error++;
}
curl_free(url);
@@ -1087,7 +1415,6 @@
error++;
}
else {
- printf("we got %s\n", url);
curl_free(url);
}
@@ -1105,7 +1432,6 @@
error++;
}
else {
- printf("we got %s\n", url);
curl_free(url);
}
@@ -1123,7 +1449,6 @@
error++;
}
else {
- printf("we got %s\n", url);
curl_free(url);
}
@@ -1142,7 +1467,6 @@
error++;
}
else {
- printf("we got %s\n", url);
curl_free(url);
}
@@ -1153,7 +1477,6 @@
error++;
}
else {
- printf("we got %s\n", url);
curl_free(url);
}
@@ -1164,7 +1487,6 @@
error++;
}
else {
- printf("we got %s\n", url);
curl_free(url);
}
@@ -1182,7 +1504,6 @@
error++;
}
else {
- printf("we got %s\n", url);
curl_free(url);
}
@@ -1233,7 +1554,7 @@
fprintf(stderr, "unexpected return code line %u\n", __LINE__);
rc = curl_url_get(u, CURLUPART_ZONEID, &p, 0);
- if(rc != CURLUE_OK)
+ if(rc != CURLUE_NO_ZONEID)
fprintf(stderr, "unexpected return code %u on line %u\n", (int)rc,
__LINE__);
@@ -1253,7 +1574,7 @@
{CURLUPART_PATH, "/hello", "/", CURLUE_OK},
{CURLUPART_QUERY, "a=b", NULL, CURLUE_NO_QUERY},
{CURLUPART_FRAGMENT, "anchor", NULL, CURLUE_NO_FRAGMENT},
- {0, NULL, NULL, CURLUE_OK},
+ {CURLUPART_URL, NULL, NULL, CURLUE_OK},
};
static int clear_url(void)
@@ -1290,10 +1611,80 @@
return error;
}
+static char total[128000];
+static char bigpart[120000];
+
+/*
+ * verify ridiculous URL part sizes
+ */
+static int huge(void)
+{
+ const char *url = "%s://%s:%s@%s/%s?%s#%s";
+ const char *smallpart = "c";
+ int i;
+ CURLU *urlp = curl_url();
+ CURLUcode rc;
+ CURLUPart part[]= {
+ CURLUPART_SCHEME,
+ CURLUPART_USER,
+ CURLUPART_PASSWORD,
+ CURLUPART_HOST,
+ CURLUPART_PATH,
+ CURLUPART_QUERY,
+ CURLUPART_FRAGMENT
+ };
+ int error = 0;
+ if(!urlp)
+ return 1;
+ bigpart[0] = '/'; /* for the path */
+ memset(&bigpart[1], 'a', sizeof(bigpart) - 2);
+ bigpart[sizeof(bigpart) - 1] = 0;
+
+ for(i = 0; i < 7; i++) {
+ char *partp;
+ msnprintf(total, sizeof(total),
+ url,
+ (i == 0)? &bigpart[1] : smallpart,
+ (i == 1)? &bigpart[1] : smallpart,
+ (i == 2)? &bigpart[1] : smallpart,
+ (i == 3)? &bigpart[1] : smallpart,
+ (i == 4)? &bigpart[1] : smallpart,
+ (i == 5)? &bigpart[1] : smallpart,
+ (i == 6)? &bigpart[1] : smallpart);
+ rc = curl_url_set(urlp, CURLUPART_URL, total, CURLU_NON_SUPPORT_SCHEME);
+ if((!i && (rc != CURLUE_BAD_SCHEME)) ||
+ (i && rc)) {
+ printf("URL %u: failed to parse [%s]\n", i, total);
+ error++;
+ }
+
+ /* only extract if the parse worked */
+ if(!rc) {
+ curl_url_get(urlp, part[i], &partp, 0);
+ if(!partp || strcmp(partp, &bigpart[1 - (i == 4)])) {
+ printf("URL %u part %u: failure\n", i, part[i]);
+ error++;
+ }
+ curl_free(partp);
+ }
+ }
+ curl_url_cleanup(urlp);
+ return error;
+}
+
int test(char *URL)
{
(void)URL; /* not used */
+ if(setget_parts())
+ return 10;
+
+ if(get_url())
+ return 3;
+
+ if(huge())
+ return 9;
+
if(get_nothing())
return 7;
@@ -1309,9 +1700,6 @@
if(set_parts())
return 2;
- if(get_url())
- return 3;
-
if(get_parts())
return 4;
diff --git a/tests/libtest/lib1564.c b/tests/libtest/lib1564.c
index d03ffa9..b10d034 100644
--- a/tests/libtest/lib1564.c
+++ b/tests/libtest/lib1564.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1565.c b/tests/libtest/lib1565.c
index f21ec09..9003951 100644
--- a/tests/libtest/lib1565.c
+++ b/tests/libtest/lib1565.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1567.c b/tests/libtest/lib1567.c
index ecf5c9e..82f2f01 100644
--- a/tests/libtest/lib1567.c
+++ b/tests/libtest/lib1567.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1568.c b/tests/libtest/lib1568.c
index 7e68b5f..78e7e6b 100644
--- a/tests/libtest/lib1568.c
+++ b/tests/libtest/lib1568.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2021 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,7 +40,7 @@
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "lib1568");
curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST);
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
- curl_easy_setopt(hnd, CURLOPT_PORT, (long)atoi(libtest_arg2));
+ curl_easy_setopt(hnd, CURLOPT_PORT, strtol(libtest_arg2, NULL, 10));
ret = curl_easy_perform(hnd);
diff --git a/tests/libtest/lib1569.c b/tests/libtest/lib1569.c
index b7da426..941bcc2 100644
--- a/tests/libtest/lib1569.c
+++ b/tests/libtest/lib1569.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2021 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1591.c b/tests/libtest/lib1591.c
index 1a6f7c2..5701e10 100644
--- a/tests/libtest/lib1591.c
+++ b/tests/libtest/lib1591.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -77,7 +77,7 @@
{
CURL *curl = NULL;
CURLcode res = CURLE_FAILED_INIT;
- /* http and proxy header list*/
+ /* http and proxy header list */
struct curl_slist *hhl = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
@@ -101,7 +101,7 @@
test_setopt(curl, CURLOPT_URL, URL);
test_setopt(curl, CURLOPT_HTTPHEADER, hhl);
- test_setopt(curl, CURLOPT_PUT, 1L);
+ test_setopt(curl, CURLOPT_UPLOAD, 1L);
test_setopt(curl, CURLOPT_READFUNCTION, read_callback);
test_setopt(curl, CURLOPT_TRAILERFUNCTION, trailers_callback);
test_setopt(curl, CURLOPT_TRAILERDATA, NULL);
diff --git a/tests/libtest/lib1592.c b/tests/libtest/lib1592.c
index 3e83941..77b637d 100644
--- a/tests/libtest/lib1592.c
+++ b/tests/libtest/lib1592.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1593.c b/tests/libtest/lib1593.c
index 01a7e2e..b0a91b9 100644
--- a/tests/libtest/lib1593.c
+++ b/tests/libtest/lib1593.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1594.c b/tests/libtest/lib1594.c
index 9411f05..5346c66 100644
--- a/tests/libtest/lib1594.c
+++ b/tests/libtest/lib1594.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1597.c b/tests/libtest/lib1597.c
new file mode 100644
index 0000000..44769f9
--- /dev/null
+++ b/tests/libtest/lib1597.c
@@ -0,0 +1,115 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+/* Testing CURLOPT_PROTOCOLS_STR */
+
+#include "test.h"
+
+#include "memdebug.h"
+
+struct pair {
+ const char *in;
+ CURLcode *exp;
+};
+
+int test(char *URL)
+{
+ CURL *curl = NULL;
+ int res = 0;
+ CURLcode result = CURLE_OK;
+ curl_version_info_data *curlinfo;
+ const char *const *proto;
+ int n;
+ int i;
+ static CURLcode ok = CURLE_OK;
+ static CURLcode bad = CURLE_BAD_FUNCTION_ARGUMENT;
+ static CURLcode unsup = CURLE_UNSUPPORTED_PROTOCOL;
+ static CURLcode httpcode = CURLE_UNSUPPORTED_PROTOCOL;
+ static CURLcode httpscode = CURLE_UNSUPPORTED_PROTOCOL;
+ static char protolist[1024];
+
+ static const struct pair prots[] = {
+ {"goobar", &unsup},
+ {"http ", &unsup},
+ {" http", &unsup},
+ {"http", &httpcode},
+ {"http,", &httpcode},
+ {"https,", &httpscode},
+ {"https,http", &httpscode},
+ {"http,http", &httpcode},
+ {"HTTP,HTTP", &httpcode},
+ {",HTTP,HTTP", &httpcode},
+ {"http,http,ft", &unsup},
+ {"", &bad},
+ {",,", &bad},
+ {protolist, &ok},
+ {"all", &ok},
+ {NULL, NULL},
+ };
+ (void)URL;
+
+ global_init(CURL_GLOBAL_ALL);
+
+ easy_init(curl);
+
+ /* Get enabled protocols.*/
+ curlinfo = curl_version_info(CURLVERSION_NOW);
+ if(!curlinfo) {
+ fputs("curl_version_info failed\n", stderr);
+ res = (int) TEST_ERR_FAILURE;
+ goto test_cleanup;
+ }
+
+ n = 0;
+ for(proto = curlinfo->protocols; *proto; proto++) {
+ if((size_t) n >= sizeof(protolist)) {
+ puts("protolist buffer too small\n");
+ res = (int) TEST_ERR_FAILURE;
+ goto test_cleanup;
+ }
+ n += msnprintf(protolist + n, sizeof(protolist) - n, ",%s", *proto);
+ if(curl_strequal(*proto, "http"))
+ httpcode = CURLE_OK;
+ if(curl_strequal(*proto, "https"))
+ httpscode = CURLE_OK;
+ }
+
+ /* Run the tests. */
+ for(i = 0; prots[i].in; i++) {
+ result = curl_easy_setopt(curl, CURLOPT_PROTOCOLS_STR, prots[i].in);
+ if(result != *prots[i].exp) {
+ printf("unexpectedly '%s' returned %u\n",
+ prots[i].in, result);
+ break;
+ }
+ }
+ printf("Tested %u strings\n", i);
+ res = (int)result;
+
+test_cleanup:
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return (int)result;
+}
diff --git a/tests/libtest/lib1662.c b/tests/libtest/lib1662.c
new file mode 100644
index 0000000..b7f8cac
--- /dev/null
+++ b/tests/libtest/lib1662.c
@@ -0,0 +1,91 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+static char data[]="mooaaa";
+
+struct WriteThis {
+ size_t sizeleft;
+};
+
+static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
+{
+ struct WriteThis *pooh = (struct WriteThis *)userp;
+ size_t len = strlen(data);
+
+ if(size*nmemb < len)
+ return 0;
+
+ if(pooh->sizeleft) {
+ memcpy(ptr, data, strlen(data));
+ pooh->sizeleft = 0;
+ return len;
+ }
+
+ return 0; /* no more data left to deliver */
+}
+
+
+int test(char *URL)
+{
+ CURLcode res = CURLE_OK;
+ CURL *hnd;
+ curl_mime *mime1;
+ curl_mimepart *part1;
+ struct WriteThis pooh = { 1 };
+
+ mime1 = NULL;
+
+ global_init(CURL_GLOBAL_ALL);
+
+ hnd = curl_easy_init();
+ if(hnd) {
+ curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
+ curl_easy_setopt(hnd, CURLOPT_URL, URL);
+ curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
+ mime1 = curl_mime_init(hnd);
+ if(mime1) {
+ part1 = curl_mime_addpart(mime1);
+ curl_mime_data_cb(part1, -1, read_callback, NULL, NULL, &pooh);
+ curl_mime_filename(part1, "poetry.txt");
+ curl_mime_name(part1, "content");
+ curl_easy_setopt(hnd, CURLOPT_MIMEPOST, mime1);
+ curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/2000");
+ curl_easy_setopt(hnd, CURLOPT_FOLLOWLOCATION, 1L);
+ curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
+ curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION,
+ (long)CURL_HTTP_VERSION_2TLS);
+ curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
+ curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
+ res = curl_easy_perform(hnd);
+ }
+ }
+
+ curl_easy_cleanup(hnd);
+ curl_mime_free(mime1);
+ curl_global_cleanup();
+ return (int)res;
+}
+
diff --git a/tests/libtest/lib1900.c b/tests/libtest/lib1900.c
deleted file mode 100644
index 37058ad..0000000
--- a/tests/libtest/lib1900.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2013 - 2022, Linus Nielsen Feltzing, <linus@haxx.se>
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-#include "test.h"
-
-#include "testutil.h"
-#include "warnless.h"
-#include "memdebug.h"
-
-#define TEST_HANG_TIMEOUT 60 * 1000
-#define MAX_URLS 200
-#define MAX_BLOCKLIST 20
-
-static int urltime[MAX_URLS];
-static char *urlstring[MAX_URLS];
-static CURL *handles[MAX_URLS];
-static char *site_blocklist[MAX_BLOCKLIST];
-static char *server_blocklist[MAX_BLOCKLIST];
-static int num_handles;
-static int blocklist_num_servers;
-static int blocklist_num_sites;
-
-static size_t
-write_callback(void *contents, size_t size, size_t nmemb, void *userp)
-{
- size_t realsize = size * nmemb;
- (void)contents;
- (void)userp;
-
- return realsize;
-}
-
-static int parse_url_file(const char *filename)
-{
- FILE *f;
- int filetime;
- char buf[200];
-
- num_handles = 0;
- blocklist_num_sites = 0;
- blocklist_num_servers = 0;
-
- f = fopen(filename, "rb");
- if(!f)
- return 0;
-
- while(!feof(f)) {
- if(fscanf(f, "%d %199s\n", &filetime, buf)) {
- urltime[num_handles] = filetime;
- urlstring[num_handles] = strdup(buf);
- num_handles++;
- continue;
- }
-
- if(fscanf(f, "blocklist_site %199s\n", buf)) {
- site_blocklist[blocklist_num_sites] = strdup(buf);
- blocklist_num_sites++;
- continue;
- }
-
- break;
- }
- fclose(f);
-
- site_blocklist[blocklist_num_sites] = NULL;
- server_blocklist[blocklist_num_servers] = NULL;
- return num_handles;
-}
-
-static void free_urls(void)
-{
- int i;
- for(i = 0; i < num_handles; i++) {
- Curl_safefree(urlstring[i]);
- }
- for(i = 0; i < blocklist_num_servers; i++) {
- Curl_safefree(server_blocklist[i]);
- }
- for(i = 0; i < blocklist_num_sites; i++) {
- Curl_safefree(site_blocklist[i]);
- }
-}
-
-static int create_handles(void)
-{
- int i;
-
- for(i = 0; i < num_handles; i++) {
- handles[i] = curl_easy_init();
- }
- return 0;
-}
-
-static void setup_handle(char *base_url, CURLM *m, int handlenum)
-{
- char urlbuf[256];
-
- msnprintf(urlbuf, sizeof(urlbuf), "%s%s", base_url, urlstring[handlenum]);
- curl_easy_setopt(handles[handlenum], CURLOPT_URL, urlbuf);
- curl_easy_setopt(handles[handlenum], CURLOPT_VERBOSE, 1L);
- curl_easy_setopt(handles[handlenum], CURLOPT_FAILONERROR, 1L);
- curl_easy_setopt(handles[handlenum], CURLOPT_WRITEFUNCTION, write_callback);
- curl_easy_setopt(handles[handlenum], CURLOPT_WRITEDATA, NULL);
- curl_multi_add_handle(m, handles[handlenum]);
-}
-
-static void remove_handles(void)
-{
- int i;
-
- for(i = 0; i < num_handles; i++) {
- if(handles[i])
- curl_easy_cleanup(handles[i]);
- }
-}
-
-int test(char *URL)
-{
- int res = 0;
- CURLM *m = NULL;
- CURLMsg *msg; /* for picking up messages with the transfer status */
- int msgs_left; /* how many messages are left */
- int running = 0;
- int handlenum = 0;
- struct timeval last_handle_add;
-
- if(parse_url_file(libtest_arg2) <= 0)
- goto test_cleanup;
-
- start_test_timing();
-
- curl_global_init(CURL_GLOBAL_ALL);
-
- multi_init(m);
-
- create_handles();
-
- multi_setopt(m, CURLMOPT_PIPELINING, 1L);
- multi_setopt(m, CURLMOPT_MAX_HOST_CONNECTIONS, 2L);
- multi_setopt(m, CURLMOPT_MAX_PIPELINE_LENGTH, 3L);
- multi_setopt(m, CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, 15000L);
- multi_setopt(m, CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, 10000L);
-
- multi_setopt(m, CURLMOPT_PIPELINING_SITE_BL, site_blocklist);
- multi_setopt(m, CURLMOPT_PIPELINING_SERVER_BL, server_blocklist);
-
- last_handle_add = tutil_tvnow();
-
- for(;;) {
- struct timeval interval;
- struct timeval now;
- fd_set rd, wr, exc;
- int maxfd = -99;
- long timeout;
-
- interval.tv_sec = 1;
- interval.tv_usec = 0;
-
- if(handlenum < num_handles) {
- now = tutil_tvnow();
- if(tutil_tvdiff(now, last_handle_add) >= urltime[handlenum]) {
- fprintf(stdout, "Adding handle %d\n", handlenum);
- setup_handle(URL, m, handlenum);
- last_handle_add = now;
- handlenum++;
- }
- }
-
- curl_multi_perform(m, &running);
-
- abort_on_test_timeout();
-
- /* See how the transfers went */
- do {
- msg = curl_multi_info_read(m, &msgs_left);
- if(msg && msg->msg == CURLMSG_DONE) {
- int i;
-
- /* Find out which handle this message is about */
- for(i = 0; i < num_handles; i++) {
- int found = (msg->easy_handle == handles[i]);
- if(found)
- break;
- }
-
- printf("Handle %d Completed with status %d\n", i, msg->data.result);
- curl_multi_remove_handle(m, handles[i]);
- }
- } while(msg);
-
- if(handlenum == num_handles && !running) {
- break; /* done */
- }
-
- FD_ZERO(&rd);
- FD_ZERO(&wr);
- FD_ZERO(&exc);
-
- curl_multi_fdset(m, &rd, &wr, &exc, &maxfd);
-
- /* At this point, maxfd is guaranteed to be greater or equal than -1. */
-
- curl_multi_timeout(m, &timeout);
-
- if(timeout < 0)
- timeout = 1;
-
- interval.tv_sec = timeout / 1000;
- interval.tv_usec = (timeout % 1000) * 1000;
-
- interval.tv_sec = 0;
- interval.tv_usec = 1000;
-
- select_test(maxfd + 1, &rd, &wr, &exc, &interval);
-
- abort_on_test_timeout();
- }
-
-test_cleanup:
-
- remove_handles();
-
- /* undocumented cleanup sequence - type UB */
-
- curl_multi_cleanup(m);
- curl_global_cleanup();
-
- free_urls();
- return res;
-}
diff --git a/lib/vquic/msh3.h b/tests/libtest/lib1903.c
similarity index 60%
copy from lib/vquic/msh3.h
copy to tests/libtest/lib1903.c
index ce884d9..79baa17 100644
--- a/lib/vquic/msh3.h
+++ b/tests/libtest/lib1903.c
@@ -1,5 +1,3 @@
-#ifndef HEADER_CURL_VQUIC_MSH3_H
-#define HEADER_CURL_VQUIC_MSH3_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,18 +21,35 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
+#include "test.h"
-#include "curl_setup.h"
+#include "testutil.h"
+#include "timediff.h"
+#include "warnless.h"
+#include "memdebug.h"
-#ifdef USE_MSH3
+int test(char *URL)
+{
+ CURL *ch = NULL;
+ curl_global_init(CURL_GLOBAL_ALL);
-#include <msh3.h>
+ ch = curl_easy_init();
+ if(!ch)
+ goto cleanup;
-struct quicsocket {
- MSH3_API* api;
- MSH3_CONNECTION* conn;
-};
+ curl_easy_setopt(ch, CURLOPT_URL, URL);
+ curl_easy_setopt(ch, CURLOPT_COOKIEFILE, libtest_arg2);
+ curl_easy_perform(ch);
-#endif /* USE_MSQUIC */
+ curl_easy_reset(ch);
-#endif /* HEADER_CURL_VQUIC_MSH3_H */
+ curl_easy_setopt(ch, CURLOPT_URL, URL);
+ curl_easy_setopt(ch, CURLOPT_COOKIEFILE, libtest_arg2);
+ curl_easy_perform(ch);
+
+cleanup:
+ curl_easy_cleanup(ch);
+ curl_global_cleanup();
+
+ return 0;
+}
diff --git a/tests/libtest/lib1905.c b/tests/libtest/lib1905.c
index 162dea2..62b9c60 100644
--- a/tests/libtest/lib1905.c
+++ b/tests/libtest/lib1905.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -55,8 +55,8 @@
curl_easy_setopt(ch, CURLOPT_SHARE, sh);
curl_easy_setopt(ch, CURLOPT_URL, URL);
- curl_easy_setopt(ch, CURLOPT_COOKIEFILE, "log/cookies1905");
- curl_easy_setopt(ch, CURLOPT_COOKIEJAR, "log/cookies1905");
+ curl_easy_setopt(ch, CURLOPT_COOKIEFILE, libtest_arg2);
+ curl_easy_setopt(ch, CURLOPT_COOKIEJAR, libtest_arg2);
curl_multi_add_handle(cm, ch);
@@ -90,7 +90,7 @@
curl_easy_setopt(ch, CURLOPT_SHARE, NULL);
curl_multi_remove_handle(cm, ch);
- cleanup:
+cleanup:
curl_easy_cleanup(ch);
curl_share_cleanup(sh);
curl_multi_cleanup(cm);
diff --git a/tests/libtest/lib1906.c b/tests/libtest/lib1906.c
index 80bb3ce..c0d485f 100644
--- a/tests/libtest/lib1906.c
+++ b/tests/libtest/lib1906.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -39,7 +39,7 @@
curl_easy_setopt(curl, CURLOPT_CURLU, curlu);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
- /* set a port number that makes this reqeuest fail */
+ /* set a port number that makes this request fail */
curl_easy_setopt(curl, CURLOPT_PORT, 1L);
curl_code = curl_easy_perform(curl);
if(!curl_code)
diff --git a/tests/libtest/lib1907.c b/tests/libtest/lib1907.c
index f0d035a..d0876dc 100644
--- a/tests/libtest/lib1907.c
+++ b/tests/libtest/lib1907.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1908.c b/tests/libtest/lib1908.c
index 17d0e3f..ff92daf 100644
--- a/tests/libtest/lib1908.c
+++ b/tests/libtest/lib1908.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2022, Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) Linus Nielsen Feltzing, <linus@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -39,7 +39,7 @@
if(hnd) {
curl_easy_setopt(hnd, CURLOPT_URL, URL);
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
- curl_easy_setopt(hnd, CURLOPT_ALTSVC, "log/altsvc-1908");
+ curl_easy_setopt(hnd, CURLOPT_ALTSVC, libtest_arg2);
ret = curl_easy_perform(hnd);
if(!ret) {
diff --git a/tests/libtest/lib1910.c b/tests/libtest/lib1910.c
index 8bb319d..fed1ca2 100644
--- a/tests/libtest/lib1910.c
+++ b/tests/libtest/lib1910.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2022, Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) Linus Nielsen Feltzing, <linus@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1911.c b/tests/libtest/lib1911.c
index e78f644..b7c50fc 100644
--- a/tests/libtest/lib1911.c
+++ b/tests/libtest/lib1911.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,7 +47,7 @@
return 1;
}
- /* make it a zero terminated C string with just As */
+ /* make it a null-terminated C string with just As */
memset(buffer, 'A', MAX_INPUT_LENGTH + 1);
buffer[MAX_INPUT_LENGTH + 1] = 0;
@@ -61,16 +61,18 @@
/*
* Whitelist string options that are safe for abuse
*/
- switch(o->id) {
- case CURLOPT_PROXY_TLSAUTH_TYPE:
- case CURLOPT_TLSAUTH_TYPE:
- case CURLOPT_RANDOM_FILE:
- case CURLOPT_EGDSOCKET:
- continue;
- default:
- /* check this */
- break;
- }
+ CURL_IGNORE_DEPRECATION(
+ switch(o->id) {
+ case CURLOPT_PROXY_TLSAUTH_TYPE:
+ case CURLOPT_TLSAUTH_TYPE:
+ case CURLOPT_RANDOM_FILE:
+ case CURLOPT_EGDSOCKET:
+ continue;
+ default:
+ /* check this */
+ break;
+ }
+ )
/* This is a string. Make sure that passing in a string longer
CURL_MAX_INPUT_LENGTH returns an error */
@@ -79,6 +81,7 @@
case CURLE_BAD_FUNCTION_ARGUMENT: /* the most normal */
case CURLE_UNKNOWN_OPTION: /* left out from the build */
case CURLE_NOT_BUILT_IN: /* not supported */
+ case CURLE_UNSUPPORTED_PROTOCOL: /* detected by protocol2num() */
break;
default:
/* all other return codes are unexpected */
diff --git a/tests/libtest/lib1912.c b/tests/libtest/lib1912.c
index d42f80f..13f25bc 100644
--- a/tests/libtest/lib1912.c
+++ b/tests/libtest/lib1912.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -39,42 +39,44 @@
for(o = curl_easy_option_next(NULL);
o;
o = curl_easy_option_next(o)) {
- /* Test for mismatch OR missing typecheck macros */
- if(curlcheck_long_option(o->id) !=
- (o->type == CURLOT_LONG || o->type == CURLOT_VALUES)) {
- print_err(o->name, "CURLOT_LONG or CURLOT_VALUES");
- error++;
- }
- if(curlcheck_off_t_option(o->id) != (o->type == CURLOT_OFF_T)) {
- print_err(o->name, "CURLOT_OFF_T");
- error++;
- }
- if(curlcheck_string_option(o->id) != (o->type == CURLOT_STRING)) {
- print_err(o->name, "CURLOT_STRING");
- error++;
- }
- if(curlcheck_slist_option(o->id) != (o->type == CURLOT_SLIST)) {
- print_err(o->name, "CURLOT_SLIST");
- error++;
- }
- if(curlcheck_cb_data_option(o->id) != (o->type == CURLOT_CBPTR)) {
- print_err(o->name, "CURLOT_CBPTR");
- error++;
- }
- /* From here: only test that the type matches if macro is known */
- if(curlcheck_write_cb_option(o->id) && (o->type != CURLOT_FUNCTION)) {
- print_err(o->name, "CURLOT_FUNCTION");
- error++;
- }
- if(curlcheck_conv_cb_option(o->id) && (o->type != CURLOT_FUNCTION)) {
- print_err(o->name, "CURLOT_FUNCTION");
- error++;
- }
- if(curlcheck_postfields_option(o->id) && (o->type != CURLOT_OBJECT)) {
- print_err(o->name, "CURLOT_OBJECT");
- error++;
- }
- /* Todo: no gcc typecheck for CURLOPTTYPE_BLOB types? */
+ CURL_IGNORE_DEPRECATION(
+ /* Test for mismatch OR missing typecheck macros */
+ if(curlcheck_long_option(o->id) !=
+ (o->type == CURLOT_LONG || o->type == CURLOT_VALUES)) {
+ print_err(o->name, "CURLOT_LONG or CURLOT_VALUES");
+ error++;
+ }
+ if(curlcheck_off_t_option(o->id) != (o->type == CURLOT_OFF_T)) {
+ print_err(o->name, "CURLOT_OFF_T");
+ error++;
+ }
+ if(curlcheck_string_option(o->id) != (o->type == CURLOT_STRING)) {
+ print_err(o->name, "CURLOT_STRING");
+ error++;
+ }
+ if(curlcheck_slist_option(o->id) != (o->type == CURLOT_SLIST)) {
+ print_err(o->name, "CURLOT_SLIST");
+ error++;
+ }
+ if(curlcheck_cb_data_option(o->id) != (o->type == CURLOT_CBPTR)) {
+ print_err(o->name, "CURLOT_CBPTR");
+ error++;
+ }
+ /* From here: only test that the type matches if macro is known */
+ if(curlcheck_write_cb_option(o->id) && (o->type != CURLOT_FUNCTION)) {
+ print_err(o->name, "CURLOT_FUNCTION");
+ error++;
+ }
+ if(curlcheck_conv_cb_option(o->id) && (o->type != CURLOT_FUNCTION)) {
+ print_err(o->name, "CURLOT_FUNCTION");
+ error++;
+ }
+ if(curlcheck_postfields_option(o->id) && (o->type != CURLOT_OBJECT)) {
+ print_err(o->name, "CURLOT_OBJECT");
+ error++;
+ }
+ /* Todo: no gcc typecheck for CURLOPTTYPE_BLOB types? */
+ )
}
#endif
(void)URL;
diff --git a/tests/libtest/lib1913.c b/tests/libtest/lib1913.c
index 3662f98..a283863 100644
--- a/tests/libtest/lib1913.c
+++ b/tests/libtest/lib1913.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1915.c b/tests/libtest/lib1915.c
index 5e5aace..1776b26 100644
--- a/tests/libtest/lib1915.c
+++ b/tests/libtest/lib1915.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1916.c b/tests/libtest/lib1916.c
index 7a251bf..b97263c 100644
--- a/tests/libtest/lib1916.c
+++ b/tests/libtest/lib1916.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1918.c b/tests/libtest/lib1918.c
index 209eef5..34c3608 100644
--- a/tests/libtest/lib1918.c
+++ b/tests/libtest/lib1918.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1919.c b/tests/libtest/lib1919.c
index fce4cb0..39ba1d9 100644
--- a/tests/libtest/lib1919.c
+++ b/tests/libtest/lib1919.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1933.c b/tests/libtest/lib1933.c
index 3ff2dc1..cc3af07 100644
--- a/tests/libtest/lib1933.c
+++ b/tests/libtest/lib1933.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,6 +29,7 @@
{
CURL *curl;
CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *connect_to = NULL;
struct curl_slist *list = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
@@ -47,6 +48,10 @@
test_setopt(curl, CURLOPT_AWS_SIGV4, "xxx");
test_setopt(curl, CURLOPT_HEADER, 0L);
test_setopt(curl, CURLOPT_URL, URL);
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
list = curl_slist_append(list, "Content-Type: application/json");
test_setopt(curl, CURLOPT_HTTPHEADER, list);
@@ -54,6 +59,7 @@
test_cleanup:
+ curl_slist_free_all(connect_to);
curl_slist_free_all(list);
curl_easy_cleanup(curl);
curl_global_cleanup();
diff --git a/tests/libtest/lib1934.c b/tests/libtest/lib1934.c
index d5f3884..36fc8f7 100644
--- a/tests/libtest/lib1934.c
+++ b/tests/libtest/lib1934.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,6 +29,7 @@
{
CURL *curl;
CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *connect_to = NULL;
struct curl_slist *list = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
@@ -48,6 +49,10 @@
test_setopt(curl, CURLOPT_USERPWD, "xxx:yyy");
test_setopt(curl, CURLOPT_HEADER, 0L);
test_setopt(curl, CURLOPT_URL, URL);
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
list = curl_slist_append(list, "Content-Type: application/json");
test_setopt(curl, CURLOPT_HTTPHEADER, list);
@@ -55,6 +60,7 @@
test_cleanup:
+ curl_slist_free_all(connect_to);
curl_slist_free_all(list);
curl_easy_cleanup(curl);
curl_global_cleanup();
diff --git a/tests/libtest/lib1935.c b/tests/libtest/lib1935.c
index e27be12..ee52d44 100644
--- a/tests/libtest/lib1935.c
+++ b/tests/libtest/lib1935.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,6 +29,7 @@
{
CURL *curl;
CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *connect_to = NULL;
struct curl_slist *list = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
@@ -48,6 +49,10 @@
test_setopt(curl, CURLOPT_USERPWD, "xxx:yyy");
test_setopt(curl, CURLOPT_HEADER, 0L);
test_setopt(curl, CURLOPT_URL, URL);
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
list = curl_slist_append(list, "Content-Type: application/json");
test_setopt(curl, CURLOPT_HTTPHEADER, list);
@@ -55,6 +60,7 @@
test_cleanup:
+ curl_slist_free_all(connect_to);
curl_slist_free_all(list);
curl_easy_cleanup(curl);
curl_global_cleanup();
diff --git a/tests/libtest/lib1936.c b/tests/libtest/lib1936.c
index 703e740..b86eee7 100644
--- a/tests/libtest/lib1936.c
+++ b/tests/libtest/lib1936.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,6 +29,7 @@
{
CURL *curl;
CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *connect_to = NULL;
struct curl_slist *list = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
@@ -48,6 +49,10 @@
test_setopt(curl, CURLOPT_USERPWD, "xxx:yyy");
test_setopt(curl, CURLOPT_HEADER, 0L);
test_setopt(curl, CURLOPT_URL, URL);
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
list = curl_slist_append(list, "Content-Type: application/json");
test_setopt(curl, CURLOPT_HTTPHEADER, list);
@@ -55,6 +60,7 @@
test_cleanup:
+ curl_slist_free_all(connect_to);
curl_slist_free_all(list);
curl_easy_cleanup(curl);
curl_global_cleanup();
diff --git a/tests/libtest/lib1937.c b/tests/libtest/lib1937.c
index b2d4518..7424966 100644
--- a/tests/libtest/lib1937.c
+++ b/tests/libtest/lib1937.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,6 +30,7 @@
{
CURL *curl;
CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *connect_to = NULL;
struct curl_slist *list = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
@@ -50,6 +51,10 @@
test_setopt(curl, CURLOPT_USERPWD, "keyId:SecretKey");
test_setopt(curl, CURLOPT_HEADER, 0L);
test_setopt(curl, CURLOPT_URL, URL);
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
list = curl_slist_append(list, "Content-Type: application/json");
test_setopt(curl, CURLOPT_HTTPHEADER, list);
test_setopt(curl, CURLOPT_POSTFIELDS, "postData");
@@ -58,6 +63,7 @@
test_cleanup:
+ curl_slist_free_all(connect_to);
curl_slist_free_all(list);
curl_easy_cleanup(curl);
curl_global_cleanup();
diff --git a/tests/libtest/lib1938.c b/tests/libtest/lib1938.c
index 3bbde8c..4b5218b 100644
--- a/tests/libtest/lib1938.c
+++ b/tests/libtest/lib1938.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,6 +30,7 @@
{
CURL *curl;
CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *connect_to = NULL;
struct curl_slist *list = NULL;
unsigned char data[] = {0x70, 0x6f, 0x73, 0x74, 0, 0x44, 0x61, 0x74, 0x61};
@@ -51,6 +52,10 @@
test_setopt(curl, CURLOPT_USERPWD, "keyId:SecretKey");
test_setopt(curl, CURLOPT_HEADER, 0L);
test_setopt(curl, CURLOPT_URL, URL);
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
list = curl_slist_append(list, "Content-Type: application/json");
test_setopt(curl, CURLOPT_HTTPHEADER, list);
test_setopt(curl, CURLOPT_POSTFIELDS, data);
@@ -60,6 +65,7 @@
test_cleanup:
+ curl_slist_free_all(connect_to);
curl_slist_free_all(list);
curl_easy_cleanup(curl);
curl_global_cleanup();
diff --git a/tests/libtest/lib1939.c b/tests/libtest/lib1939.c
index 1c88f68..4adc876 100644
--- a/tests/libtest/lib1939.c
+++ b/tests/libtest/lib1939.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1940.c b/tests/libtest/lib1940.c
index c2c91b5..5e90f6a 100644
--- a/tests/libtest/lib1940.c
+++ b/tests/libtest/lib1940.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1945.c b/tests/libtest/lib1945.c
index fad99ba..1b658b0 100644
--- a/tests/libtest/lib1945.c
+++ b/tests/libtest/lib1945.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib1947.c b/tests/libtest/lib1947.c
new file mode 100644
index 0000000..b9b4007
--- /dev/null
+++ b/tests/libtest/lib1947.c
@@ -0,0 +1,89 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "test.h"
+
+#include "memdebug.h"
+
+static size_t writecb(char *data, size_t n, size_t l, void *userp)
+{
+ /* ignore the data */
+ (void)data;
+ (void)userp;
+ return n*l;
+}
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+
+ curl = curl_easy_init();
+ if(curl) {
+ struct curl_header *h;
+ int count = 0;
+ int origins;
+
+ /* perform a request that involves redirection */
+ curl_easy_setopt(curl, CURLOPT_URL, URL);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+ res = curl_easy_perform(curl);
+ if(res)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* count the number of requests by reading the first header of each
+ request. */
+ origins = (CURLH_HEADER|CURLH_TRAILER|CURLH_CONNECT|
+ CURLH_1XX|CURLH_PSEUDO);
+ do {
+ h = curl_easy_nextheader(curl, origins, count, NULL);
+ if(h)
+ count++;
+ } while(h);
+ printf("count = %u\n", count);
+
+ /* perform another request - without redirect */
+ curl_easy_setopt(curl, CURLOPT_URL, libtest_arg2);
+ res = curl_easy_perform(curl);
+ if(res)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* count the number of requests again. */
+ count = 0;
+ do {
+ h = curl_easy_nextheader(curl, origins, count, NULL);
+ if(h)
+ count++;
+ } while(h);
+ printf("count = %u\n", count);
+ curl_easy_cleanup(curl);
+ }
+
+ curl_global_cleanup();
+ return 0;
+}
diff --git a/tests/libtest/lib1948.c b/tests/libtest/lib1948.c
new file mode 100644
index 0000000..4ee565e
--- /dev/null
+++ b/tests/libtest/lib1948.c
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "test.h"
+
+typedef struct
+{
+ char *buf;
+ size_t len;
+} put_buffer;
+
+static size_t put_callback(char *ptr, size_t size, size_t nmemb, void *stream)
+{
+ put_buffer *putdata = (put_buffer *)stream;
+ size_t totalsize = size * nmemb;
+ size_t tocopy = (putdata->len < totalsize) ? putdata->len : totalsize;
+ memcpy(ptr, putdata->buf, tocopy);
+ putdata->len -= tocopy;
+ putdata->buf += tocopy;
+ return tocopy;
+}
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OUT_OF_MEMORY;
+
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+
+ curl = curl_easy_init();
+ if(curl) {
+ const char *testput = "This is test PUT data\n";
+ put_buffer pbuf;
+
+ /* PUT */
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, put_callback);
+ pbuf.buf = (char *)testput;
+ pbuf.len = strlen(testput);
+ curl_easy_setopt(curl, CURLOPT_READDATA, &pbuf);
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, (long)strlen(testput));
+ res = curl_easy_setopt(curl, CURLOPT_URL, URL);
+ if(!res)
+ res = curl_easy_perform(curl);
+ if(!res) {
+ /* POST */
+ curl_easy_setopt(curl, CURLOPT_POST, 1L);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, testput);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(testput));
+ res = curl_easy_perform(curl);
+ }
+ curl_easy_cleanup(curl);
+ }
+
+ curl_global_cleanup();
+ return (int)res;
+}
diff --git a/tests/libtest/lib1955.c b/tests/libtest/lib1955.c
new file mode 100644
index 0000000..d92582b
--- /dev/null
+++ b/tests/libtest/lib1955.c
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *list = NULL;
+ struct curl_slist *connect_to = NULL;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_AWS_SIGV4, "xxx");
+ test_setopt(curl, CURLOPT_USERPWD, "xxx");
+ test_setopt(curl, CURLOPT_HEADER, 0L);
+ test_setopt(curl, CURLOPT_URL, URL);
+ list = curl_slist_append(list, "test2: 1234");
+ if(!list)
+ goto test_cleanup;
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
+ curl_slist_append(list, "Content-Type: application/json");
+ curl_slist_append(list, "test1:");
+ curl_slist_append(list, "test0");
+ curl_slist_append(list, "test_space: t\ts m\t end ");
+ curl_slist_append(list, "tesMixCase: MixCase");
+ test_setopt(curl, CURLOPT_HTTPHEADER, list);
+
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ curl_slist_free_all(connect_to);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib1956.c b/tests/libtest/lib1956.c
new file mode 100644
index 0000000..105418d
--- /dev/null
+++ b/tests/libtest/lib1956.c
@@ -0,0 +1,73 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *list = NULL;
+ struct curl_slist *connect_to = NULL;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_AWS_SIGV4, "xxx");
+ test_setopt(curl, CURLOPT_USERPWD, "xxx");
+ test_setopt(curl, CURLOPT_HEADER, 0L);
+ test_setopt(curl, CURLOPT_URL, URL);
+ list = curl_slist_append(list, "Content-Type: application/json");
+ if(!list)
+ goto test_cleanup;
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
+ curl_slist_append(list, "X-Xxx-Content-Sha256: "
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+ test_setopt(curl, CURLOPT_HTTPHEADER, list);
+
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ curl_slist_free_all(connect_to);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib1957.c b/tests/libtest/lib1957.c
new file mode 100644
index 0000000..8397d9d
--- /dev/null
+++ b/tests/libtest/lib1957.c
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *list = NULL;
+ struct curl_slist *connect_to = NULL;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_AWS_SIGV4, "xxx");
+ test_setopt(curl, CURLOPT_USERPWD, "xxx");
+ test_setopt(curl, CURLOPT_HEADER, 0L);
+ test_setopt(curl, CURLOPT_URL, URL);
+ list = curl_slist_append(list, "Content-Type: application/json");
+ if(!list)
+ goto test_cleanup;
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
+ curl_slist_append(list, "X-Xxx-Content-Sha256: arbitrary");
+ test_setopt(curl, CURLOPT_HTTPHEADER, list);
+
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ curl_slist_free_all(connect_to);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib1958.c b/tests/libtest/lib1958.c
new file mode 100644
index 0000000..66b8d5d
--- /dev/null
+++ b/tests/libtest/lib1958.c
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *list = NULL;
+ struct curl_slist *connect_to = NULL;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_AWS_SIGV4, "xxx");
+ test_setopt(curl, CURLOPT_USERPWD, "xxx");
+ test_setopt(curl, CURLOPT_HEADER, 0L);
+ test_setopt(curl, CURLOPT_URL, URL);
+ list = curl_slist_append(list, "Content-Type: application/json");
+ if(!list)
+ goto test_cleanup;
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
+ curl_slist_append(list, "X-Xxx-Content-Sha256: \tarbitrary ");
+ test_setopt(curl, CURLOPT_HTTPHEADER, list);
+
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ curl_slist_free_all(connect_to);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib1959.c b/tests/libtest/lib1959.c
new file mode 100644
index 0000000..5eee4f0
--- /dev/null
+++ b/tests/libtest/lib1959.c
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *list = NULL;
+ struct curl_slist *connect_to = NULL;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_AWS_SIGV4, "xxx");
+ test_setopt(curl, CURLOPT_USERPWD, "xxx");
+ test_setopt(curl, CURLOPT_HEADER, 0L);
+ test_setopt(curl, CURLOPT_URL, URL);
+ list = curl_slist_append(list, "Content-Type: application/json");
+ if(!list)
+ goto test_cleanup;
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
+ curl_slist_append(list, "X-Xxx-Content-Sha256: "
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+ test_setopt(curl, CURLOPT_HTTPHEADER, list);
+
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ curl_slist_free_all(connect_to);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib1960.c b/tests/libtest/lib1960.c
new file mode 100644
index 0000000..fc2f4b0
--- /dev/null
+++ b/tests/libtest/lib1960.c
@@ -0,0 +1,155 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#ifdef HAVE_INET_PTON
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include "memdebug.h"
+
+/* to prevent libcurl from closing our socket */
+static int closesocket_cb(void *clientp, curl_socket_t item)
+{
+ (void)clientp;
+ (void)item;
+ return 0;
+}
+
+/* provide our own socket */
+static curl_socket_t socket_cb(void *clientp,
+ curlsocktype purpose,
+ struct curl_sockaddr *address)
+{
+ int s = *(int *)clientp;
+ (void)purpose;
+ (void)address;
+ return (curl_socket_t)s;
+}
+
+/* tell libcurl the socket is connected */
+static int sockopt_cb(void *clientp,
+ curl_socket_t curlfd,
+ curlsocktype purpose)
+{
+ (void)clientp;
+ (void)curlfd;
+ (void)purpose;
+ return CURL_SOCKOPT_ALREADY_CONNECTED;
+}
+
+/* Expected args: URL IP PORT */
+int test(char *URL)
+{
+ CURL *curl = NULL;
+ CURLcode res = TEST_ERR_MAJOR_BAD;
+ int status;
+ curl_socket_t client_fd = CURL_SOCKET_BAD;
+ struct sockaddr_in serv_addr;
+ unsigned short port;
+
+ if(!strcmp("check", URL))
+ return 0; /* no output makes it not skipped */
+
+ port = (unsigned short)atoi(libtest_arg3);
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ /*
+ * This code connects to the TCP port "manually" so that we then can hand
+ * over this socket as "already connected" to libcurl and make sure that
+ * this works.
+ */
+ client_fd = socket(AF_INET, SOCK_STREAM, 0);
+ if(client_fd == CURL_SOCKET_BAD) {
+ fprintf(stderr, "socket creation error\n");
+ goto test_cleanup;
+ }
+
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_port = htons(port);
+
+ if(inet_pton(AF_INET, libtest_arg2, &serv_addr.sin_addr) <= 0) {
+ fprintf(stderr, "inet_pton failed\n");
+ goto test_cleanup;
+ }
+
+ status = connect(client_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
+ if(status < 0) {
+ fprintf(stderr, "connection failed\n");
+ goto test_cleanup;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ goto test_cleanup;
+ }
+
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, socket_cb);
+ test_setopt(curl, CURLOPT_OPENSOCKETDATA, &client_fd);
+ test_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_cb);
+ test_setopt(curl, CURLOPT_SOCKOPTDATA, NULL);
+ test_setopt(curl, CURLOPT_CLOSESOCKETFUNCTION, closesocket_cb);
+ test_setopt(curl, CURLOPT_CLOSESOCKETDATA, NULL);
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_HEADER, 1L);
+ test_setopt(curl, CURLOPT_URL, URL);
+
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+ if(client_fd != CURL_SOCKET_BAD)
+ sclose(client_fd);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
+#else
+int test(char *URL)
+{
+ (void)URL;
+ printf("lacks inet_pton\n");
+ return 0;
+}
+#endif
diff --git a/tests/libtest/lib1970.c b/tests/libtest/lib1970.c
new file mode 100644
index 0000000..ff86fdd
--- /dev/null
+++ b/tests/libtest/lib1970.c
@@ -0,0 +1,73 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *list = NULL;
+ struct curl_slist *connect_to = NULL;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_UPLOAD, 1L);
+ test_setopt(curl, CURLOPT_INFILESIZE, 0L);
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_AWS_SIGV4, "aws:amz:us-east-1:s3");
+ test_setopt(curl, CURLOPT_USERPWD, "xxx");
+ test_setopt(curl, CURLOPT_HEADER, 0L);
+ test_setopt(curl, CURLOPT_URL, URL);
+ list = curl_slist_append(list, "Content-Type: application/json");
+ if(!list)
+ goto test_cleanup;
+ test_setopt(curl, CURLOPT_HTTPHEADER, list);
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
+
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ curl_slist_free_all(connect_to);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib1971.c b/tests/libtest/lib1971.c
new file mode 100644
index 0000000..173fc2f
--- /dev/null
+++ b/tests/libtest/lib1971.c
@@ -0,0 +1,83 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+static size_t read_callback(char *buffer, size_t size, size_t nitems,
+ void *userdata)
+{
+ (void)buffer; /* unused */
+ (void)size; /* unused */
+ (void)nitems; /* unused */
+ (void)userdata; /* unused */
+ return 0;
+}
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *list = NULL;
+ struct curl_slist *connect_to = NULL;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_UPLOAD, 1L);
+ test_setopt(curl, CURLOPT_READFUNCTION, read_callback);
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_AWS_SIGV4, "aws:amz:us-east-1:s3");
+ test_setopt(curl, CURLOPT_USERPWD, "xxx");
+ test_setopt(curl, CURLOPT_HEADER, 0L);
+ test_setopt(curl, CURLOPT_URL, URL);
+ list = curl_slist_append(list, "Content-Type: application/json");
+ if(!list)
+ goto test_cleanup;
+ test_setopt(curl, CURLOPT_HTTPHEADER, list);
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
+
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ curl_slist_free_all(connect_to);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib1972.c b/tests/libtest/lib1972.c
new file mode 100644
index 0000000..c21e8da
--- /dev/null
+++ b/tests/libtest/lib1972.c
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURL *curl;
+ curl_mime *mime = NULL;
+ curl_mimepart *part = NULL;
+ CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *list = NULL;
+ struct curl_slist *connect_to = NULL;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ mime = curl_mime_init(curl);
+ if(!mime)
+ goto test_cleanup;
+ part = curl_mime_addpart(mime);
+ if(!part)
+ goto test_cleanup;
+ curl_mime_name(part, "foo");
+ curl_mime_data(part, "bar", CURL_ZERO_TERMINATED);
+
+ test_setopt(curl, CURLOPT_MIMEPOST, mime);
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_AWS_SIGV4, "aws:amz:us-east-1:s3");
+ test_setopt(curl, CURLOPT_USERPWD, "xxx");
+ test_setopt(curl, CURLOPT_HEADER, 0L);
+ test_setopt(curl, CURLOPT_URL, URL);
+ list = curl_slist_append(list, "Content-Type: application/json");
+ if(!list)
+ goto test_cleanup;
+ test_setopt(curl, CURLOPT_HTTPHEADER, list);
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
+
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ curl_slist_free_all(connect_to);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ curl_mime_free(mime);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib1973.c b/tests/libtest/lib1973.c
new file mode 100644
index 0000000..d95744f
--- /dev/null
+++ b/tests/libtest/lib1973.c
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *list = NULL;
+ struct curl_slist *connect_to = NULL;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_POSTFIELDS, "post fields\n");
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_AWS_SIGV4, "aws:amz:us-east-1:s3");
+ test_setopt(curl, CURLOPT_USERPWD, "xxx");
+ test_setopt(curl, CURLOPT_HEADER, 0L);
+ test_setopt(curl, CURLOPT_URL, URL);
+ list = curl_slist_append(list, "Content-Type: application/json");
+ if(!list)
+ goto test_cleanup;
+ test_setopt(curl, CURLOPT_HTTPHEADER, list);
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
+
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ curl_slist_free_all(connect_to);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib1974.c b/tests/libtest/lib1974.c
new file mode 100644
index 0000000..948d44d
--- /dev/null
+++ b/tests/libtest/lib1974.c
@@ -0,0 +1,65 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *connect_to = NULL;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_AWS_SIGV4, "aws:amz:us-east-1:s3");
+ test_setopt(curl, CURLOPT_USERPWD, "xxx");
+ test_setopt(curl, CURLOPT_HEADER, 0L);
+ test_setopt(curl, CURLOPT_URL, URL);
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
+
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ curl_slist_free_all(connect_to);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib1975.c b/tests/libtest/lib1975.c
new file mode 100644
index 0000000..bca0c76
--- /dev/null
+++ b/tests/libtest/lib1975.c
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+static size_t read_callback(char *buffer, size_t size, size_t nitems,
+ void *userdata)
+{
+ (void)buffer; /* unused */
+ (void)size; /* unused */
+ (void)nitems; /* unused */
+ (void)userdata; /* unused */
+ return 0;
+}
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = TEST_ERR_MAJOR_BAD;
+ struct curl_slist *list = NULL;
+ struct curl_slist *connect_to = NULL;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_UPLOAD, 1L);
+ test_setopt(curl, CURLOPT_READFUNCTION, read_callback);
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_AWS_SIGV4, "aws:amz:us-east-1:s3");
+ test_setopt(curl, CURLOPT_USERPWD, "xxx");
+ test_setopt(curl, CURLOPT_HEADER, 0L);
+ test_setopt(curl, CURLOPT_URL, URL);
+ list = curl_slist_append(list, "Content-Type: application/json");
+ if(!list)
+ goto test_cleanup;
+ curl_slist_append(list, "X-Amz-Content-Sha256: "
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+ test_setopt(curl, CURLOPT_HTTPHEADER, list);
+ if(libtest_arg2) {
+ connect_to = curl_slist_append(connect_to, libtest_arg2);
+ }
+ test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
+
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ curl_slist_free_all(connect_to);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib2301.c b/tests/libtest/lib2301.c
new file mode 100644
index 0000000..17afb5f
--- /dev/null
+++ b/tests/libtest/lib2301.c
@@ -0,0 +1,154 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "test.h"
+
+#ifdef USE_WEBSOCKETS
+#if 0
+
+static int ping(CURL *curl, const char *send_payload)
+{
+ size_t sent;
+ CURLcode result =
+ curl_ws_send(curl, send_payload, strlen(send_payload), &sent, CURLWS_PING);
+ fprintf(stderr,
+ "ws: curl_ws_send returned %u, sent %u\n", (int)result, (int)sent);
+
+ return (int)result;
+}
+
+static int recv_pong(CURL *curl, const char *exected_payload)
+{
+ size_t rlen;
+ unsigned int rflags;
+ char buffer[256];
+ CURLcode result =
+ curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &rflags);
+ if(rflags & CURLWS_PONG) {
+ int same = 0;
+ fprintf(stderr, "ws: got PONG back\n");
+ if(rlen == strlen(exected_payload)) {
+ if(!memcmp(exected_payload, buffer, rlen)) {
+ fprintf(stderr, "ws: got the same payload back\n");
+ same = 1;
+ }
+ }
+ if(!same)
+ fprintf(stderr, "ws: did NOT get the same payload back\n");
+ }
+ else {
+ fprintf(stderr, "recv_pong: got %u bytes rflags %x\n", (int)rlen, rflags);
+ }
+ fprintf(stderr, "ws: curl_ws_recv returned %u, received %u\n", (int)result,
+ rlen);
+ return (int)result;
+}
+
+/* just close the connection */
+static void websocket_close(CURL *curl)
+{
+ size_t sent;
+ CURLcode result =
+ curl_ws_send(curl, "", 0, &sent, CURLWS_CLOSE);
+ fprintf(stderr,
+ "ws: curl_ws_send returned %u, sent %u\n", (int)result, (int)sent);
+}
+
+static void websocket(CURL *curl)
+{
+ int i = 0;
+ fprintf(stderr, "ws: websocket() starts\n");
+ do {
+ if(ping(curl, "foobar"))
+ return;
+ if(recv_pong(curl, "foobar"))
+ return;
+ sleep(2);
+ } while(i++ < 10);
+ websocket_close(curl);
+}
+
+#endif
+
+static size_t writecb(char *b, size_t size, size_t nitems, void *p)
+{
+ CURL *easy = p;
+ unsigned char *buffer = (unsigned char *)b;
+ size_t i;
+ size_t sent;
+ unsigned char pong[] = {
+ 0x8a, 0x0
+ };
+ size_t incoming = nitems;
+ fprintf(stderr, "Called CURLOPT_WRITEFUNCTION with %u bytes: ",
+ (int)nitems);
+ for(i = 0; i < nitems; i++)
+ fprintf(stderr, "%02x ", (unsigned char)buffer[i]);
+ fprintf(stderr, "\n");
+ (void)size;
+ if(buffer[0] == 0x89) {
+ CURLcode result;
+ fprintf(stderr, "send back a simple PONG\n");
+ result = curl_ws_send(easy, pong, 2, &sent, 0, 0);
+ if(result)
+ nitems = 0;
+ }
+ if(nitems != incoming)
+ fprintf(stderr, "returns error from callback\n");
+ return nitems;
+}
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, URL);
+
+ /* use the callback style */
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, "webbie-sox/3");
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(curl, CURLOPT_WS_OPTIONS, CURLWS_RAW_MODE);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl);
+ res = curl_easy_perform(curl);
+ fprintf(stderr, "curl_easy_perform() returned %u\n", (int)res);
+#if 0
+ if(res == CURLE_OK)
+ websocket(curl);
+#endif
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ curl_global_cleanup();
+ return (int)res;
+}
+
+#else /* no websockets */
+NO_SUPPORT_BUILT_IN
+#endif
diff --git a/tests/libtest/lib2302.c b/tests/libtest/lib2302.c
new file mode 100644
index 0000000..063c26d
--- /dev/null
+++ b/tests/libtest/lib2302.c
@@ -0,0 +1,156 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "test.h"
+
+#ifdef USE_WEBSOCKETS
+
+#if 0
+
+static int ping(CURL *curl, const char *send_payload)
+{
+ size_t sent;
+ CURLcode result =
+ curl_ws_send(curl, send_payload, strlen(send_payload), &sent, CURLWS_PING);
+ fprintf(stderr,
+ "ws: curl_ws_send returned %u, sent %u\n", (int)result, (int)sent);
+
+ return (int)result;
+}
+
+static int recv_pong(CURL *curl, const char *exected_payload)
+{
+ size_t rlen;
+ unsigned int rflags;
+ char buffer[256];
+ CURLcode result =
+ curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &rflags);
+ if(rflags & CURLWS_PONG) {
+ int same = 0;
+ fprintf(stderr, "ws: got PONG back\n");
+ if(rlen == strlen(exected_payload)) {
+ if(!memcmp(exected_payload, buffer, rlen)) {
+ fprintf(stderr, "ws: got the same payload back\n");
+ same = 1;
+ }
+ }
+ if(!same)
+ fprintf(stderr, "ws: did NOT get the same payload back\n");
+ }
+ else {
+ fprintf(stderr, "recv_pong: got %u bytes rflags %x\n", (int)rlen, rflags);
+ }
+ fprintf(stderr, "ws: curl_ws_recv returned %u, received %u\n", (int)result,
+ rlen);
+ return (int)result;
+}
+
+/* just close the connection */
+static void websocket_close(CURL *curl)
+{
+ size_t sent;
+ CURLcode result =
+ curl_ws_send(curl, "", 0, &sent, CURLWS_CLOSE);
+ fprintf(stderr,
+ "ws: curl_ws_send returned %u, sent %u\n", (int)result, (int)sent);
+}
+
+static void websocket(CURL *curl)
+{
+ int i = 0;
+ fprintf(stderr, "ws: websocket() starts\n");
+ do {
+ if(ping(curl, "foobar"))
+ return;
+ if(recv_pong(curl, "foobar"))
+ return;
+ sleep(2);
+ } while(i++ < 10);
+ websocket_close(curl);
+}
+
+#endif
+
+static size_t writecb(char *buffer, size_t size, size_t nitems, void *p)
+{
+ CURL *easy = p;
+ size_t i;
+ size_t incoming = nitems;
+ const struct curl_ws_frame *meta;
+ (void)size;
+ for(i = 0; i < nitems; i++)
+ printf("%02x ", (unsigned char)buffer[i]);
+ printf("\n");
+
+ meta = curl_ws_meta(easy);
+ if(meta)
+ printf("RECFLAGS: %x\n", meta->flags);
+ else
+ fprintf(stderr, "RECFLAGS: NULL\n");
+
+ /* this assumes we get a simple TEXT frame first */
+ {
+ CURLcode result = CURLE_OK;
+ fprintf(stderr, "send back a TEXT\n");
+ (void)easy;
+ if(result)
+ nitems = 0;
+ }
+ if(nitems != incoming)
+ fprintf(stderr, "returns error from callback\n");
+ return nitems;
+}
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, URL);
+
+ /* use the callback style */
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, "webbie-sox/3");
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl);
+ res = curl_easy_perform(curl);
+ fprintf(stderr, "curl_easy_perform() returned %u\n", (int)res);
+#if 0
+ if(res == CURLE_OK)
+ websocket(curl);
+#endif
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ curl_global_cleanup();
+ return (int)res;
+}
+
+#else
+NO_SUPPORT_BUILT_IN
+#endif
diff --git a/tests/libtest/lib2304.c b/tests/libtest/lib2304.c
new file mode 100644
index 0000000..5e375d8
--- /dev/null
+++ b/tests/libtest/lib2304.c
@@ -0,0 +1,142 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "test.h"
+
+#ifdef USE_WEBSOCKETS
+
+static int ping(CURL *curl, const char *send_payload)
+{
+ size_t sent;
+ CURLcode result =
+ curl_ws_send(curl, send_payload, strlen(send_payload), &sent, 0,
+ CURLWS_PING);
+ fprintf(stderr,
+ "ws: curl_ws_send returned %u, sent %u\n", (int)result, (int)sent);
+
+ return (int)result;
+}
+
+static int recv_pong(CURL *curl, const char *exected_payload)
+{
+ size_t rlen;
+ const struct curl_ws_frame *meta;
+ char buffer[256];
+ CURLcode result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
+ if(!result) {
+ if(meta->flags & CURLWS_PONG) {
+ int same = 0;
+ fprintf(stderr, "ws: got PONG back\n");
+ if(rlen == strlen(exected_payload)) {
+ if(!memcmp(exected_payload, buffer, rlen)) {
+ fprintf(stderr, "ws: got the same payload back\n");
+ same = 1;
+ }
+ }
+ if(!same)
+ fprintf(stderr, "ws: did NOT get the same payload back\n");
+ }
+ else {
+ fprintf(stderr, "recv_pong: got %u bytes rflags %x\n", (int)rlen,
+ meta->flags);
+ }
+ }
+ fprintf(stderr, "ws: curl_ws_recv returned %u, received %u\n", (int)result,
+ rlen);
+ return (int)result;
+}
+
+static int recv_any(CURL *curl)
+{
+ size_t rlen;
+ const struct curl_ws_frame *meta;
+ char buffer[256];
+ CURLcode result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
+ if(result)
+ return result;
+
+ fprintf(stderr, "recv_any: got %u bytes rflags %x\n", (int)rlen,
+ meta->flags);
+ return 0;
+}
+
+/* just close the connection */
+static void websocket_close(CURL *curl)
+{
+ size_t sent;
+ CURLcode result =
+ curl_ws_send(curl, "", 0, &sent, 0, CURLWS_CLOSE);
+ fprintf(stderr,
+ "ws: curl_ws_send returned %u, sent %u\n", (int)result, (int)sent);
+}
+
+static void websocket(CURL *curl)
+{
+ int i = 0;
+ fprintf(stderr, "ws: websocket() starts\n");
+ do {
+ recv_any(curl);
+ fprintf(stderr, "Send ping\n");
+ if(ping(curl, "foobar"))
+ return;
+ fprintf(stderr, "Receive pong\n");
+ if(recv_pong(curl, "foobar")) {
+ printf("Connection closed\n");
+ return;
+ }
+ sleep(2);
+ } while(i++ < 10);
+ websocket_close(curl);
+}
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, URL);
+
+ /* use the callback style */
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, "websocket/2304");
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); /* websocket style */
+ res = curl_easy_perform(curl);
+ fprintf(stderr, "curl_easy_perform() returned %u\n", (int)res);
+ if(res == CURLE_OK)
+ websocket(curl);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ curl_global_cleanup();
+ return (int)res;
+}
+
+#else
+NO_SUPPORT_BUILT_IN
+#endif
diff --git a/tests/libtest/lib2305.c b/tests/libtest/lib2305.c
new file mode 100644
index 0000000..92fb006
--- /dev/null
+++ b/tests/libtest/lib2305.c
@@ -0,0 +1,109 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "test.h"
+#include "testtrace.h"
+
+#ifdef USE_WEBSOCKETS
+
+/* just close the connection */
+static void websocket_close(CURL *curl)
+{
+ size_t sent;
+ CURLcode result =
+ curl_ws_send(curl, "", 0, &sent, 0, CURLWS_CLOSE);
+ fprintf(stderr,
+ "ws: curl_ws_send returned %u, sent %u\n", (int)result, (int)sent);
+}
+
+static void websocket(CURL *curl)
+{
+ char buffer[256];
+ const struct curl_ws_frame *meta;
+ size_t nread;
+ size_t i = 0;
+ FILE *save = fopen(libtest_arg2, FOPEN_WRITETEXT);
+ if(!save)
+ return;
+
+ /* Three 4097-bytes frames are expected, 12291 bytes */
+ while(i < 12291) {
+ CURLcode result =
+ curl_ws_recv(curl, buffer, sizeof(buffer), &nread, &meta);
+ if(result) {
+ if(result == CURLE_AGAIN)
+ /* crude busy-loop */
+ continue;
+ printf("curl_ws_recv returned %d\n", (int)result);
+ return;
+ }
+ printf("%u: nread %u Age %u Flags %x "
+ "Offset %" CURL_FORMAT_CURL_OFF_T " "
+ "Bytesleft %" CURL_FORMAT_CURL_OFF_T "\n",
+ (int)i,
+ nread, meta->age, meta->flags, meta->offset, meta->bytesleft);
+ i += meta->len;
+ fwrite(buffer, 1, nread, save);
+ }
+ fclose(save);
+
+ websocket_close(curl);
+}
+
+extern struct libtest_trace_cfg libtest_debug_config;
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, URL);
+
+ /* use the callback style */
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, "websocket/2304");
+ libtest_debug_config.nohex = 1;
+ libtest_debug_config.tracetime = 1;
+ curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &libtest_debug_config);
+ curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, libtest_debug_cb);
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); /* websocket style */
+ res = curl_easy_perform(curl);
+ fprintf(stderr, "curl_easy_perform() returned %u\n", (int)res);
+ if(res == CURLE_OK)
+ websocket(curl);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ curl_global_cleanup();
+ return (int)res;
+}
+
+#else
+NO_SUPPORT_BUILT_IN
+#endif
diff --git a/tests/libtest/chkdecimalpoint.c b/tests/libtest/lib2306.c
similarity index 64%
rename from tests/libtest/chkdecimalpoint.c
rename to tests/libtest/lib2306.c
index 0ff0b7d..3f186a0 100644
--- a/tests/libtest/chkdecimalpoint.c
+++ b/tests/libtest/lib2306.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,22 +22,29 @@
*
***************************************************************************/
-#include "curl_printf.h"
+#include "test.h"
+#include "testtrace.h"
-#include <string.h>
-#include <locale.h>
+#include <curl/curl.h>
-#define TOTAL_STR_LEN 4
+#define URL2 libtest_arg2
-int main(void)
+int test(char *URL)
{
- char zero[TOTAL_STR_LEN] = {'\0'};
- int chars;
+ /* first a fine GET response, then a bad one */
+ CURL *cl;
+ int res = 0;
- setlocale(LC_NUMERIC, "");
- chars = msnprintf(zero, TOTAL_STR_LEN, "%.1f", 0.0);
- if((chars == (TOTAL_STR_LEN - 1)) && (strcmp(zero, "0.0") == 0))
- return 0;
- else
- return 1;
+ global_init(CURL_GLOBAL_ALL);
+
+ cl = curl_easy_init();
+ curl_easy_setopt(cl, CURLOPT_URL, URL);
+ curl_easy_perform(cl);
+
+ /* re-use handle, do a second transfer */
+ curl_easy_setopt(cl, CURLOPT_URL, URL2);
+ curl_easy_perform(cl);
+ curl_easy_cleanup(cl);
+ curl_global_cleanup();
+ return res;
}
diff --git a/tests/libtest/lib2402.c b/tests/libtest/lib2402.c
new file mode 100644
index 0000000..ab20f92
--- /dev/null
+++ b/tests/libtest/lib2402.c
@@ -0,0 +1,142 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Linus Nielsen Feltzing <linus@haxx.se>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "testutil.h"
+#include "warnless.h"
+#include "memdebug.h"
+
+#define TEST_HANG_TIMEOUT 60 * 1000
+
+#define NUM_HANDLES 4
+
+int test(char *URL)
+{
+ int res = 0;
+ CURL *curl[NUM_HANDLES] = {0};
+ int running;
+ CURLM *m = NULL;
+ int i;
+ char target_url[256];
+ char dnsentry[256];
+ struct curl_slist *slist = NULL;
+ char *port = libtest_arg3;
+ char *address = libtest_arg2;
+
+ (void)URL;
+
+ msnprintf(dnsentry, sizeof(dnsentry), "localhost:%s:%s",
+ port, address);
+ printf("%s\n", dnsentry);
+ slist = curl_slist_append(slist, dnsentry);
+ if(!slist) {
+ fprintf(stderr, "curl_slist_append() failed\n");
+ goto test_cleanup;
+ }
+
+ start_test_timing();
+
+ global_init(CURL_GLOBAL_ALL);
+
+ multi_init(m);
+
+ multi_setopt(m, CURLMOPT_MAXCONNECTS, 1L);
+
+ /* get NUM_HANDLES easy handles */
+ for(i = 0; i < NUM_HANDLES; i++) {
+ /* get an easy handle */
+ easy_init(curl[i]);
+ /* specify target */
+ msnprintf(target_url, sizeof(target_url),
+ "https://localhost:%s/path/2402%04i",
+ port, i + 1);
+ target_url[sizeof(target_url) - 1] = '\0';
+ easy_setopt(curl[i], CURLOPT_URL, target_url);
+ /* go http2 */
+ easy_setopt(curl[i], CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
+ /* no peer verify */
+ easy_setopt(curl[i], CURLOPT_SSL_VERIFYPEER, 0L);
+ easy_setopt(curl[i], CURLOPT_SSL_VERIFYHOST, 0L);
+ /* wait for first connection established to see if we can share it */
+ easy_setopt(curl[i], CURLOPT_PIPEWAIT, 1L);
+ /* go verbose */
+ easy_setopt(curl[i], CURLOPT_VERBOSE, 1L);
+ /* include headers */
+ easy_setopt(curl[i], CURLOPT_HEADER, 1L);
+
+ easy_setopt(curl[i], CURLOPT_RESOLVE, slist);
+ }
+
+ fprintf(stderr, "Start at URL 0\n");
+
+ for(i = 0; i < NUM_HANDLES; i++) {
+ /* add handle to multi */
+ multi_add_handle(m, curl[i]);
+
+ for(;;) {
+ struct timeval interval;
+ fd_set rd, wr, exc;
+ int maxfd = -99;
+
+ interval.tv_sec = 1;
+ interval.tv_usec = 0;
+
+ multi_perform(m, &running);
+
+ abort_on_test_timeout();
+
+ if(!running)
+ break; /* done */
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wr);
+ FD_ZERO(&exc);
+
+ multi_fdset(m, &rd, &wr, &exc, &maxfd);
+
+ /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+ select_test(maxfd + 1, &rd, &wr, &exc, &interval);
+
+ abort_on_test_timeout();
+ }
+ wait_ms(1); /* to ensure different end times */
+ }
+
+test_cleanup:
+
+ /* proper cleanup sequence - type PB */
+
+ for(i = 0; i < NUM_HANDLES; i++) {
+ curl_multi_remove_handle(m, curl[i]);
+ curl_easy_cleanup(curl[i]);
+ }
+
+ curl_slist_free_all(slist);
+
+ curl_multi_cleanup(m);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib2404.c b/tests/libtest/lib2404.c
new file mode 100644
index 0000000..1a282ff
--- /dev/null
+++ b/tests/libtest/lib2404.c
@@ -0,0 +1,144 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Linus Nielsen Feltzing <linus@haxx.se>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "testutil.h"
+#include "warnless.h"
+#include "memdebug.h"
+
+#define TEST_HANG_TIMEOUT 60 * 1000
+
+#define NUM_HANDLES 4
+
+int test(char *URL)
+{
+ int res = 0;
+ CURL *curl[NUM_HANDLES] = {0};
+ int running;
+ CURLM *m = NULL;
+ int i;
+ char target_url[256];
+ char dnsentry[256];
+ struct curl_slist *slist = NULL;
+ char *port = libtest_arg3;
+ char *address = libtest_arg2;
+
+ (void)URL;
+
+ msnprintf(dnsentry, sizeof(dnsentry), "localhost:%s:%s",
+ port, address);
+ printf("%s\n", dnsentry);
+ slist = curl_slist_append(slist, dnsentry);
+ if(!slist) {
+ fprintf(stderr, "curl_slist_append() failed\n");
+ goto test_cleanup;
+ }
+
+ start_test_timing();
+
+ global_init(CURL_GLOBAL_ALL);
+
+ multi_init(m);
+
+ multi_setopt(m, CURLMOPT_MAXCONNECTS, 1L);
+
+ /* get NUM_HANDLES easy handles */
+ for(i = 0; i < NUM_HANDLES; i++) {
+ /* get an easy handle */
+ easy_init(curl[i]);
+ /* specify target */
+ msnprintf(target_url, sizeof(target_url),
+ "https://localhost:%s/path/2404%04i",
+ port, i + 1);
+ target_url[sizeof(target_url) - 1] = '\0';
+ easy_setopt(curl[i], CURLOPT_URL, target_url);
+ /* go http2 */
+ easy_setopt(curl[i], CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
+ /* no peer verify */
+ easy_setopt(curl[i], CURLOPT_SSL_VERIFYPEER, 0L);
+ easy_setopt(curl[i], CURLOPT_SSL_VERIFYHOST, 0L);
+ /* wait for first connection established to see if we can share it */
+ easy_setopt(curl[i], CURLOPT_PIPEWAIT, 1L);
+ /* go verbose */
+ easy_setopt(curl[i], CURLOPT_VERBOSE, 1L);
+ /* include headers */
+ easy_setopt(curl[i], CURLOPT_HEADER, 1L);
+
+ easy_setopt(curl[i], CURLOPT_RESOLVE, slist);
+
+ easy_setopt(curl[i], CURLOPT_STREAM_WEIGHT, (long)128 + i);
+ }
+
+ fprintf(stderr, "Start at URL 0\n");
+
+ for(i = 0; i < NUM_HANDLES; i++) {
+ /* add handle to multi */
+ multi_add_handle(m, curl[i]);
+
+ for(;;) {
+ struct timeval interval;
+ fd_set rd, wr, exc;
+ int maxfd = -99;
+
+ interval.tv_sec = 1;
+ interval.tv_usec = 0;
+
+ multi_perform(m, &running);
+
+ abort_on_test_timeout();
+
+ if(!running)
+ break; /* done */
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wr);
+ FD_ZERO(&exc);
+
+ multi_fdset(m, &rd, &wr, &exc, &maxfd);
+
+ /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+ select_test(maxfd + 1, &rd, &wr, &exc, &interval);
+
+ abort_on_test_timeout();
+ }
+ wait_ms(1); /* to ensure different end times */
+ }
+
+test_cleanup:
+
+ /* proper cleanup sequence - type PB */
+
+ for(i = 0; i < NUM_HANDLES; i++) {
+ curl_multi_remove_handle(m, curl[i]);
+ curl_easy_cleanup(curl[i]);
+ }
+
+ curl_slist_free_all(slist);
+
+ curl_multi_cleanup(m);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib2502.c b/tests/libtest/lib2502.c
new file mode 100644
index 0000000..e5a7061
--- /dev/null
+++ b/tests/libtest/lib2502.c
@@ -0,0 +1,141 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Linus Nielsen Feltzing <linus@haxx.se>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "testutil.h"
+#include "warnless.h"
+#include "memdebug.h"
+
+#define TEST_HANG_TIMEOUT 60 * 1000
+
+#define NUM_HANDLES 4
+
+int test(char *URL)
+{
+ int res = 0;
+ CURL *curl[NUM_HANDLES] = {0};
+ int running;
+ CURLM *m = NULL;
+ int i;
+ char target_url[256];
+ char dnsentry[256];
+ struct curl_slist *slist = NULL;
+ char *port = libtest_arg3;
+ char *address = libtest_arg2;
+
+ (void)URL;
+
+ msnprintf(dnsentry, sizeof(dnsentry), "localhost:%s:%s",
+ port, address);
+ printf("%s\n", dnsentry);
+ slist = curl_slist_append(slist, dnsentry);
+ if(!slist) {
+ fprintf(stderr, "curl_slist_append() failed\n");
+ goto test_cleanup;
+ }
+
+ start_test_timing();
+
+ global_init(CURL_GLOBAL_ALL);
+
+ multi_init(m);
+
+ multi_setopt(m, CURLMOPT_MAXCONNECTS, 1L);
+
+ /* get NUM_HANDLES easy handles */
+ for(i = 0; i < NUM_HANDLES; i++) {
+ /* get an easy handle */
+ easy_init(curl[i]);
+ /* specify target */
+ msnprintf(target_url, sizeof(target_url),
+ "https://localhost:%s/path/2502%04i",
+ port, i + 1);
+ target_url[sizeof(target_url) - 1] = '\0';
+ easy_setopt(curl[i], CURLOPT_URL, target_url);
+ /* go http2 */
+ easy_setopt(curl[i], CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3ONLY);
+ easy_setopt(curl[i], CURLOPT_CONNECTTIMEOUT_MS, (long)5000);
+ easy_setopt(curl[i], CURLOPT_CAINFO, "./certs/EdelCurlRoot-ca.cacert");
+ /* wait for first connection established to see if we can share it */
+ easy_setopt(curl[i], CURLOPT_PIPEWAIT, 1L);
+ /* go verbose */
+ easy_setopt(curl[i], CURLOPT_VERBOSE, 1L);
+ /* include headers */
+ easy_setopt(curl[i], CURLOPT_HEADER, 1L);
+
+ easy_setopt(curl[i], CURLOPT_RESOLVE, slist);
+ }
+
+ fprintf(stderr, "Start at URL 0\n");
+
+ for(i = 0; i < NUM_HANDLES; i++) {
+ /* add handle to multi */
+ multi_add_handle(m, curl[i]);
+
+ for(;;) {
+ struct timeval interval;
+ fd_set rd, wr, exc;
+ int maxfd = -99;
+
+ interval.tv_sec = 1;
+ interval.tv_usec = 0;
+
+ multi_perform(m, &running);
+
+ abort_on_test_timeout();
+
+ if(!running)
+ break; /* done */
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wr);
+ FD_ZERO(&exc);
+
+ multi_fdset(m, &rd, &wr, &exc, &maxfd);
+
+ /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+ select_test(maxfd + 1, &rd, &wr, &exc, &interval);
+
+ abort_on_test_timeout();
+ }
+ wait_ms(1); /* to ensure different end times */
+ }
+
+test_cleanup:
+
+ /* proper cleanup sequence - type PB */
+
+ for(i = 0; i < NUM_HANDLES; i++) {
+ curl_multi_remove_handle(m, curl[i]);
+ curl_easy_cleanup(curl[i]);
+ }
+
+ curl_slist_free_all(slist);
+
+ curl_multi_cleanup(m);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib3010.c b/tests/libtest/lib3010.c
index aa5ef2a..17c90cc 100644
--- a/tests/libtest/lib3010.c
+++ b/tests/libtest/lib3010.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Nicolas Sterchele, <nicolas@sterchelen.net>
+ * Copyright (C) Nicolas Sterchele, <nicolas@sterchelen.net>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib3025.c b/tests/libtest/lib3025.c
index 0e1b3df..f3e3f92 100644
--- a/tests/libtest/lib3025.c
+++ b/tests/libtest/lib3025.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib3026.c b/tests/libtest/lib3026.c
index 43fe335..24f7768 100644
--- a/tests/libtest/lib3026.c
+++ b/tests/libtest/lib3026.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,12 +26,94 @@
#include "testutil.h"
#include "warnless.h"
-#ifdef HAVE_PTHREAD_H
+#define NUM_THREADS 100
+
+#ifdef WIN32
+#ifdef _WIN32_WCE
+static DWORD WINAPI run_thread(LPVOID ptr)
+#else
+#include <process.h>
+static unsigned int WINAPI run_thread(void *ptr)
+#endif
+{
+ CURLcode *result = ptr;
+
+ *result = curl_global_init(CURL_GLOBAL_ALL);
+ if(*result == CURLE_OK)
+ curl_global_cleanup();
+
+ return 0;
+}
+
+int test(char *URL)
+{
+#ifdef _WIN32_WCE
+ typedef HANDLE curl_win_thread_handle_t;
+#elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+ typedef unsigned long curl_win_thread_handle_t;
+#else
+ typedef uintptr_t curl_win_thread_handle_t;
+#endif
+ CURLcode results[NUM_THREADS];
+ curl_win_thread_handle_t ths[NUM_THREADS];
+ unsigned tid_count = NUM_THREADS, i;
+ int test_failure = 0;
+ curl_version_info_data *ver;
+ (void) URL;
+
+ ver = curl_version_info(CURLVERSION_NOW);
+ if((ver->features & CURL_VERSION_THREADSAFE) == 0) {
+ fprintf(stderr, "%s:%d On Windows but the "
+ "CURL_VERSION_THREADSAFE feature flag is not set\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ /* On Windows libcurl global init/cleanup calls LoadLibrary/FreeLibrary for
+ secur32.dll and iphlpapi.dll. Here we load them beforehand so that when
+ libcurl calls LoadLibrary/FreeLibrary it only increases/decreases the
+ library's refcount rather than actually loading/unloading the library,
+ which would affect the test runtime. */
+ (void)win32_load_system_library(TEXT("secur32.dll"));
+ (void)win32_load_system_library(TEXT("iphlpapi.dll"));
+
+ for(i = 0; i < tid_count; i++) {
+ curl_win_thread_handle_t th;
+ results[i] = CURL_LAST; /* initialize with invalid value */
+#ifdef _WIN32_WCE
+ th = CreateThread(NULL, 0, run_thread, &results[i], 0, NULL);
+#else
+ th = _beginthreadex(NULL, 0, run_thread, &results[i], 0, NULL);
+#endif
+ if(!th) {
+ fprintf(stderr, "%s:%d Couldn't create thread, errno %d\n",
+ __FILE__, __LINE__, GetLastError());
+ tid_count = i;
+ test_failure = -1;
+ goto cleanup;
+ }
+ ths[i] = th;
+ }
+
+cleanup:
+ for(i = 0; i < tid_count; i++) {
+ WaitForSingleObject((HANDLE)ths[i], INFINITE);
+ CloseHandle((HANDLE)ths[i]);
+ if(results[i] != CURLE_OK) {
+ fprintf(stderr, "%s:%d thread[%u]: curl_global_init() failed,"
+ "with code %d (%s)\n", __FILE__, __LINE__,
+ i, (int) results[i], curl_easy_strerror(results[i]));
+ test_failure = -1;
+ }
+ }
+
+ return test_failure;
+}
+
+#elif defined(HAVE_PTHREAD_H)
#include <pthread.h>
#include <unistd.h>
-#define NUM_THREADS 1000
-
static void *run_thread(void *ptr)
{
CURLcode *result = ptr;
@@ -61,7 +143,9 @@
}
for(i = 0; i < tid_count; i++) {
- int res = pthread_create(&tids[i], NULL, run_thread, &results[i]);
+ int res;
+ results[i] = CURL_LAST; /* initialize with invalid value */
+ res = pthread_create(&tids[i], NULL, run_thread, &results[i]);
if(res) {
fprintf(stderr, "%s:%d Couldn't create thread, errno %d\n",
__FILE__, __LINE__, res);
@@ -85,7 +169,7 @@
return test_failure;
}
-#else /* without pthread, this test doesn't work */
+#else /* without pthread or Windows, this test doesn't work */
int test(char *URL)
{
curl_version_info_data *ver;
diff --git a/tests/libtest/lib3027.c b/tests/libtest/lib3027.c
new file mode 100644
index 0000000..6808f29
--- /dev/null
+++ b/tests/libtest/lib3027.c
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "testutil.h"
+#include "warnless.h"
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURLcode ret = CURLE_OK;
+ CURL *hnd;
+ start_test_timing();
+
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ hnd = curl_easy_init();
+ if(hnd) {
+ curl_easy_setopt(hnd, CURLOPT_URL, URL);
+ curl_easy_setopt(hnd, CURLOPT_FILETIME, 1L);
+ ret = curl_easy_perform(hnd);
+ if(CURLE_OK == ret) {
+ long filetime;
+ ret = curl_easy_getinfo(hnd, CURLINFO_FILETIME, &filetime);
+ /* MTDM fails with 550, so filetime should be -1 */
+ if((CURLE_OK == ret) && (filetime != -1)) {
+ /* we just need to return something which is not CURLE_OK */
+ ret = CURLE_UNSUPPORTED_PROTOCOL;
+ }
+ }
+ curl_easy_cleanup(hnd);
+ }
+ curl_global_cleanup();
+ return (int)ret;
+}
diff --git a/tests/libtest/lib3100.c b/tests/libtest/lib3100.c
new file mode 100644
index 0000000..a508d5c
--- /dev/null
+++ b/tests/libtest/lib3100.c
@@ -0,0 +1,68 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ int res;
+ CURL *curl;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_HEADERDATA, stdout);
+ test_setopt(curl, CURLOPT_WRITEDATA, stdout);
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+ test_setopt(curl, CURLOPT_URL, URL);
+ test_setopt(curl, CURLOPT_RTSP_STREAM_URI, URL);
+
+ test_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+ test_setopt(curl, CURLOPT_USERNAME, "user");
+ test_setopt(curl, CURLOPT_PASSWORD, "password");
+ test_setopt(curl, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_DESCRIBE);
+
+ res = curl_easy_perform(curl);
+ if(res != (int)CURLE_OK) {
+ fprintf(stderr, "Failed to send DESCRIBE: %d\n", res);
+ res = TEST_ERR_MAJOR_BAD;
+ goto test_cleanup;
+ }
+
+test_cleanup:
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib3101.c b/tests/libtest/lib3101.c
new file mode 100644
index 0000000..dbcf3a6
--- /dev/null
+++ b/tests/libtest/lib3101.c
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ int res;
+ CURL *curl;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ test_setopt(curl, CURLOPT_HEADERDATA, stdout);
+ test_setopt(curl, CURLOPT_WRITEDATA, stdout);
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_URL, URL);
+ test_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+ test_setopt(curl, CURLOPT_USERNAME, "user");
+ test_setopt(curl, CURLOPT_PASSWORD, "password");
+ test_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "https");
+
+ res = curl_easy_perform(curl);
+ if(res != (int)CURLE_OK) {
+ res = TEST_ERR_MAJOR_BAD;
+ goto test_cleanup;
+ }
+
+test_cleanup:
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib500.c b/tests/libtest/lib500.c
index 37cd4b2..f99b244 100644
--- a/tests/libtest/lib500.c
+++ b/tests/libtest/lib500.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib501.c b/tests/libtest/lib501.c
index 544be2b..7ef8501 100644
--- a/tests/libtest/lib501.c
+++ b/tests/libtest/lib501.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib502.c b/tests/libtest/lib502.c
index 4509d1a..91f96e6 100644
--- a/tests/libtest/lib502.c
+++ b/tests/libtest/lib502.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib503.c b/tests/libtest/lib503.c
index 86dce97..15b0947 100644
--- a/tests/libtest/lib503.c
+++ b/tests/libtest/lib503.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib504.c b/tests/libtest/lib504.c
index a4bfe35..cbe1d57 100644
--- a/tests/libtest/lib504.c
+++ b/tests/libtest/lib504.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib505.c b/tests/libtest/lib505.c
index afa8950..6c67ed9 100644
--- a/tests/libtest/lib505.c
+++ b/tests/libtest/lib505.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib506.c b/tests/libtest/lib506.c
index b44a275..dd4759a 100644
--- a/tests/libtest/lib506.c
+++ b/tests/libtest/lib506.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,8 +24,8 @@
#include "test.h"
#include "memdebug.h"
-static const char *HOSTHEADER = "Host: www.host.foo.com";
-static const char *JAR = "log/jar506";
+static const char * const HOSTHEADER = "Host: www.host.foo.com";
+#define JAR libtest_arg2
#define THREADS 2
/* struct containing data of a thread */
@@ -349,7 +349,7 @@
printf("-----------------\n");
curl_slist_free_all(cookies);
- /* try to free share, expect to fail because share is in use*/
+ /* try to free share, expect to fail because share is in use */
printf("try SHARE_CLEANUP...\n");
scode = curl_share_cleanup(share);
if(scode == CURLSHE_OK) {
diff --git a/tests/libtest/lib507.c b/tests/libtest/lib507.c
index c57a612..be6dd7e 100644
--- a/tests/libtest/lib507.c
+++ b/tests/libtest/lib507.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib508.c b/tests/libtest/lib508.c
index f16e2d7..b793731 100644
--- a/tests/libtest/lib508.c
+++ b/tests/libtest/lib508.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib509.c b/tests/libtest/lib509.c
index 63fb12f..cb510ef 100644
--- a/tests/libtest/lib509.c
+++ b/tests/libtest/lib509.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib510.c b/tests/libtest/lib510.c
index 068cdd7..87a85a5 100644
--- a/tests/libtest/lib510.c
+++ b/tests/libtest/lib510.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib511.c b/tests/libtest/lib511.c
index 1262a6b..c532248 100644
--- a/tests/libtest/lib511.c
+++ b/tests/libtest/lib511.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib512.c b/tests/libtest/lib512.c
index 309d0ac..706acb2 100644
--- a/tests/libtest/lib512.c
+++ b/tests/libtest/lib512.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib513.c b/tests/libtest/lib513.c
index f757bac..b381098 100644
--- a/tests/libtest/lib513.c
+++ b/tests/libtest/lib513.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib514.c b/tests/libtest/lib514.c
index 138bd69..0f31c8c 100644
--- a/tests/libtest/lib514.c
+++ b/tests/libtest/lib514.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib515.c b/tests/libtest/lib515.c
index 661bf6f..3c744fb 100644
--- a/tests/libtest/lib515.c
+++ b/tests/libtest/lib515.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib516.c b/tests/libtest/lib516.c
index b7c9349..59abb09 100644
--- a/tests/libtest/lib516.c
+++ b/tests/libtest/lib516.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,7 +44,9 @@
/* First set the URL that is about to receive our POST. */
test_setopt(curl, CURLOPT_URL, URL);
- test_setopt(curl, CURLOPT_HTTPPOST, NULL);
+ CURL_IGNORE_DEPRECATION(
+ test_setopt(curl, CURLOPT_HTTPPOST, NULL);
+ )
test_setopt(curl, CURLOPT_VERBOSE, 1L); /* show verbose for debug */
test_setopt(curl, CURLOPT_HEADER, 1L); /* include header */
diff --git a/tests/libtest/lib517.c b/tests/libtest/lib517.c
index b803d08..7c65a65 100644
--- a/tests/libtest/lib517.c
+++ b/tests/libtest/lib517.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,6 +34,10 @@
{"Sun, 06 Nov 1994 08:49:37 GMT", 784111777 },
{"Sunday, 06-Nov-94 08:49:37 GMT", 784111777 },
{"Sun Nov 6 08:49:37 1994", 784111777 },
+ {"Sun Nov 6 8:49:37 1994", 784111777 },
+ {"Sun Nov 6 8:9:37 1994", 784109377 },
+ {"Sun Nov 6 008:09:37 1994", -1 },
+ {"Nov Sun 6 8:9:7 1994", 784109347 },
{"06 Nov 1994 08:49:37 GMT", 784111777 },
{"06-Nov-94 08:49:37 GMT", 784111777 },
{"Nov 6 08:49:37 1994", 784111777 },
@@ -116,6 +120,9 @@
{"20111323 12:34:56", -1 },
{"20110623 12:34:79", -1 },
{"Wed, 31 Dec 2008 23:59:60 GMT", 1230768000 },
+ {"Wed, 31 Dec 2008 23:59:61 GMT", -1 },
+ {"Wed, 31 Dec 2008 24:00:00 GMT", -1 },
+ {"Wed, 31 Dec 2008 23:60:59 GMT", -1 },
{"20110623 12:3", 1308830580 },
{"20110623 1:3", 1308790980 },
{"20110623 1:30", 1308792600 },
@@ -126,7 +133,7 @@
{"Thu, 31-Dec-1969 23:59:58 GMT", -2 },
{"Thu, 31-Dec-1969 23:59:59 GMT", 0 }, /* avoids -1 ! */
#if SIZEOF_TIME_T > 4
- {"Sun, 06 Nov 2044 08:49:37 GMT", 2362034977 },
+ {"Sun, 06 Nov 2044 08:49:37 GMT", (time_t) CURL_OFF_TU_C(2362034977) },
{"Sun, 06 Nov 3144 08:49:37 GMT", 37074617377 },
#ifndef HAVE_TIME_T_UNSIGNED
#if 0
diff --git a/tests/libtest/lib518.c b/tests/libtest/lib518.c
index 22f727a..87b6f2d 100644
--- a/tests/libtest/lib518.c
+++ b/tests/libtest/lib518.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib519.c b/tests/libtest/lib519.c
index fecaa98..a4abba0 100644
--- a/tests/libtest/lib519.c
+++ b/tests/libtest/lib519.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib520.c b/tests/libtest/lib520.c
index ef7c594..7e5d0ab 100644
--- a/tests/libtest/lib520.c
+++ b/tests/libtest/lib520.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib521.c b/tests/libtest/lib521.c
index 8385da6..e361168 100644
--- a/tests/libtest/lib521.c
+++ b/tests/libtest/lib521.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib523.c b/tests/libtest/lib523.c
index 04285bb..86128e6 100644
--- a/tests/libtest/lib523.c
+++ b/tests/libtest/lib523.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib524.c b/tests/libtest/lib524.c
index af1d5cc..6b8cc20 100644
--- a/tests/libtest/lib524.c
+++ b/tests/libtest/lib524.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib525.c b/tests/libtest/lib525.c
index 51ed658..3f8abee 100644
--- a/tests/libtest/lib525.c
+++ b/tests/libtest/lib525.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib526.c b/tests/libtest/lib526.c
index 0153d98..d6b365a 100644
--- a/tests/libtest/lib526.c
+++ b/tests/libtest/lib526.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib530.c b/tests/libtest/lib530.c
index 53816a0..0173dd9 100644
--- a/tests/libtest/lib530.c
+++ b/tests/libtest/lib530.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -92,14 +92,12 @@
sockets->max_count = 20;
}
else if(sockets->count + 1 > sockets->max_count) {
- curl_socket_t *oldptr = sockets->sockets;
- sockets->sockets = realloc(oldptr, sizeof(curl_socket_t) *
- (sockets->max_count + 20));
- if(!sockets->sockets) {
+ curl_socket_t *ptr = realloc(sockets->sockets, sizeof(curl_socket_t) *
+ (sockets->max_count + 20));
+ if(!ptr)
/* cleanup in test_cleanup */
- sockets->sockets = oldptr;
return 1;
- }
+ sockets->sockets = ptr;
sockets->max_count += 20;
}
/*
@@ -164,7 +162,7 @@
}
if(timeout_ms != -1) {
*timeout = tutil_tvnow();
- timeout->tv_usec += timeout_ms * 1000;
+ timeout->tv_usec += (int)timeout_ms * 1000;
}
else {
timeout->tv_sec = -1;
@@ -249,7 +247,7 @@
int evBitmask, const char *name)
{
int i;
- CURLMcode result = CURLM_OK;
+ int result = 0;
for(i = 0; i < sockets->count; ++i) {
if(FD_ISSET(sockets->sockets[i], fdset)) {
result = socket_action(curl, sockets->sockets[i], evBitmask, name);
@@ -257,7 +255,7 @@
break;
}
}
- return (int)result;
+ return result;
}
static int testone(char *URL, int timercb, int socketcb)
@@ -361,7 +359,6 @@
/* free local memory */
free(sockets.read.sockets);
free(sockets.write.sockets);
-
return res;
}
diff --git a/tests/libtest/lib533.c b/tests/libtest/lib533.c
index ddc96f7..ff47634 100644
--- a/tests/libtest/lib533.c
+++ b/tests/libtest/lib533.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib537.c b/tests/libtest/lib537.c
index dbced98..3782282 100644
--- a/tests/libtest/lib537.c
+++ b/tests/libtest/lib537.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib539.c b/tests/libtest/lib539.c
index 9450963..0e8aada 100644
--- a/tests/libtest/lib539.c
+++ b/tests/libtest/lib539.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib540.c b/tests/libtest/lib540.c
index d8b7a0d..88007c4 100644
--- a/tests/libtest/lib540.c
+++ b/tests/libtest/lib540.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib541.c b/tests/libtest/lib541.c
index 20d11e2..fdddae2 100644
--- a/tests/libtest/lib541.c
+++ b/tests/libtest/lib541.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib542.c b/tests/libtest/lib542.c
index d762b13..27429fd 100644
--- a/tests/libtest/lib542.c
+++ b/tests/libtest/lib542.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib543.c b/tests/libtest/lib543.c
index cea6dc9..2bec2f1 100644
--- a/tests/libtest/lib543.c
+++ b/tests/libtest/lib543.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib544.c b/tests/libtest/lib544.c
index 42710e1..192bfb2 100644
--- a/tests/libtest/lib544.c
+++ b/tests/libtest/lib544.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib547.c b/tests/libtest/lib547.c
index 647afc6..dbe657e 100644
--- a/tests/libtest/lib547.c
+++ b/tests/libtest/lib547.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -100,8 +100,10 @@
test_setopt(curl, CURLOPT_POSTFIELDS, UPLOADTHIS);
#else
/* 547 style, which means reading the POST data from a callback */
- test_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctlcallback);
- test_setopt(curl, CURLOPT_IOCTLDATA, &counter);
+ CURL_IGNORE_DEPRECATION(
+ test_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctlcallback);
+ test_setopt(curl, CURLOPT_IOCTLDATA, &counter);
+ )
test_setopt(curl, CURLOPT_READFUNCTION, readcallback);
test_setopt(curl, CURLOPT_READDATA, &counter);
/* We CANNOT do the POST fine without setting the size (or choose
diff --git a/tests/libtest/lib549.c b/tests/libtest/lib549.c
index d4861d8..8e91d93 100644
--- a/tests/libtest/lib549.c
+++ b/tests/libtest/lib549.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib552.c b/tests/libtest/lib552.c
index 764e861..8b70231 100644
--- a/tests/libtest/lib552.c
+++ b/tests/libtest/lib552.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -200,7 +200,9 @@
test_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
/* Ioctl function */
- test_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_callback);
+ CURL_IGNORE_DEPRECATION(
+ test_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_callback);
+ )
test_setopt(curl, CURLOPT_PROXY, libtest_arg2);
diff --git a/tests/libtest/lib553.c b/tests/libtest/lib553.c
index 0ab0e3e..f282c89 100644
--- a/tests/libtest/lib553.c
+++ b/tests/libtest/lib553.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib554.c b/tests/libtest/lib554.c
index 3e6f511..1d04981 100644
--- a/tests/libtest/lib554.c
+++ b/tests/libtest/lib554.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,6 +21,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
+#define CURL_DISABLE_DEPRECATION /* Using and testing the form api */
#include "test.h"
#include "memdebug.h"
diff --git a/tests/libtest/lib555.c b/tests/libtest/lib555.c
index 29e43f8..6e3e30b 100644
--- a/tests/libtest/lib555.c
+++ b/tests/libtest/lib555.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -95,8 +95,10 @@
easy_setopt(curl, CURLOPT_HEADER, 1L);
/* read the POST data from a callback */
- easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctlcallback);
- easy_setopt(curl, CURLOPT_IOCTLDATA, &counter);
+ CURL_IGNORE_DEPRECATION(
+ easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctlcallback);
+ easy_setopt(curl, CURLOPT_IOCTLDATA, &counter);
+ )
easy_setopt(curl, CURLOPT_READFUNCTION, readcallback);
easy_setopt(curl, CURLOPT_READDATA, &counter);
/* We CANNOT do the POST fine without setting the size (or choose
diff --git a/tests/libtest/lib556.c b/tests/libtest/lib556.c
index a391d5a..ead6529 100644
--- a/tests/libtest/lib556.c
+++ b/tests/libtest/lib556.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -61,7 +61,7 @@
res = curl_easy_perform(curl);
if(!res) {
- /* we are connected, now get a HTTP document the raw way */
+ /* we are connected, now get an HTTP document the raw way */
const char *request =
"GET /556 HTTP/1.1\r\n"
"Host: ninja\r\n\r\n";
diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c
index 9afc566..409550a 100644
--- a/tests/libtest/lib557.c
+++ b/tests/libtest/lib557.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -127,25 +127,6 @@
int num_ushort_tests = 0;
int failed = 0;
-#if (SIZEOF_SHORT == 1)
-
- i = 1; us_test[i].num = 0xFFU; us_test[i].expected = "256";
- i++; us_test[i].num = 0xF0U; us_test[i].expected = "240";
- i++; us_test[i].num = 0x0FU; us_test[i].expected = "15";
-
- i++; us_test[i].num = 0xE0U; us_test[i].expected = "224";
- i++; us_test[i].num = 0x0EU; us_test[i].expected = "14";
-
- i++; us_test[i].num = 0xC0U; us_test[i].expected = "192";
- i++; us_test[i].num = 0x0CU; us_test[i].expected = "12";
-
- i++; us_test[i].num = 0x01U; us_test[i].expected = "1";
- i++; us_test[i].num = 0x00U; us_test[i].expected = "0";
-
- num_ushort_tests = i;
-
-#elif (SIZEOF_SHORT == 2)
-
i = 1; us_test[i].num = 0xFFFFU; us_test[i].expected = "65535";
i++; us_test[i].num = 0xFF00U; us_test[i].expected = "65280";
i++; us_test[i].num = 0x00FFU; us_test[i].expected = "255";
@@ -165,42 +146,6 @@
num_ushort_tests = i;
-#elif (SIZEOF_SHORT == 4)
-
- i = 1; us_test[i].num = 0xFFFFFFFFU; us_test[i].expected = "4294967295";
- i++; us_test[i].num = 0xFFFF0000U; us_test[i].expected = "4294901760";
- i++; us_test[i].num = 0x0000FFFFU; us_test[i].expected = "65535";
-
- i++; us_test[i].num = 0xFF000000U; us_test[i].expected = "4278190080";
- i++; us_test[i].num = 0x00FF0000U; us_test[i].expected = "16711680";
- i++; us_test[i].num = 0x0000FF00U; us_test[i].expected = "65280";
- i++; us_test[i].num = 0x000000FFU; us_test[i].expected = "255";
-
- i++; us_test[i].num = 0xF0000000U; us_test[i].expected = "4026531840";
- i++; us_test[i].num = 0x0F000000U; us_test[i].expected = "251658240";
- i++; us_test[i].num = 0x00F00000U; us_test[i].expected = "15728640";
- i++; us_test[i].num = 0x000F0000U; us_test[i].expected = "983040";
- i++; us_test[i].num = 0x0000F000U; us_test[i].expected = "61440";
- i++; us_test[i].num = 0x00000F00U; us_test[i].expected = "3840";
- i++; us_test[i].num = 0x000000F0U; us_test[i].expected = "240";
- i++; us_test[i].num = 0x0000000FU; us_test[i].expected = "15";
-
- i++; us_test[i].num = 0xC0000000U; us_test[i].expected = "3221225472";
- i++; us_test[i].num = 0x0C000000U; us_test[i].expected = "201326592";
- i++; us_test[i].num = 0x00C00000U; us_test[i].expected = "12582912";
- i++; us_test[i].num = 0x000C0000U; us_test[i].expected = "786432";
- i++; us_test[i].num = 0x0000C000U; us_test[i].expected = "49152";
- i++; us_test[i].num = 0x00000C00U; us_test[i].expected = "3072";
- i++; us_test[i].num = 0x000000C0U; us_test[i].expected = "192";
- i++; us_test[i].num = 0x0000000CU; us_test[i].expected = "12";
-
- i++; us_test[i].num = 0x00000001U; us_test[i].expected = "1";
- i++; us_test[i].num = 0x00000000U; us_test[i].expected = "0";
-
- num_ushort_tests = i;
-
-#endif
-
for(i = 1; i <= num_ushort_tests; i++) {
for(j = 0; j<BUFSZ; j++)
@@ -234,33 +179,6 @@
int num_sshort_tests = 0;
int failed = 0;
-#if (SIZEOF_SHORT == 1)
-
- i = 1; ss_test[i].num = 0x7F; ss_test[i].expected = "127";
-
- i++; ss_test[i].num = 0x70; ss_test[i].expected = "112";
- i++; ss_test[i].num = 0x07; ss_test[i].expected = "7";
-
- i++; ss_test[i].num = 0x50; ss_test[i].expected = "80";
- i++; ss_test[i].num = 0x05; ss_test[i].expected = "5";
-
- i++; ss_test[i].num = 0x01; ss_test[i].expected = "1";
- i++; ss_test[i].num = 0x00; ss_test[i].expected = "0";
-
- i++; ss_test[i].num = -0x7F -1; ss_test[i].expected = "-128";
-
- i++; ss_test[i].num = -0x70 -1; ss_test[i].expected = "-113";
- i++; ss_test[i].num = -0x07 -1; ss_test[i].expected = "-8";
-
- i++; ss_test[i].num = -0x50 -1; ss_test[i].expected = "-81";
- i++; ss_test[i].num = -0x05 -1; ss_test[i].expected = "-6";
-
- i++; ss_test[i].num = 0x00 -1; ss_test[i].expected = "-1";
-
- num_sshort_tests = i;
-
-#elif (SIZEOF_SHORT == 2)
-
i = 1; ss_test[i].num = 0x7FFF; ss_test[i].expected = "32767";
i++; ss_test[i].num = 0x7FFE; ss_test[i].expected = "32766";
i++; ss_test[i].num = 0x7FFD; ss_test[i].expected = "32765";
@@ -302,75 +220,6 @@
num_sshort_tests = i;
-#elif (SIZEOF_SHORT == 4)
-
- i = 1; ss_test[i].num = 0x7FFFFFFF; ss_test[i].expected = "2147483647";
- i++; ss_test[i].num = 0x7FFFFFFE; ss_test[i].expected = "2147483646";
- i++; ss_test[i].num = 0x7FFFFFFD; ss_test[i].expected = "2147483645";
- i++; ss_test[i].num = 0x7FFF0000; ss_test[i].expected = "2147418112";
- i++; ss_test[i].num = 0x00007FFF; ss_test[i].expected = "32767";
-
- i++; ss_test[i].num = 0x7F000000; ss_test[i].expected = "2130706432";
- i++; ss_test[i].num = 0x007F0000; ss_test[i].expected = "8323072";
- i++; ss_test[i].num = 0x00007F00; ss_test[i].expected = "32512";
- i++; ss_test[i].num = 0x0000007F; ss_test[i].expected = "127";
-
- i++; ss_test[i].num = 0x70000000; ss_test[i].expected = "1879048192";
- i++; ss_test[i].num = 0x07000000; ss_test[i].expected = "117440512";
- i++; ss_test[i].num = 0x00700000; ss_test[i].expected = "7340032";
- i++; ss_test[i].num = 0x00070000; ss_test[i].expected = "458752";
- i++; ss_test[i].num = 0x00007000; ss_test[i].expected = "28672";
- i++; ss_test[i].num = 0x00000700; ss_test[i].expected = "1792";
- i++; ss_test[i].num = 0x00000070; ss_test[i].expected = "112";
- i++; ss_test[i].num = 0x00000007; ss_test[i].expected = "7";
-
- i++; ss_test[i].num = 0x50000000; ss_test[i].expected = "1342177280";
- i++; ss_test[i].num = 0x05000000; ss_test[i].expected = "83886080";
- i++; ss_test[i].num = 0x00500000; ss_test[i].expected = "5242880";
- i++; ss_test[i].num = 0x00050000; ss_test[i].expected = "327680";
- i++; ss_test[i].num = 0x00005000; ss_test[i].expected = "20480";
- i++; ss_test[i].num = 0x00000500; ss_test[i].expected = "1280";
- i++; ss_test[i].num = 0x00000050; ss_test[i].expected = "80";
- i++; ss_test[i].num = 0x00000005; ss_test[i].expected = "5";
-
- i++; ss_test[i].num = 0x00000001; ss_test[i].expected = "1";
- i++; ss_test[i].num = 0x00000000; ss_test[i].expected = "0";
-
- i++; ss_test[i].num = -0x7FFFFFFF -1; ss_test[i].expected = "-2147483648";
- i++; ss_test[i].num = -0x7FFFFFFE -1; ss_test[i].expected = "-2147483647";
- i++; ss_test[i].num = -0x7FFFFFFD -1; ss_test[i].expected = "-2147483646";
- i++; ss_test[i].num = -0x7FFF0000 -1; ss_test[i].expected = "-2147418113";
- i++; ss_test[i].num = -0x00007FFF -1; ss_test[i].expected = "-32768";
-
- i++; ss_test[i].num = -0x7F000000 -1; ss_test[i].expected = "-2130706433";
- i++; ss_test[i].num = -0x007F0000 -1; ss_test[i].expected = "-8323073";
- i++; ss_test[i].num = -0x00007F00 -1; ss_test[i].expected = "-32513";
- i++; ss_test[i].num = -0x0000007F -1; ss_test[i].expected = "-128";
-
- i++; ss_test[i].num = -0x70000000 -1; ss_test[i].expected = "-1879048193";
- i++; ss_test[i].num = -0x07000000 -1; ss_test[i].expected = "-117440513";
- i++; ss_test[i].num = -0x00700000 -1; ss_test[i].expected = "-7340033";
- i++; ss_test[i].num = -0x00070000 -1; ss_test[i].expected = "-458753";
- i++; ss_test[i].num = -0x00007000 -1; ss_test[i].expected = "-28673";
- i++; ss_test[i].num = -0x00000700 -1; ss_test[i].expected = "-1793";
- i++; ss_test[i].num = -0x00000070 -1; ss_test[i].expected = "-113";
- i++; ss_test[i].num = -0x00000007 -1; ss_test[i].expected = "-8";
-
- i++; ss_test[i].num = -0x50000000 -1; ss_test[i].expected = "-1342177281";
- i++; ss_test[i].num = -0x05000000 -1; ss_test[i].expected = "-83886081";
- i++; ss_test[i].num = -0x00500000 -1; ss_test[i].expected = "-5242881";
- i++; ss_test[i].num = -0x00050000 -1; ss_test[i].expected = "-327681";
- i++; ss_test[i].num = -0x00005000 -1; ss_test[i].expected = "-20481";
- i++; ss_test[i].num = -0x00000500 -1; ss_test[i].expected = "-1281";
- i++; ss_test[i].num = -0x00000050 -1; ss_test[i].expected = "-81";
- i++; ss_test[i].num = -0x00000005 -1; ss_test[i].expected = "-6";
-
- i++; ss_test[i].num = 0x00000000 -1; ss_test[i].expected = "-1";
-
- num_sshort_tests = i;
-
-#endif
-
for(i = 1; i <= num_sshort_tests; i++) {
for(j = 0; j<BUFSZ; j++)
@@ -1159,118 +1008,6 @@
int num_cofft_tests = 0;
int failed = 0;
-#if (SIZEOF_CURL_OFF_T == 2)
-
- i = 1; co_test[i].num = MPRNT_OFF_T_C(0x7FFF); co_test[i].expected = "32767";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFE); co_test[i].expected = "32766";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFD); co_test[i].expected = "32765";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x7F00); co_test[i].expected = "32512";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x07F0); co_test[i].expected = "2032";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x007F); co_test[i].expected = "127";
-
- i++; co_test[i].num = MPRNT_OFF_T_C(0x7000); co_test[i].expected = "28672";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x0700); co_test[i].expected = "1792";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x0070); co_test[i].expected = "112";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x0007); co_test[i].expected = "7";
-
- i++; co_test[i].num = MPRNT_OFF_T_C(0x5000); co_test[i].expected = "20480";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x0500); co_test[i].expected = "1280";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x0050); co_test[i].expected = "80";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x0005); co_test[i].expected = "5";
-
- i++; co_test[i].num = MPRNT_OFF_T_C(0x0001); co_test[i].expected = "1";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x0000); co_test[i].expected = "0";
-
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x7FFF) -MPRNT_OFF_T_C(1); co_test[i].expected = "-32768";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x7FFE) -MPRNT_OFF_T_C(1); co_test[i].expected = "-32767";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x7FFD) -MPRNT_OFF_T_C(1); co_test[i].expected = "-32766";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x7F00) -MPRNT_OFF_T_C(1); co_test[i].expected = "-32513";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x07F0) -MPRNT_OFF_T_C(1); co_test[i].expected = "-2033";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x007F) -MPRNT_OFF_T_C(1); co_test[i].expected = "-128";
-
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x7000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-28673";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x0700) -MPRNT_OFF_T_C(1); co_test[i].expected = "-1793";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x0070) -MPRNT_OFF_T_C(1); co_test[i].expected = "-113";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x0007) -MPRNT_OFF_T_C(1); co_test[i].expected = "-8";
-
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x5000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-20481";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x0500) -MPRNT_OFF_T_C(1); co_test[i].expected = "-1281";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x0050) -MPRNT_OFF_T_C(1); co_test[i].expected = "-81";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x0005) -MPRNT_OFF_T_C(1); co_test[i].expected = "-6";
-
- i++; co_test[i].num = MPRNT_OFF_T_C(0x0000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-1";
-
- num_cofft_tests = i;
-
-#elif (SIZEOF_CURL_OFF_T == 4)
-
- i = 1; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFF); co_test[i].expected = "2147483647";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFE); co_test[i].expected = "2147483646";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFD); co_test[i].expected = "2147483645";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFF0000); co_test[i].expected = "2147418112";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00007FFF); co_test[i].expected = "32767";
-
- i++; co_test[i].num = MPRNT_OFF_T_C(0x7F000000); co_test[i].expected = "2130706432";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x007F0000); co_test[i].expected = "8323072";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00007F00); co_test[i].expected = "32512";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x0000007F); co_test[i].expected = "127";
-
- i++; co_test[i].num = MPRNT_OFF_T_C(0x70000000); co_test[i].expected = "1879048192";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x07000000); co_test[i].expected = "117440512";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00700000); co_test[i].expected = "7340032";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00070000); co_test[i].expected = "458752";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00007000); co_test[i].expected = "28672";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00000700); co_test[i].expected = "1792";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00000070); co_test[i].expected = "112";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00000007); co_test[i].expected = "7";
-
- i++; co_test[i].num = MPRNT_OFF_T_C(0x50000000); co_test[i].expected = "1342177280";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x05000000); co_test[i].expected = "83886080";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00500000); co_test[i].expected = "5242880";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00050000); co_test[i].expected = "327680";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00005000); co_test[i].expected = "20480";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00000500); co_test[i].expected = "1280";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00000050); co_test[i].expected = "80";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00000005); co_test[i].expected = "5";
-
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00000001); co_test[i].expected = "1";
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00000000); co_test[i].expected = "0";
-
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x7FFFFFFF) -MPRNT_OFF_T_C(1); co_test[i].expected = "-2147483648";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x7FFFFFFE) -MPRNT_OFF_T_C(1); co_test[i].expected = "-2147483647";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x7FFFFFFD) -MPRNT_OFF_T_C(1); co_test[i].expected = "-2147483646";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x7FFF0000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-2147418113";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00007FFF) -MPRNT_OFF_T_C(1); co_test[i].expected = "-32768";
-
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x7F000000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-2130706433";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x007F0000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-8323073";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00007F00) -MPRNT_OFF_T_C(1); co_test[i].expected = "-32513";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x0000007F) -MPRNT_OFF_T_C(1); co_test[i].expected = "-128";
-
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x70000000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-1879048193";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x07000000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-117440513";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00700000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-7340033";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00070000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-458753";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00007000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-28673";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00000700) -MPRNT_OFF_T_C(1); co_test[i].expected = "-1793";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00000070) -MPRNT_OFF_T_C(1); co_test[i].expected = "-113";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00000007) -MPRNT_OFF_T_C(1); co_test[i].expected = "-8";
-
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x50000000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-1342177281";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x05000000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-83886081";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00500000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-5242881";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00050000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-327681";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00005000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-20481";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00000500) -MPRNT_OFF_T_C(1); co_test[i].expected = "-1281";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00000050) -MPRNT_OFF_T_C(1); co_test[i].expected = "-81";
- i++; co_test[i].num = -MPRNT_OFF_T_C(0x00000005) -MPRNT_OFF_T_C(1); co_test[i].expected = "-6";
-
- i++; co_test[i].num = MPRNT_OFF_T_C(0x00000000) -MPRNT_OFF_T_C(1); co_test[i].expected = "-1";
-
- num_cofft_tests = i;
-
-#elif (SIZEOF_CURL_OFF_T == 8)
-
i = 1; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFFFFFFFFFF); co_test[i].expected = "9223372036854775807";
i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFFFFFFFFFE); co_test[i].expected = "9223372036854775806";
i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFFFFFFFFFD); co_test[i].expected = "9223372036854775805";
@@ -1352,8 +1089,6 @@
num_cofft_tests = i;
-#endif
-
for(i = 1; i <= num_cofft_tests; i++) {
for(j = 0; j<BUFSZ; j++)
@@ -1496,7 +1231,7 @@
"0123456789" /* 10 7 */
"0123456789" /* 10 8 */
"0123456789" /* 10 9 */
- "0123456789" /* 10 10*/
+ "0123456789" /* 10 10 */
"0123456789" /* 10 11 */
"01234567" /* 8 */
);
@@ -1532,8 +1267,8 @@
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 11 */
0, 1, 2, 3, 4, 5, 6, 7, 8); /* 9 */
- if(rc != -1) {
- printf("curl_mprintf() returned %d and not -1!\n", rc);
+ if(rc) {
+ printf("curl_mprintf() returned %d and not 0\n", rc);
errors++;
}
diff --git a/tests/libtest/lib558.c b/tests/libtest/lib558.c
index 30792c9..1f42aa3 100644
--- a/tests/libtest/lib558.c
+++ b/tests/libtest/lib558.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib559.c b/tests/libtest/lib559.c
index 89dbc2d..8b06fb4 100644
--- a/tests/libtest/lib559.c
+++ b/tests/libtest/lib559.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib560.c b/tests/libtest/lib560.c
index 7dd48e4..d643b7e 100644
--- a/tests/libtest/lib560.c
+++ b/tests/libtest/lib560.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,7 +30,7 @@
#define TEST_HANG_TIMEOUT 60 * 1000
/*
- * Simply download a HTTPS file!
+ * Simply download an HTTPS file!
*
* This test was added after the HTTPS-using-multi-interface with OpenSSL
* regression of 7.19.1 to hopefully prevent this embarrassing mistake from
diff --git a/tests/libtest/lib562.c b/tests/libtest/lib562.c
index d990108..8b9807e 100644
--- a/tests/libtest/lib562.c
+++ b/tests/libtest/lib562.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib564.c b/tests/libtest/lib564.c
index 9516a25..6c785fe 100644
--- a/tests/libtest/lib564.c
+++ b/tests/libtest/lib564.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib566.c b/tests/libtest/lib566.c
index ea3ec42..7d695ad 100644
--- a/tests/libtest/lib566.c
+++ b/tests/libtest/lib566.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -51,8 +51,10 @@
if(!res) {
FILE *moo;
- res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
- &content_length);
+ CURL_IGNORE_DEPRECATION(
+ res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
+ &content_length);
+ )
moo = fopen(libtest_arg2, "wb");
if(moo) {
fprintf(moo, "CL %.0f\n", content_length);
diff --git a/tests/libtest/lib567.c b/tests/libtest/lib567.c
index de03f5e..00937e7 100644
--- a/tests/libtest/lib567.c
+++ b/tests/libtest/lib567.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib568.c b/tests/libtest/lib568.c
index 271738b..9e761e8 100644
--- a/tests/libtest/lib568.c
+++ b/tests/libtest/lib568.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -78,13 +78,13 @@
free(stream_uri);
stream_uri = NULL;
- sdp = open("log/file568.txt", O_RDONLY);
+ sdp = open(libtest_arg2, O_RDONLY);
fstat(sdp, &file_info);
close(sdp);
- sdpf = fopen("log/file568.txt", "rb");
+ sdpf = fopen(libtest_arg2, "rb");
if(!sdpf) {
- fprintf(stderr, "can't open log/file568.txt\n");
+ fprintf(stderr, "can't open %s\n", libtest_arg2);
res = TEST_ERR_MAJOR_BAD;
goto test_cleanup;
}
diff --git a/tests/libtest/lib569.c b/tests/libtest/lib569.c
index 7daea84..a66d07b 100644
--- a/tests/libtest/lib569.c
+++ b/tests/libtest/lib569.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib570.c b/tests/libtest/lib570.c
index ccd152b..b415244 100644
--- a/tests/libtest/lib570.c
+++ b/tests/libtest/lib570.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib571.c b/tests/libtest/lib571.c
index 8027c90..86106b2 100644
--- a/tests/libtest/lib571.c
+++ b/tests/libtest/lib571.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,7 +48,7 @@
((int)((unsigned char)((p)[3]))))
#define RTP_DATA_SIZE 12
-static const char *RTP_DATA = "$_1234\n\0asdf";
+static const char *RTP_DATA = "$_1234\n\0Rsdf";
static int rtp_packet_count = 0;
@@ -76,14 +76,14 @@
if(message_size - i > RTP_DATA_SIZE) {
if(memcmp(RTP_DATA, data + i, RTP_DATA_SIZE) != 0) {
printf("RTP PAYLOAD CORRUPTED [%s]\n", data + i);
- return failure;
+ /* return failure; */
}
}
else {
if(memcmp(RTP_DATA, data + i, message_size - i) != 0) {
printf("RTP PAYLOAD END CORRUPTED (%d), [%s]\n",
message_size - i, data + i);
- return failure;
+ /* return failure; */
}
}
}
@@ -196,7 +196,7 @@
fprintf(stderr, "PLAY COMPLETE\n");
/* Use Receive to get the rest of the data */
- while(!res && rtp_packet_count < 13) {
+ while(!res && rtp_packet_count < 19) {
fprintf(stderr, "LOOPY LOOP!\n");
test_setopt(curl, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_RECEIVE);
res = curl_easy_perform(curl);
diff --git a/tests/libtest/lib572.c b/tests/libtest/lib572.c
index 0cc56ee..f21037d 100644
--- a/tests/libtest/lib572.c
+++ b/tests/libtest/lib572.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -97,13 +97,13 @@
stream_uri = NULL;
/* PUT style GET_PARAMETERS */
- params = open("log/file572.txt", O_RDONLY);
+ params = open(libtest_arg2, O_RDONLY);
fstat(params, &file_info);
close(params);
- paramsf = fopen("log/file572.txt", "rb");
+ paramsf = fopen(libtest_arg2, "rb");
if(!paramsf) {
- fprintf(stderr, "can't open log/file572.txt\n");
+ fprintf(stderr, "can't open %s\n", libtest_arg2);
res = TEST_ERR_MAJOR_BAD;
goto test_cleanup;
}
diff --git a/tests/libtest/lib573.c b/tests/libtest/lib573.c
index 02b0aa7..af140e2 100644
--- a/tests/libtest/lib573.c
+++ b/tests/libtest/lib573.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib574.c b/tests/libtest/lib574.c
index dbe5c94..8bb8704 100644
--- a/tests/libtest/lib574.c
+++ b/tests/libtest/lib574.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib575.c b/tests/libtest/lib575.c
index 1c04750..1de6e32 100644
--- a/tests/libtest/lib575.c
+++ b/tests/libtest/lib575.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib576.c b/tests/libtest/lib576.c
index 34677b1..f6839e7 100644
--- a/tests/libtest/lib576.c
+++ b/tests/libtest/lib576.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib578.c b/tests/libtest/lib578.c
index 89c5bf7..7c6af99 100644
--- a/tests/libtest/lib578.c
+++ b/tests/libtest/lib578.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -78,10 +78,10 @@
test_setopt(curl, CURLOPT_POSTFIELDS, data);
/* we want to use our own progress function */
- test_setopt(curl, CURLOPT_NOPROGRESS, 0L);
- test_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
-
- /* pointer to pass to our read function */
+ CURL_IGNORE_DEPRECATION(
+ test_setopt(curl, CURLOPT_NOPROGRESS, 0L);
+ test_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
+ )
/* get verbose debug output please */
test_setopt(curl, CURLOPT_VERBOSE, 1L);
diff --git a/tests/libtest/lib579.c b/tests/libtest/lib579.c
index f8f1ae3..5f96217 100644
--- a/tests/libtest/lib579.c
+++ b/tests/libtest/lib579.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -139,7 +139,9 @@
/* we want to use our own progress function */
test_setopt(curl, CURLOPT_NOPROGRESS, 0L);
- test_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
+ CURL_IGNORE_DEPRECATION(
+ test_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
+ )
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
diff --git a/tests/libtest/lib582.c b/tests/libtest/lib582.c
index 3af6e73..a50f8a4 100644
--- a/tests/libtest/lib582.c
+++ b/tests/libtest/lib582.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -136,7 +136,7 @@
(void)multi; /* unused */
if(timeout_ms != -1) {
*timeout = tutil_tvnow();
- timeout->tv_usec += timeout_ms * 1000;
+ timeout->tv_usec += (int)timeout_ms * 1000;
}
else {
timeout->tv_sec = -1;
@@ -238,6 +238,8 @@
struct timeval timeout = {-1, 0};
int success = 0;
+ assert(test_argc >= 5);
+
start_test_timing();
if(!libtest_arg3) {
@@ -286,8 +288,8 @@
easy_setopt(curl, CURLOPT_READDATA, hd_src);
easy_setopt(curl, CURLOPT_USERPWD, libtest_arg3);
- easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "curl_client_key.pub");
- easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "curl_client_key");
+ easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, test_argv[4]);
+ easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, test_argv[5]);
easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
diff --git a/tests/libtest/lib583.c b/tests/libtest/lib583.c
index 65a2fc4..ba44b5d 100644
--- a/tests/libtest/lib583.c
+++ b/tests/libtest/lib583.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,6 +40,8 @@
CURLcode res = CURLE_OK;
CURLMcode mres;
+ assert(test_argc >= 4);
+
global_init(CURL_GLOBAL_ALL);
multi_init(multiHandle);
@@ -47,8 +49,8 @@
easy_init(curl);
easy_setopt(curl, CURLOPT_USERPWD, libtest_arg2);
- easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "curl_client_key.pub");
- easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "curl_client_key");
+ easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, test_argv[3]);
+ easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, test_argv[4]);
easy_setopt(curl, CURLOPT_UPLOAD, 1L);
easy_setopt(curl, CURLOPT_VERBOSE, 1L);
diff --git a/tests/libtest/lib586.c b/tests/libtest/lib586.c
index 8f14869..90d1800 100644
--- a/tests/libtest/lib586.c
+++ b/tests/libtest/lib586.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -217,7 +217,7 @@
printf("PERFORM\n");
curl_easy_perform(curl);
- /* try to free share, expect to fail because share is in use*/
+ /* try to free share, expect to fail because share is in use */
printf("try SHARE_CLEANUP...\n");
scode = curl_share_cleanup(share);
if(scode == CURLSHE_OK) {
diff --git a/tests/libtest/lib589.c b/tests/libtest/lib589.c
index 017b7df..5fe56db 100644
--- a/tests/libtest/lib589.c
+++ b/tests/libtest/lib589.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib590.c b/tests/libtest/lib590.c
index 1a88540..babcd19 100644
--- a/tests/libtest/lib590.c
+++ b/tests/libtest/lib590.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -64,7 +64,7 @@
res = curl_easy_perform(curl);
- test_cleanup:
+test_cleanup:
curl_easy_cleanup(curl);
curl_global_cleanup();
diff --git a/tests/libtest/lib591.c b/tests/libtest/lib591.c
index 93e30be..94fd656 100644
--- a/tests/libtest/lib591.c
+++ b/tests/libtest/lib591.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib597.c b/tests/libtest/lib597.c
index 4dcf263..4f40821 100644
--- a/tests/libtest/lib597.c
+++ b/tests/libtest/lib597.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib598.c b/tests/libtest/lib598.c
index e75cad0..62b3655 100644
--- a/tests/libtest/lib598.c
+++ b/tests/libtest/lib598.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib599.c b/tests/libtest/lib599.c
index 5b35cca..6002e0f 100644
--- a/tests/libtest/lib599.c
+++ b/tests/libtest/lib599.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -64,7 +64,9 @@
/* we want to use our own progress function */
test_setopt(curl, CURLOPT_NOPROGRESS, 0L);
- test_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
+ CURL_IGNORE_DEPRECATION(
+ test_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
+ )
/* get verbose debug output please */
test_setopt(curl, CURLOPT_VERBOSE, 1L);
@@ -80,8 +82,10 @@
if(!res) {
FILE *moo;
- res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
+ CURL_IGNORE_DEPRECATION(
+ res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
&content_length);
+ )
moo = fopen(libtest_arg2, "wb");
if(moo) {
fprintf(moo, "CL %.0f\n", content_length);
diff --git a/tests/libtest/lib643.c b/tests/libtest/lib643.c
index 5326d6d..efd508f 100644
--- a/tests/libtest/lib643.c
+++ b/tests/libtest/lib643.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,23 +35,6 @@
static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
-#ifdef LIB644
- static int count = 0;
- (void)ptr;
- (void)size;
- (void)nmemb;
- (void)userp;
- switch(count++) {
- case 0: /* Return a single byte. */
- *ptr = '\n';
- return 1;
- case 1: /* Request abort. */
- return CURL_READFUNC_ABORT;
- }
- printf("Wrongly called >2 times\n");
- exit(1); /* trigger major failure */
-#else
-
struct WriteThis *pooh = (struct WriteThis *)userp;
int eof = !*pooh->readptr;
@@ -71,7 +54,6 @@
}
return 0; /* no more data left to deliver */
-#endif
}
static int once(char *URL, bool oldstyle)
diff --git a/tests/libtest/lib650.c b/tests/libtest/lib650.c
index cc2c0ed..853029f 100644
--- a/tests/libtest/lib650.c
+++ b/tests/libtest/lib650.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,6 +21,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
+#define CURL_DISABLE_DEPRECATION /* Using and testing the form api */
#include "test.h"
#include "memdebug.h"
diff --git a/tests/libtest/lib651.c b/tests/libtest/lib651.c
index 8b2d23b..2e45ccc 100644
--- a/tests/libtest/lib651.c
+++ b/tests/libtest/lib651.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,6 +21,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
+#define CURL_DISABLE_DEPRECATION /* Using and testing the form api */
#include "test.h"
#include "memdebug.h"
diff --git a/tests/libtest/lib652.c b/tests/libtest/lib652.c
index ff5cb3f..7a100b7 100644
--- a/tests/libtest/lib652.c
+++ b/tests/libtest/lib652.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib653.c b/tests/libtest/lib653.c
index 46348ae..8a6fff3 100644
--- a/tests/libtest/lib653.c
+++ b/tests/libtest/lib653.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib654.c b/tests/libtest/lib654.c
index 0d99dd6..9655163 100644
--- a/tests/libtest/lib654.c
+++ b/tests/libtest/lib654.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -109,7 +109,7 @@
hdrs = curl_slist_append(hdrs, "X-Test-Number: 654");
curl_mime_headers(part, hdrs, TRUE);
part = curl_mime_addpart(mime);
- curl_mime_filedata(part, "log/file654.txt");
+ curl_mime_filedata(part, libtest_arg2);
part = curl_mime_addpart(mime);
curl_mime_data_cb(part, (curl_off_t) -1, read_callback, NULL, free_callback,
&pooh);
diff --git a/tests/libtest/lib655.c b/tests/libtest/lib655.c
index 7f4053b..83525e5 100644
--- a/tests/libtest/lib655.c
+++ b/tests/libtest/lib655.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib658.c b/tests/libtest/lib658.c
index 50dc4fe..5be239f 100644
--- a/tests/libtest/lib658.c
+++ b/tests/libtest/lib658.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,9 +34,9 @@
int test(char *URL)
{
CURL *handle = NULL;
- CURLcode res = 0;
+ CURLcode res = CURLE_OK;
CURLU *urlp = NULL;
- CURLUcode uc = 0;
+ CURLUcode uc = CURLUE_OK;
global_init(CURL_GLOBAL_ALL);
easy_init(handle);
diff --git a/tests/libtest/lib659.c b/tests/libtest/lib659.c
index c251b7e..97efbec 100644
--- a/tests/libtest/lib659.c
+++ b/tests/libtest/lib659.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,7 +34,7 @@
int test(char *URL)
{
CURL *handle = NULL;
- CURLcode res = 0;
+ CURLcode res = CURLE_OK;
CURLU *urlp = NULL;
global_init(CURL_GLOBAL_ALL);
diff --git a/tests/libtest/lib661.c b/tests/libtest/lib661.c
index f12a980..d51608c 100644
--- a/tests/libtest/lib661.c
+++ b/tests/libtest/lib661.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib666.c b/tests/libtest/lib666.c
index 29ddb50..6259070 100644
--- a/tests/libtest/lib666.c
+++ b/tests/libtest/lib666.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib667.c b/tests/libtest/lib667.c
index d8c14da..076361a 100644
--- a/tests/libtest/lib667.c
+++ b/tests/libtest/lib667.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/lib668.c b/tests/libtest/lib668.c
index e58f49d..35ab758 100644
--- a/tests/libtest/lib668.c
+++ b/tests/libtest/lib668.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -98,7 +98,7 @@
curl_mime_name(part, "field3");
/* Regular file part sources early end of data can be detected because
the file size is known. In addition, and EOF test is performed. */
- curl_mime_filedata(part, "log/file668.txt");
+ curl_mime_filedata(part, libtest_arg2);
/* Bind mime data to its easy handle. */
test_setopt(easy, CURLOPT_MIMEPOST, mime);
diff --git a/tests/libtest/lib670.c b/tests/libtest/lib670.c
index 0e6d525..9af4073 100644
--- a/tests/libtest/lib670.c
+++ b/tests/libtest/lib670.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,10 +22,14 @@
*
***************************************************************************/
-#include <time.h>
+#if !defined(LIB670) && !defined(LIB671)
+#define CURL_DISABLE_DEPRECATION /* Using and testing the form api */
+#endif
#include "test.h"
+#include <time.h>
+
#include "memdebug.h"
#define PAUSE_TIME 2
diff --git a/tests/libtest/lib674.c b/tests/libtest/lib674.c
index f78f2c9..1a01d9c 100644
--- a/tests/libtest/lib674.c
+++ b/tests/libtest/lib674.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,9 +35,9 @@
{
CURL *handle = NULL;
CURL *handle2;
- CURLcode res = 0;
+ CURLcode res = CURLE_OK;
CURLU *urlp = NULL;
- CURLUcode uc = 0;
+ CURLUcode uc = CURLUE_OK;
global_init(CURL_GLOBAL_ALL);
easy_init(handle);
diff --git a/tests/libtest/lib676.c b/tests/libtest/lib676.c
index aac034a..478d5f3 100644
--- a/tests/libtest/lib676.c
+++ b/tests/libtest/lib676.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -45,7 +45,7 @@
test_setopt(curl, CURLOPT_URL, URL);
test_setopt(curl, CURLOPT_HEADER, 1L);
test_setopt(curl, CURLOPT_USERAGENT, "the-moo agent next generation");
- test_setopt(curl, CURLOPT_COOKIEFILE, "log/cookies676");
+ test_setopt(curl, CURLOPT_COOKIEFILE, libtest_arg2);
test_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
diff --git a/tests/libtest/lib677.c b/tests/libtest/lib677.c
index 4102677..94530b9 100644
--- a/tests/libtest/lib677.c
+++ b/tests/libtest/lib677.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -112,7 +112,7 @@
}
curl_multi_remove_handle(mcurl, curl);
- fail:
+fail:
curl_easy_cleanup(curl);
curl_multi_cleanup(mcurl);
diff --git a/tests/libtest/lib678.c b/tests/libtest/lib678.c
index 23c7f4d..942808e 100644
--- a/tests/libtest/lib678.c
+++ b/tests/libtest/lib678.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,12 +44,12 @@
else
datasize = (size_t)cert_tell;
if(continue_reading)
- continue_reading = fseek(fInCert, 0, SEEK_SET) == 0;
+ continue_reading = fseek(fInCert, 0, SEEK_SET) == 0;
if(continue_reading)
- data = malloc(datasize + 1);
+ data = malloc(datasize + 1);
if((!data) ||
- ((int)fread(data, datasize, 1, fInCert) != 1))
- continue_reading = FALSE;
+ ((int)fread(data, datasize, 1, fInCert) != 1))
+ continue_reading = FALSE;
fclose(fInCert);
if(!continue_reading) {
free(data);
diff --git a/tests/libtest/libauthretry.c b/tests/libtest/libauthretry.c
index 3de5b3f..a71fe20 100644
--- a/tests/libtest/libauthretry.c
+++ b/tests/libtest/libauthretry.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/libntlmconnect.c b/tests/libtest/libntlmconnect.c
index 18b1443..9f1c131 100644
--- a/tests/libtest/libntlmconnect.c
+++ b/tests/libtest/libntlmconnect.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -50,7 +50,9 @@
counter[idx] += (int)(size * nmemb);
/* Get socket being used for this easy handle, otherwise CURL_SOCKET_BAD */
- code = curl_easy_getinfo(easy[idx], CURLINFO_LASTSOCKET, &longdata);
+ CURL_IGNORE_DEPRECATION(
+ code = curl_easy_getinfo(easy[idx], CURLINFO_LASTSOCKET, &longdata);
+ )
if(CURLE_OK != code) {
fprintf(stderr, "%s:%d curl_easy_getinfo() failed, "
"with code %d (%s)\n",
diff --git a/tests/libtest/libprereq.c b/tests/libtest/libprereq.c
index 3aa475c..92369d8 100644
--- a/tests/libtest/libprereq.c
+++ b/tests/libtest/libprereq.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2021 - 2022, Max Dymond, <max.dymond@microsoft.com>
+ * Copyright (C) Max Dymond, <max.dymond@microsoft.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/mk-lib1521.pl b/tests/libtest/mk-lib1521.pl
index 1e00be8..e1418a0 100755
--- a/tests/libtest/mk-lib1521.pl
+++ b/tests/libtest/mk-lib1521.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2017 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -31,6 +31,8 @@
my $maxlong = "LONG_MAX";
# maximum long unsigned value
my $maxulong = "ULONG_MAX";
+my $line = "";
+my $incomment = 0;
print <<HEADER
/***************************************************************************
@@ -40,7 +42,7 @@
* | (__| |_| | _ <| |___
* \\___|\\___/|_| \\_\\_____|
*
- * Copyright (C) 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -56,6 +58,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
+#define CURL_DISABLE_DEPRECATION /* Deprecated options are tested too */
#include "test.h"
#include "memdebug.h"
#include <limits.h>
@@ -182,7 +185,54 @@
;
while(<STDIN>) {
- if($_ =~ /^ CURLOPT\(([^ ]*), ([^ ]*), (\d*)\)/) {
+ s/^\s*(.*?)\s*$/$1/; # Trim.
+ # Remove multi-line comment trail.
+ if($incomment) {
+ if($_ !~ /.*?\*\/\s*(.*)$/) {
+ next;
+ }
+ $_ = $1;
+ $incomment = 0;
+ }
+ if($line ne "") {
+ # Unfold line.
+ $_ = "$line $1";
+ $line = "";
+ }
+ # Remove comments.
+ while($_ =~ /^(.*?)\/\*.*?\*\/(.*)$/) {
+ $_ = "$1 $2";
+ }
+ s/^\s*(.*?)\s*$/$1/; # Trim again.
+ if($_ =~ /^(.*)\/\*/) {
+ $_ = $1;
+ $incomment = 1;
+ }
+ # Ignore preprocessor directives and blank lines.
+ if($_ =~ /^(?:#|$)/) {
+ next;
+ }
+ # Handle lines that may be continued as if they were folded.
+ if($_ !~ /[;,{}]$/) {
+ # Folded line.
+ $line = $_;
+ next;
+ }
+ if($_ =~ / CURL_DEPRECATED\(/) {
+ # Drop deprecation info.
+ if($_ !~ /^(.*?) CURL_DEPRECATED\(.*?"\)(.*)$/) {
+ # Needs unfolding.
+ $line = $_;
+ next;
+ }
+ $_ = $1 . $2;
+ }
+ if($_ =~ /^CURLOPT(?:DEPRECATED)?\(/ && $_ !~ /\),$/) {
+ # Multi-line CURLOPTs need unfolding.
+ $line = $_;
+ next;
+ }
+ if($_ =~ /^CURLOPT(?:DEPRECATED)?\(([^ ]*), ([^ ]*), (\d*)[,)]/) {
my ($name, $type, $val)=($1, $2, $3);
my $w=" ";
my $pref = "${w}res = curl_easy_setopt(curl, $name,";
@@ -258,11 +308,11 @@
exit 22; # exit to make this noticed!
}
}
- elsif($_ =~ /^ CURLINFO_NONE/) {
+ elsif($_ =~ /^CURLINFO_NONE/) {
$infomode = 1;
}
elsif($infomode &&
- ($_ =~ /^ CURLINFO_([^ ]*) *= *CURLINFO_([^ ]*)/)) {
+ ($_ =~ /^CURLINFO_([^ ]*) *= *CURLINFO_([^ ]*)/)) {
my ($info, $type)=($1, $2);
my $c = " res = curl_easy_getinfo(curl, CURLINFO_$info,";
my $check = " if(UNEX(res)) {\n geterr(\"$info\", res, __LINE__);\n goto test_cleanup;\n }\n";
diff --git a/tests/libtest/notexists.pl b/tests/libtest/notexists.pl
index e4c13b7..2bc9bb5 100755
--- a/tests/libtest/notexists.pl
+++ b/tests/libtest/notexists.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/tests/libtest/sethostname.c b/tests/libtest/sethostname.c
index 3ab1241..9dcad97 100644
--- a/tests/libtest/sethostname.c
+++ b/tests/libtest/sethostname.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/sethostname.h b/tests/libtest/sethostname.h
index a0bbc14..1ffcba1 100644
--- a/tests/libtest/sethostname.h
+++ b/tests/libtest/sethostname.h
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/stub_gssapi.c b/tests/libtest/stub_gssapi.c
index 1e9c800..634dddf 100644
--- a/tests/libtest/stub_gssapi.c
+++ b/tests/libtest/stub_gssapi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -65,6 +65,17 @@
char creds[MAX_CREDS_LENGTH];
};
+/* simple implementation of strndup(), which isn't portable */
+static char *my_strndup(const char *ptr, size_t len)
+{
+ char *copy = malloc(len + 1);
+ if(!copy)
+ return NULL;
+ memcpy(copy, ptr, len);
+ copy[len] = '\0';
+ return copy;
+}
+
OM_uint32 gss_init_sec_context(OM_uint32 *min,
gss_const_cred_id_t initiator_cred_handle,
gss_ctx_id_t *context_handle,
@@ -280,7 +291,7 @@
return GSS_S_FAILURE;
}
- name = strndup(input_name_buffer->value, input_name_buffer->length);
+ name = my_strndup(input_name_buffer->value, input_name_buffer->length);
if(!name) {
*min = GSS_NO_MEMORY;
return GSS_S_FAILURE;
diff --git a/tests/libtest/stub_gssapi.h b/tests/libtest/stub_gssapi.h
index 36460e9..d29c69e 100644
--- a/tests/libtest/stub_gssapi.h
+++ b/tests/libtest/stub_gssapi.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -100,85 +100,85 @@
gss_buffer_desc application_data;
} *gss_channel_bindings_t;
-OM_uint32 gss_release_buffer(OM_uint32 * /*minor_status*/,
- gss_buffer_t /*buffer*/);
+OM_uint32 gss_release_buffer(OM_uint32 * /* minor_status */,
+ gss_buffer_t /* buffer */);
-OM_uint32 gss_init_sec_context(OM_uint32 * /*minor_status*/,
- gss_const_cred_id_t /*initiator_cred_handle*/,
- gss_ctx_id_t * /*context_handle*/,
- gss_const_name_t /*target_name*/,
- const gss_OID /*mech_type*/,
- OM_uint32 /*req_flags*/,
- OM_uint32 /*time_req*/,
- const gss_channel_bindings_t /*input_chan_bindings*/,
- const gss_buffer_t /*input_token*/,
- gss_OID * /*actual_mech_type*/,
- gss_buffer_t /*output_token*/,
- OM_uint32 * /*ret_flags*/,
- OM_uint32 * /*time_rec*/);
+OM_uint32 gss_init_sec_context(OM_uint32 * /* minor_status */,
+ gss_const_cred_id_t /* initiator_cred_handle */,
+ gss_ctx_id_t * /* context_handle */,
+ gss_const_name_t /* target_name */,
+ const gss_OID /* mech_type */,
+ OM_uint32 /* req_flags */,
+ OM_uint32 /* time_req */,
+ const gss_channel_bindings_t /* input_chan_bindings */,
+ const gss_buffer_t /* input_token */,
+ gss_OID * /* actual_mech_type */,
+ gss_buffer_t /* output_token */,
+ OM_uint32 * /* ret_flags */,
+ OM_uint32 * /* time_rec */);
-OM_uint32 gss_delete_sec_context(OM_uint32 * /*minor_status*/,
- gss_ctx_id_t * /*context_handle*/,
- gss_buffer_t /*output_token*/);
+OM_uint32 gss_delete_sec_context(OM_uint32 * /* minor_status */,
+ gss_ctx_id_t * /* context_handle */,
+ gss_buffer_t /* output_token */);
-OM_uint32 gss_inquire_context(OM_uint32 * /*minor_status*/,
- gss_const_ctx_id_t /*context_handle*/,
- gss_name_t * /*src_name*/,
- gss_name_t * /*targ_name*/,
- OM_uint32 * /*lifetime_rec*/,
- gss_OID * /*mech_type*/,
- OM_uint32 * /*ctx_flags*/,
- int * /*locally_initiated*/,
- int * /*open_context*/);
+OM_uint32 gss_inquire_context(OM_uint32 * /* minor_status */,
+ gss_const_ctx_id_t /* context_handle */,
+ gss_name_t * /* src_name */,
+ gss_name_t * /* targ_name */,
+ OM_uint32 * /* lifetime_rec */,
+ gss_OID * /* mech_type */,
+ OM_uint32 * /* ctx_flags */,
+ int * /* locally_initiated */,
+ int * /* open_context */);
-OM_uint32 gss_wrap(OM_uint32 * /*minor_status*/,
- gss_const_ctx_id_t /*context_handle*/,
- int /*conf_req_flag*/,
- gss_qop_t /*qop_req*/,
- const gss_buffer_t /*input_message_buffer*/,
- int * /*conf_state*/,
- gss_buffer_t /*output_message_buffer*/);
+OM_uint32 gss_wrap(OM_uint32 * /* minor_status */,
+ gss_const_ctx_id_t /* context_handle */,
+ int /* conf_req_flag */,
+ gss_qop_t /* qop_req */,
+ const gss_buffer_t /* input_message_buffer */,
+ int * /* conf_state */,
+ gss_buffer_t /* output_message_buffer */);
-OM_uint32 gss_unwrap(OM_uint32 * /*minor_status*/,
- gss_const_ctx_id_t /*context_handle*/,
- const gss_buffer_t /*input_message_buffer*/,
- gss_buffer_t /*output_message_buffer*/,
- int * /*conf_state*/,
- gss_qop_t * /*qop_state*/);
+OM_uint32 gss_unwrap(OM_uint32 * /* minor_status */,
+ gss_const_ctx_id_t /* context_handle */,
+ const gss_buffer_t /* input_message_buffer */,
+ gss_buffer_t /* output_message_buffer */,
+ int * /* conf_state */,
+ gss_qop_t * /* qop_state */);
-OM_uint32 gss_seal(OM_uint32 * /*minor_status*/,
- gss_ctx_id_t /*context_handle*/,
- int /*conf_req_flag*/,
- int /*qop_req*/,
- gss_buffer_t /*input_message_buffer*/,
- int * /*conf_state*/,
- gss_buffer_t /*output_message_buffer*/);
+OM_uint32 gss_seal(OM_uint32 * /* minor_status */,
+ gss_ctx_id_t /* context_handle n */,
+ int /* conf_req_flag */,
+ int /* qop_req */,
+ gss_buffer_t /* input_message_buffer */,
+ int * /* conf_state */,
+ gss_buffer_t /* output_message_buffer */);
-OM_uint32 gss_unseal(OM_uint32 * /*minor_status*/,
- gss_ctx_id_t /*context_handle*/,
- gss_buffer_t /*input_message_buffer*/,
- gss_buffer_t /*output_message_buffer*/,
- int * /*conf_state*/,
- int * /*qop_state*/);
+OM_uint32 gss_unseal(OM_uint32 * /* minor_status */,
+ gss_ctx_id_t /* context_handle */,
+ gss_buffer_t /* input_message_buffer */,
+ gss_buffer_t /* output_message_buffer */,
+ int * /* conf_state */,
+ int * /* qop_state */);
-OM_uint32 gss_import_name(OM_uint32 * /*minor_status*/,
- const gss_buffer_t /*input_name_buffer*/,
- const gss_OID /*input_name_type*/,
- gss_name_t * /*output_name*/);
+OM_uint32 gss_import_name(OM_uint32 * /* minor_status */,
+ const gss_buffer_t /* input_name_buffer */,
+ const gss_OID /* input_name_type */,
+ gss_name_t * /* output_name */);
-OM_uint32 gss_release_name(OM_uint32 * /*minor_status*/,
- gss_name_t * /*input_name*/);
+OM_uint32 gss_release_name(OM_uint32 * /* minor_status */,
+ gss_name_t * /* input_name */);
-OM_uint32 gss_display_name(OM_uint32 * /*minor_status*/,
- gss_const_name_t /*input_name*/,
- gss_buffer_t /*output_name_buffer*/,
- gss_OID * /*output_name_type*/);
+OM_uint32 gss_display_name(OM_uint32 * /* minor_status */,
+ gss_const_name_t /* input_name */,
+ gss_buffer_t /* output_name_buffer */,
+ gss_OID * /* output_name_type */);
-OM_uint32 gss_display_status(OM_uint32 * /*minor_status*/,
- OM_uint32 /*status_value*/,
- int /*status_type*/,
- const gss_OID /*mech_type*/,
- OM_uint32 * /*message_context*/,
- gss_buffer_t /*status_string*/);
+OM_uint32 gss_display_status(OM_uint32 * /* minor_status */,
+ OM_uint32 /* status_value */,
+ int /* status_type */,
+ const gss_OID /* mech_type */,
+ OM_uint32 * /* message_context */,
+ gss_buffer_t /* status_string */);
#endif /* HEADER_CURL_GSSAPI_STUBS_H */
diff --git a/tests/libtest/test.h b/tests/libtest/test.h
index f52e05f..7eb7fda 100644
--- a/tests/libtest/test.h
+++ b/tests/libtest/test.h
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,6 +42,10 @@
#include "curl_printf.h"
+#ifdef WIN32
+#define sleep(sec) Sleep ((sec)*1000)
+#endif
+
#define test_setopt(A,B,C) \
if((res = curl_easy_setopt((A), (B), (C))) != CURLE_OK) \
goto test_cleanup
@@ -69,9 +73,7 @@
extern char *hexdump(const unsigned char *buffer, size_t len);
-#ifdef UNITTESTS
extern int unitfail;
-#endif
/*
** TEST_ERR_* values must be greater than CURL_LAST CURLcode in order
@@ -438,12 +440,14 @@
tv_test_start = tutil_tvnow(); \
} while(0)
-#define exe_test_timedout(Y,Z) do { \
- if(tutil_tvdiff(tutil_tvnow(), tv_test_start) > TEST_HANG_TIMEOUT) { \
- fprintf(stderr, "%s:%d ABORTING TEST, since it seems " \
- "that it would have run forever.\n", (Y), (Z)); \
- res = TEST_ERR_RUNS_FOREVER; \
- } \
+#define exe_test_timedout(Y,Z) do { \
+ long timediff = tutil_tvdiff(tutil_tvnow(), tv_test_start); \
+ if(timediff > (TEST_HANG_TIMEOUT)) { \
+ fprintf(stderr, "%s:%d ABORTING TEST, since it seems " \
+ "that it would have run forever (%ld ms > %ld ms)\n", \
+ (Y), (Z), timediff, (long) (TEST_HANG_TIMEOUT)); \
+ res = TEST_ERR_RUNS_FOREVER; \
+ } \
} while(0)
#define res_test_timedout() \
@@ -485,4 +489,12 @@
#define global_init(A) \
chk_global_init((A), (__FILE__), (__LINE__))
+#define NO_SUPPORT_BUILT_IN \
+ int test(char *URL) \
+ { \
+ (void)URL; \
+ fprintf(stderr, "Missing support\n"); \
+ return 1; \
+ }
+
/* ---------------------------------------------------------------- */
diff --git a/tests/libtest/test1013.pl b/tests/libtest/test1013.pl
index 37f798f..aec7fb9 100755
--- a/tests/libtest/test1013.pl
+++ b/tests/libtest/test1013.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/tests/libtest/test1022.pl b/tests/libtest/test1022.pl
index 7339bb4..583b8f8 100755
--- a/tests/libtest/test1022.pl
+++ b/tests/libtest/test1022.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/tests/libtest/test307.pl b/tests/libtest/test307.pl
index 688d934..862f0e9 100755
--- a/tests/libtest/test307.pl
+++ b/tests/libtest/test307.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/tests/libtest/test610.pl b/tests/libtest/test610.pl
index 86c95b8..0ef9330 100755
--- a/tests/libtest/test610.pl
+++ b/tests/libtest/test610.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/tests/libtest/test613.pl b/tests/libtest/test613.pl
index 8d97ed9..3ad7805 100755
--- a/tests/libtest/test613.pl
+++ b/tests/libtest/test613.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/tests/libtest/testtrace.c b/tests/libtest/testtrace.c
index 6f0ae4a..f78a9b9 100644
--- a/tests/libtest/testtrace.c
+++ b/tests/libtest/testtrace.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/testtrace.h b/tests/libtest/testtrace.h
index b0773dc..35f27b0 100644
--- a/tests/libtest/testtrace.h
+++ b/tests/libtest/testtrace.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/libtest/testutil.c b/tests/libtest/testutil.c
index a46e0f9..1a1e689 100644
--- a/tests/libtest/testutil.c
+++ b/tests/libtest/testutil.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -117,7 +117,6 @@
(long)(newer.tv_usec-older.tv_usec)/1000;
}
-
/*
* Same as tutil_tvdiff but with full usec resolution.
*
@@ -130,3 +129,34 @@
(double)(newer.tv_usec-older.tv_usec)/1000000.0;
return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
}
+
+#ifdef WIN32
+HMODULE win32_load_system_library(const TCHAR *filename)
+{
+ size_t filenamelen = _tcslen(filename);
+ size_t systemdirlen = GetSystemDirectory(NULL, 0);
+ size_t written;
+ TCHAR *path;
+
+ if(!filenamelen || filenamelen > 32768 ||
+ !systemdirlen || systemdirlen > 32768)
+ return NULL;
+
+ /* systemdirlen includes null character */
+ path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen));
+ if(!path)
+ return NULL;
+
+ /* if written >= systemdirlen then nothing was written */
+ written = GetSystemDirectory(path, (unsigned int)systemdirlen);
+ if(!written || written >= systemdirlen)
+ return NULL;
+
+ if(path[written - 1] != _T('\\'))
+ path[written++] = _T('\\');
+
+ _tcscpy(path + written, filename);
+
+ return LoadLibrary(path);
+}
+#endif
diff --git a/tests/libtest/testutil.h b/tests/libtest/testutil.h
index 94550fc..36b9448 100644
--- a/tests/libtest/testutil.h
+++ b/tests/libtest/testutil.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,5 +42,8 @@
*/
double tutil_tvdiff_secs(struct timeval t1, struct timeval t2);
+#ifdef WIN32
+HMODULE win32_load_system_library(const TCHAR *filename);
+#endif
#endif /* HEADER_CURL_LIBTEST_TESTUTIL_H */
diff --git a/tests/manpage-scan.pl b/tests/manpage-scan.pl
index 040d517..0a7654d 100755
--- a/tests/manpage-scan.pl
+++ b/tests/manpage-scan.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2016 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -67,9 +67,9 @@
sub scanmanpage {
my ($file, @words) = @_;
- open(M, "<$file");
+ open(my $mh, "<", "$file");
my @m;
- while(<M>) {
+ while(<$mh>) {
if($_ =~ /^\.IP (.*)/) {
my $w = $1;
# "unquote" minuses
@@ -77,7 +77,7 @@
push @m, $w;
}
}
- close(M);
+ close($mh);
foreach my $m (@words) {
my @g = grep(/$m/, @m);
@@ -88,22 +88,24 @@
}
}
+my $r;
+
# check for define alises
-open(R, "<$curlh") ||
+open($r, "<", "$curlh") ||
die "no curl.h";
-while(<R>) {
+while(<$r>) {
if(/^\#define (CURL(OPT|INFO|MOPT)_\w+) (.*)/) {
$alias{$1}=$3;
}
}
-close(R);
+close($r);
my @curlopt;
my @curlinfo;
my @curlmopt;
-open(R, "<$syms") ||
+open($r, "<", "$syms") ||
die "no input file";
-while(<R>) {
+while(<$r>) {
chomp;
my $l= $_;
if($l =~ /(CURL(OPT|INFO|MOPT)_\w+) *([0-9.]*) *([0-9.-]*) *([0-9.]*)/) {
@@ -133,7 +135,7 @@
}
}
}
-close(R);
+close($r);
scanmanpage("$root/docs/libcurl/curl_easy_setopt.3", @curlopt);
scanmanpage("$root/docs/libcurl/curl_easy_getinfo.3", @curlinfo);
@@ -174,12 +176,12 @@
#########################################################################
# parse the curl code that parses the command line arguments!
-open(R, "<$root/src/tool_getparam.c") ||
+open($r, "<", "$root/src/tool_getparam.c") ||
die "no input file";
my $list;
my @getparam; # store all parsed parameters
-while(<R>) {
+while(<$r>) {
chomp;
my $l= $_;
if(/struct LongShort aliases/) {
@@ -206,15 +208,15 @@
}
}
}
-close(R);
+close($r);
#########################################################################
# parse the curl.1 man page, extract all documented command line options
# The man page may or may not be rebuilt, so check both possible locations
-open(R, "<$buildroot/docs/curl.1") || open(R, "<$root/docs/curl.1") ||
+open($r, "<", "$buildroot/docs/curl.1") || open($r, "<", "$root/docs/curl.1") ||
die "no input file";
my @manpage; # store all parsed parameters
-while(<R>) {
+while(<$r>) {
chomp;
my $l= $_;
$l =~ s/\\-/-/g;
@@ -235,15 +237,15 @@
}
}
}
-close(R);
+close($r);
#########################################################################
# parse the curl code that outputs the curl -h list
-open(R, "<$root/src/tool_listhelp.c") ||
+open($r, "<", "$root/src/tool_listhelp.c") ||
die "no input file";
my @toolhelp; # store all parsed parameters
-while(<R>) {
+while(<$r>) {
chomp;
my $l= $_;
if(/^ \{\" *(.*)/) {
@@ -264,7 +266,7 @@
}
}
-close(R);
+close($r);
#
# Now we have three arrays with options to cross-reference.
diff --git a/tests/manpage-syntax.pl b/tests/manpage-syntax.pl
old mode 100644
new mode 100755
index 49ab5b8..31b212f
--- a/tests/manpage-syntax.pl
+++ b/tests/manpage-syntax.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -62,15 +62,32 @@
my %shline; # section => line number
my %symbol;
+
+# some CURLINFO_ symbols are not actual options for curl_easy_getinfo,
+# mark them as "deprecated" to hide them from link-warnings
+my %deprecated = (
+ CURLINFO_TEXT => 1,
+ CURLINFO_HEADER_IN => 1,
+ CURLINFO_HEADER_OUT => 1,
+ CURLINFO_DATA_IN => 1,
+ CURLINFO_DATA_OUT => 1,
+ CURLINFO_SSL_DATA_IN => 1,
+ CURLINFO_SSL_DATA_OUT => 1,
+ );
sub allsymbols {
- open(F, "<$symbolsinversions") ||
+ open(my $f, "<", "$symbolsinversions") ||
die "$symbolsinversions: $|";
- while(<F>) {
- if($_ =~ /^([^ ]*)/) {
- $symbol{$1}=$1;
+ while(<$f>) {
+ if($_ =~ /^([^ ]*) +(.*)/) {
+ my ($name, $info) = ($1, $2);
+ $symbol{$name}=$name;
+
+ if($info =~ /([0-9.]+) +([0-9.]+)/) {
+ $deprecated{$name}=$info;
+ }
}
}
- close(F);
+ close($f);
}
sub scanmanpage {
@@ -83,8 +100,9 @@
my $shc = 0;
my $optpage = 0; # option or function
my @sh;
+ my $SH="";
- open(M, "<$file") || die "no such file: $file";
+ open(my $m, "<", "$file") || die "no such file: $file";
if($file =~ /[\/\\](CURL|curl_)[^\/\\]*.3/) {
# This is a man page for libcurl. It requires an example!
$reqex = 1;
@@ -93,11 +111,11 @@
}
}
my $line = 1;
- while(<M>) {
+ while(<$m>) {
chomp;
if($_ =~ /^.so /) {
# this man page is just a referral
- close(M);
+ close($m);
return;
}
if(($_ =~ /^\.SH SYNOPSIS/i) && ($reqex)) {
@@ -131,6 +149,7 @@
$n =~ s/\"(.*)\"\z/$1/;
push @sh, $n;
$shline{$n} = $line;
+ $SH = $n;
}
if($_ =~ /^\'/) {
@@ -144,6 +163,27 @@
$errors++;
}
}
+ if($_ =~ /(.*)\\f([^BIP])/) {
+ my ($pre, $format) = ($1, $2);
+ if($pre !~ /\\\z/) {
+ # only if there wasn't another backslash before the \f
+ print STDERR "$file:$line suspicious \\f format!\n";
+ $errors++;
+ }
+ }
+ if($optpage && $SH && ($SH !~ /^(SYNOPSIS|EXAMPLE|NAME|SEE ALSO)/i) &&
+ ($_ =~ /(.*)(CURL(OPT_|MOPT_|INFO_)[A-Z0-9_]*)/)) {
+ # an option with its own man page, check that it is tagged
+ # for linking
+ my ($pref, $symbol) = ($1, $2);
+ if($deprecated{$symbol}) {
+ # let it be
+ }
+ elsif($pref !~ /\\fI\z/) {
+ print STDERR "$file:$line option $symbol missing \\fI tagging\n";
+ $errors++;
+ }
+ }
if($_ =~ /[ \t]+$/) {
print STDERR "$file:$line trailing whitespace\n";
$errors++;
@@ -160,7 +200,7 @@
}
$line++;
}
- close(M);
+ close($m);
if($reqex) {
# only for libcurl options man-pages
diff --git a/tests/markdown-uppercase.pl b/tests/markdown-uppercase.pl
new file mode 100755
index 0000000..707f286
--- /dev/null
+++ b/tests/markdown-uppercase.pl
@@ -0,0 +1,100 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+my $root=$ARGV[0] || "..";
+
+my @m = `git ls-files -- $root`;
+
+my $errors;
+
+my %accepted=('curl' => 1,
+ 'libcurl' => 1);
+
+sub checkfile {
+ my ($f) = @_;
+ chomp $f;
+ if($f !~ /\.md\z/) {
+ return;
+ }
+ open(my $fh, "<", "$f");
+ my $l = 1;
+ my $prevl;
+ my $ignore = 0;
+ while(<$fh>) {
+ my $line = $_;
+ chomp $line;
+ if($line =~ /^(\`\`\`|\~\~\~)/) {
+ # start or stop ignore-mode
+ $ignore ^= 1;
+ }
+ if(!$ignore) {
+ if(($prevl =~ /\.\z/) && ($line =~ /^( *)([a-z]+)/)) {
+ my ($prefix, $word) = ($1, $2);
+ if(!$accepted{$word}) {
+ my $c = length($prefix);
+ print STDERR
+ "$f:$l:$c:error: lowercase $word after period\n";
+ print STDERR "$line\n";
+ print STDERR ' ' x $c;
+ print STDERR "^\n";
+ $errors++;
+ }
+ }
+ elsif($line =~ /^(.*)\. +([a-z]+)/) {
+ my ($prefix, $word) = ($1, $2);
+
+ if(($prefix =~ /\.\.\z/) ||
+ ($prefix =~ /[0-9]\z/) ||
+ ($prefix =~ /e.g\z/) ||
+ ($prefix =~ /i.e\z/) ||
+ ($prefix =~ /etc\z/) ||
+ $accepted{$word}) {
+ }
+ else {
+ my $c = length($prefix) + 2;
+ print STDERR
+ "$f:$l:$c:error: lowercase $word after period\n";
+ print STDERR "$line\n";
+ print STDERR ' ' x $c;
+ print STDERR "^\n";
+ $errors++;
+ }
+ }
+ }
+ $prevl = $line;
+ $l++;
+ }
+ close($fh);
+}
+
+
+for my $f (@m) {
+ checkfile($f);
+}
+
+if($errors) {
+ exit 1;
+}
+print "ok\n";
diff --git a/tests/mem-include-scan.pl b/tests/mem-include-scan.pl
index 52b8155..e808c2e 100755
--- a/tests/mem-include-scan.pl
+++ b/tests/mem-include-scan.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -43,8 +43,8 @@
print STDERR "checking $file...\n";
- open(F, "<$file");
- while(<F>) {
+ open(my $f, "<", "$file");
+ while(<$f>) {
if($_ =~ /\W(free|alloc|strdup)\(/) {
$memfunc++;
}
@@ -56,14 +56,14 @@
}
elsif($_ =~ /mem-include-scan/) {
# free pass
- close(F);
+ close($f);
return 0;
}
if($memfunc && $memdebug && $curlmem) {
last;
}
}
- close(F);
+ close($f);
if($memfunc) {
diff --git a/tests/memanalyze.pl b/tests/memanalyze.pl
index ee344f7..4e164fe 100755
--- a/tests/memanalyze.pl
+++ b/tests/memanalyze.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -81,22 +81,22 @@
exit;
}
-open(FILE, "<$file");
+open(my $fileh, "<", "$file");
if($showlimit) {
- while(<FILE>) {
+ while(<$fileh>) {
if(/^LIMIT.*memlimit$/) {
print $_;
last;
}
}
- close(FILE);
+ close($fileh);
exit;
}
my $lnum=0;
-while(<FILE>) {
+while(<$fileh>) {
chomp $_;
$line = $_;
$lnum++;
@@ -375,7 +375,7 @@
print "Not recognized prefix line: $line\n";
}
}
-close(FILE);
+close($fileh);
if($totalmem) {
print "Leak detected: memory still allocated: $totalmem bytes\n";
diff --git a/tests/negtelnetserver.py b/tests/negtelnetserver.py
index 2b748af..8c04bdc 100755
--- a/tests/negtelnetserver.py
+++ b/tests/negtelnetserver.py
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2017 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -29,7 +29,9 @@
import argparse
import logging
import os
+import socket
import sys
+import time
from util import ClosingFileHandler
@@ -66,9 +68,9 @@
# Need to set the allow_reuse on the class, not on the instance.
socketserver.TCPServer.allow_reuse_address = True
- server = socketserver.TCPServer(local_bind, NegotiatingTelnetHandler)
- server.serve_forever()
-
+ with socketserver.TCPServer(local_bind, NegotiatingTelnetHandler) as server:
+ server.serve_forever()
+ # leaving `with` calls server.close() automatically
return ScriptRC.SUCCESS
@@ -90,7 +92,7 @@
neg.send_wont("NAWS")
# Get the data passed through the negotiator
- data = neg.recv(1024)
+ data = neg.recv(4*1024)
log.debug("Incoming data: %r", data)
if VERIFIED_REQ.encode('utf-8') in data:
@@ -109,6 +111,12 @@
log.debug("Sending %r", response_data)
self.request.sendall(response_data)
+ # put some effort into making a clean socket shutdown
+ # that does not give the client ECONNRESET
+ self.request.settimeout(0.1)
+ self.request.recv(4*1024)
+ self.request.shutdown(socket.SHUT_RDWR)
+
except IOError:
log.exception("IOError hit during request")
diff --git a/tests/fuzz/download_fuzzer.sh b/tests/nghttpx.conf
old mode 100755
new mode 100644
similarity index 77%
copy from tests/fuzz/download_fuzzer.sh
copy to tests/nghttpx.conf
index e9d6be4..71aa7bc
--- a/tests/fuzz/download_fuzzer.sh
+++ b/tests/nghttpx.conf
@@ -1,4 +1,3 @@
-#!/bin/bash
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
@@ -6,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,8 +22,5 @@
#
###########################################################################
-# If any commands fail, fail the script immediately.
-set -ex
-
-# Clone the curl-fuzzer repository to the specified directory.
-git clone --depth=1 https://github.com/curl/curl-fuzzer "$1"
+# nghttpx reads /etc/nghttpx/nghttpx.conf if we do not give it another one.
+# This is what this otherwise empty file is for.
diff --git a/tests/nroff-scan.pl b/tests/nroff-scan.pl
index 161721f..4dddf7c 100755
--- a/tests/nroff-scan.pl
+++ b/tests/nroff-scan.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2016 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -56,14 +56,18 @@
sub file {
my ($f) = @_;
- open(F, "<$f") ||
+ open(my $fh, "<", "$f") ||
die "no file";
my $line = 1;
- while(<F>) {
+ while(<$fh>) {
chomp;
my $l = $_;
while($l =~ s/\\f(.)([^ ]*)\\f(.)//) {
my ($pre, $str, $post)=($1, $2, $3);
+ if($str =~ /^\\f[ib]/i) {
+ print "error: $f:$line: double-highlight\n";
+ $errors++;
+ }
if($post ne "P") {
print "error: $f:$line: missing \\fP after $str\n";
$errors++;
@@ -96,7 +100,7 @@
}
$line++;
}
- close(F);
+ close($fh);
}
foreach my $f (@f) {
diff --git a/tests/option-check.pl b/tests/option-check.pl
new file mode 100755
index 0000000..74d4651
--- /dev/null
+++ b/tests/option-check.pl
@@ -0,0 +1,66 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+sub showline {
+ my ($l) = @_;
+ $l =~ s/([^\x20-\x7f])/sprintf "%%%02x", ord $1/eg;
+ return $l;
+}
+
+my $root = $ARGV[0];
+
+open(my $fh, "-|", "perl $root/lib/optiontable.pl < $root/include/curl/curl.h");
+binmode $fh;
+my @gen=<$fh>;
+close($fh);
+
+open($fh, "<", "$root/lib/easyoptions.c");
+binmode $fh;
+my @file=<$fh>;
+close($fh);
+
+if(join("", @gen) ne join("", @file)) {
+ print "easyoptions.c need to be regenerated!\n";
+
+ printf "easyoptions.c is %u lines\n", scalar(@file);
+ printf "generated file is %u lines\n", scalar(@gen);
+ my $e = 0;
+ for my $i (0 .. $#gen) {
+ # strip CRLFs to unify
+ $gen[$i] =~ s/[\r\n]//g;
+ $file[$i] =~ s/[\r\n]//g;
+ if($gen[$i] ne $file[$i]) {
+ printf "File: %u:%s\nGen: %u:%s\n",
+ $i+1, showline($file[$i]),
+ $i+1, showline($gen[$i]);
+ $e++;
+ if($e > 10) {
+ # only show 10 lines diff
+ last;
+ }
+ }
+ }
+ exit 1 if($e);
+}
diff --git a/tests/options-scan.pl b/tests/options-scan.pl
old mode 100644
new mode 100755
index de84123..05e50bf
--- a/tests/options-scan.pl
+++ b/tests/options-scan.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -50,8 +50,8 @@
sub mentions {
my ($f) = @_;
my @options;
- open(F, "<$f");
- while(<F>) {
+ open(my $fh, "<", "$f");
+ while(<$fh>) {
chomp;
if(/(.*) +([0-9.]+)/) {
my ($flag, $version)=($1, $2);
@@ -71,13 +71,14 @@
$oiv{$flag} = $version;
}
}
+ close($fh);
return @options;
}
sub versioncheck {
my ($f, $v)=@_;
- open(F, "<$cmddir/$f.d");
- while(<F>) {
+ open(my $fh, "<", "$cmddir/$f.d");
+ while(<$fh>) {
chomp;
if(/^Added: ([0-9.]+)/) {
if($1 ne $v) {
@@ -87,7 +88,7 @@
last;
}
}
- close(F);
+ close($fh);
}
# get all the files
diff --git a/tests/pathhelp.pm b/tests/pathhelp.pm
index 2c65947..7d924b8 100644
--- a/tests/pathhelp.pm
+++ b/tests/pathhelp.pm
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2016 - 2022, Evgeny Grin (Karlson2k), <k2k@narod.ru>.
+# Copyright (C) Evgeny Grin (Karlson2k), <k2k@narod.ru>.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -49,30 +49,24 @@
# interpreted incorrectly in Perl and Msys/Cygwin environment have low
# control on Win32 current drive and Win32 current path on specific drive.
-
package pathhelp;
+
use strict;
use warnings;
use Cwd 'abs_path';
BEGIN {
- require Exporter;
-
- our @ISA = qw(Exporter);
-
- our @EXPORT = qw(
- sys_native_abs_path
- sys_native_path
- );
+ use base qw(Exporter);
our @EXPORT_OK = qw(
- build_sys_abs_path
- sys_native_current_path
- normalize_path
- os_is_win
- $use_cygpath
- should_use_cygpath
- drives_mounted_on_cygdrive
+ os_is_win
+ exe_ext
+ sys_native_abs_path
+ sys_native_current_path
+ build_sys_abs_path
+ normalize_path
+ should_use_cygpath
+ drives_mounted_on_cygdrive
);
}
@@ -102,21 +96,19 @@
}
}
-our $use_cygpath; # Only for Win32:
+my $use_cygpath; # Only for Win32:
# undef - autodetect
- # 1 - use cygpath
# 0 - do not use cygpath
+ # 1 - use cygpath
# Returns boolean true if 'cygpath' utility should be used for path conversion.
sub should_use_cygpath {
- unless (os_is_win()) {
- $use_cygpath = 0;
- return 0;
- }
return $use_cygpath if defined $use_cygpath;
-
- $use_cygpath = (qx{cygpath -u '.\\' 2>/dev/null} eq "./\n" && $? == 0);
-
+ if(os_is_win()) {
+ $use_cygpath = (qx{cygpath -u '.\\' 2>/dev/null} eq "./\n" && $? == 0);
+ } else {
+ $use_cygpath = 0;
+ }
return $use_cygpath;
}
@@ -134,7 +126,7 @@
# Returns current working directory in Win32 format on Windows.
#
sub sys_native_current_path {
- return Cwd::getcwd() unless os_is_win();
+ return Cwd::getcwd() if !os_is_win();
my $cur_dir;
if($^O eq 'msys') {
@@ -203,7 +195,7 @@
my ($path) = @_;
# Return untouched on non-Windows platforms.
- return $path unless (os_is_win());
+ return $path if (!os_is_win());
# Do not process empty path.
return $path if ($path eq '');
@@ -233,7 +225,7 @@
# Convert leading slash back to forward slash to indicate
# directory on Win32 current drive or capitalize drive letter.
- substr($path, 0, 1) = $first_char;
+ substr($path, 0, 1, $first_char);
return $path;
}
elsif(should_use_cygpath()) {
@@ -266,7 +258,7 @@
# program parameters if program is not Msys-based.
$path = do_msys_transform($path);
- return undef unless defined $path;
+ return undef if !defined $path;
# Capitalize drive letter for Win32 paths.
$path =~ s{^([a-z]:)}{\u$1};
@@ -303,7 +295,7 @@
sub sys_native_abs_path {
my ($path) = @_;
- unless(os_is_win()) {
+ if(!os_is_win()) {
# Convert path to absolute form.
$path = Cwd::abs_path($path);
@@ -362,7 +354,7 @@
# Path is directory or filename on Win32 current drive. ('\Windows')
my $w32drive = get_win32_current_drive();
- return undef unless defined $w32drive;
+ return undef if !defined $w32drive;
# Combine drive and path.
# Replace any possible back slashes with forward slashes,
@@ -370,7 +362,7 @@
return normalize_path($w32drive . $path);
}
- unless (substr($path, 0, 1) eq '/') {
+ if(substr($path, 0, 1) ne '/') {
# Path is in relative form. Resolve relative directories in Unix form
# *BEFORE* converting to Win32 form otherwise paths like
# '../../../cygdrive/c/windows' will not be resolved.
@@ -400,7 +392,7 @@
# Msys transforms automatically path to Windows native form in staring
# program parameters if program is not Msys-based.
$path = do_msys_transform($path);
- return undef unless defined $path;
+ return undef if !defined $path;
# Replace any back and duplicated slashes with single forward slashes.
$path =~ s{[\\/]+}{/}g;
@@ -423,7 +415,7 @@
sub build_sys_abs_path {
my ($path) = @_;
- unless(os_is_win()) {
+ if(!os_is_win()) {
# Convert path to absolute form.
$path = Cwd::abs_path($path);
@@ -442,7 +434,7 @@
# Replace any possible back slashes with forward slashes,
# remove any duplicated slashes.
$path = get_abs_path_on_win32_drive($1, $2);
- return undef unless defined $path;
+ return undef if !defined $path;
return simple_transform_win32_to_unix($path);
}
@@ -475,7 +467,7 @@
# Unix-style paths.
# Remove duplicated slashes, as they may be not processed.
$path = normalize_path($path);
- return undef unless defined $path;
+ return undef if !defined $path;
# Use 'cygpath', '-u' means Unix-stile path,
# '-a' means absolute path
@@ -500,7 +492,7 @@
# Replace any possible back slashes with forward slashes,
# remove any duplicated slashes.
$path = normalize_path($path);
- return undef unless defined $path;
+ return undef if !defined $path;
return simple_transform_win32_to_unix($path);
}
@@ -508,7 +500,7 @@
# Path is directory or filename on Win32 current drive. ('\Windows')
my $w32drive = get_win32_current_drive();
- return undef unless defined $w32drive;
+ return undef if !defined $w32drive;
# Combine drive and path.
# Resolve relative dirs in Win32-style path or paths like 'D:/../c/'
@@ -516,13 +508,13 @@
# Replace any possible back slashes with forward slashes,
# remove any duplicated slashes.
$path = normalize_path($w32drive . $path);
- return undef unless defined $path;
+ return undef if !defined $path;
return simple_transform_win32_to_unix($path);
}
# Path is not in any Win32 form.
- unless (substr($path, 0, 1) eq '/') {
+ if(substr($path, 0, 1) ne '/') {
# Path in relative form. Resolve relative directories in Unix form
# *BEFORE* converting to Win32 form otherwise paths like
# '../../../cygdrive/c/windows' will not be resolved.
@@ -561,12 +553,12 @@
# Don't process empty paths.
return $path if $path eq '';
- unless($path =~ m{(?:^|\\|/)\.{1,2}(?:\\|/|$)}) {
+ if($path !~ m{(?:^|\\|/)\.{1,2}(?:\\|/|$)}) {
# Speed up processing of simple paths.
my $first_char = substr($path, 0, 1);
$path =~ s{[\\/]+}{/}g;
# Restore starting backslash if any.
- substr($path, 0, 1) = $first_char;
+ substr($path, 0, 1, $first_char);
return $path;
}
@@ -581,7 +573,7 @@
# Process path separately from drive letter.
@arr = split(m{\/|\\}, $3);
# Replace backslash with forward slash if required.
- substr($prefix, 2, 1) = '/' if $have_root;
+ substr($prefix, 2, 1, '/') if $have_root;
}
else {
if($path =~ m{^(\/|\\)}) {
@@ -601,7 +593,7 @@
if(length($el) == 0 || $el eq '.') {
next;
}
- elsif($el eq '..' && @res > 0 && $res[$#res] ne '..') {
+ elsif($el eq '..' && @res > 0 && $res[-1] ne '..') {
pop @res;
next;
}
@@ -717,7 +709,7 @@
# '/bin/' can be mapped to '/usr/bin/'.
my $check_path = $path;
my $path_tail = '';
- do {
+ while(1) {
if(-d $check_path) {
my $res =
`(cd "$check_path" && cmd /c "echo %__CD__%") 2>/dev/null`;
@@ -732,7 +724,7 @@
return $res . $path_tail;
}
else {
- $res =~ s{/$}{} unless $check_path =~ m{/$};
+ $res =~ s{/$}{} if $check_path !~ m{/$};
return $res;
}
}
@@ -747,7 +739,7 @@
warn "Can't determine Win32 directory for path \"$path\".\n";
return undef;
}
- } while(1);
+ }
}
@@ -772,7 +764,7 @@
}
# 'cygpath' is not available, use guessed transformation.
- unless($path =~ s{^([a-zA-Z]):(?:/|\\)}{/\l$1/}) {
+ if($path !~ s{^([a-zA-Z]):(?:/|\\)}{/\l$1/}) {
warn "Can't determine Unix-style directory for Win32 " .
"directory \"$path\".\n";
return undef;
@@ -781,5 +773,22 @@
$path = '/cygdrive' . $path if(drives_mounted_on_cygdrive());
return $path;
}
+#
+#***************************************************************************
+# Return file extension for executable files on this operating system
+#
+sub exe_ext {
+ my ($component, @arr) = @_;
+ if ($ENV{'CURL_TEST_EXE_EXT'}) {
+ return $ENV{'CURL_TEST_EXE_EXT'};
+ }
+ if ($ENV{'CURL_TEST_EXE_EXT_'.$component}) {
+ return $ENV{'CURL_TEST_EXE_EXT_'.$component};
+ }
+ if ($^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys' ||
+ $^O eq 'dos' || $^O eq 'os2') {
+ return '.exe';
+ }
+}
1; # End of module
diff --git a/tests/ftp.pm b/tests/processhelp.pm
similarity index 91%
rename from tests/ftp.pm
rename to tests/processhelp.pm
index 428befd..170863f 100644
--- a/tests/ftp.pm
+++ b/tests/processhelp.pm
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -22,7 +22,27 @@
#
###########################################################################
+package processhelp;
+
+use strict;
+use warnings;
+
BEGIN {
+ use base qw(Exporter);
+
+ our @EXPORT = qw(
+ portable_sleep
+ pidfromfile
+ pidexists
+ pidwait
+ processexists
+ killpid
+ killsockfilters
+ killallsockfilters
+ set_advisor_read_lock
+ clear_advisor_read_lock
+ );
+
# portable sleeping needs Time::HiRes
eval {
no warnings "all";
@@ -35,9 +55,6 @@
}
}
-use strict;
-use warnings;
-
use serverhelp qw(
servername_id
mainsockf_pidfilename
@@ -79,10 +96,10 @@
my $pidfile = $_[0];
my $pid = 0;
- if(-f $pidfile && -s $pidfile && open(PIDFH, "<$pidfile")) {
- $pid = 0 + <PIDFH>;
- close(PIDFH);
- $pid = 0 unless($pid > 0);
+ if(-f $pidfile && -s $pidfile && open(my $pidfh, "<", "$pidfile")) {
+ $pid = 0 + <$pidfh>;
+ close($pidfh);
+ $pid = 0 if($pid < 0);
}
return $pid;
}
@@ -230,8 +247,8 @@
# with a SIGTERM signal and SIGKILLs those which haven't died on time.
#
sub killpid {
- use POSIX ":sys_wait_h";
my ($verbose, $pidlist) = @_;
+ use POSIX ":sys_wait_h";
my @requested;
my @signalled;
my @reapchild;
@@ -322,7 +339,7 @@
# killsockfilters kills sockfilter processes for a given server.
#
sub killsockfilters {
- my ($proto, $ipvnum, $idnum, $verbose, $which) = @_;
+ my ($piddir, $proto, $ipvnum, $idnum, $verbose, $which) = @_;
my $server;
my $pidfile;
my $pid;
@@ -335,7 +352,7 @@
$server = servername_id($proto, $ipvnum, $idnum) if($verbose);
if(!$which || ($which eq 'main')) {
- $pidfile = mainsockf_pidfilename($proto, $ipvnum, $idnum);
+ $pidfile = mainsockf_pidfilename($piddir, $proto, $ipvnum, $idnum);
$pid = processexists($pidfile);
if($pid > 0) {
printf("* kill pid for %s-%s => %d\n", $server,
@@ -349,7 +366,7 @@
return if($proto ne 'ftp');
if(!$which || ($which eq 'data')) {
- $pidfile = datasockf_pidfilename($proto, $ipvnum, $idnum);
+ $pidfile = datasockf_pidfilename($piddir, $proto, $ipvnum, $idnum);
$pid = processexists($pidfile);
if($pid > 0) {
printf("* kill pid for %s-data => %d\n", $server,
@@ -365,12 +382,12 @@
# killallsockfilters kills sockfilter processes for all servers.
#
sub killallsockfilters {
- my $verbose = $_[0];
+ my ($piddir, $verbose) = @_;
for my $proto (('ftp', 'imap', 'pop3', 'smtp')) {
for my $ipvnum (('4', '6')) {
for my $idnum (('1', '2')) {
- killsockfilters($proto, $ipvnum, $idnum, $verbose);
+ killsockfilters($piddir, $proto, $ipvnum, $idnum, $verbose);
}
}
}
@@ -380,11 +397,11 @@
sub set_advisor_read_lock {
my ($filename) = @_;
- if(open(FILEH, ">$filename")) {
- close(FILEH);
+ my $fileh;
+ if(open($fileh, ">", "$filename") && close($fileh)) {
return;
}
- printf "Error creating lock file $filename error: $!";
+ printf "Error creating lock file $filename error: $!\n";
}
diff --git a/tests/fuzz/download_fuzzer.sh b/tests/requirements.txt
old mode 100755
new mode 100644
similarity index 77%
copy from tests/fuzz/download_fuzzer.sh
copy to tests/requirements.txt
index e9d6be4..706043a
--- a/tests/fuzz/download_fuzzer.sh
+++ b/tests/requirements.txt
@@ -1,4 +1,4 @@
-#!/bin/bash
+# -*- coding: utf-8 -*-
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -22,9 +22,5 @@
# SPDX-License-Identifier: curl
#
###########################################################################
-
-# If any commands fail, fail the script immediately.
-set -ex
-
-# Clone the curl-fuzzer repository to the specified directory.
-git clone --depth=1 https://github.com/curl/curl-fuzzer "$1"
+#
+impacket
diff --git a/tests/rtspserver.pl b/tests/rtspserver.pl
index 40b1bc7..3282d9c 100755
--- a/tests/rtspserver.pl
+++ b/tests/rtspserver.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,20 +23,20 @@
#
#***************************************************************************
+use strict;
+use warnings;
+
BEGIN {
push(@INC, $ENV{'srcdir'}) if(defined $ENV{'srcdir'});
push(@INC, ".");
}
-use strict;
-use warnings;
-
use serverhelp qw(
server_pidfilename
server_logfilename
);
-use sshhelp qw(
+use pathhelp qw(
exe_ext
);
@@ -73,6 +73,12 @@
shift @ARGV;
}
}
+ elsif($ARGV[0] eq '--logdir') {
+ if($ARGV[1]) {
+ $logdir = $ARGV[1];
+ shift @ARGV;
+ }
+ }
elsif($ARGV[0] eq '--srcdir') {
if($ARGV[1]) {
$srcdir = $ARGV[1];
@@ -106,19 +112,24 @@
shift @ARGV;
}
+#***************************************************************************
+# Initialize command line option dependent variables
+#
+
+if(!$pidfile) {
+ $pidfile = server_pidfilename($path, $proto, $ipvnum, $idnum);
+}
if(!$srcdir) {
$srcdir = $ENV{'srcdir'} || '.';
}
-if(!$pidfile) {
- $pidfile = "$path/". server_pidfilename($proto, $ipvnum, $idnum);
-}
if(!$logfile) {
$logfile = server_logfilename($logdir, $proto, $ipvnum, $idnum);
}
$flags .= "--pidfile \"$pidfile\" ".
"--portfile \"$portfile\" ".
- "--logfile \"$logfile\" ";
+ "--logfile \"$logfile\" ".
+ "--logdir \"$logdir\" ";
$flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\"";
$| = 1;
diff --git a/tests/runner.pm b/tests/runner.pm
new file mode 100644
index 0000000..b1fe185
--- /dev/null
+++ b/tests/runner.pm
@@ -0,0 +1,1439 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+# This module contains entry points to run a single test. runner_init
+# determines whether they will run in a separate process or in the process of
+# the caller. The relevant interface is asynchronous so it will work in either
+# case. Program arguments are marshalled and then written to the end of a pipe
+# (in controlleripccall) which is later read from and the arguments
+# unmarshalled (in ipcrecv) before the desired function is called normally.
+# The function return values are then marshalled and written into another pipe
+# (again in ipcrecv) when is later read from and unmarshalled (in runnerar)
+# before being returned to the caller.
+
+package runner;
+
+use strict;
+use warnings;
+use 5.006;
+
+BEGIN {
+ use base qw(Exporter);
+
+ our @EXPORT = qw(
+ checktestcmd
+ prepro
+ readtestkeywords
+ restore_test_env
+ runner_init
+ runnerac_clearlocks
+ runnerac_shutdown
+ runnerac_stopservers
+ runnerac_test_preprocess
+ runnerac_test_run
+ runnerar
+ runnerar_ready
+ stderrfilename
+ stdoutfilename
+ $DBGCURL
+ $gdb
+ $gdbthis
+ $gdbxwin
+ $shallow
+ $tortalloc
+ $valgrind_logfile
+ $valgrind_tool
+ );
+
+ # these are for debugging only
+ our @EXPORT_OK = qw(
+ singletest_preprocess
+ );
+}
+
+use B qw(
+ svref_2object
+ );
+use Storable qw(
+ freeze
+ thaw
+ );
+
+use pathhelp qw(
+ exe_ext
+ );
+use processhelp qw(
+ portable_sleep
+ );
+use servers qw(
+ checkcmd
+ clearlocks
+ initserverconfig
+ serverfortest
+ stopserver
+ stopservers
+ subvariables
+ );
+use getpart;
+use globalconfig;
+use testutil qw(
+ clearlogs
+ logmsg
+ runclient
+ shell_quote
+ subbase64
+ subnewlines
+ );
+use valgrind;
+
+
+#######################################################################
+# Global variables set elsewhere but used only by this package
+# These may only be set *before* runner_init is called
+our $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging
+our $valgrind_logfile="--log-file"; # the option name for valgrind >=3
+our $valgrind_tool="--tool=memcheck";
+our $gdb = checktestcmd("gdb");
+our $gdbthis; # run test case with gdb debugger
+our $gdbxwin; # use windowed gdb when using gdb
+
+# torture test variables
+our $shallow;
+our $tortalloc;
+
+# local variables
+my %oldenv; # environment variables before test is started
+my $UNITDIR="./unit";
+my $CURLLOG="$LOGDIR/commands.log"; # all command lines run
+my $defserverlogslocktimeout = 2; # timeout to await server logs lock removal
+my $defpostcommanddelay = 0; # delay between command and postcheck sections
+my $multiprocess; # nonzero with a separate test runner process
+
+# pipes
+my $runnerr; # pipe that runner reads from
+my $runnerw; # pipe that runner writes to
+
+# per-runner variables, indexed by runner ID; these are used by controller only
+my %controllerr; # pipe that controller reads from
+my %controllerw; # pipe that controller writes to
+
+# redirected stdout/stderr to these files
+sub stdoutfilename {
+ my ($logdir, $testnum)=@_;
+ return "$logdir/stdout$testnum";
+}
+
+sub stderrfilename {
+ my ($logdir, $testnum)=@_;
+ return "$logdir/stderr$testnum";
+}
+
+#######################################################################
+# Initialize the runner and prepare it to run tests
+# The runner ID returned by this function must be passed into the other
+# runnerac_* functions
+# Called by controller
+sub runner_init {
+ my ($logdir, $jobs)=@_;
+
+ $multiprocess = !!$jobs;
+
+ # enable memory debugging if curl is compiled with it
+ $ENV{'CURL_MEMDEBUG'} = "$logdir/$MEMDUMP";
+ $ENV{'CURL_ENTROPY'}="12345678";
+ $ENV{'CURL_FORCETIME'}=1; # for debug NTLM magic
+ $ENV{'CURL_GLOBAL_INIT'}=1; # debug curl_global_init/cleanup use
+ $ENV{'HOME'}=$pwd;
+ $ENV{'CURL_HOME'}=$ENV{'HOME'};
+ $ENV{'XDG_CONFIG_HOME'}=$ENV{'HOME'};
+ $ENV{'COLUMNS'}=79; # screen width!
+
+ # Incorporate the $logdir into the random seed and re-seed the PRNG.
+ # This gives each runner a unique yet consistent seed which provides
+ # more unique port number selection in each runner, yet is deterministic
+ # across runs.
+ $randseed += unpack('%16C*', $logdir);
+ srand $randseed;
+
+ # create pipes for communication with runner
+ my ($thisrunnerr, $thiscontrollerw, $thiscontrollerr, $thisrunnerw);
+ pipe $thisrunnerr, $thiscontrollerw;
+ pipe $thiscontrollerr, $thisrunnerw;
+
+ my $thisrunnerid;
+ if($multiprocess) {
+ # Create a separate process in multiprocess mode
+ my $child = fork();
+ if(0 == $child) {
+ # TODO: set up better signal handlers
+ $SIG{INT} = 'IGNORE';
+ $SIG{TERM} = 'IGNORE';
+ eval {
+ # some msys2 perl versions don't define SIGUSR1
+ $SIG{USR1} = 'IGNORE';
+ };
+
+ $thisrunnerid = $$;
+ print "Runner $thisrunnerid starting\n" if($verbose);
+
+ # Here we are the child (runner).
+ close($thiscontrollerw);
+ close($thiscontrollerr);
+ $runnerr = $thisrunnerr;
+ $runnerw = $thisrunnerw;
+
+ # Set this directory as ours
+ $LOGDIR = $logdir;
+ mkdir("$LOGDIR/$PIDDIR", 0777);
+ mkdir("$LOGDIR/$LOCKDIR", 0777);
+
+ # Initialize various server variables
+ initserverconfig();
+
+ # handle IPC calls
+ event_loop();
+
+ # Can't rely on logmsg here in case it's buffered
+ print "Runner $thisrunnerid exiting\n" if($verbose);
+
+ # To reach this point, either the controller has sent
+ # runnerac_stopservers() and runnerac_shutdown() or we have called
+ # runnerabort(). In both cases, there are no more of our servers
+ # running and we can safely exit.
+ exit 0;
+ }
+
+ # Here we are the parent (controller).
+ close($thisrunnerw);
+ close($thisrunnerr);
+
+ $thisrunnerid = $child;
+
+ } else {
+ # Create our pid directory
+ mkdir("$LOGDIR/$PIDDIR", 0777);
+
+ # Don't create a separate process
+ $thisrunnerid = "integrated";
+ }
+
+ $controllerw{$thisrunnerid} = $thiscontrollerw;
+ $runnerr = $thisrunnerr;
+ $runnerw = $thisrunnerw;
+ $controllerr{$thisrunnerid} = $thiscontrollerr;
+
+ return $thisrunnerid;
+}
+
+#######################################################################
+# Loop to execute incoming IPC calls until the shutdown call
+sub event_loop {
+ while () {
+ if(ipcrecv()) {
+ last;
+ }
+ }
+}
+
+#######################################################################
+# Check for a command in the PATH of the machine running curl.
+#
+sub checktestcmd {
+ my ($cmd)=@_;
+ my @testpaths=("$LIBDIR/.libs", "$LIBDIR");
+ return checkcmd($cmd, @testpaths);
+}
+
+# See if Valgrind should actually be used
+sub use_valgrind {
+ if($valgrind) {
+ my @valgrindoption = getpart("verify", "valgrind");
+ if((!@valgrindoption) || ($valgrindoption[0] !~ /disable/)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+# Massage the command result code into a useful form
+sub normalize_cmdres {
+ my $cmdres = $_[0];
+ my $signal_num = $cmdres & 127;
+ my $dumped_core = $cmdres & 128;
+
+ if(!$anyway && ($signal_num || $dumped_core)) {
+ $cmdres = 1000;
+ }
+ else {
+ $cmdres >>= 8;
+ $cmdres = (2000 + $signal_num) if($signal_num && !$cmdres);
+ }
+ return ($cmdres, $dumped_core);
+}
+
+# 'prepro' processes the input array and replaces %-variables in the array
+# etc. Returns the processed version of the array
+sub prepro {
+ my $testnum = shift;
+ my (@entiretest) = @_;
+ my $show = 1;
+ my @out;
+ my $data_crlf;
+ for my $s (@entiretest) {
+ my $f = $s;
+ if($s =~ /^ *%if (.*)/) {
+ my $cond = $1;
+ my $rev = 0;
+
+ if($cond =~ /^!(.*)/) {
+ $cond = $1;
+ $rev = 1;
+ }
+ $rev ^= $feature{$cond} ? 1 : 0;
+ $show = $rev;
+ next;
+ }
+ elsif($s =~ /^ *%else/) {
+ $show ^= 1;
+ next;
+ }
+ elsif($s =~ /^ *%endif/) {
+ $show = 1;
+ next;
+ }
+ if($show) {
+ # The processor does CRLF replacements in the <data*> sections if
+ # necessary since those parts might be read by separate servers.
+ if($s =~ /^ *<data(.*)\>/) {
+ if($1 =~ /crlf="yes"/ ||
+ ($feature{"hyper"} && ($keywords{"HTTP"} || $keywords{"HTTPS"}))) {
+ $data_crlf = 1;
+ }
+ }
+ elsif(($s =~ /^ *<\/data/) && $data_crlf) {
+ $data_crlf = 0;
+ }
+ subvariables(\$s, $testnum, "%");
+ subbase64(\$s);
+ subnewlines(0, \$s) if($data_crlf);
+ push @out, $s;
+ }
+ }
+ return @out;
+}
+
+
+#######################################################################
+# Load test keywords into %keywords hash
+#
+sub readtestkeywords {
+ my @info_keywords = getpart("info", "keywords");
+
+ # Clear the list of keywords from the last test
+ %keywords = ();
+ for my $k (@info_keywords) {
+ chomp $k;
+ $keywords{$k} = 1;
+ }
+}
+
+
+#######################################################################
+# Return a list of log locks that still exist
+#
+sub logslocked {
+ opendir(my $lockdir, "$LOGDIR/$LOCKDIR");
+ my @locks;
+ foreach (readdir $lockdir) {
+ if(/^(.*)\.lock$/) {
+ push @locks, $1;
+ }
+ }
+ return @locks;
+}
+
+#######################################################################
+# Memory allocation test and failure torture testing.
+#
+sub torture {
+ my ($testcmd, $testnum, $gdbline) = @_;
+
+ # remove memdump first to be sure we get a new nice and clean one
+ unlink("$LOGDIR/$MEMDUMP");
+
+ # First get URL from test server, ignore the output/result
+ runclient($testcmd);
+
+ logmsg " CMD: $testcmd\n" if($verbose);
+
+ # memanalyze -v is our friend, get the number of allocations made
+ my $count=0;
+ my @out = `$memanalyze -v "$LOGDIR/$MEMDUMP"`;
+ for(@out) {
+ if(/^Operations: (\d+)/) {
+ $count = $1;
+ last;
+ }
+ }
+ if(!$count) {
+ logmsg " found no functions to make fail\n";
+ return 0;
+ }
+
+ my @ttests = (1 .. $count);
+ if($shallow && ($shallow < $count)) {
+ my $discard = scalar(@ttests) - $shallow;
+ my $percent = sprintf("%.2f%%", $shallow * 100 / scalar(@ttests));
+ logmsg " $count functions found, but only fail $shallow ($percent)\n";
+ while($discard) {
+ my $rm;
+ do {
+ # find a test to discard
+ $rm = rand(scalar(@ttests));
+ } while(!$ttests[$rm]);
+ $ttests[$rm] = undef;
+ $discard--;
+ }
+ }
+ else {
+ logmsg " $count functions to make fail\n";
+ }
+
+ for (@ttests) {
+ my $limit = $_;
+ my $fail;
+ my $dumped_core;
+
+ if(!defined($limit)) {
+ # --shallow can undefine them
+ next;
+ }
+ if($tortalloc && ($tortalloc != $limit)) {
+ next;
+ }
+
+ if($verbose) {
+ my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
+ localtime(time());
+ my $now = sprintf("%02d:%02d:%02d ", $hour, $min, $sec);
+ logmsg "Fail function no: $limit at $now\r";
+ }
+
+ # make the memory allocation function number $limit return failure
+ $ENV{'CURL_MEMLIMIT'} = $limit;
+
+ # remove memdump first to be sure we get a new nice and clean one
+ unlink("$LOGDIR/$MEMDUMP");
+
+ my $cmd = $testcmd;
+ if($valgrind && !$gdbthis) {
+ my @valgrindoption = getpart("verify", "valgrind");
+ if((!@valgrindoption) || ($valgrindoption[0] !~ /disable/)) {
+ my $valgrindcmd = "$valgrind ";
+ $valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
+ $valgrindcmd .= "--quiet --leak-check=yes ";
+ $valgrindcmd .= "--suppressions=$srcdir/valgrind.supp ";
+ # $valgrindcmd .= "--gen-suppressions=all ";
+ $valgrindcmd .= "--num-callers=16 ";
+ $valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
+ $cmd = "$valgrindcmd $testcmd";
+ }
+ }
+ logmsg "*** Function number $limit is now set to fail ***\n" if($gdbthis);
+
+ my $ret = 0;
+ if($gdbthis) {
+ runclient($gdbline);
+ }
+ else {
+ $ret = runclient($cmd);
+ }
+ #logmsg "$_ Returned " . ($ret >> 8) . "\n";
+
+ # Now clear the variable again
+ delete $ENV{'CURL_MEMLIMIT'} if($ENV{'CURL_MEMLIMIT'});
+
+ if(-r "core") {
+ # there's core file present now!
+ logmsg " core dumped\n";
+ $dumped_core = 1;
+ $fail = 2;
+ }
+
+ if($valgrind) {
+ my @e = valgrindparse("$LOGDIR/valgrind$testnum");
+ if(@e && $e[0]) {
+ if($automakestyle) {
+ logmsg "FAIL: torture $testnum - valgrind\n";
+ }
+ else {
+ logmsg " valgrind ERROR ";
+ logmsg @e;
+ }
+ $fail = 1;
+ }
+ }
+
+ # verify that it returns a proper error code, doesn't leak memory
+ # and doesn't core dump
+ if(($ret & 255) || ($ret >> 8) >= 128) {
+ logmsg " system() returned $ret\n";
+ $fail=1;
+ }
+ else {
+ my @memdata=`$memanalyze "$LOGDIR/$MEMDUMP"`;
+ my $leak=0;
+ for(@memdata) {
+ if($_ ne "") {
+ # well it could be other memory problems as well, but
+ # we call it leak for short here
+ $leak=1;
+ }
+ }
+ if($leak) {
+ logmsg "** MEMORY FAILURE\n";
+ logmsg @memdata;
+ logmsg `$memanalyze -l "$LOGDIR/$MEMDUMP"`;
+ $fail = 1;
+ }
+ }
+ if($fail) {
+ logmsg " $testnum: torture FAILED: function number $limit in test.\n",
+ " invoke with \"-t$limit\" to repeat this single case.\n";
+ stopservers($verbose);
+ return 1;
+ }
+ }
+
+ logmsg "\n" if($verbose);
+ logmsg "torture OK\n";
+ return 0;
+}
+
+
+#######################################################################
+# restore environment variables that were modified in test
+sub restore_test_env {
+ my $deleteoldenv = $_[0]; # 1 to delete the saved contents after restore
+ foreach my $var (keys %oldenv) {
+ if($oldenv{$var} eq 'notset') {
+ delete $ENV{$var} if($ENV{$var});
+ }
+ else {
+ $ENV{$var} = $oldenv{$var};
+ }
+ if($deleteoldenv) {
+ delete $oldenv{$var};
+ }
+ }
+}
+
+
+#######################################################################
+# Start the servers needed to run this test case
+sub singletest_startservers {
+ my ($testnum, $testtimings) = @_;
+
+ # remove old test server files before servers are started/verified
+ unlink("$LOGDIR/$SERVERCMD");
+ unlink("$LOGDIR/$SERVERIN");
+ unlink("$LOGDIR/$PROXYIN");
+
+ # timestamp required servers verification start
+ $$testtimings{"timesrvrini"} = Time::HiRes::time();
+
+ my $why;
+ my $error;
+ if (!$listonly) {
+ my @what = getpart("client", "server");
+ if(!$what[0]) {
+ warn "Test case $testnum has no server(s) specified";
+ $why = "no server specified";
+ $error = -1;
+ } else {
+ my $err;
+ ($why, $err) = serverfortest(@what);
+ if($err == 1) {
+ # Error indicates an actual problem starting the server
+ $error = -2;
+ } else {
+ $error = -1;
+ }
+ }
+ }
+
+ # timestamp required servers verification end
+ $$testtimings{"timesrvrend"} = Time::HiRes::time();
+
+ return ($why, $error);
+}
+
+
+#######################################################################
+# Generate preprocessed test file
+sub singletest_preprocess {
+ my $testnum = $_[0];
+
+ # Save a preprocessed version of the entire test file. This allows more
+ # "basic" test case readers to enjoy variable replacements.
+ my @entiretest = fulltest();
+ my $otest = "$LOGDIR/test$testnum";
+
+ @entiretest = prepro($testnum, @entiretest);
+
+ # save the new version
+ open(my $fulltesth, ">", "$otest") || die "Failure writing test file";
+ foreach my $bytes (@entiretest) {
+ print $fulltesth pack('a*', $bytes) or die "Failed to print '$bytes': $!";
+ }
+ close($fulltesth) || die "Failure writing test file";
+
+ # in case the process changed the file, reload it
+ loadtest("$LOGDIR/test${testnum}");
+}
+
+
+#######################################################################
+# Set up the test environment to run this test case
+sub singletest_setenv {
+ my @setenv = getpart("client", "setenv");
+ foreach my $s (@setenv) {
+ chomp $s;
+ if($s =~ /([^=]*)=(.*)/) {
+ my ($var, $content) = ($1, $2);
+ # remember current setting, to restore it once test runs
+ $oldenv{$var} = ($ENV{$var})?"$ENV{$var}":'notset';
+ # set new value
+ if(!$content) {
+ delete $ENV{$var} if($ENV{$var});
+ }
+ else {
+ if($var =~ /^LD_PRELOAD/) {
+ if(exe_ext('TOOL') && (exe_ext('TOOL') eq '.exe')) {
+ logmsg "Skipping LD_PRELOAD due to lack of OS support\n" if($verbose);
+ next;
+ }
+ if($feature{"debug"} || !$has_shared) {
+ logmsg "Skipping LD_PRELOAD due to no release shared build\n" if($verbose);
+ next;
+ }
+ }
+ $ENV{$var} = "$content";
+ logmsg "setenv $var = $content\n" if($verbose);
+ }
+ }
+ }
+ if($proxy_address) {
+ $ENV{http_proxy} = $proxy_address;
+ $ENV{HTTPS_PROXY} = $proxy_address;
+ }
+}
+
+
+#######################################################################
+# Check that test environment is fine to run this test case
+sub singletest_precheck {
+ my $testnum = $_[0];
+ my $why;
+ my @precheck = getpart("client", "precheck");
+ if(@precheck) {
+ my $cmd = $precheck[0];
+ chomp $cmd;
+ if($cmd) {
+ my @p = split(/ /, $cmd);
+ if($p[0] !~ /\//) {
+ # the first word, the command, does not contain a slash so
+ # we will scan the "improved" PATH to find the command to
+ # be able to run it
+ my $fullp = checktestcmd($p[0]);
+
+ if($fullp) {
+ $p[0] = $fullp;
+ }
+ $cmd = join(" ", @p);
+ }
+
+ my @o = `$cmd 2> $LOGDIR/precheck-$testnum`;
+ if($o[0]) {
+ $why = $o[0];
+ $why =~ s/[\r\n]//g;
+ }
+ elsif($?) {
+ $why = "precheck command error";
+ }
+ logmsg "prechecked $cmd\n" if($verbose);
+ }
+ }
+ return $why;
+}
+
+
+#######################################################################
+# Prepare the test environment to run this test case
+sub singletest_prepare {
+ my ($testnum) = @_;
+
+ if($feature{"TrackMemory"}) {
+ unlink("$LOGDIR/$MEMDUMP");
+ }
+ unlink("core");
+
+ # remove server output logfiles after servers are started/verified
+ unlink("$LOGDIR/$SERVERIN");
+ unlink("$LOGDIR/$PROXYIN");
+
+ # if this section exists, it might be FTP server instructions:
+ my @ftpservercmd = getpart("reply", "servercmd");
+ push @ftpservercmd, "Testnum $testnum\n";
+ # write the instructions to file
+ writearray("$LOGDIR/$SERVERCMD", \@ftpservercmd);
+
+ # create (possibly-empty) files before starting the test
+ for my $partsuffix (('', '1', '2', '3', '4')) {
+ my @inputfile=getpart("client", "file".$partsuffix);
+ my %fileattr = getpartattr("client", "file".$partsuffix);
+ my $filename=$fileattr{'name'};
+ if(@inputfile || $filename) {
+ if(!$filename) {
+ logmsg " $testnum: IGNORED: section client=>file has no name attribute\n";
+ return -1;
+ }
+ my $fileContent = join('', @inputfile);
+
+ # make directories if needed
+ my $path = $filename;
+ # cut off the file name part
+ $path =~ s/^(.*)\/[^\/]*/$1/;
+ my $nparts = scalar(split(/\//, $LOGDIR));
+ my @parts = split(/\//, $path);
+ if(join("/", @parts[0..$nparts-1]) eq $LOGDIR) {
+ # the file is in $LOGDIR/
+ my $d = shift @parts;
+ for(@parts) {
+ $d .= "/$_";
+ mkdir $d; # 0777
+ }
+ }
+ if (open(my $outfile, ">", "$filename")) {
+ binmode $outfile; # for crapage systems, use binary
+ if($fileattr{'nonewline'}) {
+ # cut off the final newline
+ chomp($fileContent);
+ }
+ print $outfile $fileContent;
+ close($outfile);
+ } else {
+ logmsg "ERROR: cannot write $filename\n";
+ }
+ }
+ }
+ return 0;
+}
+
+
+#######################################################################
+# Run the test command
+sub singletest_run {
+ my ($testnum, $testtimings) = @_;
+
+ # get the command line options to use
+ my ($cmd, @blaha)= getpart("client", "command");
+ if($cmd) {
+ # make some nice replace operations
+ $cmd =~ s/\n//g; # no newlines please
+ # substitute variables in the command line
+ }
+ else {
+ # there was no command given, use something silly
+ $cmd="-";
+ }
+
+ my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout
+
+ # if stdout section exists, we verify that the stdout contained this:
+ my $out="";
+ my %cmdhash = getpartattr("client", "command");
+ if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-output/)) {
+ #We may slap on --output!
+ if (!partexists("verify", "stdout") ||
+ ($cmdhash{'option'} && $cmdhash{'option'} =~ /force-output/)) {
+ $out=" --output $CURLOUT ";
+ }
+ }
+
+ my @codepieces = getpart("client", "tool");
+ my $tool="";
+ if(@codepieces) {
+ $tool = $codepieces[0];
+ chomp $tool;
+ $tool .= exe_ext('TOOL');
+ }
+
+ my $disablevalgrind;
+ my $CMDLINE="";
+ my $cmdargs;
+ my $cmdtype = $cmdhash{'type'} || "default";
+ my $fail_due_event_based = $run_event_based;
+ if($cmdtype eq "perl") {
+ # run the command line prepended with "perl"
+ $cmdargs ="$cmd";
+ $CMDLINE = "$perl ";
+ $tool=$CMDLINE;
+ $disablevalgrind=1;
+ }
+ elsif($cmdtype eq "shell") {
+ # run the command line prepended with "/bin/sh"
+ $cmdargs ="$cmd";
+ $CMDLINE = "/bin/sh ";
+ $tool=$CMDLINE;
+ $disablevalgrind=1;
+ }
+ elsif(!$tool && !$keywords{"unittest"}) {
+ # run curl, add suitable command line options
+ my $inc="";
+ if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-include/)) {
+ $inc = " --include";
+ }
+ $cmdargs = "$out$inc ";
+
+ if($cmdhash{'option'} && ($cmdhash{'option'} =~ /binary-trace/)) {
+ $cmdargs .= "--trace $LOGDIR/trace$testnum ";
+ }
+ else {
+ $cmdargs .= "--trace-ascii $LOGDIR/trace$testnum ";
+ }
+ $cmdargs .= "--trace-time ";
+ if($run_event_based) {
+ $cmdargs .= "--test-event ";
+ $fail_due_event_based--;
+ }
+ $cmdargs .= $cmd;
+ if ($proxy_address) {
+ $cmdargs .= " --proxy $proxy_address ";
+ }
+ }
+ else {
+ $cmdargs = " $cmd"; # $cmd is the command line for the test file
+ $CURLOUT = stdoutfilename($LOGDIR, $testnum); # sends received data to stdout
+
+ # Default the tool to a unit test with the same name as the test spec
+ if($keywords{"unittest"} && !$tool) {
+ $tool="unit$testnum";
+ }
+
+ if($tool =~ /^lib/) {
+ $CMDLINE="$LIBDIR/$tool";
+ }
+ elsif($tool =~ /^unit/) {
+ $CMDLINE="$UNITDIR/$tool";
+ }
+
+ if(! -f $CMDLINE) {
+ logmsg " $testnum: IGNORED: The tool set in the test case for this: '$tool' does not exist\n";
+ return (-1, 0, 0, "", "", 0);
+ }
+ $DBGCURL=$CMDLINE;
+ }
+
+ if($fail_due_event_based) {
+ logmsg " $testnum: IGNORED: This test cannot run event based\n";
+ return (-1, 0, 0, "", "", 0);
+ }
+
+ if($gdbthis) {
+ # gdb is incompatible with valgrind, so disable it when debugging
+ # Perhaps a better approach would be to run it under valgrind anyway
+ # with --db-attach=yes or --vgdb=yes.
+ $disablevalgrind=1;
+ }
+
+ my @stdintest = getpart("client", "stdin");
+
+ if(@stdintest) {
+ my $stdinfile="$LOGDIR/stdin-for-$testnum";
+
+ my %hash = getpartattr("client", "stdin");
+ if($hash{'nonewline'}) {
+ # cut off the final newline from the final line of the stdin data
+ chomp($stdintest[-1]);
+ }
+
+ writearray($stdinfile, \@stdintest);
+
+ $cmdargs .= " <$stdinfile";
+ }
+
+ if(!$tool) {
+ $CMDLINE=shell_quote($CURL);
+ }
+
+ if(use_valgrind() && !$disablevalgrind) {
+ my $valgrindcmd = "$valgrind ";
+ $valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
+ $valgrindcmd .= "--quiet --leak-check=yes ";
+ $valgrindcmd .= "--suppressions=$srcdir/valgrind.supp ";
+ # $valgrindcmd .= "--gen-suppressions=all ";
+ $valgrindcmd .= "--num-callers=16 ";
+ $valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
+ $CMDLINE = "$valgrindcmd $CMDLINE";
+ }
+
+ $CMDLINE .= "$cmdargs > " . stdoutfilename($LOGDIR, $testnum) .
+ " 2> " . stderrfilename($LOGDIR, $testnum);
+
+ if($verbose) {
+ logmsg "$CMDLINE\n";
+ }
+
+ open(my $cmdlog, ">", $CURLLOG) || die "Failure writing log file";
+ print $cmdlog "$CMDLINE\n";
+ close($cmdlog) || die "Failure writing log file";
+
+ my $dumped_core;
+ my $cmdres;
+
+ if($gdbthis) {
+ my $gdbinit = "$TESTDIR/gdbinit$testnum";
+ open(my $gdbcmd, ">", "$LOGDIR/gdbcmd") || die "Failure writing gdb file";
+ print $gdbcmd "set args $cmdargs\n";
+ print $gdbcmd "show args\n";
+ print $gdbcmd "source $gdbinit\n" if -e $gdbinit;
+ close($gdbcmd) || die "Failure writing gdb file";
+ }
+
+ # Flush output.
+ $| = 1;
+
+ # timestamp starting of test command
+ $$testtimings{"timetoolini"} = Time::HiRes::time();
+
+ # run the command line we built
+ if ($torture) {
+ $cmdres = torture($CMDLINE,
+ $testnum,
+ "$gdb --directory $LIBDIR " . shell_quote($DBGCURL) . " -x $LOGDIR/gdbcmd");
+ }
+ elsif($gdbthis) {
+ my $GDBW = ($gdbxwin) ? "-w" : "";
+ runclient("$gdb --directory $LIBDIR " . shell_quote($DBGCURL) . " $GDBW -x $LOGDIR/gdbcmd");
+ $cmdres=0; # makes it always continue after a debugged run
+ }
+ else {
+ # Convert the raw result code into a more useful one
+ ($cmdres, $dumped_core) = normalize_cmdres(runclient("$CMDLINE"));
+ }
+
+ # timestamp finishing of test command
+ $$testtimings{"timetoolend"} = Time::HiRes::time();
+
+ return (0, $cmdres, $dumped_core, $CURLOUT, $tool, use_valgrind() && !$disablevalgrind);
+}
+
+
+#######################################################################
+# Clean up after test command
+sub singletest_clean {
+ my ($testnum, $dumped_core, $testtimings)=@_;
+
+ if(!$dumped_core) {
+ if(-r "core") {
+ # there's core file present now!
+ $dumped_core = 1;
+ }
+ }
+
+ if($dumped_core) {
+ logmsg "core dumped\n";
+ if(0 && $gdb) {
+ logmsg "running gdb for post-mortem analysis:\n";
+ open(my $gdbcmd, ">", "$LOGDIR/gdbcmd2") || die "Failure writing gdb file";
+ print $gdbcmd "bt\n";
+ close($gdbcmd) || die "Failure writing gdb file";
+ runclient("$gdb --directory libtest -x $LOGDIR/gdbcmd2 -batch " . shell_quote($DBGCURL) . " core ");
+ # unlink("$LOGDIR/gdbcmd2");
+ }
+ }
+
+ # If a server logs advisor read lock file exists, it is an indication
+ # that the server has not yet finished writing out all its log files,
+ # including server request log files used for protocol verification.
+ # So, if the lock file exists the script waits here a certain amount
+ # of time until the server removes it, or the given time expires.
+ my $serverlogslocktimeout = $defserverlogslocktimeout;
+ my %cmdhash = getpartattr("client", "command");
+ if($cmdhash{'timeout'}) {
+ # test is allowed to override default server logs lock timeout
+ if($cmdhash{'timeout'} =~ /(\d+)/) {
+ $serverlogslocktimeout = $1 if($1 >= 0);
+ }
+ }
+ if($serverlogslocktimeout) {
+ my $lockretry = $serverlogslocktimeout * 20;
+ my @locks;
+ while((@locks = logslocked()) && $lockretry--) {
+ portable_sleep(0.05);
+ }
+ if(($lockretry < 0) &&
+ ($serverlogslocktimeout >= $defserverlogslocktimeout)) {
+ logmsg "Warning: server logs lock timeout ",
+ "($serverlogslocktimeout seconds) expired (locks: " .
+ join(", ", @locks) . ")\n";
+ }
+ }
+
+ # Test harness ssh server does not have this synchronization mechanism,
+ # this implies that some ssh server based tests might need a small delay
+ # once that the client command has run to avoid false test failures.
+ #
+ # gnutls-serv also lacks this synchronization mechanism, so gnutls-serv
+ # based tests might need a small delay once that the client command has
+ # run to avoid false test failures.
+ my $postcommanddelay = $defpostcommanddelay;
+ if($cmdhash{'delay'}) {
+ # test is allowed to specify a delay after command is executed
+ if($cmdhash{'delay'} =~ /(\d+)/) {
+ $postcommanddelay = $1 if($1 > 0);
+ }
+ }
+
+ portable_sleep($postcommanddelay) if($postcommanddelay);
+
+ # timestamp removal of server logs advisor read lock
+ $$testtimings{"timesrvrlog"} = Time::HiRes::time();
+
+ # test definition might instruct to stop some servers
+ # stop also all servers relative to the given one
+
+ my @killtestservers = getpart("client", "killserver");
+ if(@killtestservers) {
+ foreach my $server (@killtestservers) {
+ chomp $server;
+ if(stopserver($server)) {
+ logmsg " $testnum: killserver FAILED\n";
+ return 1; # normal error if asked to fail on unexpected alive
+ }
+ }
+ }
+ return 0;
+}
+
+#######################################################################
+# Verify that the postcheck succeeded
+sub singletest_postcheck {
+ my ($testnum)=@_;
+
+ # run the postcheck command
+ my @postcheck= getpart("client", "postcheck");
+ if(@postcheck) {
+ my $cmd = join("", @postcheck);
+ chomp $cmd;
+ if($cmd) {
+ logmsg "postcheck $cmd\n" if($verbose);
+ my $rc = runclient("$cmd");
+ # Must run the postcheck command in torture mode in order
+ # to clean up, but the result can't be relied upon.
+ if($rc != 0 && !$torture) {
+ logmsg " $testnum: postcheck FAILED\n";
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+
+###################################################################
+# Get ready to run a single test case
+sub runner_test_preprocess {
+ my ($testnum)=@_;
+ my %testtimings;
+
+ if(clearlogs()) {
+ logmsg "Warning: log messages were lost\n";
+ }
+
+ # timestamp test preparation start
+ # TODO: this metric now shows only a portion of the prep time; better would
+ # be to time singletest_preprocess below instead
+ $testtimings{"timeprepini"} = Time::HiRes::time();
+
+ ###################################################################
+ # Load test metadata
+ # ignore any error here--if there were one, it would have been
+ # caught during the selection phase and this test would not be
+ # running now
+ loadtest("${TESTDIR}/test${testnum}");
+ readtestkeywords();
+
+ ###################################################################
+ # Restore environment variables that were modified in a previous run.
+ # Test definition may instruct to (un)set environment vars.
+ restore_test_env(1);
+
+ ###################################################################
+ # Start the servers needed to run this test case
+ my ($why, $error) = singletest_startservers($testnum, \%testtimings);
+
+ if(!$why) {
+
+ ###############################################################
+ # Generate preprocessed test file
+ # This must be done after the servers are started so server
+ # variables are available for substitution.
+ singletest_preprocess($testnum);
+
+ ###############################################################
+ # Set up the test environment to run this test case
+ singletest_setenv();
+
+ ###############################################################
+ # Check that the test environment is fine to run this test case
+ if (!$listonly) {
+ $why = singletest_precheck($testnum);
+ $error = -1;
+ }
+ }
+ return ($why, $error, clearlogs(), \%testtimings);
+}
+
+
+###################################################################
+# Run a single test case with an environment that already been prepared
+# Returns 0=success, -1=skippable failure, -2=permanent error,
+# 1=unskippable test failure, as first integer, plus any log messages,
+# plus more return values when error is 0
+sub runner_test_run {
+ my ($testnum)=@_;
+
+ if(clearlogs()) {
+ logmsg "Warning: log messages were lost\n";
+ }
+
+ #######################################################################
+ # Prepare the test environment to run this test case
+ my $error = singletest_prepare($testnum);
+ if($error) {
+ return (-2, clearlogs());
+ }
+
+ #######################################################################
+ # Run the test command
+ my %testtimings;
+ my $cmdres;
+ my $dumped_core;
+ my $CURLOUT;
+ my $tool;
+ my $usedvalgrind;
+ ($error, $cmdres, $dumped_core, $CURLOUT, $tool, $usedvalgrind) = singletest_run($testnum, \%testtimings);
+ if($error) {
+ return (-2, clearlogs(), \%testtimings);
+ }
+
+ #######################################################################
+ # Clean up after test command
+ $error = singletest_clean($testnum, $dumped_core, \%testtimings);
+ if($error) {
+ return ($error, clearlogs(), \%testtimings);
+ }
+
+ #######################################################################
+ # Verify that the postcheck succeeded
+ $error = singletest_postcheck($testnum);
+ if($error) {
+ return ($error, clearlogs(), \%testtimings);
+ }
+
+ #######################################################################
+ # restore environment variables that were modified
+ restore_test_env(0);
+
+ return (0, clearlogs(), \%testtimings, $cmdres, $CURLOUT, $tool, $usedvalgrind);
+}
+
+# Async call runner_clearlocks
+# Called by controller
+sub runnerac_clearlocks {
+ return controlleripccall(\&runner_clearlocks, @_);
+}
+
+# Async call runner_shutdown
+# This call does NOT generate an IPC response and must be the last IPC call
+# received.
+# Called by controller
+sub runnerac_shutdown {
+ my ($runnerid)=$_[0];
+ my $err = controlleripccall(\&runner_shutdown, @_);
+
+ # These have no more use
+ close($controllerw{$runnerid});
+ undef $controllerw{$runnerid};
+ close($controllerr{$runnerid});
+ undef $controllerr{$runnerid};
+ return $err;
+}
+
+# Async call of runner_stopservers
+# Called by controller
+sub runnerac_stopservers {
+ return controlleripccall(\&runner_stopservers, @_);
+}
+
+# Async call of runner_test_preprocess
+# Called by controller
+sub runnerac_test_preprocess {
+ return controlleripccall(\&runner_test_preprocess, @_);
+}
+
+# Async call of runner_test_run
+# Called by controller
+sub runnerac_test_run {
+ return controlleripccall(\&runner_test_run, @_);
+}
+
+###################################################################
+# Call an arbitrary function via IPC
+# The first argument is the function reference, the second is the runner ID
+# Returns 0 on success, -1 on error writing to runner
+# Called by controller (indirectly, via a more specific function)
+sub controlleripccall {
+ my $funcref = shift @_;
+ my $runnerid = shift @_;
+ # Get the name of the function from the reference
+ my $cv = svref_2object($funcref);
+ my $gv = $cv->GV;
+ # Prepend the name to the function arguments so it's marshalled along with them
+ unshift @_, $gv->NAME;
+ # Marshall the arguments into a flat string
+ my $margs = freeze \@_;
+
+ # Send IPC call via pipe
+ my $err;
+ while(! defined ($err = syswrite($controllerw{$runnerid}, (pack "L", length($margs)) . $margs)) || $err <= 0) {
+ if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
+ # Runner has likely died
+ return -1;
+ }
+ # system call was interrupted, probably by ^C; restart it so we stay in sync
+ }
+
+ if(!$multiprocess) {
+ # Call the remote function here in single process mode
+ ipcrecv();
+ }
+ return 0;
+}
+
+###################################################################
+# Receive async response of a previous call via IPC
+# The first return value is the runner ID or undef on error
+# Called by controller
+sub runnerar {
+ my ($runnerid) = @_;
+ my $err;
+ my $datalen;
+ while(! defined ($err = sysread($controllerr{$runnerid}, $datalen, 4)) || $err <= 0) {
+ if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
+ # Runner is likely dead and closed the pipe
+ return undef;
+ }
+ # system call was interrupted, probably by ^C; restart it so we stay in sync
+ }
+ my $len=unpack("L", $datalen);
+ my $buf;
+ while(! defined ($err = sysread($controllerr{$runnerid}, $buf, $len)) || $err <= 0) {
+ if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
+ # Runner is likely dead and closed the pipe
+ return undef;
+ }
+ # system call was interrupted, probably by ^C; restart it so we stay in sync
+ }
+
+ # Decode response values
+ my $resarrayref = thaw $buf;
+
+ # First argument is runner ID
+ # TODO: remove this; it's unneeded since it's passed in
+ unshift @$resarrayref, $runnerid;
+ return @$resarrayref;
+}
+
+###################################################################
+# Returns runner ID if a response from an async call is ready or error
+# First value is ready, second is error, however an error case shows up
+# as ready in Linux, so you can't trust it.
+# argument is 0 for nonblocking, undef for blocking, anything else for timeout
+# Called by controller
+sub runnerar_ready {
+ my ($blocking) = @_;
+ my $rin = "";
+ my %idbyfileno;
+ my $maxfileno=0;
+ foreach my $p (keys(%controllerr)) {
+ my $fd = fileno($controllerr{$p});
+ vec($rin, $fd, 1) = 1;
+ $idbyfileno{$fd} = $p; # save the runner ID for each pipe fd
+ if($fd > $maxfileno) {
+ $maxfileno = $fd;
+ }
+ }
+ $maxfileno || die "Internal error: no runners are available to wait on\n";
+
+ # Wait for any pipe from any runner to be ready
+ # This may be interrupted and return EINTR, but this is ignored and the
+ # caller will need to later call this function again.
+ # TODO: this is relatively slow with hundreds of fds
+ my $ein = $rin;
+ if(select(my $rout=$rin, undef, my $eout=$ein, $blocking) >= 1) {
+ for my $fd (0..$maxfileno) {
+ # Return an error condition first in case it's both
+ if(vec($eout, $fd, 1)) {
+ return (undef, $idbyfileno{$fd});
+ }
+ if(vec($rout, $fd, 1)) {
+ return ($idbyfileno{$fd}, undef);
+ }
+ }
+ die "Internal pipe readiness inconsistency\n";
+ }
+ return (undef, undef);
+}
+
+
+###################################################################
+# Cleanly abort and exit the runner
+# This uses print since there is no longer any controller to write logs.
+sub runnerabort{
+ print "Controller is gone: runner $$ for $LOGDIR exiting\n";
+ my ($error, $logs) = runner_stopservers();
+ print $logs;
+ runner_shutdown();
+}
+
+###################################################################
+# Receive an IPC call in the runner and execute it
+# The IPC is read from the $runnerr pipe and the response is
+# written to the $runnerw pipe
+# Returns 0 if more IPC calls are expected or 1 if the runner should exit
+sub ipcrecv {
+ my $err;
+ my $datalen;
+ while(! defined ($err = sysread($runnerr, $datalen, 4)) || $err <= 0) {
+ if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
+ # pipe has closed; controller is gone and we must exit
+ runnerabort();
+ # Special case: no response will be forthcoming
+ return 1;
+ }
+ # system call was interrupted, probably by ^C; restart it so we stay in sync
+ }
+ my $len=unpack("L", $datalen);
+ my $buf;
+ while(! defined ($err = sysread($runnerr, $buf, $len)) || $err <= 0) {
+ if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
+ # pipe has closed; controller is gone and we must exit
+ runnerabort();
+ # Special case: no response will be forthcoming
+ return 1;
+ }
+ # system call was interrupted, probably by ^C; restart it so we stay in sync
+ }
+
+ # Decode the function name and arguments
+ my $argsarrayref = thaw $buf;
+
+ # The name of the function to call is the frist argument
+ my $funcname = shift @$argsarrayref;
+
+ # print "ipcrecv $funcname\n";
+ # Synchronously call the desired function
+ my @res;
+ if($funcname eq "runner_clearlocks") {
+ @res = runner_clearlocks(@$argsarrayref);
+ }
+ elsif($funcname eq "runner_shutdown") {
+ runner_shutdown(@$argsarrayref);
+ # Special case: no response will be forthcoming
+ return 1;
+ }
+ elsif($funcname eq "runner_stopservers") {
+ @res = runner_stopservers(@$argsarrayref);
+ }
+ elsif($funcname eq "runner_test_preprocess") {
+ @res = runner_test_preprocess(@$argsarrayref);
+ }
+ elsif($funcname eq "runner_test_run") {
+ @res = runner_test_run(@$argsarrayref);
+ } else {
+ die "Unknown IPC function $funcname\n";
+ }
+ # print "ipcrecv results\n";
+
+ # Marshall the results to return
+ $buf = freeze \@res;
+
+ while(! defined ($err = syswrite($runnerw, (pack "L", length($buf)) . $buf)) || $err <= 0) {
+ if((!defined $err && ! $!{EINTR}) || (defined $err && $err == 0)) {
+ # pipe has closed; controller is gone and we must exit
+ runnerabort();
+ # Special case: no response will be forthcoming
+ return 1;
+ }
+ # system call was interrupted, probably by ^C; restart it so we stay in sync
+ }
+
+ return 0;
+}
+
+###################################################################
+# Kill the server processes that still have lock files in a directory
+sub runner_clearlocks {
+ my ($lockdir)=@_;
+ if(clearlogs()) {
+ logmsg "Warning: log messages were lost\n";
+ }
+ clearlocks($lockdir);
+ return clearlogs();
+}
+
+
+###################################################################
+# Kill all server processes
+sub runner_stopservers {
+ my $error = stopservers($verbose);
+ my $logs = clearlogs();
+ return ($error, $logs);
+}
+
+###################################################################
+# Shut down this runner
+sub runner_shutdown {
+ close($runnerr);
+ undef $runnerr;
+ close($runnerw);
+ undef $runnerw;
+}
+
+
+1;
diff --git a/tests/runtests.1 b/tests/runtests.1
index 2393eb6..e2a6ad3 100644
--- a/tests/runtests.1
+++ b/tests/runtests.1
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH runtests.pl 1 "19 Jan 2021" "Curl 7.75.0" "runtests"
+.TH runtests.pl 1 "06 Jun 2023" runtests runtests
.SH NAME
runtests.pl \- run one or more test cases
.SH SYNOPSIS
@@ -57,11 +57,17 @@
.IP "-a"
Continue running the rest of the test cases even if one test fails. By
default, the test script stops as soon as an error is detected.
+.IP "-ac <curl>"
+Provide a path to a curl binary to talk to APIs (currently only CI test APIs).
+.IP "-am"
+Display test results in automake style output (PASS/FAIL: [number] [name]).
.IP "-c <curl>"
Provide a path to a custom curl binary to run the tests with. Default is the
curl executable in the build tree.
.IP "-d"
-Enable protocol debug: have the servers display protocol output.
+Enable protocol debug: have the servers display protocol output. If used in
+conjuction with parallel testing, it will be difficult to associate the logs
+with the test being run.
.IP "-E <exclude_file>"
Load the \fBexclude_file\fP with additional reasons why certain tests
should be skipped. Useful when testing with external HTTP proxies in
@@ -81,27 +87,39 @@
curl built --disable-shared. This then fires up gdb with command line set to
run the specified test case. Simply (set a break-point and) type 'run' to
start.
-.IP "-h"
+.IP "-gw"
+Run the given test(s) with gdb as a windowed application.
+.IP "-h, --help"
Displays a help text about this program's command line options.
.IP "-k"
Keep output and log files in log/ after a test run, even if no error was
detected. Useful for debugging.
+.IP "-j[num]"
+Spawn num processes to run tests. This defaults to 0 to run tests serially
+within a single process. Using a number greater than one allows multiple tests
+to run in parallel, speeding up a test run. The optimum number is dependent on
+the system and set of tests to run, but 7*number of CPU cores is a good figure
+to start with, or 1.3*number of CPU cores if Valgrind is in use. Enabling
+parallel tests is not recommended in conjunction with the \-g option.
.IP "-L <file>"
Load and execute the specified file which should contain perl code.
-This option allows to change \fIruntests.pl\fP behaviour by overwriting
+This option allows one to change \fIruntests.pl\fP behaviour by overwriting
functions and variables and is useful when testing external proxies
using curl's regression test suite.
.IP "-l"
Lists all test case names.
.IP "-n"
Disable the check for and use of valgrind.
+.IP "--no-debuginfod"
+Delete the DEBUGINFOD_URLS variable if that is defined. Makes valgrind, gdb
+etc not able to use this functionality.
.IP "-o <variablename=value>"
Overwrite the specified internal \fBvariable\fP with \fBvalue\fP.
Useful to change variables that didn't get a dedicated flag to change them.
Check the source to see which variables are available.
.IP "-P <proxy>"
Use the specified HTTP proxy when executing tests, even if the tests
-themselves don't specify a proxy. This option allows to test external
+themselves don't specify a proxy. This option allows one to test external
proxies using curl's regression test suite.
.IP "-p"
Prints out all files in "log/" to stdout when a test case fails. Very
@@ -130,7 +148,7 @@
.IP "-s"
Shorter output. Speaks less than default.
.IP "--seed=[num]"
-When using \fI--shallow\fP or \fI-R\rP that random certain aspects of the
+When using \fI--shallow\fP or \fI-R\fP that randomize certain aspects of the
behavior, this option can set the initial seed. If not set, the random seed
will be set based on the currently set local year and month and the first line
of the "curl -V" output.
@@ -152,7 +170,9 @@
.IP "-u"
Error instead of warning on server unexpectedly alive.
.IP "-v"
-Enable verbose output. Speaks more than default.
+Enable verbose output. Speaks more than by default. If used in conjuction with
+parallel testing, it will be difficult to associate the logs with the test
+being run.
.IP "-vc <curl>"
Provide a path to a custom curl binary to run when verifying that the servers
running are indeed our test servers. Default is the curl executable in the
@@ -173,4 +193,4 @@
.SH "WRITING TESTS"
The simplest way to write test cases is to start with a similar existing test,
save it with a new number and then adjust it to fit. There's an attempt to
-document the test case file format in the tests/FILEFORMAT.
+document the test case file format in the tests/FILEFORMAT.md.
diff --git a/tests/runtests.pl b/tests/runtests.pl
index 80370ba..c27fbfa 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -54,6 +54,10 @@
# fixed. As long as the -g option is never given, and the -n is always
# given, this won't be a problem.
+use strict;
+# Promote all warnings to fatal
+use warnings FATAL => 'all';
+use 5.006;
# These should be the only variables that might be needed to get edited:
@@ -74,124 +78,30 @@
}
}
-use strict;
-use warnings;
-use Cwd;
use Digest::MD5 qw(md5);
-use MIME::Base64;
+use List::Util 'sum';
-# Subs imported from serverhelp module
-use serverhelp qw(
- serverfactors
- servername_id
- servername_str
- servername_canon
- server_pidfilename
- server_portfilename
- server_logfilename
- );
-
-# Variables and subs imported from sshhelp module
-use sshhelp qw(
- $sshdexe
- $sshexe
- $sftpexe
- $sshconfig
- $sftpconfig
- $sshdlog
- $sshlog
- $sftplog
- $sftpcmds
- display_sshdconfig
- display_sshconfig
- display_sftpconfig
- display_sshdlog
- display_sshlog
- display_sftplog
+use pathhelp qw(
exe_ext
- find_sshd
- find_ssh
- find_sftp
- find_httptlssrv
- sshversioninfo
+ sys_native_current_path
+ );
+use processhelp qw(
+ portable_sleep
);
-use pathhelp;
+use appveyor;
+use azure;
+use getpart; # array functions
+use servers;
+use valgrind; # valgrind report parser
+use globalconfig;
+use runner;
+use testutil;
-require "getpart.pm"; # array functions
-require "valgrind.pm"; # valgrind report parser
-require "ftp.pm";
-require "azure.pm";
-require "appveyor.pm";
-
-my $HOSTIP="127.0.0.1"; # address on which the test server listens
-my $HOST6IP="[::1]"; # address on which the test server listens
-my $CLIENTIP="127.0.0.1"; # address which curl uses for incoming connections
-my $CLIENT6IP="[::1]"; # address which curl uses for incoming connections
-
-my $noport="[not running]";
-
-my $NOLISTENPORT=47; # port number we use for a local non-listening service
-my $MQTTPORT=$noport; # MQTT server port
-my $HTTPPORT=$noport; # HTTP server port
-my $HTTP6PORT=$noport; # HTTP IPv6 server port
-my $HTTPSPORT=$noport; # HTTPS (stunnel) server port
-my $HTTPSPROXYPORT = $noport; # HTTPS-proxy (stunnel) port
-my $FTPPORT=$noport; # FTP server port
-my $FTPSPORT=$noport; # FTPS (stunnel) server port
-my $FTP6PORT=$noport; # FTP IPv6 server port
-my $TFTPPORT=$noport; # TFTP
-my $TFTP6PORT=$noport; # TFTP
-my $SSHPORT=$noport; # SCP/SFTP
-my $SOCKSPORT=$noport; # SOCKS4/5 port
-my $POP3PORT=$noport; # POP3
-my $POP36PORT=$noport; # POP3 IPv6 server port
-my $IMAPPORT=$noport; # IMAP
-my $IMAP6PORT=$noport; # IMAP IPv6 server port
-my $SMTPPORT=$noport; # SMTP
-my $SMTP6PORT=$noport; # SMTP IPv6 server port
-my $RTSPPORT=$noport; # RTSP
-my $RTSP6PORT=$noport; # RTSP IPv6 server port
-my $GOPHERPORT=$noport; # Gopher
-my $GOPHERSPORT=$noport; # Gophers
-my $GOPHER6PORT=$noport; # Gopher IPv6 server port
-my $HTTPTLSPORT=$noport; # HTTP TLS (non-stunnel) server port
-my $HTTPTLS6PORT=$noport; # HTTP TLS (non-stunnel) IPv6 server port
-my $HTTPPROXYPORT=$noport; # HTTP proxy port, when using CONNECT
-my $HTTP2PORT=$noport; # HTTP/2 server port
-my $DICTPORT=$noport; # DICT server port
-my $SMBPORT=$noport; # SMB server port
-my $SMBSPORT=$noport; # SMBS server port
-my $TELNETPORT=$noport; # TELNET server port with negotiation
-my $HTTPUNIXPATH; # HTTP server Unix domain socket path
-my $SOCKSUNIXPATH; # socks server Unix domain socket path
-
-my $use_external_proxy = 0;
-my $proxy_address;
my %custom_skip_reasons;
-my $SSHSRVMD5 = "[uninitialized]"; # MD5 of ssh server public key
-my $SSHSRVSHA256 = "[uninitialized]"; # SHA256 of ssh server public key
-my $VERSION=""; # curl's reported version number
-
-my $srcdir = $ENV{'srcdir'} || '.';
-my $CURL="../src/curl".exe_ext('TOOL'); # what curl executable to run on the tests
-my $VCURL=$CURL; # what curl binary to use to verify the servers with
- # VCURL is handy to set to the system one when the one you
- # just built hangs or crashes and thus prevent verification
-my $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging
-my $LOGDIR="log";
-my $TESTDIR="$srcdir/data";
-my $LIBDIR="./libtest";
-my $UNITDIR="./unit";
-# TODO: change this to use server_inputfilename()
-my $SERVERIN="$LOGDIR/server.input"; # what curl sent the server
-my $SERVER2IN="$LOGDIR/server2.input"; # what curl sent the second server
-my $PROXYIN="$LOGDIR/proxy.input"; # what curl sent the proxy
-my $SOCKSIN="$LOGDIR/socksd-request.log"; # what curl sent to the SOCKS proxy
-my $CURLLOG="commands.log"; # all command lines run
-my $FTPDCMD="$LOGDIR/ftpserver.cmd"; # copy server instructions here
-my $SERVERLOGS_LOCK="$LOGDIR/serverlogs.lock"; # server logs advisor read lock
+my $ACURL=$VCURL; # what curl binary to use to talk to APIs (relevant for CI)
+ # ACURL is handy to set to the system one for reliability
my $CURLCONFIG="../curl-config"; # curl-config from current build
# Normally, all test cases should be run, but at times it is handy to
@@ -205,107 +115,23 @@
# No variables below this point should need to be modified
#
-# invoke perl like this:
-my $perl="perl -I$srcdir";
-my $server_response_maxtime=13;
-
-my $debug_build=0; # built debug enabled (--enable-debug)
-my $has_memory_tracking=0; # built with memory tracking (--enable-curldebug)
my $libtool;
my $repeat = 0;
-# name of the file that the memory debugging creates:
-my $memdump="$LOGDIR/memdump";
-
-# the path to the script that analyzes the memory debug output file:
-my $memanalyze="$perl $srcdir/memanalyze.pl";
-
-my $pwd = getcwd(); # current working directory
-my $posix_pwd = $pwd;
-
-my $start;
-my $ftpchecktime=1; # time it took to verify our test FTP server
-my $scrambleorder;
-my $stunnel = checkcmd("stunnel4") || checkcmd("tstunnel") || checkcmd("stunnel");
-my $valgrind = checktestcmd("valgrind");
-my $valgrind_logfile="--logfile";
-my $valgrind_tool;
-my $gdb = checktestcmd("gdb");
-my $httptlssrv = find_httptlssrv();
+my $start; # time at which testing started
my $uname_release = `uname -r`;
my $is_wsl = $uname_release =~ /Microsoft$/;
-my $has_ssl; # set if libcurl is built with SSL support
-my $has_largefile; # set if libcurl is built with large file support
-my $has_idn; # set if libcurl is built with IDN support
my $http_ipv6; # set if HTTP server has IPv6 support
my $http_unix; # set if HTTP server has Unix sockets support
my $ftp_ipv6; # set if FTP server has IPv6 support
-my $tftp_ipv6; # set if TFTP server has IPv6 support
-my $gopher_ipv6; # set if Gopher server has IPv6 support
-my $has_ipv6; # set if libcurl is built with IPv6 support
-my $has_unix; # set if libcurl is built with Unix sockets support
-my $has_libz; # set if libcurl is built with libz support
-my $has_brotli; # set if libcurl is built with brotli support
-my $has_zstd; # set if libcurl is built with zstd support
-my $has_getrlimit; # set if system has getrlimit()
-my $has_ntlm; # set if libcurl is built with NTLM support
-my $has_ntlm_wb; # set if libcurl is built with NTLM delegation to winbind
-my $has_sspi; # set if libcurl is built with Windows SSPI
-my $has_gssapi; # set if libcurl is built with a GSS-API library
-my $has_kerberos; # set if libcurl is built with Kerberos support
-my $has_spnego; # set if libcurl is built with SPNEGO support
-my $has_charconv; # set if libcurl is built with CharConv support
-my $has_tls_srp; # set if libcurl is built with TLS-SRP support
-my $has_http2; # set if libcurl is built with HTTP2 support
-my $has_h2c; # set if libcurl is built with h2c support
-my $has_httpsproxy; # set if libcurl is built with HTTPS-proxy support
-my $has_crypto; # set if libcurl is built with cryptographic support
-my $has_cares; # set if built with c-ares
-my $has_threadedres;# set if built with threaded resolver
-my $has_psl; # set if libcurl is built with PSL support
-my $has_altsvc; # set if libcurl is built with alt-svc support
-my $has_hsts; # set if libcurl is built with HSTS support
-my $has_ldpreload; # set if built for systems supporting LD_PRELOAD
-my $has_multissl; # set if build with MultiSSL support
-my $has_manual; # set if built with built-in manual
-my $has_win32; # set if built for Windows
-my $has_mingw; # set if built with MinGW (as opposed to MinGW-w64)
-my $has_hyper = 0; # set if built with Hyper
-my $has_libssh2; # set if built with libssh2
-my $has_libssh; # set if built with libssh
-my $has_oldlibssh; # set if built with libssh < 0.9.4
-my $has_wolfssh; # set if built with wolfssh
-my $has_unicode; # set if libcurl is built with Unicode support
-my $has_threadsafe; # set if libcurl is built with thread-safety support
-
-# this version is decided by the particular nghttp2 library that is being used
-my $h2cver = "h2c";
-
-my $has_rustls; # built with rustls
-my $has_openssl; # built with a lib using an OpenSSL-like API
-my $has_gnutls; # built with GnuTLS
-my $has_nss; # built with NSS
-my $has_wolfssl; # built with wolfSSL
-my $has_bearssl; # built with BearSSL
-my $has_schannel; # built with Schannel
-my $has_sectransp; # built with Secure Transport
-my $has_boringssl; # built with BoringSSL
-my $has_libressl; # built with libressl
-my $has_mbedtls; # built with mbedTLS
-
-my $has_sslpinning; # built with a TLS backend that supports pinning
-
-my $has_shared = "unknown"; # built shared
my $resolver; # name of the resolver backend (for human presentation)
my $has_textaware; # set if running on a system that has a text mode concept
# on files. Windows for example
-my @protocols; # array of lowercase supported protocol servers
-my $skipped=0; # number of tests skipped; reported in main loop
my %skipped; # skipped{reason}=counter, reasons for skip
my @teststat; # teststat[testnum]=reason, reasons for skip
my %disabled_keywords; # key words of tests to skip
@@ -313,14 +139,7 @@
my %enabled_keywords; # key words of tests to run
my %disabled; # disabled test cases
my %ignored; # ignored results of test cases
-
-my $sshdid; # for socks server, ssh daemon version id
-my $sshdvernum; # for socks server, ssh daemon version number
-my $sshdverstr; # for socks server, ssh daemon version string
-my $sshderror; # for socks server, ssh daemon version error
-
-my $defserverlogslocktimeout = 2; # timeout to await server logs lock removal
-my $defpostcommanddelay = 0; # delay between command and postcheck sections
+my %ignoretestcodes; # if test results are to be ignored
my $timestats; # time stamping and stats generation
my $fullstats; # show time stats for every single test
@@ -331,43 +150,35 @@
my %timetoolend; # timestamp for each test command run stopping
my %timesrvrlog; # timestamp for each test server logs lock removal
my %timevrfyend; # timestamp for each test result verification end
+my $globalabort; # flag signalling program abort
-my $testnumcheck; # test number, set in singletest sub.
-my %oldenv;
-my %feature; # array of enabled features
-my %keywords; # array of keywords from the test spec
+# values for $singletest_state
+use constant {
+ ST_INIT => 0,
+ ST_CLEARLOCKS => 1,
+ ST_INITED => 2,
+ ST_PREPROCESS => 3,
+ ST_RUN => 4,
+};
+my %singletest_state; # current state of singletest() by runner ID
+my %singletest_logs; # log messages while in singletest array ref by runner
+my $singletest_bufferedrunner; # runner ID which is buffering logs
+my %runnerids; # runner IDs by number
+my @runnersidle; # runner IDs idle and ready to execute a test
+my %countforrunner; # test count by runner ID
+my %runnersrunning; # tests currently running by runner ID
#######################################################################
# variables that command line options may set
#
-
my $short;
-my $automakestyle;
-my $verbose;
-my $debugprotocol;
-my $anyway;
-my $gdbthis; # run test case with gdb debugger
-my $gdbxwin; # use windowed gdb when using gdb
+my $no_debuginfod;
my $keepoutfiles; # keep stdout and stderr files after tests
my $clearlocks; # force removal of files by killing locking processes
-my $listonly; # only list the tests
my $postmortem; # display detailed info about failed tests
-my $err_unexpected; # error instead of warning on server unexpectedly alive
-my $run_event_based; # run curl with --test-event to test the event API
-my $run_disabeled; # run the specific tests even if listed in DISABLED
-
-my %run; # running server
-my %doesntrun; # servers that don't work, identified by pidfile
-my %serverpidfile;# all server pid file names, identified by server id
-my %serverportfile;# all server port file names, identified by server id
-my %runcert; # cert file currently in use by an ssl running server
-
-# torture test variables
-my $torture;
-my $tortnum;
-my $tortalloc;
-my $shallow;
-my $randseed = 0;
+my $run_disabled; # run the specific tests even if listed in DISABLED
+my $scrambleorder;
+my $jobs = 0;
# Azure Pipelines specific variables
my $AZURE_RUN_ID = 0;
@@ -377,8 +188,15 @@
# logmsg is our general message logging subroutine.
#
sub logmsg {
+ if($singletest_bufferedrunner) {
+ # Logs are currently being buffered
+ return singletest_logmsg(@_);
+ }
for(@_) {
my $line = $_;
+ if(!$line) {
+ next;
+ }
if ($is_wsl) {
# use \r\n for WSL shell
$line =~ s/\r?\n$/\r\n/g;
@@ -387,40 +205,83 @@
}
}
-# get the name of the current user
-my $USER = $ENV{USER}; # Linux
-if (!$USER) {
- $USER = $ENV{USERNAME}; # Windows
- if (!$USER) {
- $USER = $ENV{LOGNAME}; # Some Unix (I think)
+#######################################################################
+# enable logmsg buffering for the given runner ID
+#
+sub logmsg_bufferfortest {
+ my ($runnerid)=@_;
+ if($jobs) {
+ # Only enable buffering in multiprocess mode
+ $singletest_bufferedrunner = $runnerid;
}
}
+#######################################################################
+# Store a log message in a buffer for this test
+# The messages can then be displayed all at once at the end of the test
+# which prevents messages from different tests from being interleaved.
+sub singletest_logmsg {
+ if(!exists $singletest_logs{$singletest_bufferedrunner}) {
+ # initialize to a reference to an empty anonymous array
+ $singletest_logs{$singletest_bufferedrunner} = [];
+ }
+ my $logsref = $singletest_logs{$singletest_bufferedrunner};
+ push @$logsref, @_;
+}
-# enable memory debugging if curl is compiled with it
-$ENV{'CURL_MEMDEBUG'} = $memdump;
-$ENV{'CURL_ENTROPY'}="12345678";
-$ENV{'CURL_FORCETIME'}=1; # for debug NTLM magic
-$ENV{'CURL_GLOBAL_INIT'}=1; # debug curl_global_init/cleanup use
-$ENV{'HOME'}=$pwd;
-$ENV{'CURL_HOME'}=$ENV{'HOME'};
-$ENV{'XDG_CONFIG_HOME'}=$ENV{'HOME'};
-$ENV{'COLUMNS'}=79; # screen width!
+#######################################################################
+# Stop buffering log messages, but don't touch them
+sub singletest_unbufferlogs {
+ undef $singletest_bufferedrunner;
+}
+
+#######################################################################
+# Clear the buffered log messages & stop buffering after returning them
+sub singletest_dumplogs {
+ if(!defined $singletest_bufferedrunner) {
+ # probably not multiprocess mode and logs weren't buffered
+ return undef;
+ }
+ my $logsref = $singletest_logs{$singletest_bufferedrunner};
+ my $msg = join("", @$logsref);
+ delete $singletest_logs{$singletest_bufferedrunner};
+ singletest_unbufferlogs();
+ return $msg;
+}
sub catch_zap {
my $signame = shift;
- logmsg "runtests.pl received SIG$signame, exiting\n";
- stopservers($verbose);
- die "Somebody sent me a SIG$signame";
+ print "runtests.pl received SIG$signame, exiting\r\n";
+ $globalabort = 1;
}
$SIG{INT} = \&catch_zap;
$SIG{TERM} = \&catch_zap;
+sub catch_usr1 {
+ print "runtests.pl internal state:\r\n";
+ print scalar(%runnersrunning) . " busy test runner(s) of " . scalar(keys %runnerids) . "\r\n";
+ foreach my $rid (sort(keys(%runnersrunning))) {
+ my $runnernum = "unknown";
+ foreach my $rnum (keys %runnerids) {
+ if($runnerids{$rnum} == $rid) {
+ $runnernum = $rnum;
+ last;
+ }
+ }
+ print "Runner $runnernum (id $rid) running test $runnersrunning{$rid} in state $singletest_state{$rid}\r\n";
+ }
+}
+
+eval {
+ # some msys2 perl versions don't define SIGUSR1
+ $SIG{USR1} = \&catch_usr1;
+};
+$SIG{PIPE} = 'IGNORE'; # these errors are captured in the read/write calls
+
##########################################################################
# Clear all possible '*_proxy' environment variables for various protocols
# to prevent them to interfere with our testing!
-my $protocol;
-foreach $protocol (('ftp', 'http', 'ftps', 'https', 'no', 'all')) {
+foreach my $protocol (('ftp', 'http', 'ftps', 'https', 'no', 'all')) {
my $proxy = "${protocol}_proxy";
# clear lowercase version
delete $ENV{$proxy} if($ENV{$proxy});
@@ -433,162 +294,31 @@
delete $ENV{'SSL_CERT_DIR'} if($ENV{'SSL_CERT_DIR'});
delete $ENV{'SSL_CERT_PATH'} if($ENV{'SSL_CERT_PATH'});
-delete $ENV{'DEBUGINFOD_URLS'} if($ENV{'DEBUGINFOD_URLS'});
delete $ENV{'CURL_CA_BUNDLE'} if($ENV{'CURL_CA_BUNDLE'});
-#######################################################################
-# Load serverpidfile and serverportfile hashes with file names for all
-# possible servers.
-#
-sub init_serverpidfile_hash {
- for my $proto (('ftp', 'gopher', 'http', 'imap', 'pop3', 'smtp', 'http/2')) {
- for my $ssl (('', 's')) {
- for my $ipvnum ((4, 6)) {
- for my $idnum ((1, 2, 3)) {
- my $serv = servername_id("$proto$ssl", $ipvnum, $idnum);
- my $pidf = server_pidfilename("$proto$ssl", $ipvnum, $idnum);
- $serverpidfile{$serv} = $pidf;
- my $portf = server_portfilename("$proto$ssl", $ipvnum, $idnum);
- $serverportfile{$serv} = $portf;
- }
- }
+# provide defaults from our config file for ENV vars not explicitly
+# set by the caller
+if (open(my $fd, "<", "config")) {
+ while(my $line = <$fd>) {
+ next if ($line =~ /^#/);
+ chomp $line;
+ my ($name, $val) = split(/\s*:\s*/, $line, 2);
+ $ENV{$name} = $val if(!$ENV{$name});
}
- }
- for my $proto (('tftp', 'sftp', 'socks', 'ssh', 'rtsp', 'httptls',
- 'dict', 'smb', 'smbs', 'telnet', 'mqtt')) {
- for my $ipvnum ((4, 6)) {
- for my $idnum ((1, 2)) {
- my $serv = servername_id($proto, $ipvnum, $idnum);
- my $pidf = server_pidfilename($proto, $ipvnum, $idnum);
- $serverpidfile{$serv} = $pidf;
- my $portf = server_portfilename($proto, $ipvnum, $idnum);
- $serverportfile{$serv} = $portf;
- }
- }
- }
- for my $proto (('http', 'imap', 'pop3', 'smtp', 'http/2')) {
- for my $ssl (('', 's')) {
- my $serv = servername_id("$proto$ssl", "unix", 1);
- my $pidf = server_pidfilename("$proto$ssl", "unix", 1);
- $serverpidfile{$serv} = $pidf;
- my $portf = server_portfilename("$proto$ssl", "unix", 1);
- $serverportfile{$serv} = $portf;
- }
- }
+ close($fd);
}
-#######################################################################
-# Check if a given child process has just died. Reaps it if so.
-#
-sub checkdied {
- use POSIX ":sys_wait_h";
- my $pid = $_[0];
- if((not defined $pid) || $pid <= 0) {
- return 0;
- }
- my $rc = pidwait($pid, &WNOHANG);
- return ($rc == $pid)?1:0;
+# Check if we have nghttpx available and if it talks http/3
+my $nghttpx_h3 = 0;
+if (!$ENV{"NGHTTPX"}) {
+ $ENV{"NGHTTPX"} = checktestcmd("nghttpx");
+}
+if ($ENV{"NGHTTPX"}) {
+ my $nghttpx_version=join(' ', `"$ENV{'NGHTTPX'} -v 2>/dev/null"`);
+ $nghttpx_h3 = $nghttpx_version =~ /nghttp3\//;
+ chomp $nghttpx_h3;
}
-#######################################################################
-# Start a new thread/process and run the given command line in there.
-# Return the pids (yes plural) of the new child process to the parent.
-#
-sub startnew {
- my ($cmd, $pidfile, $timeout, $fake)=@_;
-
- logmsg "startnew: $cmd\n" if ($verbose);
-
- my $child = fork();
- my $pid2 = 0;
-
- if(not defined $child) {
- logmsg "startnew: fork() failure detected\n";
- return (-1,-1);
- }
-
- if(0 == $child) {
- # Here we are the child. Run the given command.
-
- # Flush output.
- $| = 1;
-
- # Put an "exec" in front of the command so that the child process
- # keeps this child's process ID.
- exec("exec $cmd") || die "Can't exec() $cmd: $!";
-
- # exec() should never return back here to this process. We protect
- # ourselves by calling die() just in case something goes really bad.
- die "error: exec() has returned";
- }
-
- # Ugly hack but ssh client and gnutls-serv don't support pid files
- if ($fake) {
- if(open(OUT, ">$pidfile")) {
- print OUT $child . "\n";
- close(OUT);
- logmsg "startnew: $pidfile faked with pid=$child\n" if($verbose);
- }
- else {
- logmsg "startnew: failed to write fake $pidfile with pid=$child\n";
- }
- # could/should do a while connect fails sleep a bit and loop
- portable_sleep($timeout);
- if (checkdied($child)) {
- logmsg "startnew: child process has failed to start\n" if($verbose);
- return (-1,-1);
- }
- }
-
- my $count = $timeout;
- while($count--) {
- if(-f $pidfile && -s $pidfile && open(PID, "<$pidfile")) {
- $pid2 = 0 + <PID>;
- close(PID);
- if(($pid2 > 0) && pidexists($pid2)) {
- # if $pid2 is valid, then make sure this pid is alive, as
- # otherwise it is just likely to be the _previous_ pidfile or
- # similar!
- last;
- }
- # invalidate $pid2 if not actually alive
- $pid2 = 0;
- }
- if (checkdied($child)) {
- logmsg "startnew: child process has died, server might start up\n"
- if($verbose);
- # We can't just abort waiting for the server with a
- # return (-1,-1);
- # because the server might have forked and could still start
- # up normally. Instead, just reduce the amount of time we remain
- # waiting.
- $count >>= 2;
- }
- sleep(1);
- }
-
- # Return two PIDs, the one for the child process we spawned and the one
- # reported by the server itself (in case it forked again on its own).
- # Both (potentially) need to be killed at the end of the test.
- return ($child, $pid2);
-}
-
-
-#######################################################################
-# Check for a command in the PATH of the test server.
-#
-sub checkcmd {
- my ($cmd)=@_;
- my @paths=(split(":", $ENV{'PATH'}), "/usr/sbin", "/usr/local/sbin",
- "/sbin", "/usr/bin", "/usr/local/bin",
- "$LIBDIR/.libs", "$LIBDIR");
- for(@paths) {
- if( -x "$_/$cmd" && ! -d "$_/$cmd") {
- # executable bit but not a directory!
- return "$_/$cmd";
- }
- }
-}
#######################################################################
# Get the list of tests that the tests/data/Makefile.am knows about!
@@ -597,2245 +327,34 @@
sub get_disttests {
# If a non-default $TESTDIR is being used there may not be any
# Makefile.inc in which case there's nothing to do.
- open(D, "<$TESTDIR/Makefile.inc") or return;
- while(<D>) {
+ open(my $dh, "<", "$TESTDIR/Makefile.inc") or return;
+ while(<$dh>) {
chomp $_;
if(($_ =~ /^#/) ||($_ !~ /test/)) {
next;
}
$disttests .= $_;
}
- close(D);
+ close($dh);
}
-#######################################################################
-# Check for a command in the PATH of the machine running curl.
-#
-sub checktestcmd {
- my ($cmd)=@_;
- return checkcmd($cmd);
-}
-
-#######################################################################
-# Run the application under test and return its return code
-#
-sub runclient {
- my ($cmd)=@_;
- my $ret = system($cmd);
- print "CMD ($ret): $cmd\n" if($verbose && !$torture);
- return $ret;
-
-# This is one way to test curl on a remote machine
-# my $out = system("ssh $CLIENTIP cd \'$pwd\' \\; \'$cmd\'");
-# sleep 2; # time to allow the NFS server to be updated
-# return $out;
-}
-
-#######################################################################
-# Run the application under test and return its stdout
-#
-sub runclientoutput {
- my ($cmd)=@_;
- return `$cmd`;
-
-# This is one way to test curl on a remote machine
-# my @out = `ssh $CLIENTIP cd \'$pwd\' \\; \'$cmd\'`;
-# sleep 2; # time to allow the NFS server to be updated
-# return @out;
- }
-
-#######################################################################
-# Memory allocation test and failure torture testing.
-#
-sub torture {
- my ($testcmd, $testnum, $gdbline) = @_;
-
- # remove memdump first to be sure we get a new nice and clean one
- unlink($memdump);
-
- # First get URL from test server, ignore the output/result
- runclient($testcmd);
-
- logmsg " CMD: $testcmd\n" if($verbose);
-
- # memanalyze -v is our friend, get the number of allocations made
- my $count=0;
- my @out = `$memanalyze -v $memdump`;
- for(@out) {
- if(/^Operations: (\d+)/) {
- $count = $1;
- last;
- }
- }
- if(!$count) {
- logmsg " found no functions to make fail\n";
- return 0;
- }
-
- my @ttests = (1 .. $count);
- if($shallow && ($shallow < $count)) {
- my $discard = scalar(@ttests) - $shallow;
- my $percent = sprintf("%.2f%%", $shallow * 100 / scalar(@ttests));
- logmsg " $count functions found, but only fail $shallow ($percent)\n";
- while($discard) {
- my $rm;
- do {
- # find a test to discard
- $rm = rand(scalar(@ttests));
- } while(!$ttests[$rm]);
- $ttests[$rm] = undef;
- $discard--;
- }
- }
- else {
- logmsg " $count functions to make fail\n";
- }
-
- for (@ttests) {
- my $limit = $_;
- my $fail;
- my $dumped_core;
-
- if(!defined($limit)) {
- # --shallow can undefine them
- next;
- }
- if($tortalloc && ($tortalloc != $limit)) {
- next;
- }
-
- if($verbose) {
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
- localtime(time());
- my $now = sprintf("%02d:%02d:%02d ", $hour, $min, $sec);
- logmsg "Fail function no: $limit at $now\r";
- }
-
- # make the memory allocation function number $limit return failure
- $ENV{'CURL_MEMLIMIT'} = $limit;
-
- # remove memdump first to be sure we get a new nice and clean one
- unlink($memdump);
-
- my $cmd = $testcmd;
- if($valgrind && !$gdbthis) {
- my @valgrindoption = getpart("verify", "valgrind");
- if((!@valgrindoption) || ($valgrindoption[0] !~ /disable/)) {
- my $valgrindcmd = "$valgrind ";
- $valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
- $valgrindcmd .= "--quiet --leak-check=yes ";
- $valgrindcmd .= "--suppressions=$srcdir/valgrind.supp ";
- # $valgrindcmd .= "--gen-suppressions=all ";
- $valgrindcmd .= "--num-callers=16 ";
- $valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
- $cmd = "$valgrindcmd $testcmd";
- }
- }
- logmsg "*** Function number $limit is now set to fail ***\n" if($gdbthis);
-
- my $ret = 0;
- if($gdbthis) {
- runclient($gdbline);
- }
- else {
- $ret = runclient($cmd);
- }
- #logmsg "$_ Returned " . ($ret >> 8) . "\n";
-
- # Now clear the variable again
- delete $ENV{'CURL_MEMLIMIT'} if($ENV{'CURL_MEMLIMIT'});
-
- if(-r "core") {
- # there's core file present now!
- logmsg " core dumped\n";
- $dumped_core = 1;
- $fail = 2;
- }
-
- if($valgrind) {
- my @e = valgrindparse("$LOGDIR/valgrind$testnum");
- if(@e && $e[0]) {
- if($automakestyle) {
- logmsg "FAIL: torture $testnum - valgrind\n";
- }
- else {
- logmsg " valgrind ERROR ";
- logmsg @e;
- }
- $fail = 1;
- }
- }
-
- # verify that it returns a proper error code, doesn't leak memory
- # and doesn't core dump
- if(($ret & 255) || ($ret >> 8) >= 128) {
- logmsg " system() returned $ret\n";
- $fail=1;
- }
- else {
- my @memdata=`$memanalyze $memdump`;
- my $leak=0;
- for(@memdata) {
- if($_ ne "") {
- # well it could be other memory problems as well, but
- # we call it leak for short here
- $leak=1;
- }
- }
- if($leak) {
- logmsg "** MEMORY FAILURE\n";
- logmsg @memdata;
- logmsg `$memanalyze -l $memdump`;
- $fail = 1;
- }
- }
- if($fail) {
- logmsg " Failed on function number $limit in test.\n",
- " invoke with \"-t$limit\" to repeat this single case.\n";
- stopservers($verbose);
- return 1;
- }
- }
-
- logmsg "torture OK\n";
- return 0;
-}
-
-#######################################################################
-# Stop a test server along with pids which aren't in the %run hash yet.
-# This also stops all servers which are relative to the given one.
-#
-sub stopserver {
- my ($server, $pidlist) = @_;
-
- #
- # kill sockfilter processes for pingpong relative server
- #
- if($server =~ /^(ftp|imap|pop3|smtp)s?(\d*)(-ipv6|)$/) {
- my $proto = $1;
- my $idnum = ($2 && ($2 > 1)) ? $2 : 1;
- my $ipvnum = ($3 && ($3 =~ /6$/)) ? 6 : 4;
- killsockfilters($proto, $ipvnum, $idnum, $verbose);
- }
- #
- # All servers relative to the given one must be stopped also
- #
- my @killservers;
- if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
- # given a stunnel based ssl server, also kill non-ssl underlying one
- push @killservers, "${1}${2}";
- }
- elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|-unix|))$/) {
- # given a non-ssl server, also kill stunnel based ssl piggybacking one
- push @killservers, "${1}s${2}";
- }
- elsif($server =~ /^(socks)((\d*)(-ipv6|))$/) {
- # given a socks server, also kill ssh underlying one
- push @killservers, "ssh${2}";
- }
- elsif($server =~ /^(ssh)((\d*)(-ipv6|))$/) {
- # given a ssh server, also kill socks piggybacking one
- push @killservers, "socks${2}";
- }
- if($server eq "http") {
- # since the http2 server is a proxy that needs to know about the
- # dynamic http port it too needs to get restarted when the http server
- # is killed
- push @killservers, "http/2";
- }
- push @killservers, $server;
- #
- # kill given pids and server relative ones clearing them in %run hash
- #
- foreach my $server (@killservers) {
- if($run{$server}) {
- # we must prepend a space since $pidlist may already contain a pid
- $pidlist .= " $run{$server}";
- $run{$server} = 0;
- }
- $runcert{$server} = 0 if($runcert{$server});
- }
- killpid($verbose, $pidlist);
- #
- # cleanup server pid files
- #
- my $result = 0;
- foreach my $server (@killservers) {
- my $pidfile = $serverpidfile{$server};
- my $pid = processexists($pidfile);
- if($pid > 0) {
- if($err_unexpected) {
- logmsg "ERROR: ";
- $result = -1;
- }
- else {
- logmsg "Warning: ";
- }
- logmsg "$server server unexpectedly alive\n";
- killpid($verbose, $pid);
- }
- unlink($pidfile) if(-f $pidfile);
- }
-
- return $result;
-}
-
-#######################################################################
-# Return flags to let curl use an external HTTP proxy
-#
-sub getexternalproxyflags {
- return " --proxy $proxy_address ";
-}
-
-#######################################################################
-# Verify that the server that runs on $ip, $port is our server. This also
-# implies that we can speak with it, as there might be occasions when the
-# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
-# assign requested address")
-#
-sub verifyhttp {
- my ($proto, $ipvnum, $idnum, $ip, $port_or_path) = @_;
- my $server = servername_id($proto, $ipvnum, $idnum);
- my $pid = 0;
- my $bonus="";
- # $port_or_path contains a path for Unix sockets, sws ignores the port
- my $port = ($ipvnum eq "unix") ? 80 : $port_or_path;
-
- my $verifyout = "$LOGDIR/".
- servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
- unlink($verifyout) if(-f $verifyout);
-
- my $verifylog = "$LOGDIR/".
- servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
- unlink($verifylog) if(-f $verifylog);
-
- if($proto eq "gopher") {
- # gopher is funny
- $bonus="1/";
- }
-
- my $flags = "--max-time $server_response_maxtime ";
- $flags .= "--output $verifyout ";
- $flags .= "--silent ";
- $flags .= "--verbose ";
- $flags .= "--globoff ";
- $flags .= "--unix-socket '$port_or_path' " if $ipvnum eq "unix";
- $flags .= "--insecure " if($proto eq 'https');
- if($use_external_proxy) {
- $flags .= getexternalproxyflags();
- }
- $flags .= "\"$proto://$ip:$port/${bonus}verifiedserver\"";
-
- my $cmd = "$VCURL $flags 2>$verifylog";
-
- # verify if our/any server is running on this port
- logmsg "RUN: $cmd\n" if($verbose);
- my $res = runclient($cmd);
-
- $res >>= 8; # rotate the result
- if($res & 128) {
- logmsg "RUN: curl command died with a coredump\n";
- return -1;
- }
-
- if($res && $verbose) {
- logmsg "RUN: curl command returned $res\n";
- if(open(FILE, "<$verifylog")) {
- while(my $string = <FILE>) {
- logmsg "RUN: $string" if($string !~ /^([ \t]*)$/);
- }
- close(FILE);
- }
- }
-
- my $data;
- if(open(FILE, "<$verifyout")) {
- while(my $string = <FILE>) {
- $data = $string;
- last; # only want first line
- }
- close(FILE);
- }
-
- if($data && ($data =~ /WE ROOLZ: (\d+)/)) {
- $pid = 0+$1;
- }
- elsif($res == 6) {
- # curl: (6) Couldn't resolve host '::1'
- logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n";
- return -1;
- }
- elsif($data || ($res && ($res != 7))) {
- logmsg "RUN: Unknown server on our $server port: $port ($res)\n";
- return -1;
- }
- return $pid;
-}
-
-#######################################################################
-# Verify that the server that runs on $ip, $port is our server. This also
-# implies that we can speak with it, as there might be occasions when the
-# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
-# assign requested address")
-#
-sub verifyftp {
- my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
- my $server = servername_id($proto, $ipvnum, $idnum);
- my $pid = 0;
- my $time=time();
- my $extra="";
-
- my $verifylog = "$LOGDIR/".
- servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
- unlink($verifylog) if(-f $verifylog);
-
- if($proto eq "ftps") {
- $extra .= "--insecure --ftp-ssl-control ";
- }
-
- my $flags = "--max-time $server_response_maxtime ";
- $flags .= "--silent ";
- $flags .= "--verbose ";
- $flags .= "--globoff ";
- $flags .= $extra;
- if($use_external_proxy) {
- $flags .= getexternalproxyflags();
- }
- $flags .= "\"$proto://$ip:$port/verifiedserver\"";
-
- my $cmd = "$VCURL $flags 2>$verifylog";
-
- # check if this is our server running on this port:
- logmsg "RUN: $cmd\n" if($verbose);
- my @data = runclientoutput($cmd);
-
- my $res = $? >> 8; # rotate the result
- if($res & 128) {
- logmsg "RUN: curl command died with a coredump\n";
- return -1;
- }
-
- foreach my $line (@data) {
- if($line =~ /WE ROOLZ: (\d+)/) {
- # this is our test server with a known pid!
- $pid = 0+$1;
- last;
- }
- }
- if($pid <= 0 && @data && $data[0]) {
- # this is not a known server
- logmsg "RUN: Unknown server on our $server port: $port\n";
- return 0;
- }
- # we can/should use the time it took to verify the FTP server as a measure
- # on how fast/slow this host/FTP is.
- my $took = int(0.5+time()-$time);
-
- if($verbose) {
- logmsg "RUN: Verifying our test $server server took $took seconds\n";
- }
- $ftpchecktime = $took>=1?$took:1; # make sure it never is below 1
-
- return $pid;
-}
-
-#######################################################################
-# Verify that the server that runs on $ip, $port is our server. This also
-# implies that we can speak with it, as there might be occasions when the
-# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
-# assign requested address")
-#
-sub verifyrtsp {
- my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
- my $server = servername_id($proto, $ipvnum, $idnum);
- my $pid = 0;
-
- my $verifyout = "$LOGDIR/".
- servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
- unlink($verifyout) if(-f $verifyout);
-
- my $verifylog = "$LOGDIR/".
- servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
- unlink($verifylog) if(-f $verifylog);
-
- my $flags = "--max-time $server_response_maxtime ";
- $flags .= "--output $verifyout ";
- $flags .= "--silent ";
- $flags .= "--verbose ";
- $flags .= "--globoff ";
- if($use_external_proxy) {
- $flags .= getexternalproxyflags();
- }
- # currently verification is done using http
- $flags .= "\"http://$ip:$port/verifiedserver\"";
-
- my $cmd = "$VCURL $flags 2>$verifylog";
-
- # verify if our/any server is running on this port
- logmsg "RUN: $cmd\n" if($verbose);
- my $res = runclient($cmd);
-
- $res >>= 8; # rotate the result
- if($res & 128) {
- logmsg "RUN: curl command died with a coredump\n";
- return -1;
- }
-
- if($res && $verbose) {
- logmsg "RUN: curl command returned $res\n";
- if(open(FILE, "<$verifylog")) {
- while(my $string = <FILE>) {
- logmsg "RUN: $string" if($string !~ /^([ \t]*)$/);
- }
- close(FILE);
- }
- }
-
- my $data;
- if(open(FILE, "<$verifyout")) {
- while(my $string = <FILE>) {
- $data = $string;
- last; # only want first line
- }
- close(FILE);
- }
-
- if($data && ($data =~ /RTSP_SERVER WE ROOLZ: (\d+)/)) {
- $pid = 0+$1;
- }
- elsif($res == 6) {
- # curl: (6) Couldn't resolve host '::1'
- logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n";
- return -1;
- }
- elsif($data || ($res != 7)) {
- logmsg "RUN: Unknown server on our $server port: $port\n";
- return -1;
- }
- return $pid;
-}
-
-#######################################################################
-# Verify that the ssh server has written out its pidfile, recovering
-# the pid from the file and returning it if a process with that pid is
-# actually alive.
-#
-sub verifyssh {
- my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
- my $server = servername_id($proto, $ipvnum, $idnum);
- my $pidfile = server_pidfilename($proto, $ipvnum, $idnum);
- my $pid = 0;
- if(open(FILE, "<$pidfile")) {
- $pid=0+<FILE>;
- close(FILE);
- }
- if($pid > 0) {
- # if we have a pid it is actually our ssh server,
- # since runsshserver() unlinks previous pidfile
- if(!pidexists($pid)) {
- logmsg "RUN: SSH server has died after starting up\n";
- checkdied($pid);
- unlink($pidfile);
- $pid = -1;
- }
- }
- return $pid;
-}
-
-#######################################################################
-# Verify that we can connect to the sftp server, properly authenticate
-# with generated config and key files and run a simple remote pwd.
-#
-sub verifysftp {
- my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
- my $server = servername_id($proto, $ipvnum, $idnum);
- my $verified = 0;
- # Find out sftp client canonical file name
- my $sftp = find_sftp();
- if(!$sftp) {
- logmsg "RUN: SFTP server cannot find $sftpexe\n";
- return -1;
- }
- # Find out ssh client canonical file name
- my $ssh = find_ssh();
- if(!$ssh) {
- logmsg "RUN: SFTP server cannot find $sshexe\n";
- return -1;
- }
- # Connect to sftp server, authenticate and run a remote pwd
- # command using our generated configuration and key files
- my $cmd = "\"$sftp\" -b $sftpcmds -F $sftpconfig -S \"$ssh\" $ip > $sftplog 2>&1";
- my $res = runclient($cmd);
- # Search for pwd command response in log file
- if(open(SFTPLOGFILE, "<$sftplog")) {
- while(<SFTPLOGFILE>) {
- if(/^Remote working directory: /) {
- $verified = 1;
- last;
- }
- }
- close(SFTPLOGFILE);
- }
- return $verified;
-}
-
-#######################################################################
-# Verify that the non-stunnel HTTP TLS extensions capable server that runs
-# on $ip, $port is our server. This also implies that we can speak with it,
-# as there might be occasions when the server runs fine but we cannot talk
-# to it ("Failed to connect to ::1: Can't assign requested address")
-#
-sub verifyhttptls {
- my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
- my $server = servername_id($proto, $ipvnum, $idnum);
- my $pidfile = server_pidfilename($proto, $ipvnum, $idnum);
- my $pid = 0;
-
- my $verifyout = "$LOGDIR/".
- servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
- unlink($verifyout) if(-f $verifyout);
-
- my $verifylog = "$LOGDIR/".
- servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
- unlink($verifylog) if(-f $verifylog);
-
- my $flags = "--max-time $server_response_maxtime ";
- $flags .= "--output $verifyout ";
- $flags .= "--verbose ";
- $flags .= "--globoff ";
- $flags .= "--insecure ";
- $flags .= "--tlsauthtype SRP ";
- $flags .= "--tlsuser jsmith ";
- $flags .= "--tlspassword abc ";
- if($use_external_proxy) {
- $flags .= getexternalproxyflags();
- }
- $flags .= "\"https://$ip:$port/verifiedserver\"";
-
- my $cmd = "$VCURL $flags 2>$verifylog";
-
- # verify if our/any server is running on this port
- logmsg "RUN: $cmd\n" if($verbose);
- my $res = runclient($cmd);
-
- $res >>= 8; # rotate the result
- if($res & 128) {
- logmsg "RUN: curl command died with a coredump\n";
- return -1;
- }
-
- if($res && $verbose) {
- logmsg "RUN: curl command returned $res\n";
- if(open(FILE, "<$verifylog")) {
- while(my $string = <FILE>) {
- logmsg "RUN: $string" if($string !~ /^([ \t]*)$/);
- }
- close(FILE);
- }
- }
-
- my $data;
- if(open(FILE, "<$verifyout")) {
- while(my $string = <FILE>) {
- $data .= $string;
- }
- close(FILE);
- }
-
- if($data && ($data =~ /(GNUTLS|GnuTLS)/) && open(FILE, "<$pidfile")) {
- $pid=0+<FILE>;
- close(FILE);
- if($pid > 0) {
- # if we have a pid it is actually our httptls server,
- # since runhttptlsserver() unlinks previous pidfile
- if(!pidexists($pid)) {
- logmsg "RUN: $server server has died after starting up\n";
- checkdied($pid);
- unlink($pidfile);
- $pid = -1;
- }
- }
- return $pid;
- }
- elsif($res == 6) {
- # curl: (6) Couldn't resolve host '::1'
- logmsg "RUN: failed to resolve host (https://$ip:$port/verifiedserver)\n";
- return -1;
- }
- elsif($data || ($res && ($res != 7))) {
- logmsg "RUN: Unknown server on our $server port: $port ($res)\n";
- return -1;
- }
- return $pid;
-}
-
-#######################################################################
-# STUB for verifying socks
-#
-sub verifysocks {
- my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
- my $server = servername_id($proto, $ipvnum, $idnum);
- my $pidfile = server_pidfilename($proto, $ipvnum, $idnum);
- my $pid = 0;
- if(open(FILE, "<$pidfile")) {
- $pid=0+<FILE>;
- close(FILE);
- }
- if($pid > 0) {
- # if we have a pid it is actually our socks server,
- # since runsocksserver() unlinks previous pidfile
- if(!pidexists($pid)) {
- logmsg "RUN: SOCKS server has died after starting up\n";
- checkdied($pid);
- unlink($pidfile);
- $pid = -1;
- }
- }
- return $pid;
-}
-
-#######################################################################
-# Verify that the server that runs on $ip, $port is our server. This also
-# implies that we can speak with it, as there might be occasions when the
-# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
-# assign requested address")
-#
-sub verifysmb {
- my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
- my $server = servername_id($proto, $ipvnum, $idnum);
- my $pid = 0;
- my $time=time();
- my $extra="";
-
- my $verifylog = "$LOGDIR/".
- servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
- unlink($verifylog) if(-f $verifylog);
-
- my $flags = "--max-time $server_response_maxtime ";
- $flags .= "--silent ";
- $flags .= "--verbose ";
- $flags .= "--globoff ";
- $flags .= "-u 'curltest:curltest' ";
- $flags .= $extra;
- $flags .= "\"$proto://$ip:$port/SERVER/verifiedserver\"";
-
- my $cmd = "$VCURL $flags 2>$verifylog";
-
- # check if this is our server running on this port:
- logmsg "RUN: $cmd\n" if($verbose);
- my @data = runclientoutput($cmd);
-
- my $res = $? >> 8; # rotate the result
- if($res & 128) {
- logmsg "RUN: curl command died with a coredump\n";
- return -1;
- }
-
- foreach my $line (@data) {
- if($line =~ /WE ROOLZ: (\d+)/) {
- # this is our test server with a known pid!
- $pid = 0+$1;
- last;
- }
- }
- if($pid <= 0 && @data && $data[0]) {
- # this is not a known server
- logmsg "RUN: Unknown server on our $server port: $port\n";
- return 0;
- }
- # we can/should use the time it took to verify the server as a measure
- # on how fast/slow this host is.
- my $took = int(0.5+time()-$time);
-
- if($verbose) {
- logmsg "RUN: Verifying our test $server server took $took seconds\n";
- }
- $ftpchecktime = $took>=1?$took:1; # make sure it never is below 1
-
- return $pid;
-}
-
-#######################################################################
-# Verify that the server that runs on $ip, $port is our server. This also
-# implies that we can speak with it, as there might be occasions when the
-# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
-# assign requested address")
-#
-sub verifytelnet {
- my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
- my $server = servername_id($proto, $ipvnum, $idnum);
- my $pid = 0;
- my $time=time();
- my $extra="";
-
- my $verifylog = "$LOGDIR/".
- servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
- unlink($verifylog) if(-f $verifylog);
-
- my $flags = "--max-time $server_response_maxtime ";
- $flags .= "--silent ";
- $flags .= "--verbose ";
- $flags .= "--globoff ";
- $flags .= "--upload-file - ";
- $flags .= $extra;
- $flags .= "\"$proto://$ip:$port\"";
-
- my $cmd = "echo 'verifiedserver' | $VCURL $flags 2>$verifylog";
-
- # check if this is our server running on this port:
- logmsg "RUN: $cmd\n" if($verbose);
- my @data = runclientoutput($cmd);
-
- my $res = $? >> 8; # rotate the result
- if($res & 128) {
- logmsg "RUN: curl command died with a coredump\n";
- return -1;
- }
-
- foreach my $line (@data) {
- if($line =~ /WE ROOLZ: (\d+)/) {
- # this is our test server with a known pid!
- $pid = 0+$1;
- last;
- }
- }
- if($pid <= 0 && @data && $data[0]) {
- # this is not a known server
- logmsg "RUN: Unknown server on our $server port: $port\n";
- return 0;
- }
- # we can/should use the time it took to verify the server as a measure
- # on how fast/slow this host is.
- my $took = int(0.5+time()-$time);
-
- if($verbose) {
- logmsg "RUN: Verifying our test $server server took $took seconds\n";
- }
-
- return $pid;
-}
-
-
-#######################################################################
-# Verify that the server that runs on $ip, $port is our server.
-# Retry over several seconds before giving up. The ssh server in
-# particular can take a long time to start if it needs to generate
-# keys on a slow or loaded host.
-#
-# Just for convenience, test harness uses 'https' and 'httptls' literals
-# as values for 'proto' variable in order to differentiate different
-# servers. 'https' literal is used for stunnel based https test servers,
-# and 'httptls' is used for non-stunnel https test servers.
-#
-
-my %protofunc = ('http' => \&verifyhttp,
- 'https' => \&verifyhttp,
- 'rtsp' => \&verifyrtsp,
- 'ftp' => \&verifyftp,
- 'pop3' => \&verifyftp,
- 'imap' => \&verifyftp,
- 'smtp' => \&verifyftp,
- 'ftps' => \&verifyftp,
- 'tftp' => \&verifyftp,
- 'ssh' => \&verifyssh,
- 'socks' => \&verifysocks,
- 'socks5unix' => \&verifysocks,
- 'gopher' => \&verifyhttp,
- 'httptls' => \&verifyhttptls,
- 'dict' => \&verifyftp,
- 'smb' => \&verifysmb,
- 'telnet' => \&verifytelnet);
-
-sub verifyserver {
- my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
-
- my $count = 30; # try for this many seconds
- my $pid;
-
- while($count--) {
- my $fun = $protofunc{$proto};
-
- $pid = &$fun($proto, $ipvnum, $idnum, $ip, $port);
-
- if($pid > 0) {
- last;
- }
- elsif($pid < 0) {
- # a real failure, stop trying and bail out
- return 0;
- }
- sleep(1);
- }
- return $pid;
-}
-
-#######################################################################
-# Single shot server responsiveness test. This should only be used
-# to verify that a server present in %run hash is still functional
-#
-sub responsiveserver {
- my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
- my $prev_verbose = $verbose;
-
- $verbose = 0;
- my $fun = $protofunc{$proto};
- my $pid = &$fun($proto, $ipvnum, $idnum, $ip, $port);
- $verbose = $prev_verbose;
-
- if($pid > 0) {
- return 1; # responsive
- }
-
- my $srvrname = servername_str($proto, $ipvnum, $idnum);
- logmsg " server precheck FAILED (unresponsive $srvrname server)\n";
- return 0;
-}
-
-#######################################################################
-# start the http2 server
-#
-sub runhttp2server {
- my ($verbose) = @_;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $flags = "";
- my $proto="http/2";
- my $ipvnum = 4;
- my $idnum = 0;
- my $exe = "$perl $srcdir/http2-server.pl";
- my $verbose_flag = "--verbose ";
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0, 0, 0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
- $flags .= "--connect $HOSTIP:$HTTPPORT ";
- $flags .= $verbose_flag if($debugprotocol);
-
- my ($http2pid, $pid2);
- my $port = 23113;
- for(1 .. 10) {
- $port += int(rand(900));
- my $aflags = "--port $port $flags";
-
- my $cmd = "$exe $aflags";
- ($http2pid, $pid2) = startnew($cmd, $pidfile, 15, 0);
-
- if($http2pid <= 0 || !pidexists($http2pid)) {
- # it is NOT alive
- stopserver($server, "$pid2");
- $doesntrun{$pidfile} = 1;
- $http2pid = $pid2 = 0;
- next;
- }
- $doesntrun{$pidfile} = 0;
-
- if($verbose) {
- logmsg "RUN: $srvrname server PID $http2pid port $port\n";
- }
- last;
- }
-
- logmsg "RUN: failed to start the $srvrname server\n" if(!$http2pid);
-
- return ($http2pid, $pid2, $port);
-}
-
-#######################################################################
-# start the http server
-#
-sub runhttpserver {
- my ($proto, $verbose, $alt, $port_or_path) = @_;
- my $ip = $HOSTIP;
- my $ipvnum = 4;
- my $idnum = 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $flags = "";
- my $exe = "$perl $srcdir/httpserver.pl";
- my $verbose_flag = "--verbose ";
-
- if($alt eq "ipv6") {
- # if IPv6, use a different setup
- $ipvnum = 6;
- $ip = $HOST6IP;
- }
- elsif($alt eq "proxy") {
- # basically the same, but another ID
- $idnum = 2;
- }
- elsif($alt eq "unix") {
- # IP (protocol) is mutually exclusive with Unix sockets
- $ipvnum = "unix";
- }
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
- my $portfile = $serverportfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0, 0, 0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- $flags .= "--gopher " if($proto eq "gopher");
- $flags .= "--connect $HOSTIP " if($alt eq "proxy");
- $flags .= $verbose_flag if($debugprotocol);
- $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
- $flags .= "--portfile $portfile ";
- $flags .= "--id $idnum " if($idnum > 1);
- if($ipvnum eq "unix") {
- $flags .= "--unix-socket '$port_or_path' ";
- } else {
- $flags .= "--ipv$ipvnum --port 0 ";
- }
- $flags .= "--srcdir \"$TESTDIR/..\"";
-
- my $cmd = "$exe $flags";
- my ($httppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
-
- if($httppid <= 0 || !pidexists($httppid)) {
- # it is NOT alive
- logmsg "RUN: failed to start the $srvrname server\n";
- stopserver($server, "$pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- return (0, 0, 0);
- }
-
- # where is it?
- my $port;
- if(!$port_or_path) {
- $port = $port_or_path = pidfromfile($portfile);
- }
-
- # Server is up. Verify that we can speak to it.
- my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
- if(!$pid3) {
- logmsg "RUN: $srvrname server failed verification\n";
- # failed to talk to it properly. Kill the server and return failure
- stopserver($server, "$httppid $pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- return (0, 0, 0);
- }
- $pid2 = $pid3;
-
- if($verbose) {
- logmsg "RUN: $srvrname server is on PID $httppid port $port\n";
- }
-
- return ($httppid, $pid2, $port);
-}
-
-#######################################################################
-# start the https stunnel based server
-#
-sub runhttpsserver {
- my ($verbose, $proto, $proxy, $certfile) = @_;
- my $ip = $HOSTIP;
- my $ipvnum = 4;
- my $idnum = 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $flags = "";
-
- if($proxy eq "proxy") {
- # the https-proxy runs as https2
- $idnum = 2;
- }
-
- if(!$stunnel) {
- return (0, 0, 0);
- }
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0, 0, 0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $certfile = 'stunnel.pem' unless($certfile);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- $flags .= "--verbose " if($debugprotocol);
- $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
- $flags .= "--id $idnum " if($idnum > 1);
- $flags .= "--ipv$ipvnum --proto $proto ";
- $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
- $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
- if($proto eq "gophers") {
- $flags .= "--connect $GOPHERPORT";
- }
- elsif(!$proxy) {
- $flags .= "--connect $HTTPPORT";
- }
- else {
- # for HTTPS-proxy we connect to the HTTP proxy
- $flags .= "--connect $HTTPPROXYPORT";
- }
-
- my $pid2;
- my $httpspid;
- my $port = 24512; # start attempt
- for (1 .. 10) {
- $port += int(rand(600));
- my $options = "$flags --accept $port";
-
- my $cmd = "$perl $srcdir/secureserver.pl $options";
- ($httpspid, $pid2) = startnew($cmd, $pidfile, 15, 0);
-
- if($httpspid <= 0 || !pidexists($httpspid)) {
- # it is NOT alive
- stopserver($server, "$pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- $httpspid = $pid2 = 0;
- next;
- }
- # we have a server!
- if($verbose) {
- logmsg "RUN: $srvrname server is PID $httpspid port $port\n";
- }
- last;
- }
- $runcert{$server} = $certfile;
- logmsg "RUN: failed to start the $srvrname server\n" if(!$httpspid);
-
- return ($httpspid, $pid2, $port);
-}
-
-#######################################################################
-# start the non-stunnel HTTP TLS extensions capable server
-#
-sub runhttptlsserver {
- my ($verbose, $ipv6) = @_;
- my $proto = "httptls";
- my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
- my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
- my $idnum = 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $flags = "";
-
- if(!$httptlssrv) {
- return (0,0);
- }
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0, 0, 0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- $flags .= "--http ";
- $flags .= "--debug 1 " if($debugprotocol);
- $flags .= "--priority NORMAL:+SRP ";
- $flags .= "--srppasswd $srcdir/certs/srp-verifier-db ";
- $flags .= "--srppasswdconf $srcdir/certs/srp-verifier-conf";
-
- my $port = 24367;
- my ($httptlspid, $pid2);
- for (1 .. 10) {
- $port += int(rand(800));
- my $allflags = "--port $port $flags";
-
- my $cmd = "$httptlssrv $allflags > $logfile 2>&1";
- ($httptlspid, $pid2) = startnew($cmd, $pidfile, 10, 1);
-
- if($httptlspid <= 0 || !pidexists($httptlspid)) {
- # it is NOT alive
- stopserver($server, "$pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- $httptlspid = $pid2 = 0;
- next;
- }
- $doesntrun{$pidfile} = 0;
-
- if($verbose) {
- logmsg "RUN: $srvrname server PID $httptlspid port $port\n";
- }
- last;
- }
- logmsg "RUN: failed to start the $srvrname server\n" if(!$httptlspid);
- return ($httptlspid, $pid2, $port);
-}
-
-#######################################################################
-# start the pingpong server (FTP, POP3, IMAP, SMTP)
-#
-sub runpingpongserver {
- my ($proto, $id, $verbose, $ipv6) = @_;
- my $port;
- my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
- my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
- my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $flags = "";
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
- my $portfile = $serverportfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0,0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- $flags .= "--verbose " if($debugprotocol);
- $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
- $flags .= "--portfile \"$portfile\" ";
- $flags .= "--srcdir \"$srcdir\" --proto $proto ";
- $flags .= "--id $idnum " if($idnum > 1);
- $flags .= "--ipv$ipvnum --port 0 --addr \"$ip\"";
-
- my $cmd = "$perl $srcdir/ftpserver.pl $flags";
- my ($ftppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
-
- if($ftppid <= 0 || !pidexists($ftppid)) {
- # it is NOT alive
- logmsg "RUN: failed to start the $srvrname server\n";
- stopserver($server, "$pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- return (0,0);
- }
-
- # where is it?
- $port = pidfromfile($portfile);
-
- logmsg "PINGPONG runs on port $port ($portfile)\n" if($verbose);
-
- # Server is up. Verify that we can speak to it.
- my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
- if(!$pid3) {
- logmsg "RUN: $srvrname server failed verification\n";
- # failed to talk to it properly. Kill the server and return failure
- stopserver($server, "$ftppid $pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- return (0,0);
- }
- $pid2 = $pid3;
-
- logmsg "RUN: $srvrname server is PID $ftppid port $port\n" if($verbose);
-
- # Assign the correct port variable!
- if($proto eq "ftp") {
- if($ipvnum == 6) {
- # if IPv6, use a different setup
- $FTP6PORT = $port;
- }
- else {
- $FTPPORT = $port;
- }
- }
- elsif($proto eq "pop3") {
- if($ipvnum == 6) {
- $POP36PORT = $port;
- }
- else {
- $POP3PORT = $port;
- }
- }
- elsif($proto eq "imap") {
- if($ipvnum == 6) {
- $IMAP6PORT = $port;
- }
- else {
- $IMAPPORT = $port;
- }
- }
- elsif($proto eq "smtp") {
- if($ipvnum == 6) {
- $SMTP6PORT = $port;
- }
- else {
- $SMTPPORT = $port;
- }
- }
- else {
- print STDERR "Unsupported protocol $proto!!\n";
- return (0,0);
- }
-
- return ($pid2, $ftppid);
-}
-
-#######################################################################
-# start the ftps server (or rather, tunnel)
-#
-sub runftpsserver {
- my ($verbose, $ipv6, $certfile) = @_;
- my $proto = 'ftps';
- my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
- my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
- my $idnum = 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $flags = "";
-
- if(!$stunnel) {
- return (0,0);
- }
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0, 0, 0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $certfile = 'stunnel.pem' unless($certfile);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- $flags .= "--verbose " if($debugprotocol);
- $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
- $flags .= "--id $idnum " if($idnum > 1);
- $flags .= "--ipv$ipvnum --proto $proto ";
- $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
- $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
- $flags .= "--connect $FTPPORT";
-
- my $ftpspid;
- my $pid2;
- my $port = 26713;
- for (1 .. 10) {
- $port += int(rand(700));
- my $options = "$flags --accept $port";
- my $cmd = "$perl $srcdir/secureserver.pl $options";
- ($ftpspid, $pid2) = startnew($cmd, $pidfile, 15, 0);
-
- if($ftpspid <= 0 || !pidexists($ftpspid)) {
- # it is NOT alive
- stopserver($server, "$pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- $ftpspid = $pid2 = 0;
- next;
- }
-
- $doesntrun{$pidfile} = 0;
- $runcert{$server} = $certfile;
-
- if($verbose) {
- logmsg "RUN: $srvrname server is PID $ftpspid port $port\n";
- }
- last;
- }
-
- logmsg "RUN: failed to start the $srvrname server\n" if(!$ftpspid);
-
- return ($ftpspid, $pid2, $port);
-}
-
-#######################################################################
-# start the tftp server
-#
-sub runtftpserver {
- my ($id, $verbose, $ipv6) = @_;
- my $ip = $HOSTIP;
- my $proto = 'tftp';
- my $ipvnum = 4;
- my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $flags = "";
-
- if($ipv6) {
- # if IPv6, use a different setup
- $ipvnum = 6;
- $ip = $HOST6IP;
- }
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
- my $portfile = $serverportfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0, 0, 0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- $flags .= "--verbose " if($debugprotocol);
- $flags .= "--pidfile \"$pidfile\" ".
- "--portfile \"$portfile\" ".
- "--logfile \"$logfile\" ";
- $flags .= "--id $idnum " if($idnum > 1);
- $flags .= "--ipv$ipvnum --port 0 --srcdir \"$srcdir\"";
-
- my $cmd = "$perl $srcdir/tftpserver.pl $flags";
- my ($tftppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
-
- if($tftppid <= 0 || !pidexists($tftppid)) {
- # it is NOT alive
- logmsg "RUN: failed to start the $srvrname server\n";
- stopserver($server, "$pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- return (0, 0, 0);
- }
-
- my $port = pidfromfile($portfile);
-
- # Server is up. Verify that we can speak to it.
- my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
- if(!$pid3) {
- logmsg "RUN: $srvrname server failed verification\n";
- # failed to talk to it properly. Kill the server and return failure
- stopserver($server, "$tftppid $pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- return (0, 0, 0);
- }
- $pid2 = $pid3;
-
- if($verbose) {
- logmsg "RUN: $srvrname server on PID $tftppid port $port\n";
- }
-
- return ($pid2, $tftppid, $port);
-}
-
-
-#######################################################################
-# start the rtsp server
-#
-sub runrtspserver {
- my ($verbose, $ipv6) = @_;
- my $ip = $HOSTIP;
- my $proto = 'rtsp';
- my $ipvnum = 4;
- my $idnum = 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $flags = "";
-
- if($ipv6) {
- # if IPv6, use a different setup
- $ipvnum = 6;
- $ip = $HOST6IP;
- }
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
- my $portfile = $serverportfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0, 0, 0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- $flags .= "--verbose " if($debugprotocol);
- $flags .= "--pidfile \"$pidfile\" ".
- "--portfile \"$portfile\" ".
- "--logfile \"$logfile\" ";
- $flags .= "--id $idnum " if($idnum > 1);
- $flags .= "--ipv$ipvnum --port 0 --srcdir \"$srcdir\"";
-
- my $cmd = "$perl $srcdir/rtspserver.pl $flags";
- my ($rtsppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
-
- if($rtsppid <= 0 || !pidexists($rtsppid)) {
- # it is NOT alive
- logmsg "RUN: failed to start the $srvrname server\n";
- stopserver($server, "$pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- return (0, 0, 0);
- }
-
- my $port = pidfromfile($portfile);
-
- # Server is up. Verify that we can speak to it.
- my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
- if(!$pid3) {
- logmsg "RUN: $srvrname server failed verification\n";
- # failed to talk to it properly. Kill the server and return failure
- stopserver($server, "$rtsppid $pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- return (0, 0, 0);
- }
- $pid2 = $pid3;
-
- if($verbose) {
- logmsg "RUN: $srvrname server PID $rtsppid port $port\n";
- }
-
- return ($rtsppid, $pid2, $port);
-}
-
-
-#######################################################################
-# Start the ssh (scp/sftp) server
-#
-sub runsshserver {
- my ($id, $verbose, $ipv6) = @_;
- my $ip=$HOSTIP;
- my $proto = 'ssh';
- my $ipvnum = 4;
- my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $port = 20000; # no lower port
-
- if(!$USER) {
- logmsg "Can't start ssh server due to lack of USER name";
- return (0,0,0);
- }
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0, 0, 0);
- }
-
- my $sshd = find_sshd();
- if($sshd) {
- ($sshdid,$sshdvernum,$sshdverstr,$sshderror) = sshversioninfo($sshd);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- my $flags = "";
- $flags .= "--verbose " if($verbose);
- $flags .= "--debugprotocol " if($debugprotocol);
- $flags .= "--pidfile \"$pidfile\" ";
- $flags .= "--id $idnum " if($idnum > 1);
- $flags .= "--ipv$ipvnum --addr \"$ip\" ";
- $flags .= "--user \"$USER\"";
-
- my $sshpid;
- my $pid2;
-
- my $wport = 0,
- my @tports;
- for(1 .. 10) {
-
- # sshd doesn't have a way to pick an unused random port number, so
- # instead we iterate over possible port numbers to use until we find
- # one that works
- $port += int(rand(500));
- push @tports, $port;
-
- my $options = "$flags --sshport $port";
-
- my $cmd = "$perl $srcdir/sshserver.pl $options";
- ($sshpid, $pid2) = startnew($cmd, $pidfile, 60, 0);
-
- # on loaded systems sshserver start up can take longer than the
- # timeout passed to startnew, when this happens startnew completes
- # without being able to read the pidfile and consequently returns a
- # zero pid2 above.
- if($sshpid <= 0 || !pidexists($sshpid)) {
- # it is NOT alive
- stopserver($server, "$pid2");
- $doesntrun{$pidfile} = 1;
- $sshpid = $pid2 = 0;
- next;
- }
-
- # once it is known that the ssh server is alive, sftp server
- # verification is performed actually connecting to it, authenticating
- # and performing a very simple remote command. This verification is
- # tried only one time.
-
- $sshdlog = server_logfilename($LOGDIR, 'ssh', $ipvnum, $idnum);
- $sftplog = server_logfilename($LOGDIR, 'sftp', $ipvnum, $idnum);
-
- if(verifysftp('sftp', $ipvnum, $idnum, $ip, $port) < 1) {
- logmsg "RUN: SFTP server failed verification\n";
- # failed to talk to it properly. Kill the server and return failure
- display_sftplog();
- display_sftpconfig();
- display_sshdlog();
- display_sshdconfig();
- stopserver($server, "$sshpid $pid2");
- $doesntrun{$pidfile} = 1;
- $sshpid = $pid2 = 0;
- next;
- }
- # we're happy, no need to loop anymore!
- $doesntrun{$pidfile} = 0;
- $wport = $port;
- last;
- }
- logmsg "RUN: failed to start the $srvrname server on $port\n" if(!$sshpid);
-
- if(!$wport) {
- logmsg "RUN: couldn't start $srvrname. Tried these ports:";
- logmsg "RUN: ".join(", ", @tports);
- return (0,0,0);
- }
-
- my $hstpubmd5f = "curl_host_rsa_key.pub_md5";
- if(!open(PUBMD5FILE, "<", $hstpubmd5f) ||
- (read(PUBMD5FILE, $SSHSRVMD5, 32) != 32) ||
- !close(PUBMD5FILE) ||
- ($SSHSRVMD5 !~ /^[a-f0-9]{32}$/i))
- {
- my $msg = "Fatal: $srvrname pubkey md5 missing : \"$hstpubmd5f\" : $!";
- logmsg "$msg\n";
- stopservers($verbose);
- die $msg;
- }
-
- my $hstpubsha256f = "curl_host_rsa_key.pub_sha256";
- if(!open(PUBSHA256FILE, "<", $hstpubsha256f) ||
- (read(PUBSHA256FILE, $SSHSRVSHA256, 48) == 0) ||
- !close(PUBSHA256FILE))
- {
- my $msg = "Fatal: $srvrname pubkey sha256 missing : \"$hstpubsha256f\" : $!";
- logmsg "$msg\n";
- stopservers($verbose);
- die $msg;
- }
-
- logmsg "RUN: $srvrname on PID $pid2 port $wport\n" if($verbose);
-
- return ($pid2, $sshpid, $wport);
-}
-
-#######################################################################
-# Start the MQTT server
-#
-sub runmqttserver {
- my ($id, $verbose, $ipv6) = @_;
- my $ip=$HOSTIP;
- my $port = $MQTTPORT;
- my $proto = 'mqtt';
- my $ipvnum = 4;
- my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $portfile;
- my $logfile;
- my $flags = "";
-
- $server = servername_id($proto, $ipvnum, $idnum);
- $pidfile = $serverpidfile{$server};
- $portfile = $serverportfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0,0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- # start our MQTT server - on a random port!
- my $cmd="server/mqttd".exe_ext('SRV').
- " --port 0 ".
- " --pidfile $pidfile".
- " --portfile $portfile".
- " --config $FTPDCMD";
- my ($sockspid, $pid2) = startnew($cmd, $pidfile, 30, 0);
-
- if($sockspid <= 0 || !pidexists($sockspid)) {
- # it is NOT alive
- logmsg "RUN: failed to start the $srvrname server\n";
- stopserver($server, "$pid2");
- $doesntrun{$pidfile} = 1;
- return (0,0);
- }
-
- $MQTTPORT = pidfromfile($portfile);
-
- if($verbose) {
- logmsg "RUN: $srvrname server is now running PID $pid2 on PORT $MQTTPORT\n";
- }
-
- return ($pid2, $sockspid);
-}
-
-#######################################################################
-# Start the socks server
-#
-sub runsocksserver {
- my ($id, $verbose, $ipv6, $is_unix) = @_;
- my $ip=$HOSTIP;
- my $proto = 'socks';
- my $ipvnum = 4;
- my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $flags = "";
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
- my $portfile = $serverportfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0, 0, 0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- # start our socks server, get commands from the FTP cmd file
- my $cmd="";
- if($is_unix) {
- $cmd="server/socksd".exe_ext('SRV').
- " --pidfile $pidfile".
- " --unix-socket $SOCKSUNIXPATH".
- " --backend $HOSTIP".
- " --config $FTPDCMD";
- } else {
- $cmd="server/socksd".exe_ext('SRV').
- " --port 0 ".
- " --pidfile $pidfile".
- " --portfile $portfile".
- " --backend $HOSTIP".
- " --config $FTPDCMD";
- }
- my ($sockspid, $pid2) = startnew($cmd, $pidfile, 30, 0);
-
- if($sockspid <= 0 || !pidexists($sockspid)) {
- # it is NOT alive
- logmsg "RUN: failed to start the $srvrname server\n";
- stopserver($server, "$pid2");
- $doesntrun{$pidfile} = 1;
- return (0, 0, 0);
- }
-
- my $port = pidfromfile($portfile);
-
- if($verbose) {
- logmsg "RUN: $srvrname server is now running PID $pid2\n";
- }
-
- return ($pid2, $sockspid, $port);
-}
-
-#######################################################################
-# start the dict server
-#
-sub rundictserver {
- my ($verbose, $alt) = @_;
- my $proto = "dict";
- my $ip = $HOSTIP;
- my $ipvnum = 4;
- my $idnum = 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $flags = "";
-
- if($alt eq "ipv6") {
- # No IPv6
- }
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0, 0, 0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- $flags .= "--verbose 1 " if($debugprotocol);
- $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
- $flags .= "--id $idnum " if($idnum > 1);
- $flags .= "--srcdir \"$srcdir\" ";
- $flags .= "--host $HOSTIP";
-
- my $port = 29000;
- my ($dictpid, $pid2);
- for(1 .. 10) {
- $port += int(rand(900));
- my $aflags = "--port $port $flags";
- my $cmd = "$srcdir/dictserver.py $aflags";
- ($dictpid, $pid2) = startnew($cmd, $pidfile, 15, 0);
-
- if($dictpid <= 0 || !pidexists($dictpid)) {
- # it is NOT alive
- stopserver($server, "$pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- $dictpid = $pid2 = 0;
- next;
- }
- $doesntrun{$pidfile} = 0;
-
- if($verbose) {
- logmsg "RUN: $srvrname server PID $dictpid port $port\n";
- }
- last;
- }
- logmsg "RUN: failed to start the $srvrname server\n" if(!$dictpid);
-
- return ($dictpid, $pid2, $port);
-}
-
-#######################################################################
-# start the SMB server
-#
-sub runsmbserver {
- my ($verbose, $alt) = @_;
- my $proto = "smb";
- my $ip = $HOSTIP;
- my $ipvnum = 4;
- my $idnum = 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $flags = "";
-
- if($alt eq "ipv6") {
- # No IPv6
- }
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0, 0, 0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- $flags .= "--verbose 1 " if($debugprotocol);
- $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
- $flags .= "--id $idnum " if($idnum > 1);
- $flags .= "--srcdir \"$srcdir\" ";
- $flags .= "--host $HOSTIP";
-
- my ($smbpid, $pid2);
- my $port = 31923;
- for(1 .. 10) {
- $port += int(rand(760));
- my $aflags = "--port $port $flags";
- my $cmd = "$srcdir/smbserver.py $aflags";
- ($smbpid, $pid2) = startnew($cmd, $pidfile, 15, 0);
-
- if($smbpid <= 0 || !pidexists($smbpid)) {
- # it is NOT alive
- stopserver($server, "$pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- $smbpid = $pid2 = 0;
- next;
- }
- $doesntrun{$pidfile} = 0;
-
- if($verbose) {
- logmsg "RUN: $srvrname server PID $smbpid port $port\n";
- }
- last;
- }
- logmsg "RUN: failed to start the $srvrname server\n" if(!$smbpid);
-
- return ($smbpid, $pid2, $port);
-}
-
-#######################################################################
-# start the telnet server
-#
-sub runnegtelnetserver {
- my ($verbose, $alt) = @_;
- my $proto = "telnet";
- my $ip = $HOSTIP;
- my $ipvnum = 4;
- my $idnum = 1;
- my $server;
- my $srvrname;
- my $pidfile;
- my $logfile;
- my $flags = "";
-
- if($alt eq "ipv6") {
- # No IPv6
- }
-
- $server = servername_id($proto, $ipvnum, $idnum);
-
- $pidfile = $serverpidfile{$server};
-
- # don't retry if the server doesn't work
- if ($doesntrun{$pidfile}) {
- return (0, 0, 0);
- }
-
- my $pid = processexists($pidfile);
- if($pid > 0) {
- stopserver($server, "$pid");
- }
- unlink($pidfile) if(-f $pidfile);
-
- $srvrname = servername_str($proto, $ipvnum, $idnum);
-
- $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
-
- $flags .= "--verbose 1 " if($debugprotocol);
- $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
- $flags .= "--id $idnum " if($idnum > 1);
- $flags .= "--srcdir \"$srcdir\"";
-
- my ($ntelpid, $pid2);
- my $port = 32000;
- for(1 .. 10) {
- $port += int(rand(800));
- my $aflags = "--port $port $flags";
- my $cmd = "$srcdir/negtelnetserver.py $aflags";
- ($ntelpid, $pid2) = startnew($cmd, $pidfile, 15, 0);
-
- if($ntelpid <= 0 || !pidexists($ntelpid)) {
- # it is NOT alive
- stopserver($server, "$pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- $ntelpid = $pid2 = 0;
- next;
- }
- $doesntrun{$pidfile} = 0;
-
- if($verbose) {
- logmsg "RUN: $srvrname server PID $ntelpid port $port\n";
- }
- last;
- }
- logmsg "RUN: failed to start the $srvrname server\n" if(!$ntelpid);
-
- return ($ntelpid, $pid2, $port);
-}
-
-
-#######################################################################
-# Single shot http and gopher server responsiveness test. This should only
-# be used to verify that a server present in %run hash is still functional
-#
-sub responsive_http_server {
- my ($proto, $verbose, $alt, $port_or_path) = @_;
- my $ip = $HOSTIP;
- my $ipvnum = 4;
- my $idnum = 1;
-
- if($alt eq "ipv6") {
- # if IPv6, use a different setup
- $ipvnum = 6;
- $ip = $HOST6IP;
- }
- elsif($alt eq "proxy") {
- $idnum = 2;
- }
- elsif($alt eq "unix") {
- # IP (protocol) is mutually exclusive with Unix sockets
- $ipvnum = "unix";
- }
-
- return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
-}
-
-#######################################################################
-# Single shot pingpong server responsiveness test. This should only be
-# used to verify that a server present in %run hash is still functional
-#
-sub responsive_pingpong_server {
- my ($proto, $id, $verbose, $ipv6) = @_;
- my $port;
- my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
- my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
- my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
-
- if($proto eq "ftp") {
- $port = $FTPPORT;
-
- if($ipvnum==6) {
- # if IPv6, use a different setup
- $port = $FTP6PORT;
- }
- }
- elsif($proto eq "pop3") {
- $port = ($ipvnum==6) ? $POP36PORT : $POP3PORT;
- }
- elsif($proto eq "imap") {
- $port = ($ipvnum==6) ? $IMAP6PORT : $IMAPPORT;
- }
- elsif($proto eq "smtp") {
- $port = ($ipvnum==6) ? $SMTP6PORT : $SMTPPORT;
- }
- else {
- print STDERR "Unsupported protocol $proto!!\n";
- return 0;
- }
-
- return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
-}
-
-#######################################################################
-# Single shot rtsp server responsiveness test. This should only be
-# used to verify that a server present in %run hash is still functional
-#
-sub responsive_rtsp_server {
- my ($verbose, $ipv6) = @_;
- my $port = $RTSPPORT;
- my $ip = $HOSTIP;
- my $proto = 'rtsp';
- my $ipvnum = 4;
- my $idnum = 1;
-
- if($ipv6) {
- # if IPv6, use a different setup
- $ipvnum = 6;
- $port = $RTSP6PORT;
- $ip = $HOST6IP;
- }
-
- return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
-}
-
-#######################################################################
-# Single shot tftp server responsiveness test. This should only be
-# used to verify that a server present in %run hash is still functional
-#
-sub responsive_tftp_server {
- my ($id, $verbose, $ipv6) = @_;
- my $port = $TFTPPORT;
- my $ip = $HOSTIP;
- my $proto = 'tftp';
- my $ipvnum = 4;
- my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
-
- if($ipv6) {
- # if IPv6, use a different setup
- $ipvnum = 6;
- $port = $TFTP6PORT;
- $ip = $HOST6IP;
- }
-
- return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
-}
-
-#######################################################################
-# Single shot non-stunnel HTTP TLS extensions capable server
-# responsiveness test. This should only be used to verify that a
-# server present in %run hash is still functional
-#
-sub responsive_httptls_server {
- my ($verbose, $ipv6) = @_;
- my $proto = "httptls";
- my $port = ($ipv6 && ($ipv6 =~ /6$/)) ? $HTTPTLS6PORT : $HTTPTLSPORT;
- my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
- my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
- my $idnum = 1;
-
- return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
-}
-
-#######################################################################
-# Kill the processes that still lock files in a directory
-#
-sub clearlocks {
- my $dir = $_[0];
- my $done = 0;
-
- if(pathhelp::os_is_win()) {
- $dir = pathhelp::sys_native_abs_path($dir);
- $dir =~ s/\//\\\\/g;
- my $handle = "handle.exe";
- if($ENV{"PROCESSOR_ARCHITECTURE"} =~ /64$/) {
- $handle = "handle64.exe";
- }
- my @handles = `$handle $dir -accepteula -nobanner`;
- for $handle (@handles) {
- if($handle =~ /^(\S+)\s+pid:\s+(\d+)\s+type:\s+(\w+)\s+([0-9A-F]+):\s+(.+)\r\r/) {
- logmsg "Found $3 lock of '$5' ($4) by $1 ($2)\n";
- # Ignore stunnel since we cannot do anything about its locks
- if("$3" eq "File" && "$1" ne "tstunnel.exe") {
- logmsg "Killing IMAGENAME eq $1 and PID eq $2\n";
- system("taskkill.exe -f -fi \"IMAGENAME eq $1\" -fi \"PID eq $2\" >nul 2>&1");
- $done = 1;
- }
- }
- }
- }
- return $done;
-}
#######################################################################
# Remove all files in the specified directory
#
sub cleardir {
my $dir = $_[0];
- my $done = 1;
+ my $done = 1; # success
my $file;
# Get all files
opendir(my $dh, $dir) ||
return 0; # can't open dir
while($file = readdir($dh)) {
- if(($file !~ /^(\.|\.\.)\z/)) {
+ # Don't clear the $PIDDIR or $LOCKDIR since those need to live beyond
+ # one test
+ if(($file !~ /^(\.|\.\.)\z/) &&
+ "$file" ne $PIDDIR && "$file" ne $LOCKDIR) {
if(-d "$dir/$file") {
if(!cleardir("$dir/$file")) {
$done = 0;
@@ -2856,12 +375,53 @@
return $done;
}
+
+#######################################################################
+# Given two array references, this function will store them in two temporary
+# files, run 'diff' on them, store the result and return the diff output!
+sub showdiff {
+ my ($logdir, $firstref, $secondref)=@_;
+
+ my $file1="$logdir/check-generated";
+ my $file2="$logdir/check-expected";
+
+ open(my $temp, ">", "$file1") || die "Failure writing diff file";
+ for(@$firstref) {
+ my $l = $_;
+ $l =~ s/\r/[CR]/g;
+ $l =~ s/\n/[LF]/g;
+ $l =~ s/([^\x20-\x7f])/sprintf "%%%02x", ord $1/eg;
+ print $temp $l;
+ print $temp "\n";
+ }
+ close($temp) || die "Failure writing diff file";
+
+ open($temp, ">", "$file2") || die "Failure writing diff file";
+ for(@$secondref) {
+ my $l = $_;
+ $l =~ s/\r/[CR]/g;
+ $l =~ s/\n/[LF]/g;
+ $l =~ s/([^\x20-\x7f])/sprintf "%%%02x", ord $1/eg;
+ print $temp $l;
+ print $temp "\n";
+ }
+ close($temp) || die "Failure writing diff file";
+ my @out = `diff -u $file2 $file1 2>/dev/null`;
+
+ if(!$out[0]) {
+ @out = `diff -c $file2 $file1 2>/dev/null`;
+ }
+
+ return @out;
+}
+
+
#######################################################################
# compare test results with the expected output, we might filter off
# some pattern that is allowed to differ, output test results
#
sub compare {
- my ($testnum, $testname, $subject, $firstref, $secondref)=@_;
+ my ($runnerid, $testnum, $testname, $subject, $firstref, $secondref)=@_;
my $result = compareparts($firstref, $secondref);
@@ -2871,7 +431,8 @@
if(!$short) {
logmsg "\n $testnum: $subject FAILED:\n";
- logmsg showdiff($LOGDIR, $firstref, $secondref);
+ my $logdir = getrunnerlogdir($runnerid);
+ logmsg showdiff($logdir, $firstref, $secondref);
}
elsif(!$automakestyle) {
logmsg "FAILED\n";
@@ -2884,88 +445,32 @@
return $result;
}
-sub setupfeatures {
- $feature{"alt-svc"} = $has_altsvc;
- $feature{"bearssl"} = $has_bearssl;
- $feature{"brotli"} = $has_brotli;
- $feature{"c-ares"} = $has_cares;
- $feature{"crypto"} = $has_crypto;
- $feature{"debug"} = $debug_build;
- $feature{"getrlimit"} = $has_getrlimit;
- $feature{"GnuTLS"} = $has_gnutls;
- $feature{"GSS-API"} = $has_gssapi;
- $feature{"h2c"} = $has_h2c;
- $feature{"HSTS"} = $has_hsts;
- $feature{"http/2"} = $has_http2;
- $feature{"https-proxy"} = $has_httpsproxy;
- $feature{"hyper"} = $has_hyper;
- $feature{"idn"} = $has_idn;
- $feature{"ipv6"} = $has_ipv6;
- $feature{"Kerberos"} = $has_kerberos;
- $feature{"large_file"} = $has_largefile;
- $feature{"ld_preload"} = ($has_ldpreload && !$debug_build);
- $feature{"libssh"} = $has_libssh;
- $feature{"libssh2"} = $has_libssh2;
- $feature{"libz"} = $has_libz;
- $feature{"manual"} = $has_manual;
- $feature{"MinGW"} = $has_mingw;
- $feature{"MultiSSL"} = $has_multissl;
- $feature{"NSS"} = $has_nss;
- $feature{"NTLM"} = $has_ntlm;
- $feature{"NTLM_WB"} = $has_ntlm_wb;
- $feature{"oldlibssh"} = $has_oldlibssh;
- $feature{"OpenSSL"} = $has_openssl || $has_libressl || $has_boringssl;
- $feature{"PSL"} = $has_psl;
- $feature{"rustls"} = $has_rustls;
- $feature{"Schannel"} = $has_schannel;
- $feature{"sectransp"} = $has_sectransp;
- $feature{"SPNEGO"} = $has_spnego;
- $feature{"SSL"} = $has_ssl;
- $feature{"SSLpinning"} = $has_sslpinning;
- $feature{"SSPI"} = $has_sspi;
- $feature{"threaded-resolver"} = $has_threadedres;
- $feature{"threadsafe"} = $has_threadsafe;
- $feature{"TLS-SRP"} = $has_tls_srp;
- $feature{"TrackMemory"} = $has_memory_tracking;
- $feature{"Unicode"} = $has_unicode;
- $feature{"unittest"} = $debug_build;
- $feature{"unix-sockets"} = $has_unix;
- $feature{"win32"} = $has_win32;
- $feature{"wolfssh"} = $has_wolfssh;
- $feature{"wolfssl"} = $has_wolfssl;
- $feature{"zstd"} = $has_zstd;
+#######################################################################
+# Parse and store the protocols in curl's Protocols: line
+sub parseprotocols {
+ my ($line)=@_;
- # make each protocol an enabled "feature"
- for my $p (@protocols) {
- $feature{$p} = 1;
- }
- # 'socks' was once here but is now removed
+ @protocols = split(' ', lc($line));
- #
- # strings that must match the names used in server/disabled.c
- #
- $feature{"cookies"} = 1;
- $feature{"DoH"} = 1;
- $feature{"HTTP-auth"} = 1;
- $feature{"Mime"} = 1;
- $feature{"netrc"} = 1;
- $feature{"parsedate"} = 1;
- $feature{"proxy"} = 1;
- $feature{"shuffle-dns"} = 1;
- $feature{"typecheck"} = 1;
- $feature{"verbose-strings"} = 1;
- $feature{"wakeup"} = 1;
- $feature{"headers-api"} = 1;
+ # Generate a "proto-ipv6" version of each protocol to match the
+ # IPv6 <server> name and a "proto-unix" to match the variant which
+ # uses Unix domain sockets. This works even if support isn't
+ # compiled in because the <features> test will fail.
+ push @protocols, map(("$_-ipv6", "$_-unix"), @protocols);
+ # 'http-proxy' is used in test cases to do CONNECT through
+ push @protocols, 'http-proxy';
+
+ # 'none' is used in test cases to mean no server
+ push @protocols, 'none';
}
+
#######################################################################
-# display information about curl and the host the test suite runs on
-#
-sub checksystem {
-
- unlink($memdump); # remove this if there was one left
-
+# Check & display information about curl and the host the test suite runs on.
+# Information to do with servers is displayed in displayserverfeatures, after
+# the server initialization is performed.
+sub checksystemfeatures {
my $feat;
my $curl;
my $libcurl;
@@ -2977,7 +482,7 @@
my $curlverout="$LOGDIR/curlverout.log";
my $curlvererr="$LOGDIR/curlvererr.log";
- my $versioncmd="$CURL --version 1>$curlverout 2>$curlvererr";
+ my $versioncmd=shell_quote($CURL) . " --version 1>$curlverout 2>$curlvererr";
unlink($curlverout);
unlink($curlvererr);
@@ -2985,16 +490,16 @@
$versretval = runclient($versioncmd);
$versnoexec = $!;
- open(VERSOUT, "<$curlverout");
- @version = <VERSOUT>;
- close(VERSOUT);
+ open(my $versout, "<", "$curlverout");
+ @version = <$versout>;
+ close($versout);
- open(DISABLED, "server/disabled".exe_ext('TOOL')."|");
- @disabled = <DISABLED>;
- close(DISABLED);
+ open(my $disabledh, "-|", "server/disabled".exe_ext('TOOL'));
+ @disabled = <$disabledh>;
+ close($disabledh);
if($disabled[0]) {
- map s/[\r\n]//g, @disabled;
+ s/[\r\n]//g for @disabled;
$dis = join(", ", @disabled);
}
@@ -3004,225 +509,173 @@
if($_ =~ /^curl ([^ ]*)/) {
$curl = $_;
- $VERSION = $1;
- $curl =~ s/^(.*)(libcurl.*)/$1/g;
+ $CURLVERSION = $1;
+ $curl =~ s/^(.*)(libcurl.*)/$1/g || die "Failure determining curl binary version";
$libcurl = $2;
if($curl =~ /linux|bsd|solaris/) {
- $has_ldpreload = 1;
+ # system support LD_PRELOAD; may be disabled later
+ $feature{"ld_preload"} = 1;
}
if($curl =~ /win32|Windows|mingw(32|64)/) {
# This is a Windows MinGW build or native build, we need to use
# Win32-style path.
- $pwd = pathhelp::sys_native_current_path();
+ $pwd = sys_native_current_path();
$has_textaware = 1;
- $has_win32 = 1;
- $has_mingw = 1 if ($curl =~ /-pc-mingw32/);
+ $feature{"win32"} = 1;
+ # set if built with MinGW (as opposed to MinGW-w64)
+ $feature{"MinGW"} = 1 if ($curl =~ /-pc-mingw32/);
}
- if ($libcurl =~ /(winssl|schannel)/i) {
- $has_schannel=1;
- $has_sslpinning=1;
+ if ($libcurl =~ /\s(winssl|schannel)\b/i) {
+ $feature{"Schannel"} = 1;
+ $feature{"SSLpinning"} = 1;
}
- elsif ($libcurl =~ /openssl/i) {
- $has_openssl=1;
- $has_sslpinning=1;
+ elsif ($libcurl =~ /\sopenssl\b/i) {
+ $feature{"OpenSSL"} = 1;
+ $feature{"SSLpinning"} = 1;
}
- elsif ($libcurl =~ /gnutls/i) {
- $has_gnutls=1;
- $has_sslpinning=1;
+ elsif ($libcurl =~ /\sgnutls\b/i) {
+ $feature{"GnuTLS"} = 1;
+ $feature{"SSLpinning"} = 1;
}
- elsif ($libcurl =~ /rustls-ffi/i) {
- $has_rustls=1;
+ elsif ($libcurl =~ /\srustls-ffi\b/i) {
+ $feature{"rustls"} = 1;
}
- elsif ($libcurl =~ /nss/i) {
- $has_nss=1;
- $has_sslpinning=1;
+ elsif ($libcurl =~ /\snss\b/i) {
+ $feature{"NSS"} = 1;
+ $feature{"SSLpinning"} = 1;
}
- elsif ($libcurl =~ /wolfssl/i) {
- $has_wolfssl=1;
- $has_sslpinning=1;
+ elsif ($libcurl =~ /\swolfssl\b/i) {
+ $feature{"wolfssl"} = 1;
+ $feature{"SSLpinning"} = 1;
}
- elsif ($libcurl =~ /bearssl/i) {
- $has_bearssl=1;
+ elsif ($libcurl =~ /\sbearssl\b/i) {
+ $feature{"bearssl"} = 1;
}
- elsif ($libcurl =~ /securetransport/i) {
- $has_sectransp=1;
- $has_sslpinning=1;
+ elsif ($libcurl =~ /\ssecuretransport\b/i) {
+ $feature{"sectransp"} = 1;
+ $feature{"SSLpinning"} = 1;
}
- elsif ($libcurl =~ /BoringSSL/i) {
- $has_boringssl=1;
- $has_sslpinning=1;
+ elsif ($libcurl =~ /\sBoringSSL\b/i) {
+ # OpenSSL compatible API
+ $feature{"OpenSSL"} = 1;
+ $feature{"SSLpinning"} = 1;
}
- elsif ($libcurl =~ /libressl/i) {
- $has_libressl=1;
- $has_sslpinning=1;
+ elsif ($libcurl =~ /\slibressl\b/i) {
+ # OpenSSL compatible API
+ $feature{"OpenSSL"} = 1;
+ $feature{"SSLpinning"} = 1;
}
- elsif ($libcurl =~ /mbedTLS/i) {
- $has_mbedtls=1;
- $has_sslpinning=1;
+ elsif ($libcurl =~ /\smbedTLS\b/i) {
+ $feature{"mbedtls"} = 1;
+ $feature{"SSLpinning"} = 1;
}
if ($libcurl =~ /ares/i) {
- $has_cares=1;
+ $feature{"c-ares"} = 1;
$resolver="c-ares";
}
if ($libcurl =~ /Hyper/i) {
- $has_hyper=1;
+ $feature{"hyper"} = 1;
}
if ($libcurl =~ /nghttp2/i) {
# nghttp2 supports h2c, hyper does not
- $has_h2c=1;
+ $feature{"h2c"} = 1;
}
if ($libcurl =~ /libssh2/i) {
- $has_libssh2=1;
+ $feature{"libssh2"} = 1;
}
if ($libcurl =~ /libssh\/([0-9.]*)\//i) {
- $has_libssh=1;
+ $feature{"libssh"} = 1;
if($1 =~ /(\d+)\.(\d+).(\d+)/) {
my $v = $1 * 100 + $2 * 10 + $3;
if($v < 94) {
# before 0.9.4
- $has_oldlibssh = 1;
+ $feature{"oldlibssh"} = 1;
}
}
}
if ($libcurl =~ /wolfssh/i) {
- $has_wolfssh=1;
+ $feature{"wolfssh"} = 1;
}
}
elsif($_ =~ /^Protocols: (.*)/i) {
# these are the protocols compiled in to this libcurl
- @protocols = split(' ', lc($1));
-
- # Generate a "proto-ipv6" version of each protocol to match the
- # IPv6 <server> name and a "proto-unix" to match the variant which
- # uses Unix domain sockets. This works even if support isn't
- # compiled in because the <features> test will fail.
- push @protocols, map(("$_-ipv6", "$_-unix"), @protocols);
-
- # 'http-proxy' is used in test cases to do CONNECT through
- push @protocols, 'http-proxy';
-
- # 'none' is used in test cases to mean no server
- push @protocols, 'none';
+ parseprotocols($1);
}
elsif($_ =~ /^Features: (.*)/i) {
$feat = $1;
- if($feat =~ /TrackMemory/i) {
- # built with memory tracking support (--enable-curldebug)
- $has_memory_tracking = 1;
- }
- if($feat =~ /debug/i) {
- # curl was built with --enable-debug
- $debug_build = 1;
- }
- if($feat =~ /SSL/i) {
- # ssl enabled
- $has_ssl=1;
- }
- if($feat =~ /MultiSSL/i) {
- # multiple ssl backends available.
- $has_multissl=1;
- }
- if($feat =~ /Largefile/i) {
- # large file support
- $has_largefile=1;
- }
- if($feat =~ /IDN/i) {
- # IDN support
- $has_idn=1;
- }
- if($feat =~ /IPv6/i) {
- $has_ipv6 = 1;
- }
- if($feat =~ /UnixSockets/i) {
- $has_unix = 1;
- }
- if($feat =~ /libz/i) {
- $has_libz = 1;
- }
- if($feat =~ /brotli/i) {
- $has_brotli = 1;
- }
- if($feat =~ /zstd/i) {
- $has_zstd = 1;
- }
- if($feat =~ /NTLM/i) {
- # NTLM enabled
- $has_ntlm=1;
- # Use this as a proxy for any cryptographic authentication
- $has_crypto=1;
- }
- if($feat =~ /NTLM_WB/i) {
- # NTLM delegation to winbind daemon ntlm_auth helper enabled
- $has_ntlm_wb=1;
- }
- if($feat =~ /SSPI/i) {
- # SSPI enabled
- $has_sspi=1;
- }
- if($feat =~ /GSS-API/i) {
- # GSS-API enabled
- $has_gssapi=1;
- }
- if($feat =~ /Kerberos/i) {
- # Kerberos enabled
- $has_kerberos=1;
-
- # Use this as a proxy for any cryptographic authentication
- $has_crypto=1;
- }
- if($feat =~ /SPNEGO/i) {
- # SPNEGO enabled
- $has_spnego=1;
-
- # Use this as a proxy for any cryptographic authentication
- $has_crypto=1;
- }
- if($feat =~ /CharConv/i) {
- # CharConv enabled
- $has_charconv=1;
- }
- if($feat =~ /TLS-SRP/i) {
- # TLS-SRP enabled
- $has_tls_srp=1;
- }
- if($feat =~ /PSL/i) {
- # PSL enabled
- $has_psl=1;
- }
- if($feat =~ /alt-svc/i) {
- # alt-svc enabled
- $has_altsvc=1;
- }
- if($feat =~ /HSTS/i) {
- $has_hsts=1;
- }
+ # built with memory tracking support (--enable-curldebug); may be disabled later
+ $feature{"TrackMemory"} = $feat =~ /TrackMemory/i;
+ # curl was built with --enable-debug
+ $feature{"debug"} = $feat =~ /debug/i;
+ # ssl enabled
+ $feature{"SSL"} = $feat =~ /SSL/i;
+ # multiple ssl backends available.
+ $feature{"MultiSSL"} = $feat =~ /MultiSSL/i;
+ # large file support
+ $feature{"large_file"} = $feat =~ /Largefile/i;
+ # IDN support
+ $feature{"idn"} = $feat =~ /IDN/i;
+ # IPv6 support
+ $feature{"ipv6"} = $feat =~ /IPv6/i;
+ # Unix sockets support
+ $feature{"unix-sockets"} = $feat =~ /UnixSockets/i;
+ # libz compression
+ $feature{"libz"} = $feat =~ /libz/i;
+ # Brotli compression
+ $feature{"brotli"} = $feat =~ /brotli/i;
+ # Zstd compression
+ $feature{"zstd"} = $feat =~ /zstd/i;
+ # NTLM enabled
+ $feature{"NTLM"} = $feat =~ /NTLM/i;
+ # NTLM delegation to winbind daemon ntlm_auth helper enabled
+ $feature{"NTLM_WB"} = $feat =~ /NTLM_WB/i;
+ # SSPI enabled
+ $feature{"SSPI"} = $feat =~ /SSPI/i;
+ # GSS-API enabled
+ $feature{"GSS-API"} = $feat =~ /GSS-API/i;
+ # Kerberos enabled
+ $feature{"Kerberos"} = $feat =~ /Kerberos/i;
+ # SPNEGO enabled
+ $feature{"SPNEGO"} = $feat =~ /SPNEGO/i;
+ # CharConv enabled
+ $feature{"CharConv"} = $feat =~ /CharConv/i;
+ # TLS-SRP enabled
+ $feature{"TLS-SRP"} = $feat =~ /TLS-SRP/i;
+ # PSL enabled
+ $feature{"PSL"} = $feat =~ /PSL/i;
+ # alt-svc enabled
+ $feature{"alt-svc"} = $feat =~ /alt-svc/i;
+ # HSTS support
+ $feature{"HSTS"} = $feat =~ /HSTS/i;
if($feat =~ /AsynchDNS/i) {
- if(!$has_cares) {
+ if(!$feature{"c-ares"}) {
# this means threaded resolver
- $has_threadedres=1;
+ $feature{"threaded-resolver"} = 1;
$resolver="threaded";
}
}
- if($feat =~ /HTTP2/) {
- # http2 enabled
- $has_http2=1;
-
+ # http2 enabled
+ $feature{"http/2"} = $feat =~ /HTTP2/;
+ if($feature{"http/2"}) {
push @protocols, 'http/2';
}
- if($feat =~ /HTTPS-proxy/) {
- $has_httpsproxy=1;
-
+ # http3 enabled
+ $feature{"http/3"} = $feat =~ /HTTP3/;
+ if($feature{"http/3"}) {
+ push @protocols, 'http/3';
+ }
+ # https proxy support
+ $feature{"https-proxy"} = $feat =~ /HTTPS-proxy/;
+ if($feature{"https-proxy"}) {
# 'https-proxy' is used as "server" so consider it a protocol
push @protocols, 'https-proxy';
}
- if($feat =~ /Unicode/i) {
- $has_unicode = 1;
- }
- if($feat =~ /threadsafe/i) {
- $has_threadsafe = 1;
- }
+ # UNICODE support
+ $feature{"Unicode"} = $feat =~ /Unicode/i;
+ # Thread-safe init
+ $feature{"threadsafe"} = $feat =~ /threadsafe/i;
}
#
# Test harness currently uses a non-stunnel server in order to
@@ -3232,7 +685,7 @@
# to differentiate this from classic stunnel based 'https' test
# harness server.
#
- if($has_tls_srp) {
+ if($feature{"TLS-SRP"}) {
my $add_httptls;
for(@protocols) {
if($_ =~ /^https(-ipv6|)$/) {
@@ -3246,6 +699,7 @@
}
}
}
+
if(!$curl) {
logmsg "unable to get curl's version, further details are:\n";
logmsg "issued command: \n";
@@ -3269,16 +723,20 @@
}
if(-r "../lib/curl_config.h") {
- open(CONF, "<../lib/curl_config.h");
- while(<CONF>) {
+ open(my $conf, "<", "../lib/curl_config.h");
+ while(<$conf>) {
if($_ =~ /^\#define HAVE_GETRLIMIT/) {
- $has_getrlimit = 1;
+ # set if system has getrlimit()
+ $feature{"getrlimit"} = 1;
}
}
- close(CONF);
+ close($conf);
}
- if($has_ipv6) {
+ # allow this feature only if debug mode is disabled
+ $feature{"ld_preload"} = $feature{"ld_preload"} && !$feature{"debug"};
+
+ if($feature{"ipv6"}) {
# client has IPv6 support
# check if the HTTP server has it!
@@ -3287,7 +745,6 @@
if($sws[0] =~ /IPv6/) {
# HTTP server has IPv6 support!
$http_ipv6 = 1;
- $gopher_ipv6 = 1;
}
# check if the FTP server has it!
@@ -3299,36 +756,67 @@
}
}
- if($has_unix) {
+ if($feature{"unix-sockets"}) {
# client has Unix sockets support, check whether the HTTP server has it
my $cmd = "server/sws".exe_ext('SRV')." --version";
my @sws = `$cmd`;
$http_unix = 1 if($sws[0] =~ /unix/);
}
- if(!$has_memory_tracking && $torture) {
- die "can't run torture tests since curl was built without ".
- "TrackMemory feature (--enable-curldebug)";
- }
-
- open(M, "$CURL -M 2>&1|");
- while(my $s = <M>) {
+ open(my $manh, "-|", shell_quote($CURL) . " -M 2>&1");
+ while(my $s = <$manh>) {
if($s =~ /built-in manual was disabled at build-time/) {
- $has_manual = 0;
+ $feature{"manual"} = 0;
last;
}
- $has_manual = 1;
+ $feature{"manual"} = 1;
last;
}
- close(M);
+ close($manh);
+
+ $feature{"unittest"} = $feature{"debug"};
+ $feature{"nghttpx"} = !!$ENV{'NGHTTPX'};
+ $feature{"nghttpx-h3"} = !!$nghttpx_h3;
+
+ #
+ # strings that must exactly match the names used in server/disabled.c
+ #
+ $feature{"cookies"} = 1;
+ # Use this as a proxy for any cryptographic authentication
+ $feature{"crypto"} = $feature{"NTLM"} || $feature{"Kerberos"} || $feature{"SPNEGO"};
+ $feature{"DoH"} = 1;
+ $feature{"HTTP-auth"} = 1;
+ $feature{"Mime"} = 1;
+ $feature{"netrc"} = 1;
+ $feature{"parsedate"} = 1;
+ $feature{"proxy"} = 1;
+ $feature{"shuffle-dns"} = 1;
+ $feature{"typecheck"} = 1;
+ $feature{"verbose-strings"} = 1;
+ $feature{"wakeup"} = 1;
+ $feature{"headers-api"} = 1;
+ $feature{"xattr"} = 1;
+
+ # make each protocol an enabled "feature"
+ for my $p (@protocols) {
+ $feature{$p} = 1;
+ }
+ # 'socks' was once here but is now removed
$has_shared = `sh $CURLCONFIG --built-shared`;
chomp $has_shared;
+ $has_shared = $has_shared eq "yes";
+
+ if(!$feature{"TrackMemory"} && $torture) {
+ die "can't run torture tests since curl was built without ".
+ "TrackMemory feature (--enable-curldebug)";
+ }
my $hostname=join(' ', runclientoutput("hostname"));
my $hosttype=join(' ', runclientoutput("uname -a"));
my $hostos=$^O;
+ # display summary information about curl and the test host
logmsg ("********* System characteristics ******** \n",
"* $curl\n",
"* $libcurl\n",
@@ -3338,36 +826,25 @@
"* System: $hosttype",
"* OS: $hostos\n");
- if($has_memory_tracking && $has_threadedres) {
- $has_memory_tracking = 0;
+ if($jobs) {
+ # Only show if not the default for now
+ logmsg "* Jobs: $jobs\n";
+ }
+ if($feature{"TrackMemory"} && $feature{"threaded-resolver"}) {
logmsg("*\n",
"*** DISABLES memory tracking when using threaded resolver\n",
"*\n");
}
- logmsg sprintf("* Servers: %s", $stunnel?"SSL ":"");
- logmsg sprintf("%s", $http_ipv6?"HTTP-IPv6 ":"");
- logmsg sprintf("%s", $http_unix?"HTTP-unix ":"");
- logmsg sprintf("%s\n", $ftp_ipv6?"FTP-IPv6 ":"");
-
- logmsg sprintf("* Env: %s%s", $valgrind?"Valgrind ":"",
- $run_event_based?"event-based ":"");
+ logmsg sprintf("* Env: %s%s%s", $valgrind?"Valgrind ":"",
+ $run_event_based?"event-based ":"",
+ $nghttpx_h3);
logmsg sprintf("%s\n", $libtool?"Libtool ":"");
logmsg ("* Seed: $randseed\n");
- if($verbose) {
- if($has_unix) {
- logmsg "* Unix socket paths:\n";
- if($http_unix) {
- logmsg sprintf("* HTTP-Unix:%s\n", $HTTPUNIXPATH);
- logmsg sprintf("* Socks-Unix:%s\n", $SOCKSUNIXPATH);
- }
- }
- }
+ # Disable memory tracking when using threaded resolver
+ $feature{"TrackMemory"} = $feature{"TrackMemory"} && !$feature{"threaded-resolver"};
- logmsg "***************************************** \n";
-
- setupfeatures();
# toggle off the features that were disabled in the build
for my $d(@disabled) {
$feature{$d} = 0;
@@ -3375,155 +852,14 @@
}
#######################################################################
-# substitute the variable stuff into either a joined up file or
-# a command, in either case passed by reference
+# display information about server features
#
-sub subVariables {
- my ($thing, $testnum, $prefix) = @_;
-
- if(!$prefix) {
- $prefix = "%";
- }
-
- # test server ports
- $$thing =~ s/${prefix}FTP6PORT/$FTP6PORT/g;
- $$thing =~ s/${prefix}FTPSPORT/$FTPSPORT/g;
- $$thing =~ s/${prefix}FTPPORT/$FTPPORT/g;
- $$thing =~ s/${prefix}GOPHER6PORT/$GOPHER6PORT/g;
- $$thing =~ s/${prefix}GOPHERPORT/$GOPHERPORT/g;
- $$thing =~ s/${prefix}GOPHERSPORT/$GOPHERSPORT/g;
- $$thing =~ s/${prefix}HTTPTLS6PORT/$HTTPTLS6PORT/g;
- $$thing =~ s/${prefix}HTTPTLSPORT/$HTTPTLSPORT/g;
- $$thing =~ s/${prefix}HTTP6PORT/$HTTP6PORT/g;
- $$thing =~ s/${prefix}HTTPSPORT/$HTTPSPORT/g;
- $$thing =~ s/${prefix}HTTPSPROXYPORT/$HTTPSPROXYPORT/g;
- $$thing =~ s/${prefix}HTTP2PORT/$HTTP2PORT/g;
- $$thing =~ s/${prefix}HTTPPORT/$HTTPPORT/g;
- $$thing =~ s/${prefix}PROXYPORT/$HTTPPROXYPORT/g;
- $$thing =~ s/${prefix}MQTTPORT/$MQTTPORT/g;
- $$thing =~ s/${prefix}IMAP6PORT/$IMAP6PORT/g;
- $$thing =~ s/${prefix}IMAPPORT/$IMAPPORT/g;
- $$thing =~ s/${prefix}POP36PORT/$POP36PORT/g;
- $$thing =~ s/${prefix}POP3PORT/$POP3PORT/g;
- $$thing =~ s/${prefix}RTSP6PORT/$RTSP6PORT/g;
- $$thing =~ s/${prefix}RTSPPORT/$RTSPPORT/g;
- $$thing =~ s/${prefix}SMTP6PORT/$SMTP6PORT/g;
- $$thing =~ s/${prefix}SMTPPORT/$SMTPPORT/g;
- $$thing =~ s/${prefix}SOCKSPORT/$SOCKSPORT/g;
- $$thing =~ s/${prefix}SSHPORT/$SSHPORT/g;
- $$thing =~ s/${prefix}TFTP6PORT/$TFTP6PORT/g;
- $$thing =~ s/${prefix}TFTPPORT/$TFTPPORT/g;
- $$thing =~ s/${prefix}DICTPORT/$DICTPORT/g;
- $$thing =~ s/${prefix}SMBPORT/$SMBPORT/g;
- $$thing =~ s/${prefix}SMBSPORT/$SMBSPORT/g;
- $$thing =~ s/${prefix}TELNETPORT/$TELNETPORT/g;
- $$thing =~ s/${prefix}NOLISTENPORT/$NOLISTENPORT/g;
-
- # server Unix domain socket paths
- $$thing =~ s/${prefix}HTTPUNIXPATH/$HTTPUNIXPATH/g;
- $$thing =~ s/${prefix}SOCKSUNIXPATH/$SOCKSUNIXPATH/g;
-
- # client IP addresses
- $$thing =~ s/${prefix}CLIENT6IP/$CLIENT6IP/g;
- $$thing =~ s/${prefix}CLIENTIP/$CLIENTIP/g;
-
- # server IP addresses
- $$thing =~ s/${prefix}HOST6IP/$HOST6IP/g;
- $$thing =~ s/${prefix}HOSTIP/$HOSTIP/g;
-
- # misc
- $$thing =~ s/${prefix}CURL/$CURL/g;
- $$thing =~ s/${prefix}PWD/$pwd/g;
- $$thing =~ s/${prefix}POSIX_PWD/$posix_pwd/g;
- $$thing =~ s/${prefix}VERSION/$VERSION/g;
- $$thing =~ s/${prefix}TESTNUMBER/$testnum/g;
-
- my $file_pwd = $pwd;
- if($file_pwd !~ /^\//) {
- $file_pwd = "/$file_pwd";
- }
- my $ssh_pwd = $posix_pwd;
- if ($sshdid && $sshdid =~ /OpenSSH-Windows/) {
- $ssh_pwd = $file_pwd;
- }
-
- $$thing =~ s/${prefix}FILE_PWD/$file_pwd/g;
- $$thing =~ s/${prefix}SSH_PWD/$ssh_pwd/g;
- $$thing =~ s/${prefix}SRCDIR/$srcdir/g;
- $$thing =~ s/${prefix}USER/$USER/g;
-
- $$thing =~ s/${prefix}SSHSRVMD5/$SSHSRVMD5/g;
- $$thing =~ s/${prefix}SSHSRVSHA256/$SSHSRVSHA256/g;
-
- # The purpose of FTPTIME2 and FTPTIME3 is to provide times that can be
- # used for time-out tests and that would work on most hosts as these
- # adjust for the startup/check time for this particular host. We needed to
- # do this to make the test suite run better on very slow hosts.
- my $ftp2 = $ftpchecktime * 2;
- my $ftp3 = $ftpchecktime * 3;
-
- $$thing =~ s/${prefix}FTPTIME2/$ftp2/g;
- $$thing =~ s/${prefix}FTPTIME3/$ftp3/g;
-
- # HTTP2
- $$thing =~ s/${prefix}H2CVER/$h2cver/g;
-}
-
-sub subBase64 {
- my ($thing) = @_;
-
- # cut out the base64 piece
- if($$thing =~ s/%b64\[(.*)\]b64%/%%B64%%/i) {
- my $d = $1;
- # encode %NN characters
- $d =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
- my $enc = encode_base64($d, "");
- # put the result into there
- $$thing =~ s/%%B64%%/$enc/;
- }
- # hex decode
- if($$thing =~ s/%hex\[(.*)\]hex%/%%HEX%%/i) {
- # decode %NN characters
- my $d = $1;
- $d =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
- $$thing =~ s/%%HEX%%/$d/;
- }
- if($$thing =~ s/%repeat\[(\d+) x (.*)\]%/%%REPEAT%%/i) {
- # decode %NN characters
- my ($d, $n) = ($2, $1);
- $d =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
- my $all = $d x $n;
- $$thing =~ s/%%REPEAT%%/$all/;
- }
-}
-
-my $prevupdate;
-sub subNewlines {
- my ($thing) = @_;
-
- # When curl is built with Hyper, it gets all response headers delivered as
- # name/value pairs and curl "invents" the newlines when it saves the
- # headers. Therefore, curl will always save headers with CRLF newlines
- # when built to use Hyper. By making sure we deliver all tests using CRLF
- # as well, all test comparisons will survive without knowing about this
- # little quirk.
-
- if(($$thing =~ /^HTTP\/(1.1|1.0|2) [1-5][^\x0d]*\z/) ||
- (($$thing =~ /^[a-z0-9_-]+: [^\x0d]*\z/i) &&
- # skip curl error messages
- ($$thing !~ /^curl: \(\d+\) /))) {
- # enforce CRLF newline
- $$thing =~ s/\x0a/\x0d\x0a/;
- $prevupdate = 1;
- }
- else {
- if(($$thing =~ /^\n\z/) && $prevupdate) {
- # if there's a blank link after a line we update, we hope it is
- # the empty line following headers
- $$thing =~ s/\x0a/\x0d\x0a/;
- }
- $prevupdate = 0;
- }
+sub displayserverfeatures {
+ logmsg sprintf("* Servers: %s", $stunnel?"SSL ":"");
+ logmsg sprintf("%s", $http_ipv6?"HTTP-IPv6 ":"");
+ logmsg sprintf("%s", $http_unix?"HTTP-unix ":"");
+ logmsg sprintf("%s\n", $ftp_ipv6?"FTP-IPv6 ":"");
+ logmsg "***************************************** \n";
}
#######################################################################
@@ -3576,82 +912,119 @@
}
}
-#
-# 'prepro' processes the input array and replaces %-variables in the array
-# etc. Returns the processed version of the array
-sub prepro {
- my $testnum = shift;
- my (@entiretest) = @_;
- my $show = 1;
- my @out;
- for my $s (@entiretest) {
- my $f = $s;
- if($s =~ /^ *%if (.*)/) {
- my $cond = $1;
- my $rev = 0;
-
- if($cond =~ /^!(.*)/) {
- $cond = $1;
- $rev = 1;
- }
- $rev ^= $feature{$cond} ? 1 : 0;
- $show = $rev;
- next;
- }
- elsif($s =~ /^ *%else/) {
- $show ^= 1;
- next;
- }
- elsif($s =~ /^ *%endif/) {
- $show = 1;
- next;
- }
- if($show) {
- subVariables(\$s, $testnum, "%");
- subBase64(\$s);
- subNewlines(\$s) if($has_hyper && ($keywords{"HTTP"} ||
- $keywords{"HTTPS"}));
- push @out, $s;
- }
+# Setup CI Test Run
+sub citest_starttestrun {
+ if(azure_check_environment()) {
+ $AZURE_RUN_ID = azure_create_test_run($ACURL);
+ logmsg "Azure Run ID: $AZURE_RUN_ID\n" if ($verbose);
}
- return @out;
+ # Appveyor doesn't require anything here
+}
+
+
+# Register the test case with the CI runner
+sub citest_starttest {
+ my $testnum = $_[0];
+
+ # get the name of the test early
+ my $testname= (getpart("client", "name"))[0];
+ chomp $testname;
+
+ # create test result in CI services
+ if(azure_check_environment() && $AZURE_RUN_ID) {
+ $AZURE_RESULT_ID = azure_create_test_result($ACURL, $AZURE_RUN_ID, $testnum, $testname);
+ }
+ elsif(appveyor_check_environment()) {
+ appveyor_create_test_result($ACURL, $testnum, $testname);
+ }
+}
+
+
+# Submit the test case result with the CI runner
+sub citest_finishtest {
+ my ($testnum, $error) = @_;
+ # update test result in CI services
+ if(azure_check_environment() && $AZURE_RUN_ID && $AZURE_RESULT_ID) {
+ $AZURE_RESULT_ID = azure_update_test_result($ACURL, $AZURE_RUN_ID, $AZURE_RESULT_ID, $testnum, $error,
+ $timeprepini{$testnum}, $timevrfyend{$testnum});
+ }
+ elsif(appveyor_check_environment()) {
+ appveyor_update_test_result($ACURL, $testnum, $error, $timeprepini{$testnum}, $timevrfyend{$testnum});
+ }
+}
+
+# Complete CI test run
+sub citest_finishtestrun {
+ if(azure_check_environment() && $AZURE_RUN_ID) {
+ $AZURE_RUN_ID = azure_update_test_run($ACURL, $AZURE_RUN_ID);
+ }
+ # Appveyor doesn't require anything here
+}
+
+
+# add one set of test timings from the runner to global set
+sub updatetesttimings {
+ my ($testnum, %testtimings)=@_;
+
+ if(defined $testtimings{"timeprepini"}) {
+ $timeprepini{$testnum} = $testtimings{"timeprepini"};
+ }
+ if(defined $testtimings{"timesrvrini"}) {
+ $timesrvrini{$testnum} = $testtimings{"timesrvrini"};
+ }
+ if(defined $testtimings{"timesrvrend"}) {
+ $timesrvrend{$testnum} = $testtimings{"timesrvrend"};
+ }
+ if(defined $testtimings{"timetoolini"}) {
+ $timetoolini{$testnum} = $testtimings{"timetoolini"};
+ }
+ if(defined $testtimings{"timetoolend"}) {
+ $timetoolend{$testnum} = $testtimings{"timetoolend"};
+ }
+ if(defined $testtimings{"timesrvrlog"}) {
+ $timesrvrlog{$testnum} = $testtimings{"timesrvrlog"};
+ }
+}
+
+
+#######################################################################
+# Return the log directory for the given test runner
+sub getrunnernumlogdir {
+ my $runnernum = $_[0];
+ return $jobs > 1 ? "$LOGDIR/$runnernum" : $LOGDIR;
}
#######################################################################
-# Run a single specified test case
-#
-sub singletest {
- my ($evbased, # 1 means switch on if possible (and "curl" is tested)
- # returns "not a test" if it can't be used for this test
- $testnum,
- $count,
- $total)=@_;
-
- my @what;
- my $why;
- my $cmd;
- my $disablevalgrind;
- my $errorreturncode = 1; # 1 means normal error, 2 means ignored error
-
- # fist, remove all lingering log files
- if(!cleardir($LOGDIR) && $clearlocks) {
- clearlocks($LOGDIR);
- cleardir($LOGDIR);
+# Return the log directory for the given test runner ID
+sub getrunnerlogdir {
+ my $runnerid = $_[0];
+ if($jobs <= 1) {
+ return $LOGDIR;
}
+ # TODO: speed up this O(n) operation
+ for my $runnernum (keys %runnerids) {
+ if($runnerid eq $runnerids{$runnernum}) {
+ return "$LOGDIR/$runnernum";
+ }
+ }
+ die "Internal error: runner ID $runnerid not found";
+}
- # copy test number to a global scope var, this allows
- # testnum checking when starting test harness servers.
- $testnumcheck = $testnum;
- # timestamp test preparation start
- $timeprepini{$testnum} = Time::HiRes::time();
+#######################################################################
+# Verify that this test case should be run
+sub singletest_shouldrun {
+ my $testnum = $_[0];
+ my $why; # why the test won't be run
+ my $errorreturncode = 1; # 1 means normal error, 2 means ignored error
+ my @what; # what features are needed
if($disttests !~ /test$testnum(\W|\z)/ ) {
logmsg "Warning: test$testnum not present in tests/data/Makefile.inc\n";
}
if($disabled{$testnum}) {
- if(!$run_disabeled) {
+ if(!$run_disabled) {
$why = "listed in DISABLED";
}
else {
@@ -3663,7 +1036,6 @@
$errorreturncode = 2;
}
- # load the test case file definition
if(loadtest("${TESTDIR}/test${testnum}")) {
if($verbose) {
# this is not a test
@@ -3710,31 +1082,27 @@
}
}
+ my @info_keywords;
if(!$why) {
- my @info_keywords = getpart("info", "keywords");
- my $match;
- my $k;
-
- # Clear the list of keywords from the last test
- %keywords = ();
+ @info_keywords = getpart("info", "keywords");
if(!$info_keywords[0]) {
$why = "missing the <keywords> section!";
}
- for $k (@info_keywords) {
+ my $match;
+ for my $k (@info_keywords) {
chomp $k;
if ($disabled_keywords{lc($k)}) {
$why = "disabled by keyword";
- } elsif ($enabled_keywords{lc($k)}) {
+ }
+ elsif ($enabled_keywords{lc($k)}) {
$match = 1;
}
if ($ignored_keywords{lc($k)}) {
logmsg "Warning: test$testnum result is ignored due to $k\n";
$errorreturncode = 2;
}
-
- $keywords{$k} = 1;
}
if(!$why && !$match && %enabled_keywords) {
@@ -3757,7 +1125,7 @@
}
if (!$why && defined $custom_skip_reasons{keyword}) {
- foreach my $keyword (getpart("info", "keywords")) {
+ foreach my $keyword (@info_keywords) {
foreach my $keyword_skip_pattern (keys %{$custom_skip_reasons{keyword}}) {
if ($keyword =~ /$keyword_skip_pattern/i) {
$why = $custom_skip_reasons{keyword}{$keyword_skip_pattern};
@@ -3766,133 +1134,17 @@
}
}
+ return ($why, $errorreturncode);
+}
- # test definition may instruct to (un)set environment vars
- # this is done this early, so that the precheck can use environment
- # variables and still bail out fine on errors
- # restore environment variables that were modified in a previous run
- foreach my $var (keys %oldenv) {
- if($oldenv{$var} eq 'notset') {
- delete $ENV{$var} if($ENV{$var});
- }
- else {
- $ENV{$var} = $oldenv{$var};
- }
- delete $oldenv{$var};
- }
-
- # get the name of the test early
- my @testname= getpart("client", "name");
- my $testname = $testname[0];
- $testname =~ s/\n//g;
-
- # create test result in CI services
- if(azure_check_environment() && $AZURE_RUN_ID) {
- $AZURE_RESULT_ID = azure_create_test_result($VCURL, $AZURE_RUN_ID, $testnum, $testname);
- }
- elsif(appveyor_check_environment()) {
- appveyor_create_test_result($VCURL, $testnum, $testname);
- }
-
- # remove test server commands file before servers are started/verified
- unlink($FTPDCMD) if(-f $FTPDCMD);
-
- # timestamp required servers verification start
- $timesrvrini{$testnum} = Time::HiRes::time();
-
- if(!$why) {
- $why = serverfortest($testnum);
- }
-
- # Save a preprocessed version of the entire test file. This allows more
- # "basic" test case readers to enjoy variable replacements.
- my @entiretest = fulltest();
- my $otest = "log/test$testnum";
-
- @entiretest = prepro($testnum, @entiretest);
-
- # save the new version
- open(D, ">$otest");
- foreach my $bytes (@entiretest) {
- print D pack('a*', $bytes) or die "Failed to print '$bytes': $!";
- }
- close(D);
-
- # in case the process changed the file, reload it
- loadtest("log/test${testnum}");
-
- # timestamp required servers verification end
- $timesrvrend{$testnum} = Time::HiRes::time();
-
- my @setenv = getpart("client", "setenv");
- if(@setenv) {
- foreach my $s (@setenv) {
- chomp $s;
- if($s =~ /([^=]*)=(.*)/) {
- my ($var, $content) = ($1, $2);
- # remember current setting, to restore it once test runs
- $oldenv{$var} = ($ENV{$var})?"$ENV{$var}":'notset';
- # set new value
- if(!$content) {
- delete $ENV{$var} if($ENV{$var});
- }
- else {
- if($var =~ /^LD_PRELOAD/) {
- if(exe_ext('TOOL') && (exe_ext('TOOL') eq '.exe')) {
- # print "Skipping LD_PRELOAD due to lack of OS support\n";
- next;
- }
- if($debug_build || ($has_shared ne "yes")) {
- # print "Skipping LD_PRELOAD due to no release shared build\n";
- next;
- }
- }
- $ENV{$var} = "$content";
- print "setenv $var = $content\n" if($verbose);
- }
- }
- }
- }
- if($use_external_proxy) {
- $ENV{http_proxy} = $proxy_address;
- $ENV{HTTPS_PROXY} = $proxy_address;
- }
-
- if(!$why) {
- my @precheck = getpart("client", "precheck");
- if(@precheck) {
- $cmd = $precheck[0];
- chomp $cmd;
- if($cmd) {
- my @p = split(/ /, $cmd);
- if($p[0] !~ /\//) {
- # the first word, the command, does not contain a slash so
- # we will scan the "improved" PATH to find the command to
- # be able to run it
- my $fullp = checktestcmd($p[0]);
-
- if($fullp) {
- $p[0] = $fullp;
- }
- $cmd = join(" ", @p);
- }
-
- my @o = `$cmd 2>log/precheck-$testnum`;
- if($o[0]) {
- $why = $o[0];
- chomp $why;
- } elsif($?) {
- $why = "precheck command error";
- }
- logmsg "prechecked $cmd\n" if($verbose);
- }
- }
- }
+#######################################################################
+# Print the test name and count tests
+sub singletest_count {
+ my ($testnum, $why) = @_;
if($why && !$listonly) {
# there's a problem, count it as "skipped"
- $skipped++;
$skipped{$why}++;
$teststat[$testnum]=$why; # store reason for this test case
@@ -3906,472 +1158,49 @@
timestampskippedevents($testnum);
return -1;
}
+
+ # At this point we've committed to run this test
logmsg sprintf("test %04d...", $testnum) if(!$automakestyle);
- my %replyattr = getpartattr("reply", "data");
- my @reply;
- if (partexists("reply", "datacheck")) {
- for my $partsuffix (('', '1', '2', '3', '4')) {
- my @replycheckpart = getpart("reply", "datacheck".$partsuffix);
- if(@replycheckpart) {
- my %replycheckpartattr = getpartattr("reply", "datacheck".$partsuffix);
- # get the mode attribute
- my $filemode=$replycheckpartattr{'mode'};
- if($filemode && ($filemode eq "text") && $has_textaware) {
- # text mode when running on windows: fix line endings
- map s/\r\n/\n/g, @replycheckpart;
- map s/\n/\r\n/g, @replycheckpart;
- }
- if($replycheckpartattr{'nonewline'}) {
- # Yes, we must cut off the final newline from the final line
- # of the datacheck
- chomp($replycheckpart[$#replycheckpart]);
- }
- push(@reply, @replycheckpart);
- }
- }
- }
- else {
- # check against the data section
- @reply = getpart("reply", "data");
- if(@reply) {
- my %hash = getpartattr("reply", "data");
- if($hash{'nonewline'}) {
- # cut off the final newline from the final line of the data
- chomp($reply[$#reply]);
- }
- }
- # get the mode attribute
- my $filemode=$replyattr{'mode'};
- if($filemode && ($filemode eq "text") && $has_textaware) {
- # text mode when running on windows: fix line endings
- map s/\r\n/\n/g, @reply;
- map s/\n/\r\n/g, @reply;
- }
- }
-
- # this is the valid protocol blurb curl should generate
- my @protocol= getpart("verify", "protocol");
-
- # this is the valid protocol blurb curl should generate to a proxy
- my @proxyprot = getpart("verify", "proxy");
-
- # redirected stdout/stderr to these files
- $STDOUT="$LOGDIR/stdout$testnum";
- $STDERR="$LOGDIR/stderr$testnum";
-
- # if this section exists, we verify that the stdout contained this:
- my @validstdout = getpart("verify", "stdout");
- my @validstderr = getpart("verify", "stderr");
-
- # if this section exists, we verify upload
- my @upload = getpart("verify", "upload");
- if(@upload) {
- my %hash = getpartattr("verify", "upload");
- if($hash{'nonewline'}) {
- # cut off the final newline from the final line of the upload data
- chomp($upload[$#upload]);
- }
- }
-
- # if this section exists, it might be FTP server instructions:
- my @ftpservercmd = getpart("reply", "servercmd");
-
- my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout
-
# name of the test
+ my $testname= (getpart("client", "name"))[0];
+ chomp $testname;
logmsg "[$testname]\n" if(!$short);
if($listonly) {
timestampskippedevents($testnum);
- return 0; # look successful
}
+ return 0;
+}
- my @codepieces = getpart("client", "tool");
- my $tool="";
- if(@codepieces) {
- $tool = $codepieces[0];
- chomp $tool;
- $tool .= exe_ext('TOOL');
- }
-
- # remove server output logfile
- unlink($SERVERIN);
- unlink($SERVER2IN);
- unlink($PROXYIN);
-
- push @ftpservercmd, "Testnum $testnum\n";
- # write the instructions to file
- writearray($FTPDCMD, \@ftpservercmd);
-
- # get the command line options to use
- my @blaha;
- ($cmd, @blaha)= getpart("client", "command");
-
- if($cmd) {
- # make some nice replace operations
- $cmd =~ s/\n//g; # no newlines please
- # substitute variables in the command line
- }
- else {
- # there was no command given, use something silly
- $cmd="-";
- }
- if($has_memory_tracking) {
- unlink($memdump);
- }
-
- # create (possibly-empty) files before starting the test
- for my $partsuffix (('', '1', '2', '3', '4')) {
- my @inputfile=getpart("client", "file".$partsuffix);
- my %fileattr = getpartattr("client", "file".$partsuffix);
- my $filename=$fileattr{'name'};
- if(@inputfile || $filename) {
- if(!$filename) {
- logmsg "ERROR: section client=>file has no name attribute\n";
- timestampskippedevents($testnum);
- return -1;
- }
- my $fileContent = join('', @inputfile);
-
- # make directories if needed
- my $path = $filename;
- # cut off the file name part
- $path =~ s/^(.*)\/[^\/]*/$1/;
- my @parts = split(/\//, $path);
- if($parts[0] eq "log") {
- # the file is in log/
- my $d = shift @parts;
- for(@parts) {
- $d .= "/$_";
- mkdir $d; # 0777
- }
- }
- open(OUTFILE, ">$filename");
- binmode OUTFILE; # for crapage systems, use binary
- if($fileattr{'nonewline'}) {
- # cut off the final newline
- chomp($fileContent);
- }
- print OUTFILE $fileContent;
- close(OUTFILE);
- }
- }
-
- my %cmdhash = getpartattr("client", "command");
-
- my $out="";
-
- if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-output/)) {
- #We may slap on --output!
- if (!@validstdout ||
- ($cmdhash{'option'} && $cmdhash{'option'} =~ /force-output/)) {
- $out=" --output $CURLOUT ";
- }
- }
-
- my $serverlogslocktimeout = $defserverlogslocktimeout;
- if($cmdhash{'timeout'}) {
- # test is allowed to override default server logs lock timeout
- if($cmdhash{'timeout'} =~ /(\d+)/) {
- $serverlogslocktimeout = $1 if($1 >= 0);
- }
- }
-
- my $postcommanddelay = $defpostcommanddelay;
- if($cmdhash{'delay'}) {
- # test is allowed to specify a delay after command is executed
- if($cmdhash{'delay'} =~ /(\d+)/) {
- $postcommanddelay = $1 if($1 > 0);
- }
- }
-
- my $CMDLINE;
- my $cmdargs;
- my $cmdtype = $cmdhash{'type'} || "default";
- my $fail_due_event_based = $evbased;
- if($cmdtype eq "perl") {
- # run the command line prepended with "perl"
- $cmdargs ="$cmd";
- $CMDLINE = "$perl ";
- $tool=$CMDLINE;
- $disablevalgrind=1;
- }
- elsif($cmdtype eq "shell") {
- # run the command line prepended with "/bin/sh"
- $cmdargs ="$cmd";
- $CMDLINE = "/bin/sh ";
- $tool=$CMDLINE;
- $disablevalgrind=1;
- }
- elsif(!$tool && !$keywords{"unittest"}) {
- # run curl, add suitable command line options
- my $inc="";
- if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-include/)) {
- $inc = " --include";
- }
- $cmdargs = "$out$inc ";
-
- if($cmdhash{'option'} && ($cmdhash{'option'} =~ /binary-trace/)) {
- $cmdargs .= "--trace log/trace$testnum ";
- }
- else {
- $cmdargs .= "--trace-ascii log/trace$testnum ";
- }
- $cmdargs .= "--trace-time ";
- if($evbased) {
- $cmdargs .= "--test-event ";
- $fail_due_event_based--;
- }
- $cmdargs .= $cmd;
- if ($use_external_proxy) {
- $cmdargs .= " --proxy $proxy_address ";
- }
- }
- else {
- $cmdargs = " $cmd"; # $cmd is the command line for the test file
- $CURLOUT = $STDOUT; # sends received data to stdout
-
- # Default the tool to a unit test with the same name as the test spec
- if($keywords{"unittest"} && !$tool) {
- $tool="unit$testnum";
- }
-
- if($tool =~ /^lib/) {
- $CMDLINE="$LIBDIR/$tool";
- }
- elsif($tool =~ /^unit/) {
- $CMDLINE="$UNITDIR/$tool";
- }
-
- if(! -f $CMDLINE) {
- logmsg "The tool set in the test case for this: '$tool' does not exist\n";
- timestampskippedevents($testnum);
- return -1;
- }
- $DBGCURL=$CMDLINE;
- }
-
- if($fail_due_event_based) {
- logmsg "This test cannot run event based\n";
- timestampskippedevents($testnum);
- return -1;
- }
-
- if($gdbthis) {
- # gdb is incompatible with valgrind, so disable it when debugging
- # Perhaps a better approach would be to run it under valgrind anyway
- # with --db-attach=yes or --vgdb=yes.
- $disablevalgrind=1;
- }
-
- my @stdintest = getpart("client", "stdin");
-
- if(@stdintest) {
- my $stdinfile="$LOGDIR/stdin-for-$testnum";
-
- my %hash = getpartattr("client", "stdin");
- if($hash{'nonewline'}) {
- # cut off the final newline from the final line of the stdin data
- chomp($stdintest[$#stdintest]);
- }
-
- writearray($stdinfile, \@stdintest);
-
- $cmdargs .= " <$stdinfile";
- }
-
- if(!$tool) {
- $CMDLINE="$CURL";
- }
-
- my $usevalgrind;
- if($valgrind && !$disablevalgrind) {
- my @valgrindoption = getpart("verify", "valgrind");
- if((!@valgrindoption) || ($valgrindoption[0] !~ /disable/)) {
- $usevalgrind = 1;
- my $valgrindcmd = "$valgrind ";
- $valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
- $valgrindcmd .= "--quiet --leak-check=yes ";
- $valgrindcmd .= "--suppressions=$srcdir/valgrind.supp ";
- # $valgrindcmd .= "--gen-suppressions=all ";
- $valgrindcmd .= "--num-callers=16 ";
- $valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
- $CMDLINE = "$valgrindcmd $CMDLINE";
- }
- }
-
- $CMDLINE .= "$cmdargs >$STDOUT 2>$STDERR";
-
- if($verbose) {
- logmsg "$CMDLINE\n";
- }
-
- open(CMDLOG, ">", "$LOGDIR/$CURLLOG");
- print CMDLOG "$CMDLINE\n";
- close(CMDLOG);
-
- unlink("core");
-
- my $dumped_core;
- my $cmdres;
-
- if($gdbthis) {
- my $gdbinit = "$TESTDIR/gdbinit$testnum";
- open(GDBCMD, ">$LOGDIR/gdbcmd");
- print GDBCMD "set args $cmdargs\n";
- print GDBCMD "show args\n";
- print GDBCMD "source $gdbinit\n" if -e $gdbinit;
- close(GDBCMD);
- }
-
- # Flush output.
- $| = 1;
-
- # timestamp starting of test command
- $timetoolini{$testnum} = Time::HiRes::time();
-
- # run the command line we built
- if ($torture) {
- $cmdres = torture($CMDLINE,
- $testnum,
- "$gdb --directory $LIBDIR $DBGCURL -x $LOGDIR/gdbcmd");
- }
- elsif($gdbthis) {
- my $GDBW = ($gdbxwin) ? "-w" : "";
- runclient("$gdb --directory $LIBDIR $DBGCURL $GDBW -x $LOGDIR/gdbcmd");
- $cmdres=0; # makes it always continue after a debugged run
- }
- else {
- $cmdres = runclient("$CMDLINE");
- my $signal_num = $cmdres & 127;
- $dumped_core = $cmdres & 128;
-
- if(!$anyway && ($signal_num || $dumped_core)) {
- $cmdres = 1000;
- }
- else {
- $cmdres >>= 8;
- $cmdres = (2000 + $signal_num) if($signal_num && !$cmdres);
- }
- }
-
- # timestamp finishing of test command
- $timetoolend{$testnum} = Time::HiRes::time();
-
- if(!$dumped_core) {
- if(-r "core") {
- # there's core file present now!
- $dumped_core = 1;
- }
- }
-
- if($dumped_core) {
- logmsg "core dumped\n";
- if(0 && $gdb) {
- logmsg "running gdb for post-mortem analysis:\n";
- open(GDBCMD, ">$LOGDIR/gdbcmd2");
- print GDBCMD "bt\n";
- close(GDBCMD);
- runclient("$gdb --directory libtest -x $LOGDIR/gdbcmd2 -batch $DBGCURL core ");
- # unlink("$LOGDIR/gdbcmd2");
- }
- }
-
- # If a server logs advisor read lock file exists, it is an indication
- # that the server has not yet finished writing out all its log files,
- # including server request log files used for protocol verification.
- # So, if the lock file exists the script waits here a certain amount
- # of time until the server removes it, or the given time expires.
-
- if($serverlogslocktimeout) {
- my $lockretry = $serverlogslocktimeout * 20;
- while((-f $SERVERLOGS_LOCK) && $lockretry--) {
- portable_sleep(0.05);
- }
- if(($lockretry < 0) &&
- ($serverlogslocktimeout >= $defserverlogslocktimeout)) {
- logmsg "Warning: server logs lock timeout ",
- "($serverlogslocktimeout seconds) expired\n";
- }
- }
-
- # Test harness ssh server does not have this synchronization mechanism,
- # this implies that some ssh server based tests might need a small delay
- # once that the client command has run to avoid false test failures.
- #
- # gnutls-serv also lacks this synchronization mechanism, so gnutls-serv
- # based tests might need a small delay once that the client command has
- # run to avoid false test failures.
-
- portable_sleep($postcommanddelay) if($postcommanddelay);
-
- # timestamp removal of server logs advisor read lock
- $timesrvrlog{$testnum} = Time::HiRes::time();
-
- # test definition might instruct to stop some servers
- # stop also all servers relative to the given one
-
- my @killtestservers = getpart("client", "killserver");
- if(@killtestservers) {
- foreach my $server (@killtestservers) {
- chomp $server;
- if(stopserver($server)) {
- return 1; # normal error if asked to fail on unexpected alive
- }
- }
- }
-
- # run the postcheck command
- my @postcheck= getpart("client", "postcheck");
- if(@postcheck) {
- $cmd = join("", @postcheck);
- chomp $cmd;
- if($cmd) {
- logmsg "postcheck $cmd\n" if($verbose);
- my $rc = runclient("$cmd");
- # Must run the postcheck command in torture mode in order
- # to clean up, but the result can't be relied upon.
- if($rc != 0 && !$torture) {
- logmsg " postcheck FAILED\n";
- # timestamp test result verification end
- $timevrfyend{$testnum} = Time::HiRes::time();
- return $errorreturncode;
- }
- }
- }
-
- # restore environment variables that were modified
- if(%oldenv) {
- foreach my $var (keys %oldenv) {
- if($oldenv{$var} eq 'notset') {
- delete $ENV{$var} if($ENV{$var});
- }
- else {
- $ENV{$var} = "$oldenv{$var}";
- }
- }
- }
+#######################################################################
+# Verify test succeeded
+sub singletest_check {
+ my ($runnerid, $testnum, $cmdres, $CURLOUT, $tool, $usedvalgrind)=@_;
# Skip all the verification on torture tests
if ($torture) {
# timestamp test result verification end
$timevrfyend{$testnum} = Time::HiRes::time();
- return $cmdres;
+ return -2;
}
+ my $logdir = getrunnerlogdir($runnerid);
my @err = getpart("verify", "errorcode");
my $errorcode = $err[0] || "0";
my $ok="";
my $res;
chomp $errorcode;
+ my $testname= (getpart("client", "name"))[0];
+ chomp $testname;
+ # what parts to cut off from stdout/stderr
+ my @stripfile = getpart("verify", "stripfile");
+
+ my @validstdout = getpart("verify", "stdout");
if (@validstdout) {
# verify redirected stdout
- my @actual = loadarray($STDOUT);
-
- # what parts to cut off from stdout
- my @stripfile = getpart("verify", "stripfile");
+ my @actual = loadarray(stdoutfilename($logdir, $testnum));
foreach my $strip (@stripfile) {
chomp $strip;
@@ -4394,19 +1223,25 @@
my $filemode=$hash{'mode'};
if($filemode && ($filemode eq "text") && $has_textaware) {
# text mode when running on windows: fix line endings
- map s/\r\n/\n/g, @validstdout;
- map s/\n/\r\n/g, @validstdout;
+ s/\r\n/\n/g for @validstdout;
+ s/\n/\r\n/g for @validstdout;
}
if($hash{'nonewline'}) {
# Yes, we must cut off the final newline from the final line
# of the protocol data
- chomp($validstdout[$#validstdout]);
+ chomp($validstdout[-1]);
}
- $res = compare($testnum, $testname, "stdout", \@actual, \@validstdout);
+ if($hash{'crlf'} ||
+ ($feature{"hyper"} && ($keywords{"HTTP"}
+ || $keywords{"HTTPS"}))) {
+ subnewlines(0, \$_) for @validstdout;
+ }
+
+ $res = compare($runnerid, $testnum, $testname, "stdout", \@actual, \@validstdout);
if($res) {
- return $errorreturncode;
+ return -1;
}
$ok .= "s";
}
@@ -4414,12 +1249,10 @@
$ok .= "-"; # stdout not checked
}
+ my @validstderr = getpart("verify", "stderr");
if (@validstderr) {
# verify redirected stderr
- my @actual = loadarray($STDERR);
-
- # what parts to cut off from stderr
- my @stripfile = getpart("verify", "stripfile");
+ my @actual = loadarray(stderrfilename($logdir, $testnum));
foreach my $strip (@stripfile) {
chomp $strip;
@@ -4440,27 +1273,27 @@
# get the mode attribute
my $filemode=$hash{'mode'};
- if($filemode && ($filemode eq "text") && $has_hyper) {
+ if($filemode && ($filemode eq "text") && $feature{"hyper"}) {
# text mode check in hyper-mode. Sometimes necessary if the stderr
# data *looks* like HTTP and thus has gotten CRLF newlines
# mistakenly
- map s/\r\n/\n/g, @validstderr;
+ s/\r\n/\n/g for @validstderr;
}
if($filemode && ($filemode eq "text") && $has_textaware) {
# text mode when running on windows: fix line endings
- map s/\r\n/\n/g, @validstderr;
- map s/\n/\r\n/g, @validstderr;
+ s/\r\n/\n/g for @validstderr;
+ s/\n/\r\n/g for @validstderr;
}
if($hash{'nonewline'}) {
# Yes, we must cut off the final newline from the final line
# of the protocol data
- chomp($validstderr[$#validstderr]);
+ chomp($validstderr[-1]);
}
- $res = compare($testnum, $testname, "stderr", \@actual, \@validstderr);
+ $res = compare($runnerid, $testnum, $testname, "stderr", \@actual, \@validstderr);
if($res) {
- return $errorreturncode;
+ return -1;
}
$ok .= "r";
}
@@ -4468,14 +1301,17 @@
$ok .= "-"; # stderr not checked
}
+ # what to cut off from the live protocol sent by curl
+ my @strip = getpart("verify", "strip");
+
+ # what parts to cut off from the protocol & upload
+ my @strippart = getpart("verify", "strippart");
+
+ # this is the valid protocol blurb curl should generate
+ my @protocol= getpart("verify", "protocol");
if(@protocol) {
# Verify the sent request
- my @out = loadarray($SERVERIN);
-
- # what to cut off from the live protocol sent by curl
- my @strip = getpart("verify", "strip");
-
- my @protstrip=@protocol;
+ my @out = loadarray("$logdir/$SERVERIN");
# check if there's any attributes on the verify/protocol section
my %hash = getpartattr("verify", "protocol");
@@ -4483,37 +1319,39 @@
if($hash{'nonewline'}) {
# Yes, we must cut off the final newline from the final line
# of the protocol data
- chomp($protstrip[$#protstrip]);
+ chomp($protocol[-1]);
}
for(@strip) {
# strip off all lines that match the patterns from both arrays
chomp $_;
@out = striparray( $_, \@out);
- @protstrip= striparray( $_, \@protstrip);
+ @protocol= striparray( $_, \@protocol);
}
- # what parts to cut off from the protocol
- my @strippart = getpart("verify", "strippart");
- my $strip;
-
- for $strip (@strippart) {
+ for my $strip (@strippart) {
chomp $strip;
for(@out) {
eval $strip;
}
}
- if((!$out[0] || ($out[0] eq "")) && $protstrip[0]) {
- logmsg "\n $testnum: protocol FAILED!\n".
- " There was no content at all in the file $SERVERIN.\n".
- " Server glitch? Total curl failure? Returned: $cmdres\n";
- return $errorreturncode;
+ if($hash{'crlf'}) {
+ subnewlines(1, \$_) for @protocol;
}
- $res = compare($testnum, $testname, "protocol", \@out, \@protstrip);
+ if((!$out[0] || ($out[0] eq "")) && $protocol[0]) {
+ logmsg "\n $testnum: protocol FAILED!\n".
+ " There was no content at all in the file $logdir/$SERVERIN.\n".
+ " Server glitch? Total curl failure? Returned: $cmdres\n";
+ # timestamp test result verification end
+ $timevrfyend{$testnum} = Time::HiRes::time();
+ return -1;
+ }
+
+ $res = compare($runnerid, $testnum, $testname, "protocol", \@out, \@protocol);
if($res) {
- return $errorreturncode;
+ return -1;
}
$ok .= "p";
@@ -4523,12 +1361,63 @@
$ok .= "-"; # protocol not checked
}
+ my %replyattr = getpartattr("reply", "data");
+ my @reply;
+ if (partexists("reply", "datacheck")) {
+ for my $partsuffix (('', '1', '2', '3', '4')) {
+ my @replycheckpart = getpart("reply", "datacheck".$partsuffix);
+ if(@replycheckpart) {
+ my %replycheckpartattr = getpartattr("reply", "datacheck".$partsuffix);
+ # get the mode attribute
+ my $filemode=$replycheckpartattr{'mode'};
+ if($filemode && ($filemode eq "text") && $has_textaware) {
+ # text mode when running on windows: fix line endings
+ s/\r\n/\n/g for @replycheckpart;
+ s/\n/\r\n/g for @replycheckpart;
+ }
+ if($replycheckpartattr{'nonewline'}) {
+ # Yes, we must cut off the final newline from the final line
+ # of the datacheck
+ chomp($replycheckpart[-1]);
+ }
+ if($replycheckpartattr{'crlf'} ||
+ ($feature{"hyper"} && ($keywords{"HTTP"}
+ || $keywords{"HTTPS"}))) {
+ subnewlines(0, \$_) for @replycheckpart;
+ }
+ push(@reply, @replycheckpart);
+ }
+ }
+ }
+ else {
+ # check against the data section
+ @reply = getpart("reply", "data");
+ if(@reply) {
+ if($replyattr{'nonewline'}) {
+ # cut off the final newline from the final line of the data
+ chomp($reply[-1]);
+ }
+ }
+ # get the mode attribute
+ my $filemode=$replyattr{'mode'};
+ if($filemode && ($filemode eq "text") && $has_textaware) {
+ # text mode when running on windows: fix line endings
+ s/\r\n/\n/g for @reply;
+ s/\n/\r\n/g for @reply;
+ }
+ if($replyattr{'crlf'} ||
+ ($feature{"hyper"} && ($keywords{"HTTP"}
+ || $keywords{"HTTPS"}))) {
+ subnewlines(0, \$_) for @reply;
+ }
+ }
+
if(!$replyattr{'nocheck'} && (@reply || $replyattr{'sendzero'})) {
# verify the received data
my @out = loadarray($CURLOUT);
- $res = compare($testnum, $testname, "data", \@out, \@reply);
+ $res = compare($runnerid, $testnum, $testname, "data", \@out, \@reply);
if ($res) {
- return $errorreturncode;
+ return -1;
}
$ok .= "d";
}
@@ -4536,23 +1425,27 @@
$ok .= "-"; # data not checked
}
+ # if this section exists, we verify upload
+ my @upload = getpart("verify", "upload");
if(@upload) {
- # verify uploaded data
- my @out = loadarray("$LOGDIR/upload.$testnum");
+ my %hash = getpartattr("verify", "upload");
+ if($hash{'nonewline'}) {
+ # cut off the final newline from the final line of the upload data
+ chomp($upload[-1]);
+ }
- # what parts to cut off from the upload
- my @strippart = getpart("verify", "strippart");
- my $strip;
- for $strip (@strippart) {
+ # verify uploaded data
+ my @out = loadarray("$logdir/upload.$testnum");
+ for my $strip (@strippart) {
chomp $strip;
for(@out) {
eval $strip;
}
}
- $res = compare($testnum, $testname, "upload", \@out, \@upload);
+ $res = compare($runnerid, $testnum, $testname, "upload", \@out, \@upload);
if ($res) {
- return $errorreturncode;
+ return -1;
}
$ok .= "u";
}
@@ -4560,45 +1453,42 @@
$ok .= "-"; # upload not checked
}
+ # this is the valid protocol blurb curl should generate to a proxy
+ my @proxyprot = getpart("verify", "proxy");
if(@proxyprot) {
# Verify the sent proxy request
- my @out = loadarray($PROXYIN);
-
- # what to cut off from the live protocol sent by curl, we use the
- # same rules as for <protocol>
- my @strip = getpart("verify", "strip");
-
- my @protstrip=@proxyprot;
-
# check if there's any attributes on the verify/protocol section
my %hash = getpartattr("verify", "proxy");
if($hash{'nonewline'}) {
# Yes, we must cut off the final newline from the final line
# of the protocol data
- chomp($protstrip[$#protstrip]);
+ chomp($proxyprot[-1]);
}
+ my @out = loadarray("$logdir/$PROXYIN");
for(@strip) {
# strip off all lines that match the patterns from both arrays
chomp $_;
@out = striparray( $_, \@out);
- @protstrip= striparray( $_, \@protstrip);
+ @proxyprot= striparray( $_, \@proxyprot);
}
- # what parts to cut off from the protocol
- my @strippart = getpart("verify", "strippart");
- my $strip;
- for $strip (@strippart) {
+ for my $strip (@strippart) {
chomp $strip;
for(@out) {
eval $strip;
}
}
- $res = compare($testnum, $testname, "proxy", \@out, \@protstrip);
+ if($hash{'crlf'} ||
+ ($feature{"hyper"} && ($keywords{"HTTP"} || $keywords{"HTTPS"}))) {
+ subnewlines(0, \$_) for @proxyprot;
+ }
+
+ $res = compare($runnerid, $testnum, $testname, "proxy", \@out, \@proxyprot);
if($res) {
- return $errorreturncode;
+ return -1;
}
$ok .= "P";
@@ -4617,9 +1507,25 @@
my $filename=$hash{'name'};
if(!$filename) {
- logmsg "ERROR: section verify=>file$partsuffix ".
+ logmsg " $testnum: IGNORED: section verify=>file$partsuffix ".
"has no name attribute\n";
- stopservers($verbose);
+ if (runnerac_stopservers($runnerid)) {
+ logmsg "ERROR: runner $runnerid seems to have died\n";
+ } else {
+
+ # TODO: this is a blocking call that will stall the controller,
+ if($verbose) {
+ logmsg "WARNING: blocking call in async function\n";
+ }
+ # but this error condition should never happen except during
+ # development.
+ my ($rid, $unexpected, $logs) = runnerar($runnerid);
+ if(!$rid) {
+ logmsg "ERROR: runner $runnerid seems to have died\n";
+ } else {
+ logmsg $logs;
+ }
+ }
# timestamp test result verification end
$timevrfyend{$testnum} = Time::HiRes::time();
return -1;
@@ -4627,17 +1533,21 @@
my @generated=loadarray($filename);
# what parts to cut off from the file
- my @stripfile = getpart("verify", "stripfile".$partsuffix);
+ my @stripfilepar = getpart("verify", "stripfile".$partsuffix);
my $filemode=$hash{'mode'};
if($filemode && ($filemode eq "text") && $has_textaware) {
# text mode when running on windows: fix line endings
- map s/\r\n/\n/g, @outfile;
- map s/\n/\r\n/g, @outfile;
+ s/\r\n/\n/g for @outfile;
+ s/\n/\r\n/g for @outfile;
+ }
+ if($hash{'crlf'} ||
+ ($feature{"hyper"} && ($keywords{"HTTP"}
+ || $keywords{"HTTPS"}))) {
+ subnewlines(0, \$_) for @outfile;
}
- my $strip;
- for $strip (@stripfile) {
+ for my $strip (@stripfilepar) {
chomp $strip;
my @newgen;
for(@generated) {
@@ -4651,10 +1561,10 @@
@generated = @newgen;
}
- $res = compare($testnum, $testname, "output ($filename)",
+ $res = compare($runnerid, $testnum, $testname, "output ($filename)",
\@generated, \@outfile);
if($res) {
- return $errorreturncode;
+ return -1;
}
$outputok = 1; # output checked
@@ -4666,10 +1576,10 @@
my @socksprot = getpart("verify", "socks");
if(@socksprot) {
# Verify the sent SOCKS proxy details
- my @out = loadarray($SOCKSIN);
- $res = compare($testnum, $testname, "socks", \@out, \@socksprot);
+ my @out = loadarray("$logdir/$SOCKSIN");
+ $res = compare($runnerid, $testnum, $testname, "socks", \@out, \@socksprot);
if($res) {
- return $errorreturncode;
+ return -1;
}
}
@@ -4692,19 +1602,22 @@
logmsg sprintf("\n%s returned $cmdres, when expecting %s\n",
(!$tool)?"curl":$tool, $errorcode);
}
- logmsg " exit FAILED\n";
+ logmsg " $testnum: exit FAILED\n";
# timestamp test result verification end
$timevrfyend{$testnum} = Time::HiRes::time();
- return $errorreturncode;
+ return -1;
}
- if($has_memory_tracking) {
- if(! -f $memdump) {
+ if($feature{"TrackMemory"}) {
+ if(! -f "$logdir/$MEMDUMP") {
+ my %cmdhash = getpartattr("client", "command");
+ my $cmdtype = $cmdhash{'type'} || "default";
logmsg "\n** ALERT! memory tracking with no output file?\n"
if(!$cmdtype eq "perl");
+ $ok .= "-"; # problem with memory checking
}
else {
- my @memdata=`$memanalyze $memdump`;
+ my @memdata=`$memanalyze "$logdir/$MEMDUMP"`;
my $leak=0;
for(@memdata) {
if($_ ne "") {
@@ -4718,7 +1631,7 @@
logmsg @memdata;
# timestamp test result verification end
$timevrfyend{$testnum} = Time::HiRes::time();
- return $errorreturncode;
+ return -1;
}
else {
$ok .= "m";
@@ -4730,12 +1643,12 @@
}
if($valgrind) {
- if($usevalgrind) {
- unless(opendir(DIR, "$LOGDIR")) {
- logmsg "ERROR: unable to read $LOGDIR\n";
+ if($usedvalgrind) {
+ if(!opendir(DIR, "$logdir")) {
+ logmsg "ERROR: unable to read $logdir\n";
# timestamp test result verification end
$timevrfyend{$testnum} = Time::HiRes::time();
- return $errorreturncode;
+ return -1;
}
my @files = readdir(DIR);
closedir(DIR);
@@ -4750,9 +1663,9 @@
logmsg "ERROR: valgrind log file missing for test $testnum\n";
# timestamp test result verification end
$timevrfyend{$testnum} = Time::HiRes::time();
- return $errorreturncode;
+ return -1;
}
- my @e = valgrindparse("$LOGDIR/$vgfile");
+ my @e = valgrindparse("$logdir/$vgfile");
if(@e && $e[0]) {
if($automakestyle) {
logmsg "FAIL: $testnum - $testname - valgrind\n";
@@ -4763,12 +1676,12 @@
}
# timestamp test result verification end
$timevrfyend{$testnum} = Time::HiRes::time();
- return $errorreturncode;
+ return -1;
}
$ok .= "v";
}
else {
- if($verbose && !$disablevalgrind) {
+ if($verbose) {
logmsg " valgrind SKIPPED\n";
}
$ok .= "-"; # skipped
@@ -4778,17 +1691,26 @@
$ok .= "-"; # valgrind not checked
}
# add 'E' for event-based
- $ok .= $evbased ? "E" : "-";
+ $ok .= $run_event_based ? "E" : "-";
logmsg "$ok " if(!$short);
# timestamp test result verification end
$timevrfyend{$testnum} = Time::HiRes::time();
+ return 0;
+}
+
+
+#######################################################################
+# Report a successful test
+sub singletest_success {
+ my ($testnum, $count, $total, $errorreturncode)=@_;
+
my $sofar= time()-$start;
my $esttotal = $sofar/$count * $total;
my $estleft = $esttotal - $sofar;
- my $left=sprintf("remaining: %02d:%02d",
+ my $timeleft=sprintf("remaining: %02d:%02d",
$estleft/60,
$estleft%60);
my $took = $timevrfyend{$testnum} - $timeprepini{$testnum};
@@ -4796,636 +1718,223 @@
$sofar/60, $sofar%60);
if(!$automakestyle) {
logmsg sprintf("OK (%-3d out of %-3d, %s, took %.3fs, %s)\n",
- $count, $total, $left, $took, $duration);
+ $count, $total, $timeleft, $took, $duration);
}
else {
+ my $testname= (getpart("client", "name"))[0];
+ chomp $testname;
logmsg "PASS: $testnum - $testname\n";
}
if($errorreturncode==2) {
logmsg "Warning: test$testnum result is ignored, but passed!\n";
}
-
- return 0;
}
#######################################################################
-# Stop all running test servers
+# Run a single specified test case
+# This is structured as a state machine which changes state after an
+# asynchronous call is made that awaits a response. The function returns with
+# an error code and a flag that indicates if the state machine has completed,
+# which means (if not) the function must be called again once the response has
+# arrived.
#
-sub stopservers {
- my $verbose = $_[0];
- #
- # kill sockfilter processes for all pingpong servers
- #
- killallsockfilters($verbose);
- #
- # kill all server pids from %run hash clearing them
- #
- my $pidlist;
- foreach my $server (keys %run) {
- if($run{$server}) {
- if($verbose) {
- my $prev = 0;
- my $pids = $run{$server};
- foreach my $pid (split(' ', $pids)) {
- if($pid != $prev) {
- logmsg sprintf("* kill pid for %s => %d\n",
- $server, $pid);
- $prev = $pid;
- }
- }
- }
- $pidlist .= "$run{$server} ";
- $run{$server} = 0;
- }
- $runcert{$server} = 0 if($runcert{$server});
- }
- killpid($verbose, $pidlist);
- #
- # cleanup all server pid files
- #
- my $result = 0;
- foreach my $server (keys %serverpidfile) {
- my $pidfile = $serverpidfile{$server};
- my $pid = processexists($pidfile);
- if($pid > 0) {
- if($err_unexpected) {
- logmsg "ERROR: ";
- $result = -1;
- }
- else {
- logmsg "Warning: ";
- }
- logmsg "$server server unexpectedly alive\n";
- killpid($verbose, $pid);
- }
- unlink($pidfile) if(-f $pidfile);
+sub singletest {
+ my ($runnerid, $testnum, $count, $total)=@_;
+
+ # start buffering logmsg; stop it on return
+ logmsg_bufferfortest($runnerid);
+ if(!exists $singletest_state{$runnerid}) {
+ # First time in singletest() for this test
+ $singletest_state{$runnerid} = ST_INIT;
}
- return $result;
-}
-
-#######################################################################
-# startservers() starts all the named servers
-#
-# Returns: string with error reason or blank for success
-#
-sub startservers {
- my @what = @_;
- my ($pid, $pid2);
- for(@what) {
- my (@whatlist) = split(/\s+/,$_);
- my $what = lc($whatlist[0]);
- $what =~ s/[^a-z0-9\/-]//g;
-
- my $certfile;
- if($what =~ /^(ftp|gopher|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
- $certfile = ($whatlist[1]) ? $whatlist[1] : 'stunnel.pem';
+ if($singletest_state{$runnerid} == ST_INIT) {
+ my $logdir = getrunnerlogdir($runnerid);
+ # first, remove all lingering log & lock files
+ if((!cleardir($logdir) || !cleardir("$logdir/$LOCKDIR"))
+ && $clearlocks) {
+ # On Windows, lock files can't be deleted when the process still
+ # has them open, so kill those processes first
+ if(runnerac_clearlocks($runnerid, "$logdir/$LOCKDIR")) {
+ logmsg "ERROR: runner $runnerid seems to have died\n";
+ $singletest_state{$runnerid} = ST_INIT;
+ return (-1, 0);
+ }
+ $singletest_state{$runnerid} = ST_CLEARLOCKS;
+ } else {
+ $singletest_state{$runnerid} = ST_INITED;
+ # Recursively call the state machine again because there is no
+ # event expected that would otherwise trigger a new call.
+ return singletest(@_);
}
- if(($what eq "pop3") ||
- ($what eq "ftp") ||
- ($what eq "imap") ||
- ($what eq "smtp")) {
- if($torture && $run{$what} &&
- !responsive_pingpong_server($what, "", $verbose)) {
- if(stopserver($what)) {
- return "failed stopping unresponsive ".uc($what)." server";
- }
- }
- if(!$run{$what}) {
- ($pid, $pid2) = runpingpongserver($what, "", $verbose);
- if($pid <= 0) {
- return "failed starting ". uc($what) ." server";
- }
- printf ("* pid $what => %d %d\n", $pid, $pid2) if($verbose);
- $run{$what}="$pid $pid2";
- }
+ } elsif($singletest_state{$runnerid} == ST_CLEARLOCKS) {
+ my ($rid, $logs) = runnerar($runnerid);
+ if(!$rid) {
+ logmsg "ERROR: runner $runnerid seems to have died\n";
+ $singletest_state{$runnerid} = ST_INIT;
+ return (-1, 0);
}
- elsif($what eq "ftp-ipv6") {
- if($torture && $run{'ftp-ipv6'} &&
- !responsive_pingpong_server("ftp", "", $verbose, "ipv6")) {
- if(stopserver('ftp-ipv6')) {
- return "failed stopping unresponsive FTP-IPv6 server";
- }
- }
- if(!$run{'ftp-ipv6'}) {
- ($pid, $pid2) = runpingpongserver("ftp", "", $verbose, "ipv6");
- if($pid <= 0) {
- return "failed starting FTP-IPv6 server";
- }
- logmsg sprintf("* pid ftp-ipv6 => %d %d\n", $pid,
- $pid2) if($verbose);
- $run{'ftp-ipv6'}="$pid $pid2";
- }
- }
- elsif($what eq "gopher") {
- if($torture && $run{'gopher'} &&
- !responsive_http_server("gopher", $verbose, 0, $GOPHERPORT)) {
- if(stopserver('gopher')) {
- return "failed stopping unresponsive GOPHER server";
- }
- }
- if(!$run{'gopher'}) {
- ($pid, $pid2, $GOPHERPORT) =
- runhttpserver("gopher", $verbose, 0);
- if($pid <= 0) {
- return "failed starting GOPHER server";
- }
- logmsg sprintf ("* pid gopher => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'gopher'}="$pid $pid2";
- }
- }
- elsif($what eq "gopher-ipv6") {
- if($torture && $run{'gopher-ipv6'} &&
- !responsive_http_server("gopher", $verbose, "ipv6",
- $GOPHER6PORT)) {
- if(stopserver('gopher-ipv6')) {
- return "failed stopping unresponsive GOPHER-IPv6 server";
- }
- }
- if(!$run{'gopher-ipv6'}) {
- ($pid, $pid2, $GOPHER6PORT) =
- runhttpserver("gopher", $verbose, "ipv6");
- if($pid <= 0) {
- return "failed starting GOPHER-IPv6 server";
- }
- logmsg sprintf("* pid gopher-ipv6 => %d %d\n", $pid,
- $pid2) if($verbose);
- $run{'gopher-ipv6'}="$pid $pid2";
- }
- }
- elsif($what eq "http/2") {
- if(!$run{'http/2'}) {
- ($pid, $pid2, $HTTP2PORT) = runhttp2server($verbose);
- if($pid <= 0) {
- return "failed starting HTTP/2 server";
- }
- logmsg sprintf ("* pid http/2 => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'http/2'}="$pid $pid2";
- }
- }
- elsif($what eq "http") {
- if($torture && $run{'http'} &&
- !responsive_http_server("http", $verbose, 0, $HTTPPORT)) {
- if(stopserver('http')) {
- return "failed stopping unresponsive HTTP server";
- }
- }
- if(!$run{'http'}) {
- ($pid, $pid2, $HTTPPORT) =
- runhttpserver("http", $verbose, 0);
- if($pid <= 0) {
- return "failed starting HTTP server";
- }
- logmsg sprintf ("* pid http => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'http'}="$pid $pid2";
- }
- }
- elsif($what eq "http-proxy") {
- if($torture && $run{'http-proxy'} &&
- !responsive_http_server("http", $verbose, "proxy",
- $HTTPPROXYPORT)) {
- if(stopserver('http-proxy')) {
- return "failed stopping unresponsive HTTP-proxy server";
- }
- }
- if(!$run{'http-proxy'}) {
- ($pid, $pid2, $HTTPPROXYPORT) =
- runhttpserver("http", $verbose, "proxy");
- if($pid <= 0) {
- return "failed starting HTTP-proxy server";
- }
- logmsg sprintf ("* pid http-proxy => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'http-proxy'}="$pid $pid2";
- }
- }
- elsif($what eq "http-ipv6") {
- if($torture && $run{'http-ipv6'} &&
- !responsive_http_server("http", $verbose, "ipv6", $HTTP6PORT)) {
- if(stopserver('http-ipv6')) {
- return "failed stopping unresponsive HTTP-IPv6 server";
- }
- }
- if(!$run{'http-ipv6'}) {
- ($pid, $pid2, $HTTP6PORT) =
- runhttpserver("http", $verbose, "ipv6");
- if($pid <= 0) {
- return "failed starting HTTP-IPv6 server";
- }
- logmsg sprintf("* pid http-ipv6 => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'http-ipv6'}="$pid $pid2";
- }
- }
- elsif($what eq "rtsp") {
- if($torture && $run{'rtsp'} &&
- !responsive_rtsp_server($verbose)) {
- if(stopserver('rtsp')) {
- return "failed stopping unresponsive RTSP server";
- }
- }
- if(!$run{'rtsp'}) {
- ($pid, $pid2, $RTSPPORT) = runrtspserver($verbose);
- if($pid <= 0) {
- return "failed starting RTSP server";
- }
- printf ("* pid rtsp => %d %d\n", $pid, $pid2) if($verbose);
- $run{'rtsp'}="$pid $pid2";
- }
- }
- elsif($what eq "rtsp-ipv6") {
- if($torture && $run{'rtsp-ipv6'} &&
- !responsive_rtsp_server($verbose, "ipv6")) {
- if(stopserver('rtsp-ipv6')) {
- return "failed stopping unresponsive RTSP-IPv6 server";
- }
- }
- if(!$run{'rtsp-ipv6'}) {
- ($pid, $pid2, $RTSP6PORT) = runrtspserver($verbose, "ipv6");
- if($pid <= 0) {
- return "failed starting RTSP-IPv6 server";
- }
- logmsg sprintf("* pid rtsp-ipv6 => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'rtsp-ipv6'}="$pid $pid2";
- }
- }
- elsif($what eq "ftps") {
- if(!$stunnel) {
- # we can't run ftps tests without stunnel
- return "no stunnel";
- }
- if($runcert{'ftps'} && ($runcert{'ftps'} ne $certfile)) {
- # stop server when running and using a different cert
- if(stopserver('ftps')) {
- return "failed stopping FTPS server with different cert";
- }
- }
- if($torture && $run{'ftp'} &&
- !responsive_pingpong_server("ftp", "", $verbose)) {
- if(stopserver('ftp')) {
- return "failed stopping unresponsive FTP server";
- }
- }
- if(!$run{'ftp'}) {
- ($pid, $pid2) = runpingpongserver("ftp", "", $verbose);
- if($pid <= 0) {
- return "failed starting FTP server";
- }
- printf ("* pid ftp => %d %d\n", $pid, $pid2) if($verbose);
- $run{'ftp'}="$pid $pid2";
- }
- if(!$run{'ftps'}) {
- ($pid, $pid2, $FTPSPORT) =
- runftpsserver($verbose, "", $certfile);
- if($pid <= 0) {
- return "failed starting FTPS server (stunnel)";
- }
- logmsg sprintf("* pid ftps => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'ftps'}="$pid $pid2";
- }
- }
- elsif($what eq "file") {
- # we support it but have no server!
- }
- elsif($what eq "https") {
- if(!$stunnel) {
- # we can't run https tests without stunnel
- return "no stunnel";
- }
- if($runcert{'https'} && ($runcert{'https'} ne $certfile)) {
- # stop server when running and using a different cert
- if(stopserver('https')) {
- return "failed stopping HTTPS server with different cert";
- }
- }
- if($torture && $run{'http'} &&
- !responsive_http_server("http", $verbose, 0, $HTTPPORT)) {
- if(stopserver('http')) {
- return "failed stopping unresponsive HTTP server";
- }
- }
- if(!$run{'http'}) {
- ($pid, $pid2, $HTTPPORT) =
- runhttpserver("http", $verbose, 0);
- if($pid <= 0) {
- return "failed starting HTTP server";
- }
- printf ("* pid http => %d %d\n", $pid, $pid2) if($verbose);
- $run{'http'}="$pid $pid2";
- }
- if(!$run{'https'}) {
- ($pid, $pid2, $HTTPSPORT) =
- runhttpsserver($verbose, "https", "", $certfile);
- if($pid <= 0) {
- return "failed starting HTTPS server (stunnel)";
- }
- logmsg sprintf("* pid https => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'https'}="$pid $pid2";
- }
- }
- elsif($what eq "gophers") {
- if(!$stunnel) {
- # we can't run TLS tests without stunnel
- return "no stunnel";
- }
- if($runcert{'gophers'} && ($runcert{'gophers'} ne $certfile)) {
- # stop server when running and using a different cert
- if(stopserver('gophers')) {
- return "failed stopping GOPHERS server with different crt";
- }
- }
- if($torture && $run{'gopher'} &&
- !responsive_http_server("gopher", $verbose, 0, $GOPHERPORT)) {
- if(stopserver('gopher')) {
- return "failed stopping unresponsive GOPHER server";
- }
- }
- if(!$run{'gopher'}) {
- ($pid, $pid2, $GOPHERPORT) =
- runhttpserver("gopher", $verbose, 0);
- if($pid <= 0) {
- return "failed starting GOPHER server";
- }
- printf ("* pid gopher => %d %d\n", $pid, $pid2) if($verbose);
- print "GOPHERPORT => $GOPHERPORT\n" if($verbose);
- $run{'gopher'}="$pid $pid2";
- }
- if(!$run{'gophers'}) {
- ($pid, $pid2, $GOPHERSPORT) =
- runhttpsserver($verbose, "gophers", "", $certfile);
- if($pid <= 0) {
- return "failed starting GOPHERS server (stunnel)";
- }
- logmsg sprintf("* pid gophers => %d %d\n", $pid, $pid2)
- if($verbose);
- print "GOPHERSPORT => $GOPHERSPORT\n" if($verbose);
- $run{'gophers'}="$pid $pid2";
- }
- }
- elsif($what eq "https-proxy") {
- if(!$stunnel) {
- # we can't run https-proxy tests without stunnel
- return "no stunnel";
- }
- if($runcert{'https-proxy'} &&
- ($runcert{'https-proxy'} ne $certfile)) {
- # stop server when running and using a different cert
- if(stopserver('https-proxy')) {
- return "failed stopping HTTPS-proxy with different cert";
- }
- }
+ logmsg $logs;
+ my $logdir = getrunnerlogdir($runnerid);
+ cleardir($logdir);
+ $singletest_state{$runnerid} = ST_INITED;
+ # Recursively call the state machine again because there is no
+ # event expected that would otherwise trigger a new call.
+ return singletest(@_);
- # we front the http-proxy with stunnel so we need to make sure the
- # proxy runs as well
- my $f = startservers("http-proxy");
- if($f) {
- return $f;1
- }
+ } elsif($singletest_state{$runnerid} == ST_INITED) {
+ ###################################################################
+ # Restore environment variables that were modified in a previous run.
+ # Test definition may instruct to (un)set environment vars.
+ # This is done this early so that leftover variables don't affect
+ # starting servers or CI registration.
+ # restore_test_env(1);
- if(!$run{'https-proxy'}) {
- ($pid, $pid2, $HTTPSPROXYPORT) =
- runhttpsserver($verbose, "https", "proxy", $certfile);
- if($pid <= 0) {
- return "failed starting HTTPS-proxy (stunnel)";
- }
- logmsg sprintf("* pid https-proxy => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'https-proxy'}="$pid $pid2";
+ ###################################################################
+ # Load test file so CI registration can get the right data before the
+ # runner is called
+ loadtest("${TESTDIR}/test${testnum}");
+
+ ###################################################################
+ # Register the test case with the CI environment
+ citest_starttest($testnum);
+
+ if(runnerac_test_preprocess($runnerid, $testnum)) {
+ logmsg "ERROR: runner $runnerid seems to have died\n";
+ $singletest_state{$runnerid} = ST_INIT;
+ return (-1, 0);
+ }
+ $singletest_state{$runnerid} = ST_PREPROCESS;
+
+ } elsif($singletest_state{$runnerid} == ST_PREPROCESS) {
+ my ($rid, $why, $error, $logs, $testtimings) = runnerar($runnerid);
+ if(!$rid) {
+ logmsg "ERROR: runner $runnerid seems to have died\n";
+ $singletest_state{$runnerid} = ST_INIT;
+ return (-1, 0);
+ }
+ logmsg $logs;
+ updatetesttimings($testnum, %$testtimings);
+ if($error == -2) {
+ if($postmortem) {
+ # Error indicates an actual problem starting the server, so
+ # display the server logs
+ displaylogs($rid, $testnum);
}
}
- elsif($what eq "httptls") {
- if(!$httptlssrv) {
- # for now, we can't run http TLS-EXT tests without gnutls-serv
- return "no gnutls-serv";
- }
- if($torture && $run{'httptls'} &&
- !responsive_httptls_server($verbose, "IPv4")) {
- if(stopserver('httptls')) {
- return "failed stopping unresponsive HTTPTLS server";
- }
- }
- if(!$run{'httptls'}) {
- ($pid, $pid2, $HTTPTLSPORT) =
- runhttptlsserver($verbose, "IPv4");
- if($pid <= 0) {
- return "failed starting HTTPTLS server (gnutls-serv)";
- }
- logmsg sprintf("* pid httptls => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'httptls'}="$pid $pid2";
- }
+
+ #######################################################################
+ # Load test file for this test number
+ my $logdir = getrunnerlogdir($runnerid);
+ loadtest("${logdir}/test${testnum}");
+
+ #######################################################################
+ # Print the test name and count tests
+ $error = singletest_count($testnum, $why);
+ if($error) {
+ # Submit the test case result with the CI environment
+ citest_finishtest($testnum, $error);
+ $singletest_state{$runnerid} = ST_INIT;
+ logmsg singletest_dumplogs();
+ return ($error, 0);
}
- elsif($what eq "httptls-ipv6") {
- if(!$httptlssrv) {
- # for now, we can't run http TLS-EXT tests without gnutls-serv
- return "no gnutls-serv";
- }
- if($torture && $run{'httptls-ipv6'} &&
- !responsive_httptls_server($verbose, "ipv6")) {
- if(stopserver('httptls-ipv6')) {
- return "failed stopping unresponsive HTTPTLS-IPv6 server";
- }
- }
- if(!$run{'httptls-ipv6'}) {
- ($pid, $pid2, $HTTPTLS6PORT) =
- runhttptlsserver($verbose, "ipv6");
- if($pid <= 0) {
- return "failed starting HTTPTLS-IPv6 server (gnutls-serv)";
- }
- logmsg sprintf("* pid httptls-ipv6 => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'httptls-ipv6'}="$pid $pid2";
- }
+
+ #######################################################################
+ # Execute this test number
+ my $cmdres;
+ my $CURLOUT;
+ my $tool;
+ my $usedvalgrind;
+ if(runnerac_test_run($runnerid, $testnum)) {
+ logmsg "ERROR: runner $runnerid seems to have died\n";
+ $singletest_state{$runnerid} = ST_INIT;
+ return (-1, 0);
}
- elsif($what eq "tftp") {
- if($torture && $run{'tftp'} &&
- !responsive_tftp_server("", $verbose)) {
- if(stopserver('tftp')) {
- return "failed stopping unresponsive TFTP server";
- }
- }
- if(!$run{'tftp'}) {
- ($pid, $pid2, $TFTPPORT) =
- runtftpserver("", $verbose);
- if($pid <= 0) {
- return "failed starting TFTP server";
- }
- printf ("* pid tftp => %d %d\n", $pid, $pid2) if($verbose);
- $run{'tftp'}="$pid $pid2";
- }
+ $singletest_state{$runnerid} = ST_RUN;
+
+ } elsif($singletest_state{$runnerid} == ST_RUN) {
+ my ($rid, $error, $logs, $testtimings, $cmdres, $CURLOUT, $tool, $usedvalgrind) = runnerar($runnerid);
+ if(!$rid) {
+ logmsg "ERROR: runner $runnerid seems to have died\n";
+ $singletest_state{$runnerid} = ST_INIT;
+ return (-1, 0);
}
- elsif($what eq "tftp-ipv6") {
- if($torture && $run{'tftp-ipv6'} &&
- !responsive_tftp_server("", $verbose, "ipv6")) {
- if(stopserver('tftp-ipv6')) {
- return "failed stopping unresponsive TFTP-IPv6 server";
- }
- }
- if(!$run{'tftp-ipv6'}) {
- ($pid, $pid2, $TFTP6PORT) =
- runtftpserver("", $verbose, "ipv6");
- if($pid <= 0) {
- return "failed starting TFTP-IPv6 server";
- }
- printf("* pid tftp-ipv6 => %d %d\n", $pid, $pid2) if($verbose);
- $run{'tftp-ipv6'}="$pid $pid2";
- }
+ logmsg $logs;
+ updatetesttimings($testnum, %$testtimings);
+ if($error == -1) {
+ # no further verification will occur
+ $timevrfyend{$testnum} = Time::HiRes::time();
+ my $err = ignoreresultcode($testnum);
+ # Submit the test case result with the CI environment
+ citest_finishtest($testnum, $err);
+ $singletest_state{$runnerid} = ST_INIT;
+ logmsg singletest_dumplogs();
+ # return a test failure, either to be reported or to be ignored
+ return ($err, 0);
}
- elsif($what eq "sftp" || $what eq "scp") {
- if(!$run{'ssh'}) {
- ($pid, $pid2, $SSHPORT) = runsshserver("", $verbose);
- if($pid <= 0) {
- return "failed starting SSH server";
- }
- printf ("* pid ssh => %d %d\n", $pid, $pid2) if($verbose);
- $run{'ssh'}="$pid $pid2";
- }
+ elsif($error == -2) {
+ # fill in the missing timings on error
+ timestampskippedevents($testnum);
+ # Submit the test case result with the CI environment
+ citest_finishtest($testnum, $error);
+ $singletest_state{$runnerid} = ST_INIT;
+ logmsg singletest_dumplogs();
+ return ($error, 0);
}
- elsif($what eq "socks4" || $what eq "socks5" ) {
- if(!$run{'socks'}) {
- ($pid, $pid2, $SOCKSPORT) = runsocksserver("", $verbose);
- if($pid <= 0) {
- return "failed starting socks server";
- }
- printf ("* pid socks => %d %d\n", $pid, $pid2) if($verbose);
- $run{'socks'}="$pid $pid2";
- }
+ elsif($error > 0) {
+ # no further verification will occur
+ $timevrfyend{$testnum} = Time::HiRes::time();
+ # Submit the test case result with the CI environment
+ citest_finishtest($testnum, $error);
+ $singletest_state{$runnerid} = ST_INIT;
+ logmsg singletest_dumplogs();
+ return ($error, 0);
}
- elsif($what eq "socks5unix") {
- if(!$run{'socks5unix'}) {
- ($pid, $pid2) = runsocksserver("2", $verbose, "", "unix");
- if($pid <= 0) {
- return "failed starting socks5unix server";
- }
- printf ("* pid socks5unix => %d %d\n", $pid, $pid2) if($verbose);
- $run{'socks5unix'}="$pid $pid2";
- }
+
+ #######################################################################
+ # Verify that the test succeeded
+ #
+ # Load test file for this test number
+ my $logdir = getrunnerlogdir($runnerid);
+ loadtest("${logdir}/test${testnum}");
+ readtestkeywords();
+
+ $error = singletest_check($runnerid, $testnum, $cmdres, $CURLOUT, $tool, $usedvalgrind);
+ if($error == -1) {
+ my $err = ignoreresultcode($testnum);
+ # Submit the test case result with the CI environment
+ citest_finishtest($testnum, $err);
+ $singletest_state{$runnerid} = ST_INIT;
+ logmsg singletest_dumplogs();
+ # return a test failure, either to be reported or to be ignored
+ return ($err, 0);
}
- elsif($what eq "mqtt" ) {
- if(!$run{'mqtt'}) {
- ($pid, $pid2) = runmqttserver("", $verbose);
- if($pid <= 0) {
- return "failed starting mqtt server";
- }
- printf ("* pid mqtt => %d %d\n", $pid, $pid2) if($verbose);
- $run{'mqtt'}="$pid $pid2";
- }
+ elsif($error == -2) {
+ # torture test; there is no verification, so the run result holds the
+ # test success code
+ # Submit the test case result with the CI environment
+ citest_finishtest($testnum, $cmdres);
+ $singletest_state{$runnerid} = ST_INIT;
+ logmsg singletest_dumplogs();
+ return ($cmdres, 0);
}
- elsif($what eq "http-unix") {
- if($torture && $run{'http-unix'} &&
- !responsive_http_server("http", $verbose, "unix", $HTTPUNIXPATH)) {
- if(stopserver('http-unix')) {
- return "failed stopping unresponsive HTTP-unix server";
- }
- }
- if(!$run{'http-unix'}) {
- my $unused;
- ($pid, $pid2, $unused) =
- runhttpserver("http", $verbose, "unix", $HTTPUNIXPATH);
- if($pid <= 0) {
- return "failed starting HTTP-unix server";
- }
- logmsg sprintf("* pid http-unix => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'http-unix'}="$pid $pid2";
- }
- }
- elsif($what eq "dict") {
- if(!$run{'dict'}) {
- ($pid, $pid2, $DICTPORT) = rundictserver($verbose, "");
- if($pid <= 0) {
- return "failed starting DICT server";
- }
- logmsg sprintf ("* pid DICT => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'dict'}="$pid $pid2";
- }
- }
- elsif($what eq "smb") {
- if(!$run{'smb'}) {
- ($pid, $pid2, $SMBPORT) = runsmbserver($verbose, "");
- if($pid <= 0) {
- return "failed starting SMB server";
- }
- logmsg sprintf ("* pid SMB => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'smb'}="$pid $pid2";
- }
- }
- elsif($what eq "telnet") {
- if(!$run{'telnet'}) {
- ($pid, $pid2, $TELNETPORT) =
- runnegtelnetserver($verbose, "");
- if($pid <= 0) {
- return "failed starting neg TELNET server";
- }
- logmsg sprintf ("* pid neg TELNET => %d %d\n", $pid, $pid2)
- if($verbose);
- $run{'telnet'}="$pid $pid2";
- }
- }
- elsif($what eq "none") {
- logmsg "* starts no server\n" if ($verbose);
- }
- else {
- warn "we don't support a server for $what";
- return "no server for $what";
- }
+
+
+ #######################################################################
+ # Report a successful test
+ singletest_success($testnum, $count, $total, ignoreresultcode($testnum));
+
+ # Submit the test case result with the CI environment
+ citest_finishtest($testnum, 0);
+ $singletest_state{$runnerid} = ST_INIT;
+
+ logmsg singletest_dumplogs();
+ return (0, 0); # state machine is finished
}
- return 0;
-}
-
-##############################################################################
-# This function makes sure the right set of server is running for the
-# specified test case. This is a useful design when we run single tests as not
-# all servers need to run then!
-#
-# Returns: a string, blank if everything is fine or a reason why it failed
-#
-sub serverfortest {
- my ($testnum)=@_;
-
- my @what = getpart("client", "server");
-
- if(!$what[0]) {
- warn "Test case $testnum has no server(s) specified";
- return "no server specified";
- }
-
- for(my $i = scalar(@what) - 1; $i >= 0; $i--) {
- my $srvrline = $what[$i];
- chomp $srvrline if($srvrline);
- if($srvrline =~ /^(\S+)((\s*)(.*))/) {
- my $server = "${1}";
- my $lnrest = "${2}";
- my $tlsext;
- if($server =~ /^(httptls)(\+)(ext|srp)(\d*)(-ipv6|)$/) {
- $server = "${1}${4}${5}";
- $tlsext = uc("TLS-${3}");
- }
- if(! grep /^\Q$server\E$/, @protocols) {
- if(substr($server,0,5) ne "socks") {
- if($tlsext) {
- return "curl lacks $tlsext support";
- }
- else {
- return "curl lacks $server server support";
- }
- }
- }
- $what[$i] = "$server$lnrest" if($tlsext);
- }
- }
-
- return &startservers(@what);
+ singletest_unbufferlogs();
+ return (0, 1); # state machine must be called again on event
}
#######################################################################
@@ -5565,6 +2074,54 @@
}
#######################################################################
+# returns code indicating why a test was skipped
+# 0=unknown test, 1=use test result, 2=ignore test result
+#
+sub ignoreresultcode {
+ my ($testnum)=@_;
+ if(defined $ignoretestcodes{$testnum}) {
+ return $ignoretestcodes{$testnum};
+ }
+ return 0;
+}
+
+#######################################################################
+# Put the given runner ID onto the queue of runners ready for a new task
+#
+sub runnerready {
+ my ($runnerid)=@_;
+ push @runnersidle, $runnerid;
+}
+
+#######################################################################
+# Create test runners
+#
+sub createrunners {
+ my ($numrunners)=@_;
+ if(! $numrunners) {
+ $numrunners++;
+ }
+ # create $numrunners runners with minimum 1
+ for my $runnernum (1..$numrunners) {
+ my $dir = getrunnernumlogdir($runnernum);
+ cleardir($dir);
+ mkdir($dir, 0777);
+ $runnerids{$runnernum} = runner_init($dir, $jobs);
+ runnerready($runnerids{$runnernum});
+ }
+}
+
+#######################################################################
+# Pick a test runner for the given test
+#
+sub pickrunner {
+ my ($testnum)=@_;
+ scalar(@runnersidle) || die "No runners available";
+
+ return pop @runnersidle;
+}
+
+#######################################################################
# Check options to this test program
#
@@ -5575,6 +2132,7 @@
push(@ARGV, split(' ', $ENV{'TFLAGS'})) if defined($ENV{'TFLAGS'});
}
+$valgrind = checktestcmd("valgrind");
my $number=0;
my $fromnum=-1;
my @testthis;
@@ -5585,7 +2143,7 @@
}
elsif ($ARGV[0] eq "-c") {
# use this path to curl instead of default
- $DBGCURL=$CURL="\"$ARGV[1]\"";
+ $DBGCURL=$CURL=$ARGV[1];
shift @ARGV;
}
elsif ($ARGV[0] eq "-vc") {
@@ -5595,7 +2153,12 @@
# the development version as then it won't be able to run any tests
# since it can't verify the servers!
- $VCURL="\"$ARGV[1]\"";
+ $VCURL=shell_quote($ARGV[1]);
+ shift @ARGV;
+ }
+ elsif ($ARGV[0] eq "-ac") {
+ # use this curl only to talk to APIs (currently only CI test APIs)
+ $ACURL=shell_quote($ARGV[1]);
shift @ARGV;
}
elsif ($ARGV[0] eq "-d") {
@@ -5608,7 +2171,7 @@
}
elsif($ARGV[0] eq "-f") {
# force - run the test case even if listed in DISABLED
- $run_disabeled=1;
+ $run_disabled=1;
}
elsif($ARGV[0] eq "-E") {
# load additional reasons to skip tests
@@ -5623,7 +2186,7 @@
die "Unsupported type: $type\n" if($type !~ /^keyword|test|tool$/);
foreach my $pattern (split(/,/, $patterns)) {
- if($type =~ /^test$/) {
+ if($type eq "test") {
# Strip leading zeros in the test number
$pattern = int($pattern);
}
@@ -5654,6 +2217,10 @@
# no valgrind
undef $valgrind;
}
+ elsif($ARGV[0] eq "--no-debuginfod") {
+ # disable the valgrind debuginfod functionality
+ $no_debuginfod = 1;
+ }
elsif ($ARGV[0] eq "-R") {
# execute in scrambled order
$scrambleorder=1;
@@ -5699,7 +2266,6 @@
}
elsif($ARGV[0] eq "-P") {
shift @ARGV;
- $use_external_proxy=1;
$proxy_address=$ARGV[0];
}
elsif($ARGV[0] eq "-L") {
@@ -5711,6 +2277,14 @@
# lists the test case names only
$listonly=1;
}
+ elsif($ARGV[0] =~ /^-j(.*)/) {
+ # parallel jobs
+ $jobs=1;
+ my $xtra = $1;
+ if($xtra =~ s/(\d+)$//) {
+ $jobs = $1;
+ }
+ }
elsif($ARGV[0] eq "-k") {
# keep stdout and stderr files after tests
$keepoutfiles=1;
@@ -5718,13 +2292,14 @@
elsif($ARGV[0] eq "-r") {
# run time statistics needs Time::HiRes
if($Time::HiRes::VERSION) {
- keys(%timeprepini) = 1000;
- keys(%timesrvrini) = 1000;
- keys(%timesrvrend) = 1000;
- keys(%timetoolini) = 1000;
- keys(%timetoolend) = 1000;
- keys(%timesrvrlog) = 1000;
- keys(%timevrfyend) = 1000;
+ # presize hashes appropriately to hold an entire test run
+ keys(%timeprepini) = 2000;
+ keys(%timesrvrini) = 2000;
+ keys(%timesrvrend) = 2000;
+ keys(%timetoolini) = 2000;
+ keys(%timetoolend) = 2000;
+ keys(%timesrvrlog) = 2000;
+ keys(%timevrfyend) = 2000;
$timestats=1;
$fullstats=0;
}
@@ -5732,13 +2307,14 @@
elsif($ARGV[0] eq "-rf") {
# run time statistics needs Time::HiRes
if($Time::HiRes::VERSION) {
- keys(%timeprepini) = 1000;
- keys(%timesrvrini) = 1000;
- keys(%timesrvrend) = 1000;
- keys(%timetoolini) = 1000;
- keys(%timetoolend) = 1000;
- keys(%timesrvrlog) = 1000;
- keys(%timevrfyend) = 1000;
+ # presize hashes appropriately to hold an entire test run
+ keys(%timeprepini) = 2000;
+ keys(%timesrvrini) = 2000;
+ keys(%timesrvrend) = 2000;
+ keys(%timetoolini) = 2000;
+ keys(%timetoolend) = 2000;
+ keys(%timesrvrlog) = 2000;
+ keys(%timevrfyend) = 2000;
$timestats=1;
$fullstats=1;
}
@@ -5753,9 +2329,10 @@
}
elsif(($ARGV[0] eq "-h") || ($ARGV[0] eq "--help")) {
# show help text
- print <<EOHELP
+ print <<"EOHELP"
Usage: runtests.pl [options] [test selection(s)]
-a continue even if a test fails
+ -ac path use this curl only to talk to APIs (currently only CI test APIs)
-am automake style output PASS/FAIL: [number] [name]
-c path use this curl executable
-d display server debug info
@@ -5765,10 +2342,12 @@
-g run the test case with gdb
-gw run the test case with gdb as a windowed application
-h this help text
+ -j[N] spawn this number of processes to run tests (default 0)
-k keep stdout and stderr files present after tests
-L path require an additional perl library file to replace certain functions
-l list all test case names/descriptions
-n no valgrind
+ --no-debuginfod disable the valgrind debuginfod functionality
-o variable=value set internal variable to the specified value
-P proxy use the specified proxy
-p print log file contents when a test fails
@@ -5833,14 +2412,17 @@
shift @ARGV;
}
+delete $ENV{'DEBUGINFOD_URLS'} if($ENV{'DEBUGINFOD_URLS'} && $no_debuginfod);
+
if(!$randseed) {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
# seed of the month. December 2019 becomes 201912
$randseed = ($year+1900)*100 + $mon+1;
- open(C, "$CURL --version 2>/dev/null|");
- my @c = <C>;
- close(C);
+ open(my $curlvh, "-|", shell_quote($CURL) . " --version 2>/dev/null") ||
+ die "could not get curl version!";
+ my @c = <$curlvh>;
+ close($curlvh) || die "could not get curl version!";
# use the first line of output and get the md5 out of it
my $str = md5($c[0]);
$randseed += unpack('S', $str); # unsigned 16 bit value
@@ -5864,27 +2446,31 @@
# since valgrind 2.1.x, '--tool' option is mandatory
# use it, if it is supported by the version installed on the system
+ # (this happened in 2003, so we could probably don't need to care about
+ # that old version any longer and just delete this check)
runclient("valgrind --help 2>&1 | grep -- --tool > /dev/null 2>&1");
- if (($? >> 8)==0) {
- $valgrind_tool="--tool=memcheck";
+ if (($? >> 8)) {
+ $valgrind_tool="";
}
- open(C, "<$CURL");
- my $l = <C>;
+ open(my $curlh, "<", "$CURL");
+ my $l = <$curlh>;
if($l =~ /^\#\!/) {
# A shell script. This is typically when built with libtool,
$valgrind="../libtool --mode=execute $valgrind";
}
- close(C);
+ close($curlh);
# valgrind 3 renamed the --logfile option to --log-file!!!
+ # (this happened in 2005, so we could probably don't need to care about
+ # that old version any longer and just delete this check)
my $ver=join(' ', runclientoutput("valgrind --version"));
# cut off all but digits and dots
$ver =~ s/[^0-9.]//g;
if($ver =~ /^(\d+)/) {
$ver = $1;
- if($ver >= 3) {
- $valgrind_logfile="--log-file";
+ if($ver < 3) {
+ $valgrind_logfile="--logfile";
}
}
}
@@ -5892,10 +2478,10 @@
if ($gdbthis) {
# open the executable curl and read the first 4 bytes of it
- open(CHECK, "<$CURL");
+ open(my $check, "<", "$CURL");
my $c;
- sysread CHECK, $c, 4;
- close(CHECK);
+ sysread $check, $c, 4;
+ close($check);
if($c eq "#! /") {
# A shell script. This is typically when built with libtool,
$libtool = 1;
@@ -5903,33 +2489,47 @@
}
}
-$HTTPUNIXPATH = "http$$.sock"; # HTTP server Unix domain socket path
-$SOCKSUNIXPATH = $pwd."/socks$$.sock"; # HTTP server Unix domain socket path, absolute path
-
#######################################################################
# clear and create logging directory:
#
+# TODO: figure how to get around this. This dir is needed for checksystemfeatures()
+# Maybe create & use & delete a temporary directory in that function
cleardir($LOGDIR);
mkdir($LOGDIR, 0777);
+mkdir("$LOGDIR/$LOCKDIR", 0777);
#######################################################################
# initialize some variables
#
get_disttests();
-init_serverpidfile_hash();
+if(!$jobs) {
+ # Disable buffered logging with only one test job
+ setlogfunc(\&logmsg);
+}
#######################################################################
# Output curl version and host info being tested
#
if(!$listonly) {
- checksystem();
+ checksystemfeatures();
}
-# globally disabled tests
-disabledtests("$TESTDIR/DISABLED");
+#######################################################################
+# initialize configuration needed to set up servers
+# TODO: rearrange things so this can be called only in runner_init()
+#
+initserverconfig();
+
+if(!$listonly) {
+ # these can only be displayed after initserverconfig() has been called
+ displayserverfeatures();
+
+ # globally disabled tests
+ disabledtests("$TESTDIR/DISABLED");
+}
#######################################################################
# Fetch all disabled tests, if there are any
@@ -5939,15 +2539,15 @@
my ($file) = @_;
my @input;
- if(open(D, "<$file")) {
- while(<D>) {
+ if(open(my $disabledh, "<", "$file")) {
+ while(<$disabledh>) {
if(/^ *\#/) {
# allow comments
next;
}
push @input, $_;
}
- close(D);
+ close($disabledh);
# preprocess the input to make conditionally disabled tests depending
# on variables
@@ -5992,7 +2592,6 @@
if($disabled{$n}) {
# skip disabled test cases
my $why = "configured as DISABLED";
- $skipped++;
$skipped{$why}++;
$teststat[$n]=$why; # store reason for this test case
next;
@@ -6002,11 +2601,11 @@
}
else {
my $verified="";
- map {
+ for(split(" ", $TESTCASES)) {
if (-e "$TESTDIR/test$_") {
$verified.="$_ ";
}
- } split(" ", $TESTCASES);
+ }
if($verified eq "") {
print "No existing test cases were specified\n";
exit;
@@ -6042,16 +2641,16 @@
# and excessively long files are elided
sub displaylogcontent {
my ($file)=@_;
- if(open(SINGLE, "<$file")) {
+ if(open(my $single, "<", "$file")) {
my $linecount = 0;
my $truncate;
my @tail;
- while(my $string = <SINGLE>) {
+ while(my $string = <$single>) {
$string =~ s/\r\n/\n/g;
$string =~ s/[\r\f\032]/\n/g;
$string .= "\n" unless ($string =~ /\n$/);
$string =~ tr/\n//;
- for my $line (split("\n", $string)) {
+ for my $line (split(m/\n/, $string)) {
$line =~ s/\s*\!$//;
if ($truncate) {
push @tail, " $line\n";
@@ -6062,6 +2661,7 @@
$truncate = $linecount > 1000;
}
}
+ close($single);
if(@tail) {
my $tailshow = 200;
my $tailskip = 0;
@@ -6074,18 +2674,18 @@
logmsg "$tail[$_]";
}
}
- close(SINGLE);
}
}
sub displaylogs {
- my ($testnum)=@_;
- opendir(DIR, "$LOGDIR") ||
+ my ($runnerid, $testnum)=@_;
+ my $logdir = getrunnerlogdir($runnerid);
+ opendir(DIR, "$logdir") ||
die "can't open dir: $!";
my @logs = readdir(DIR);
closedir(DIR);
- logmsg "== Contents of files in the $LOGDIR/ dir after test $testnum\n";
+ logmsg "== Contents of files in the $logdir/ dir after test $testnum\n";
foreach my $log (sort @logs) {
if($log =~ /\.(\.|)$/) {
next; # skip "." and ".."
@@ -6096,7 +2696,7 @@
if(($log eq "memdump") || ($log eq "core")) {
next; # skip "memdump" and "core"
}
- if((-d "$LOGDIR/$log") || (! -s "$LOGDIR/$log")) {
+ if((-d "$logdir/$log") || (! -s "$logdir/$log")) {
next; # skip directory and empty files
}
if(($log =~ /^stdout\d+/) && ($log !~ /^stdout$testnum/)) {
@@ -6123,34 +2723,24 @@
if(($log =~ /^trace\d+/) && ($log !~ /^trace$testnum/)) {
next; # skip traceNnn of other tests
}
- if(($log =~ /^valgrind\d+/) && ($log !~ /^valgrind$testnum(\..*|)$/)) {
+ if(($log =~ /^valgrind\d+/) && ($log !~ /^valgrind$testnum(?:\..*)?$/)) {
next; # skip valgrindNnn of other tests
}
if(($log =~ /^test$testnum$/)) {
next; # skip test$testnum since it can be very big
}
logmsg "=== Start of file $log\n";
- displaylogcontent("$LOGDIR/$log");
+ displaylogcontent("$logdir/$log");
logmsg "=== End of file $log\n";
}
}
#######################################################################
-# Setup Azure Pipelines Test Run (if running in Azure DevOps)
-#
-
-if(azure_check_environment()) {
- $AZURE_RUN_ID = azure_create_test_run($VCURL);
- logmsg "Azure Run ID: $AZURE_RUN_ID\n" if ($verbose);
-}
-
-#######################################################################
-# The main test-loop
+# Scan tests to find suitable candidates
#
my $failed;
my $failedign;
-my $testnum;
my $ok=0;
my $ign=0;
my $total=0;
@@ -6160,71 +2750,195 @@
$start = time();
-foreach $testnum (@at) {
-
+# scan all tests to find ones we should try to run
+my @runtests;
+foreach my $testnum (@at) {
$lasttest = $testnum if($testnum > $lasttest);
- $count++;
-
- my $error = singletest($run_event_based, $testnum, $count, scalar(@at));
-
- # update test result in CI services
- if(azure_check_environment() && $AZURE_RUN_ID && $AZURE_RESULT_ID) {
- $AZURE_RESULT_ID = azure_update_test_result($VCURL, $AZURE_RUN_ID, $AZURE_RESULT_ID, $testnum, $error,
- $timeprepini{$testnum}, $timevrfyend{$testnum});
- }
- elsif(appveyor_check_environment()) {
- appveyor_update_test_result($VCURL, $testnum, $error, $timeprepini{$testnum}, $timevrfyend{$testnum});
- }
-
- if($error < 0) {
- # not a test we can run
+ my ($why, $errorreturncode) = singletest_shouldrun($testnum);
+ if($why || $listonly) {
+ # Display test name now--test will be completely skipped later
+ my $error = singletest_count($testnum, $why);
next;
}
+ $ignoretestcodes{$testnum} = $errorreturncode;
+ push(@runtests, $testnum);
+}
+my $totaltests = scalar(@runtests);
- $total++; # number of tests we've run
+if($listonly) {
+ exit(0);
+}
- if($error>0) {
- if($error==2) {
- # ignored test failures
- $failedign .= "$testnum ";
+#######################################################################
+# Setup CI Test Run
+citest_starttestrun();
+
+#######################################################################
+# Start test runners
+#
+my $numrunners = $jobs < scalar(@runtests) ? $jobs : scalar(@runtests);
+createrunners($numrunners);
+
+#######################################################################
+# The main test-loop
+#
+# Every iteration through the loop consists of these steps:
+# - if the global abort flag is set, exit the loop; we are done
+# - if a runner is idle, start a new test on it
+# - if all runners are idle, exit the loop; we are done
+# - if a runner has a response for us, process the response
+
+# run through each candidate test and execute it
+while () {
+ # check the abort flag
+ if($globalabort) {
+ logmsg singletest_dumplogs();
+ logmsg "Aborting tests\n";
+ logmsg "Waiting for " . scalar((keys %runnersrunning)) . " outstanding test(s) to finish...\n";
+ # Wait for the last requests to complete and throw them away so
+ # that IPC calls & responses stay in sync
+ # TODO: send a signal to the runners to interrupt a long test
+ foreach my $rid (keys %runnersrunning) {
+ runnerar($rid);
+ delete $runnersrunning{$rid};
+ logmsg ".";
+ $| = 1;
}
- else {
- $failed.= "$testnum ";
- }
- if($postmortem) {
- # display all files in log/ in a nice way
- displaylogs($testnum);
- }
- if($error==2) {
- $ign++; # ignored test result counter
- }
- elsif(!$anyway) {
- # a test failed, abort
- logmsg "\n - abort tests\n";
- last;
- }
- }
- elsif(!$error) {
- $ok++; # successful test counter
+ logmsg "\n";
+ last;
}
- # loop for next test
+ # Start a new test if possible
+ if(scalar(@runnersidle) && scalar(@runtests)) {
+ # A runner is ready to run a test, and tests are still available to run
+ # so start a new test.
+ $count++;
+ my $testnum = shift(@runtests);
+
+ # pick a runner for this new test
+ my $runnerid = pickrunner($testnum);
+ $countforrunner{$runnerid} = $count;
+
+ # Start the test
+ my ($error, $again) = singletest($runnerid, $testnum, $countforrunner{$runnerid}, $totaltests);
+ if($again) {
+ # this runner is busy running a test
+ $runnersrunning{$runnerid} = $testnum;
+ } else {
+ runnerready($runnerid);
+ if($error >= 0) {
+ # We make this simplifying assumption to avoid having to handle
+ # $error properly here, but we must handle the case of runner
+ # death without abending here.
+ die "Internal error: test must not complete on first call";
+ }
+ }
+ }
+
+ # See if we've completed all the tests
+ if(!scalar(%runnersrunning)) {
+ # No runners are running; we must be done
+ scalar(@runtests) && die 'Internal error: still have tests to run';
+ last;
+ }
+
+ # See if a test runner needs attention
+ # If we could be running more tests, don't wait so we can schedule a new
+ # one immediately. If all runners are busy, wait a fraction of a second
+ # for one to finish so we can still loop around to check the abort flag.
+ my $runnerwait = scalar(@runnersidle) && scalar(@runtests) ? 0 : 0.5;
+ my ($ridready, $riderror) = runnerar_ready($runnerwait);
+ if($ridready && ! defined $runnersrunning{$ridready}) {
+ # On Linux, a closed pipe still shows up as ready instead of error.
+ # Detect this here by seeing if we are expecting it to be ready and
+ # treat it as an error if not.
+ logmsg "ERROR: Runner $ridready is unexpectedly ready; is probably actually dead\n";
+ $riderror = $ridready;
+ undef $ridready;
+ }
+ if($ridready) {
+ # This runner is ready to be serviced
+ my $testnum = $runnersrunning{$ridready};
+ defined $testnum || die "Internal error: test for runner $ridready unknown";
+ delete $runnersrunning{$ridready};
+ my ($error, $again) = singletest($ridready, $testnum, $countforrunner{$ridready}, $totaltests);
+ if($again) {
+ # this runner is busy running a test
+ $runnersrunning{$ridready} = $testnum;
+ } else {
+ # Test is complete
+ runnerready($ridready);
+
+ if($error < 0) {
+ # not a test we can run
+ next;
+ }
+
+ $total++; # number of tests we've run
+
+ if($error>0) {
+ if($error==2) {
+ # ignored test failures
+ $failedign .= "$testnum ";
+ }
+ else {
+ $failed.= "$testnum ";
+ }
+ if($postmortem) {
+ # display all files in $LOGDIR/ in a nice way
+ displaylogs($ridready, $testnum);
+ }
+ if($error==2) {
+ $ign++; # ignored test result counter
+ }
+ elsif(!$anyway) {
+ # a test failed, abort
+ logmsg "\n - abort tests\n";
+ undef @runtests; # empty out the remaining tests
+ }
+ }
+ elsif(!$error) {
+ $ok++; # successful test counter
+ }
+ }
+ }
+ if($riderror) {
+ logmsg "ERROR: runner $riderror is dead! aborting test run\n";
+ delete $runnersrunning{$riderror} if(defined $runnersrunning{$riderror});
+ $globalabort = 1;
+ }
}
my $sofar = time() - $start;
#######################################################################
-# Finish Azure Pipelines Test Run (if running in Azure DevOps)
-#
-
-if(azure_check_environment() && $AZURE_RUN_ID) {
- $AZURE_RUN_ID = azure_update_test_run($VCURL, $AZURE_RUN_ID);
-}
+# Finish CI Test Run
+citest_finishtestrun();
# Tests done, stop the servers
-my $unexpected = stopservers($verbose);
+foreach my $runnerid (values %runnerids) {
+ runnerac_stopservers($runnerid);
+}
-my $all = $total + $skipped;
+# Wait for servers to stop
+my $unexpected;
+foreach my $runnerid (values %runnerids) {
+ my ($rid, $unexpect, $logs) = runnerar($runnerid);
+ $unexpected ||= $unexpect;
+ logmsg $logs;
+}
+
+# Kill the runners
+# There is a race condition here since we don't know exactly when the runners
+# have each finished shutting themselves down, but we're about to exit so it
+# doesn't make much difference.
+foreach my $runnerid (values %runnerids) {
+ runnerac_shutdown($runnerid);
+ sleep 0; # give runner a context switch so it can shut itself down
+}
+
+my $numskipped = %skipped ? sum values %skipped : 0;
+my $all = $total + $numskipped;
runtimestats($lasttest);
@@ -6233,12 +2947,12 @@
sprintf("%.0f", $sofar) ." seconds.\n";
}
-if($skipped && !$short) {
+if(%skipped && !$short) {
my $s=0;
# Temporary hash to print the restraints sorted by the number
# of their occurrences
my %restraints;
- logmsg "TESTINFO: $skipped tests were skipped due to these restraints:\n";
+ logmsg "TESTINFO: $numskipped tests were skipped due to these restraints:\n";
for(keys %skipped) {
my $r = $_;
@@ -6278,7 +2992,7 @@
logmsg sprintf("TESTDONE: $ok tests out of $total reported OK: %d%%\n",
$ok/$total*100);
- if($ok != $total) {
+ if($failed && ($ok != $total)) {
logmsg "\nTESTFAIL: These test cases failed: $failed\n\n";
}
}
diff --git a/tests/secureserver.pl b/tests/secureserver.pl
index 3d2ab15..b84dd45 100755
--- a/tests/secureserver.pl
+++ b/tests/secureserver.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -27,15 +27,17 @@
# harness. Actually just a layer that runs stunnel properly using the
# non-secure test harness servers.
+use strict;
+use warnings;
+
BEGIN {
push(@INC, $ENV{'srcdir'}) if(defined $ENV{'srcdir'});
push(@INC, ".");
}
-use strict;
-use warnings;
use Cwd;
use Cwd 'abs_path';
+use File::Basename;
use serverhelp qw(
server_pidfilename
@@ -77,6 +79,7 @@
my $path = getcwd();
my $srcdir = $path;
my $logdir = $path .'/log';
+my $piddir;
#***************************************************************************
# Signal handler to remove our stunnel 4.00 and newer configuration file.
@@ -167,6 +170,12 @@
shift @ARGV;
}
}
+ elsif($ARGV[0] eq '--logdir') {
+ if($ARGV[1]) {
+ $logdir = "$path/". $ARGV[1];
+ shift @ARGV;
+ }
+ }
else {
print STDERR "\nWarning: secureserver.pl unknown parameter: $ARGV[0]\n";
}
@@ -176,14 +185,20 @@
#***************************************************************************
# Initialize command line option dependent variables
#
-if(!$pidfile) {
- $pidfile = "$path/". server_pidfilename($proto, $ipvnum, $idnum);
+if($pidfile) {
+ # Use our pidfile directory to store the conf files
+ $piddir = dirname($pidfile);
+}
+else {
+ # Use the current directory to store the conf files
+ $piddir = $path;
+ $pidfile = server_pidfilename($piddir, $proto, $ipvnum, $idnum);
}
if(!$logfile) {
$logfile = server_logfilename($logdir, $proto, $ipvnum, $idnum);
}
-$conffile = "$path/${proto}_stunnel.conf";
+$conffile = "$piddir/${proto}_stunnel.conf";
$capath = abs_path($path);
$certfile = "$srcdir/". ($stuncert?"certs/$stuncert":"stunnel.pem");
@@ -277,26 +292,26 @@
$SIG{INT} = \&exit_signal_handler;
$SIG{TERM} = \&exit_signal_handler;
# stunnel configuration file
- if(open(STUNCONF, ">$conffile")) {
- print STUNCONF "CApath = $capath\n";
- print STUNCONF "cert = $certfile\n";
- print STUNCONF "debug = $loglevel\n";
- print STUNCONF "socket = $socketopt\n";
+ if(open(my $stunconf, ">", "$conffile")) {
+ print $stunconf "CApath = $capath\n";
+ print $stunconf "cert = $certfile\n";
+ print $stunconf "debug = $loglevel\n";
+ print $stunconf "socket = $socketopt\n";
if($fips_support) {
# disable fips in case OpenSSL doesn't support it
- print STUNCONF "fips = no\n";
+ print $stunconf "fips = no\n";
}
if(!$tstunnel_windows) {
# do not use Linux-specific options on Windows
- print STUNCONF "output = $logfile\n";
- print STUNCONF "pid = $pidfile\n";
- print STUNCONF "foreground = yes\n";
+ print $stunconf "output = $logfile\n";
+ print $stunconf "pid = $pidfile\n";
+ print $stunconf "foreground = yes\n";
}
- print STUNCONF "\n";
- print STUNCONF "[curltest]\n";
- print STUNCONF "accept = $accept_port\n";
- print STUNCONF "connect = $target_port\n";
- if(!close(STUNCONF)) {
+ print $stunconf "\n";
+ print $stunconf "[curltest]\n";
+ print $stunconf "accept = $accept_port\n";
+ print $stunconf "connect = $target_port\n";
+ if(!close($stunconf)) {
print "$ssltext Error closing file $conffile\n";
exit 1;
}
@@ -338,9 +353,9 @@
#
if($tstunnel_windows) {
# Fake pidfile for tstunnel on Windows.
- if(open(OUT, ">$pidfile")) {
- print OUT $$ . "\n";
- close(OUT);
+ if(open(my $out, ">", "$pidfile")) {
+ print $out $$ . "\n";
+ close($out);
}
# Flush output.
diff --git a/tests/server/.gitignore b/tests/server/.gitignore
index 77c5e93..fee1925 100644
--- a/tests/server/.gitignore
+++ b/tests/server/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/tests/server/CMakeLists.txt b/tests/server/CMakeLists.txt
index 1280423..d92f60f 100644
--- a/tests/server/CMakeLists.txt
+++ b/tests/server/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2009 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -36,6 +36,7 @@
${CURL_SOURCE_DIR}/lib # To be able to reach "curl_setup_once.h"
${CURL_BINARY_DIR}/lib # To be able to reach "curl_config.h"
${CURL_BINARY_DIR}/include # To be able to reach "curl/curl.h"
+ ${CURL_SOURCE_DIR}/src # To be able to reach "tool_xattr.h"
)
if(USE_ARES)
include_directories(${CARES_INCLUDE_DIR})
diff --git a/tests/server/Makefile.am b/tests/server/Makefile.am
index 964fab2..b089422 100644
--- a/tests/server/Makefile.am
+++ b/tests/server/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -36,6 +36,9 @@
-I$(top_builddir)/lib \
-I$(top_srcdir)/lib
+disabled_CPPFLAGS = $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/src
+
# Prevent LIBS from being used for all link targets
LIBS = $(BLANK_AT_MAKETIME)
diff --git a/tests/server/Makefile.inc b/tests/server/Makefile.inc
index 2953704..efd2fa0 100644
--- a/tests/server/Makefile.inc
+++ b/tests/server/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2009 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -31,9 +31,9 @@
../../lib/strtoofft.c \
../../lib/warnless.c \
../../lib/timediff.c \
- ../../lib/curl_ctype.c \
../../lib/dynbuf.c \
../../lib/strdup.c \
+ ../../lib/strcase.c \
../../lib/curl_multibyte.c
CURLX_HDRS = \
diff --git a/tests/server/base64.pl b/tests/server/base64.pl
index b025255..885e6f4 100755
--- a/tests/server/base64.pl
+++ b/tests/server/base64.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2004 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/tests/server/disabled.c b/tests/server/disabled.c
index b9bc9b7..7ce2903 100644
--- a/tests/server/disabled.c
+++ b/tests/server/disabled.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,6 +33,7 @@
#include "curl_setup.h"
#include "multihandle.h" /* for ENABLE_WAKEUP */
+#include "tool_xattr.h" /* for USE_XATTR */
#include <stdio.h>
static const char *disabled[]={
@@ -75,6 +76,9 @@
#ifdef CURL_DISABLE_HEADERS_API
"headers-api",
#endif
+#ifndef USE_XATTR
+ "xattr",
+#endif
NULL
};
diff --git a/tests/server/fake_ntlm.c b/tests/server/fake_ntlm.c
index 976096a..fe59578 100644
--- a/tests/server/fake_ntlm.c
+++ b/tests/server/fake_ntlm.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010, Mandy Wu, <mandy.wu@intel.com>
- * Copyright (C) 2011 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Mandy Wu, <mandy.wu@intel.com>
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -39,7 +39,8 @@
/* include memdebug.h last */
#include "memdebug.h"
-#define LOGFILE "log/fake_ntlm%ld.log"
+#define LOGFILE "%s/fake_ntlm%ld.log"
+const char *logdir = "log";
const char *serverlogfile;
@@ -159,6 +160,11 @@
}
}
+ env = getenv("CURL_NTLM_LOGDIR");
+ if(env) {
+ logdir = env;
+ }
+
env = getenv("CURL_NTLM_AUTH_TESTNUM");
if(env) {
char *endptr;
@@ -175,7 +181,7 @@
}
/* logmsg cannot be used until this file name is set */
- msnprintf(logfilename, sizeof(logfilename), LOGFILE, testnum);
+ msnprintf(logfilename, sizeof(logfilename), LOGFILE, logdir, testnum);
serverlogfile = logfilename;
logmsg("fake_ntlm (user: %s) (proto: %s) (domain: %s) (cached creds: %s)",
@@ -187,7 +193,7 @@
path = env;
}
- stream = test2fopen(testnum);
+ stream = test2fopen(testnum, logdir);
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -204,7 +210,7 @@
}
}
- stream = test2fopen(testnum);
+ stream = test2fopen(testnum, logdir);
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -222,7 +228,7 @@
while(fgets(buf, sizeof(buf), stdin)) {
if(strcmp(buf, type1_input) == 0) {
- stream = test2fopen(testnum);
+ stream = test2fopen(testnum, logdir);
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -243,7 +249,7 @@
fflush(stdout);
}
else if(strncmp(buf, type3_input, strlen(type3_input)) == 0) {
- stream = test2fopen(testnum);
+ stream = test2fopen(testnum, logdir);
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
diff --git a/tests/server/getpart.c b/tests/server/getpart.c
index fb54bfe..7d3bff7 100644
--- a/tests/server/getpart.c
+++ b/tests/server/getpart.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -149,7 +149,7 @@
char *newptr;
if(!*buffer) {
- *buffer = malloc(128);
+ *buffer = calloc(128, 1);
if(!*buffer)
return GPE_OUT_OF_MEMORY;
*bufsize = 128;
@@ -171,6 +171,7 @@
newptr = realloc(*buffer, *bufsize * 2);
if(!newptr)
return GPE_OUT_OF_MEMORY;
+ memset(&newptr[*bufsize], 0, *bufsize);
*buffer = newptr;
*bufsize *= 2;
}
diff --git a/tests/server/getpart.h b/tests/server/getpart.h
index bb71c2d..e9323d4 100644
--- a/tests/server/getpart.h
+++ b/tests/server/getpart.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/server/mqttd.c b/tests/server/mqttd.c
index d653917..a9894b6 100644
--- a/tests/server/mqttd.c
+++ b/tests/server/mqttd.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -62,7 +62,6 @@
#include "curlx.h" /* from the private lib dir */
#include "getpart.h"
#include "inet_pton.h"
-#include "util.h"
#include "server_sockaddr.h"
#include "warnless.h"
@@ -113,13 +112,15 @@
int testnum;
};
-#define REQUEST_DUMP "log/server.input"
+#define REQUEST_DUMP "server.input"
#define CONFIG_VERSION 5
static struct configurable config;
const char *serverlogfile = DEFAULT_LOGFILE;
static const char *configfile = DEFAULT_CONFIG;
+const char *logdir = "log";
+char loglockfile[256];
#ifdef ENABLE_IPV6
static bool use_ipv6 = FALSE;
@@ -505,14 +506,16 @@
char client_id[MAX_CLIENT_ID_LENGTH];
long testno;
FILE *stream = NULL;
-
+ FILE *dump;
+ char dumpfile[256];
static const char protocol[7] = {
0x00, 0x04, /* protocol length */
'M','Q','T','T', /* protocol name */
0x04 /* protocol level */
};
- FILE *dump = fopen(REQUEST_DUMP, "ab");
+ msnprintf(dumpfile, sizeof(dumpfile), "%s/%s", logdir, REQUEST_DUMP);
+ dump = fopen(dumpfile, "ab");
if(!dump)
goto end;
@@ -643,7 +646,7 @@
/* there's a QoS byte (two bits) after the topic */
logmsg("SUBSCRIBE to '%s' [%d]", topic, packet_id);
- stream = test2fopen(testno);
+ stream = test2fopen(testno, logdir);
error = getpart(&data, &datalen, "reply", "data", stream);
if(!error) {
if(!config.publish_before_suback) {
@@ -699,7 +702,7 @@
}
} while(1);
- end:
+end:
if(buffer)
free(buffer);
if(dump)
@@ -768,14 +771,14 @@
if(CURL_SOCKET_BAD == newfd) {
error = SOCKERRNO;
logmsg("accept(%d, NULL, NULL) failed with error: (%d) %s",
- sockfd, error, strerror(error));
+ sockfd, error, sstrerror(error));
}
else {
logmsg("====> Client connect, fd %d. Read config from %s",
newfd, configfile);
- set_advisor_read_lock(SERVERLOGS_LOCK);
+ set_advisor_read_lock(loglockfile);
(void)mqttit(newfd); /* until done */
- clear_advisor_read_lock(SERVERLOGS_LOCK);
+ clear_advisor_read_lock(loglockfile);
logmsg("====> Client disconnect");
sclose(newfd);
@@ -807,7 +810,7 @@
if(rc) {
error = SOCKERRNO;
logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
if(maxretr) {
rc = wait_ms(delay);
if(rc) {
@@ -857,7 +860,7 @@
if(rc) {
error = SOCKERRNO;
logmsg("Error binding socket on port %hu: (%d) %s",
- *listenport, error, strerror(error));
+ *listenport, error, sstrerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
}
@@ -879,7 +882,7 @@
if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
error = SOCKERRNO;
logmsg("getsockname() failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
}
@@ -911,7 +914,7 @@
if(0 != rc) {
error = SOCKERRNO;
logmsg("listen(%d, 5) failed with error: (%d) %s",
- sock, error, strerror(error));
+ sock, error, sstrerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
}
@@ -963,6 +966,11 @@
if(argc>arg)
serverlogfile = argv[arg++];
}
+ else if(!strcmp("--logdir", argv[arg])) {
+ arg++;
+ if(argc>arg)
+ logdir = argv[arg++];
+ }
else if(!strcmp("--ipv6", argv[arg])) {
#ifdef ENABLE_IPV6
ipv_inuse = "IPv6";
@@ -998,6 +1006,7 @@
" --config [file]\n"
" --version\n"
" --logfile [file]\n"
+ " --logdir [directory]\n"
" --pidfile [file]\n"
" --portfile [file]\n"
" --ipv4\n"
@@ -1007,6 +1016,9 @@
}
}
+ msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/mqtt-%s.lock",
+ logdir, SERVERLOGS_LOCKDIR, ipv_inuse);
+
#ifdef WIN32
win32_init();
atexit(win32_cleanup);
@@ -1029,8 +1041,7 @@
if(CURL_SOCKET_BAD == sock) {
error = SOCKERRNO;
- logmsg("Error creating socket: (%d) %s",
- error, strerror(error));
+ logmsg("Error creating socket: (%d) %s", error, sstrerror(error));
goto mqttd_cleanup;
}
diff --git a/tests/server/resolve.c b/tests/server/resolve.c
index 492ffde..37432e4 100644
--- a/tests/server/resolve.c
+++ b/tests/server/resolve.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/server/rtspd.c b/tests/server/rtspd.c
index 32ab0af..1e962c1 100644
--- a/tests/server/rtspd.c
+++ b/tests/server/rtspd.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -133,11 +133,13 @@
#endif
const char *serverlogfile = DEFAULT_LOGFILE;
+const char *logdir = "log";
+char loglockfile[256];
#define RTSPDVERSION "curl test suite RTSP server/0.1"
-#define REQUEST_DUMP "log/server.input"
-#define RESPONSE_DUMP "log/server.response"
+#define REQUEST_DUMP "server.input"
+#define RESPONSE_DUMP "server.response"
/* very-big-path support */
#define MAXDOCNAMELEN 140000
@@ -201,7 +203,7 @@
/* Default size to send away fake RTP data */
#define RTP_DATA_SIZE 12
-static const char *RTP_DATA = "$_1234\n\0asdf";
+static const char *RTP_DATA = "$_1234\n\0Rsdf";
static int ProcessRequest(struct httprequest *req)
{
@@ -288,7 +290,7 @@
req->testno, req->partno);
logmsg("%s", logbuf);
- stream = test2fopen(req->testno);
+ stream = test2fopen(req->testno, logdir);
if(!stream) {
int error = errno;
@@ -304,6 +306,7 @@
int rtp_channel = 0;
int rtp_size = 0;
+ int rtp_size_err = 0;
int rtp_partno = -1;
char *rtp_scratch = NULL;
@@ -320,6 +323,7 @@
if(cmdsize) {
logmsg("Found a reply-servercmd section!");
do {
+ rtp_size_err = 0;
if(!strncmp(CMD_AUTH_REQUIRED, ptr, strlen(CMD_AUTH_REQUIRED))) {
logmsg("instructed to require authorization header");
req->auth_req = TRUE;
@@ -345,13 +349,15 @@
logmsg("instructed to skip this number of bytes %d", num);
req->skip = num;
}
- else if(3 == sscanf(ptr, "rtp: part %d channel %d size %d",
- &rtp_partno, &rtp_channel, &rtp_size)) {
+ else if(3 <= sscanf(ptr,
+ "rtp: part %d channel %d size %d size_err %d",
+ &rtp_partno, &rtp_channel, &rtp_size,
+ &rtp_size_err)) {
if(rtp_partno == req->partno) {
int i = 0;
- logmsg("RTP: part %d channel %d size %d",
- rtp_partno, rtp_channel, rtp_size);
+ logmsg("RTP: part %d channel %d size %d size_err %d",
+ rtp_partno, rtp_channel, rtp_size, rtp_size_err);
/* Make our scratch buffer enough to fit all the
* desired data and one for padding */
@@ -364,7 +370,7 @@
SET_RTP_PKT_CHN(rtp_scratch, rtp_channel);
/* Length follows and is a two byte short in network order */
- SET_RTP_PKT_LEN(rtp_scratch, rtp_size);
+ SET_RTP_PKT_LEN(rtp_scratch, rtp_size + rtp_size_err);
/* Fill it with junk data */
for(i = 0; i < rtp_size; i += RTP_DATA_SIZE) {
@@ -450,10 +456,10 @@
/* **** Persistence ****
*
- * If the request is a HTTP/1.0 one, we close the connection unconditionally
+ * If the request is an HTTP/1.0 one, we close the connection unconditionally
* when we're done.
*
- * If the request is a HTTP/1.1 one, we MUST check for a "Connection:"
+ * If the request is an HTTP/1.1 one, we MUST check for a "Connection:"
* header that might say "close". If it does, we close a connection when
* this request is processed. Otherwise, we keep the connection alive for X
* seconds.
@@ -600,6 +606,9 @@
size_t written;
size_t writeleft;
FILE *dump;
+ char dumpfile[256];
+
+ msnprintf(dumpfile, sizeof(dumpfile), "%s/%s", logdir, REQUEST_DUMP);
if(!reqbuf)
return;
@@ -607,12 +616,12 @@
return;
do {
- dump = fopen(REQUEST_DUMP, "ab");
+ dump = fopen(dumpfile, "ab");
} while(!dump && ((error = errno) == EINTR));
if(!dump) {
logmsg("Error opening file %s error: %d %s",
- REQUEST_DUMP, error, strerror(error));
- logmsg("Failed to write request input to " REQUEST_DUMP);
+ dumpfile, error, strerror(error));
+ logmsg("Failed to write request input to %s", dumpfile);
return;
}
@@ -627,12 +636,12 @@
} while((writeleft > 0) && ((error = errno) == EINTR));
if(writeleft == 0)
- logmsg("Wrote request (%zu bytes) input to " REQUEST_DUMP, totalsize);
+ logmsg("Wrote request (%zu bytes) input to %s", totalsize, dumpfile);
else if(writeleft > 0) {
logmsg("Error writing file %s error: %d %s",
- REQUEST_DUMP, error, strerror(error));
+ dumpfile, error, strerror(error));
logmsg("Wrote only (%zu bytes) of (%zu bytes) request input to %s",
- totalsize-writeleft, totalsize, REQUEST_DUMP);
+ totalsize-writeleft, totalsize, dumpfile);
}
storerequest_cleanup:
@@ -642,7 +651,7 @@
} while(res && ((error = errno) == EINTR));
if(res)
logmsg("Error closing file %s error: %d %s",
- REQUEST_DUMP, error, strerror(error));
+ dumpfile, error, strerror(error));
}
/* return 0 on success, non-zero on failure */
@@ -708,7 +717,7 @@
}
else if(got < 0) {
error = SOCKERRNO;
- logmsg("recv() returned error: (%d) %s", error, strerror(error));
+ logmsg("recv() returned error: (%d) %s", error, sstrerror(error));
fail = 1;
}
if(fail) {
@@ -771,8 +780,11 @@
size_t responsesize;
int error = 0;
int res;
-
static char weare[256];
+ char responsedump[256];
+
+ msnprintf(responsedump, sizeof(responsedump), "%s/%s",
+ logdir, RESPONSE_DUMP);
logmsg("Send response number %ld part %ld", req->testno, req->partno);
@@ -846,7 +858,7 @@
count = strlen(buffer);
}
else {
- FILE *stream = test2fopen(req->testno);
+ FILE *stream = test2fopen(req->testno, logdir);
char partbuf[80]="data";
if(0 != req->partno)
msnprintf(partbuf, sizeof(partbuf), "data%ld", req->partno);
@@ -872,7 +884,7 @@
}
/* re-open the same file again */
- stream = test2fopen(req->testno);
+ stream = test2fopen(req->testno, logdir);
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -912,12 +924,12 @@
else
prevbounce = FALSE;
- dump = fopen(RESPONSE_DUMP, "ab");
+ dump = fopen(responsedump, "ab");
if(!dump) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
- logmsg("Error opening file: %s", RESPONSE_DUMP);
- logmsg("couldn't create logfile: " RESPONSE_DUMP);
+ logmsg("Error opening file: %s", responsedump);
+ logmsg("couldn't create logfile: %s", responsedump);
free(ptr);
free(cmd);
return -1;
@@ -974,7 +986,7 @@
} while(res && ((error = errno) == EINTR));
if(res)
logmsg("Error closing file %s error: %d %s",
- RESPONSE_DUMP, error, strerror(error));
+ responsedump, error, strerror(error));
if(got_exit_signal) {
free(ptr);
@@ -991,8 +1003,8 @@
return -1;
}
- logmsg("Response sent (%zu bytes) and written to " RESPONSE_DUMP,
- responsesize);
+ logmsg("Response sent (%zu bytes) and written to %s",
+ responsesize, responsedump);
free(ptr);
if(cmdsize > 0) {
@@ -1087,6 +1099,11 @@
if(argc>arg)
serverlogfile = argv[arg++];
}
+ else if(!strcmp("--logdir", argv[arg])) {
+ arg++;
+ if(argc>arg)
+ logdir = argv[arg++];
+ }
else if(!strcmp("--ipv4", argv[arg])) {
#ifdef ENABLE_IPV6
ipv_inuse = "IPv4";
@@ -1121,6 +1138,7 @@
puts("Usage: rtspd [option]\n"
" --version\n"
" --logfile [file]\n"
+ " --logdir [directory]\n"
" --pidfile [file]\n"
" --portfile [file]\n"
" --ipv4\n"
@@ -1131,6 +1149,9 @@
}
}
+ msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/rtsp-%s.lock",
+ logdir, SERVERLOGS_LOCKDIR, ipv_inuse);
+
#ifdef WIN32
win32_init();
atexit(win32_cleanup);
@@ -1149,8 +1170,7 @@
if(CURL_SOCKET_BAD == sock) {
error = SOCKERRNO;
- logmsg("Error creating socket: (%d) %s",
- error, strerror(error));
+ logmsg("Error creating socket: (%d) %s", error, sstrerror(error));
goto server_cleanup;
}
@@ -1159,7 +1179,7 @@
(void *)&flag, sizeof(flag))) {
error = SOCKERRNO;
logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
goto server_cleanup;
}
@@ -1184,7 +1204,7 @@
if(0 != rc) {
error = SOCKERRNO;
logmsg("Error binding socket on port %hu: (%d) %s",
- port, error, strerror(error));
+ port, error, sstrerror(error));
goto server_cleanup;
}
@@ -1205,7 +1225,7 @@
if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
error = SOCKERRNO;
logmsg("getsockname() failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
sclose(sock);
goto server_cleanup;
}
@@ -1238,7 +1258,7 @@
if(0 != rc) {
error = SOCKERRNO;
logmsg("listen() failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
goto server_cleanup;
}
@@ -1265,7 +1285,7 @@
if(CURL_SOCKET_BAD == msgsock) {
error = SOCKERRNO;
logmsg("MAJOR ERROR: accept() failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
break;
}
@@ -1275,7 +1295,7 @@
** logs should not be read until this lock is removed by this server.
*/
- set_advisor_read_lock(SERVERLOGS_LOCK);
+ set_advisor_read_lock(loglockfile);
serverlogslocked = 1;
logmsg("====> Client connect");
@@ -1347,7 +1367,7 @@
if(serverlogslocked) {
serverlogslocked = 0;
- clear_advisor_read_lock(SERVERLOGS_LOCK);
+ clear_advisor_read_lock(loglockfile);
}
if(req.testno == DOCNUMBER_QUIT)
@@ -1372,7 +1392,7 @@
if(serverlogslocked) {
serverlogslocked = 0;
- clear_advisor_read_lock(SERVERLOGS_LOCK);
+ clear_advisor_read_lock(loglockfile);
}
restore_signal_handlers(false);
diff --git a/tests/server/server_setup.h b/tests/server/server_setup.h
index 8c642e5..8bdcc91 100644
--- a/tests/server/server_setup.h
+++ b/tests/server/server_setup.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/server/server_sockaddr.h b/tests/server/server_sockaddr.h
index 024cf70..c48c7c7 100644
--- a/tests/server/server_sockaddr.h
+++ b/tests/server/server_sockaddr.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/server/sockfilt.c b/tests/server/sockfilt.c
index bf6f701..d478b4f 100644
--- a/tests/server/sockfilt.c
+++ b/tests/server/sockfilt.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -404,13 +404,17 @@
struct select_ws_wait_data {
HANDLE handle; /* actual handle to wait for during select */
HANDLE signal; /* internal event to signal handle trigger */
- HANDLE abort; /* internal event to abort waiting thread */
- HANDLE mutex; /* mutex to prevent event race-condition */
+ HANDLE abort; /* internal event to abort waiting threads */
};
+#ifdef _WIN32_WCE
static DWORD WINAPI select_ws_wait_thread(LPVOID lpParameter)
+#else
+#include <process.h>
+static unsigned int WINAPI select_ws_wait_thread(void *lpParameter)
+#endif
{
struct select_ws_wait_data *data;
- HANDLE mutex, signal, handle, handles[2];
+ HANDLE signal, handle, handles[2];
INPUT_RECORD inputrecord;
LARGE_INTEGER size, pos;
DWORD type, length, ret;
@@ -422,7 +426,6 @@
handles[0] = data->abort;
handles[1] = handle;
signal = data->signal;
- mutex = data->mutex;
free(data);
}
else
@@ -442,41 +445,29 @@
*/
while(WaitForMultipleObjectsEx(1, handles, FALSE, 0, FALSE)
== WAIT_TIMEOUT) {
- ret = WaitForSingleObjectEx(mutex, 0, FALSE);
- if(ret == WAIT_OBJECT_0) {
- /* get total size of file */
- length = 0;
- size.QuadPart = 0;
- size.LowPart = GetFileSize(handle, &length);
- if((size.LowPart != INVALID_FILE_SIZE) ||
- (GetLastError() == NO_ERROR)) {
- size.HighPart = length;
- /* get the current position within the file */
- pos.QuadPart = 0;
- pos.LowPart = SetFilePointer(handle, 0, &pos.HighPart,
- FILE_CURRENT);
- if((pos.LowPart != INVALID_SET_FILE_POINTER) ||
- (GetLastError() == NO_ERROR)) {
- /* compare position with size, abort if not equal */
- if(size.QuadPart == pos.QuadPart) {
- /* sleep and continue waiting */
- SleepEx(0, FALSE);
- ReleaseMutex(mutex);
- continue;
- }
+ /* get total size of file */
+ length = 0;
+ size.QuadPart = 0;
+ size.LowPart = GetFileSize(handle, &length);
+ if((size.LowPart != INVALID_FILE_SIZE) ||
+ (GetLastError() == NO_ERROR)) {
+ size.HighPart = length;
+ /* get the current position within the file */
+ pos.QuadPart = 0;
+ pos.LowPart = SetFilePointer(handle, 0, &pos.HighPart, FILE_CURRENT);
+ if((pos.LowPart != INVALID_SET_FILE_POINTER) ||
+ (GetLastError() == NO_ERROR)) {
+ /* compare position with size, abort if not equal */
+ if(size.QuadPart == pos.QuadPart) {
+ /* sleep and continue waiting */
+ SleepEx(0, FALSE);
+ continue;
}
}
- /* there is some data available, stop waiting */
- logmsg("[select_ws_wait_thread] data available, DISK: %p", handle);
- SetEvent(signal);
- ReleaseMutex(mutex);
- break;
}
- else if(ret == WAIT_ABANDONED) {
- /* we are not allowed to process this event, because select_ws
- is post-processing the signalled events and we must exit. */
- break;
- }
+ /* there is some data available, stop waiting */
+ logmsg("[select_ws_wait_thread] data available, DISK: %p", handle);
+ SetEvent(signal);
}
break;
@@ -490,33 +481,22 @@
*/
while(WaitForMultipleObjectsEx(2, handles, FALSE, INFINITE, FALSE)
== WAIT_OBJECT_0 + 1) {
- ret = WaitForSingleObjectEx(mutex, 0, FALSE);
- if(ret == WAIT_OBJECT_0) {
- /* check if this is an actual console handle */
- if(GetConsoleMode(handle, &ret)) {
- /* retrieve an event from the console buffer */
- length = 0;
- if(PeekConsoleInput(handle, &inputrecord, 1, &length)) {
- /* check if the event is not an actual key-event */
- if(length == 1 && inputrecord.EventType != KEY_EVENT) {
- /* purge the non-key-event and continue waiting */
- ReadConsoleInput(handle, &inputrecord, 1, &length);
- ReleaseMutex(mutex);
- continue;
- }
+ /* check if this is an actual console handle */
+ if(GetConsoleMode(handle, &ret)) {
+ /* retrieve an event from the console buffer */
+ length = 0;
+ if(PeekConsoleInput(handle, &inputrecord, 1, &length)) {
+ /* check if the event is not an actual key-event */
+ if(length == 1 && inputrecord.EventType != KEY_EVENT) {
+ /* purge the non-key-event and continue waiting */
+ ReadConsoleInput(handle, &inputrecord, 1, &length);
+ continue;
}
}
- /* there is some data available, stop waiting */
- logmsg("[select_ws_wait_thread] data available, CHAR: %p", handle);
- SetEvent(signal);
- ReleaseMutex(mutex);
- break;
}
- else if(ret == WAIT_ABANDONED) {
- /* we are not allowed to process this event, because select_ws
- is post-processing the signalled events and we must exit. */
- break;
- }
+ /* there is some data available, stop waiting */
+ logmsg("[select_ws_wait_thread] data available, CHAR: %p", handle);
+ SetEvent(signal);
}
break;
@@ -530,45 +510,33 @@
*/
while(WaitForMultipleObjectsEx(1, handles, FALSE, 0, FALSE)
== WAIT_TIMEOUT) {
- ret = WaitForSingleObjectEx(mutex, 0, FALSE);
- if(ret == WAIT_OBJECT_0) {
- /* peek into the pipe and retrieve the amount of data available */
- length = 0;
- if(PeekNamedPipe(handle, NULL, 0, NULL, &length, NULL)) {
- /* if there is no data available, sleep and continue waiting */
- if(length == 0) {
- SleepEx(0, FALSE);
- ReleaseMutex(mutex);
- continue;
- }
- else {
- logmsg("[select_ws_wait_thread] PeekNamedPipe len: %d", length);
- }
+ /* peek into the pipe and retrieve the amount of data available */
+ length = 0;
+ if(PeekNamedPipe(handle, NULL, 0, NULL, &length, NULL)) {
+ /* if there is no data available, sleep and continue waiting */
+ if(length == 0) {
+ SleepEx(0, FALSE);
+ continue;
}
else {
- /* if the pipe has NOT been closed, sleep and continue waiting */
- ret = GetLastError();
- if(ret != ERROR_BROKEN_PIPE) {
- logmsg("[select_ws_wait_thread] PeekNamedPipe error: %d", ret);
- SleepEx(0, FALSE);
- ReleaseMutex(mutex);
- continue;
- }
- else {
- logmsg("[select_ws_wait_thread] pipe closed, PIPE: %p", handle);
- }
+ logmsg("[select_ws_wait_thread] PeekNamedPipe len: %d", length);
}
- /* there is some data available, stop waiting */
- logmsg("[select_ws_wait_thread] data available, PIPE: %p", handle);
- SetEvent(signal);
- ReleaseMutex(mutex);
- break;
}
- else if(ret == WAIT_ABANDONED) {
- /* we are not allowed to process this event, because select_ws
- is post-processing the signalled events and we must exit. */
- break;
+ else {
+ /* if the pipe has NOT been closed, sleep and continue waiting */
+ ret = GetLastError();
+ if(ret != ERROR_BROKEN_PIPE) {
+ logmsg("[select_ws_wait_thread] PeekNamedPipe error: %d", ret);
+ SleepEx(0, FALSE);
+ continue;
+ }
+ else {
+ logmsg("[select_ws_wait_thread] pipe closed, PIPE: %p", handle);
+ }
}
+ /* there is some data available, stop waiting */
+ logmsg("[select_ws_wait_thread] data available, PIPE: %p", handle);
+ SetEvent(signal);
}
break;
@@ -576,22 +544,25 @@
/* The handle has an unknown type, try to wait on it */
if(WaitForMultipleObjectsEx(2, handles, FALSE, INFINITE, FALSE)
== WAIT_OBJECT_0 + 1) {
- if(WaitForSingleObjectEx(mutex, 0, FALSE) == WAIT_OBJECT_0) {
- logmsg("[select_ws_wait_thread] data available, HANDLE: %p", handle);
- SetEvent(signal);
- ReleaseMutex(mutex);
- }
+ logmsg("[select_ws_wait_thread] data available, HANDLE: %p", handle);
+ SetEvent(signal);
}
break;
}
return 0;
}
-static HANDLE select_ws_wait(HANDLE handle, HANDLE signal,
- HANDLE abort, HANDLE mutex)
+static HANDLE select_ws_wait(HANDLE handle, HANDLE signal, HANDLE abort)
{
+#ifdef _WIN32_WCE
+ typedef HANDLE curl_win_thread_handle_t;
+#elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+ typedef unsigned long curl_win_thread_handle_t;
+#else
+ typedef uintptr_t curl_win_thread_handle_t;
+#endif
struct select_ws_wait_data *data;
- HANDLE thread = NULL;
+ curl_win_thread_handle_t thread;
/* allocate internal waiting data structure */
data = malloc(sizeof(struct select_ws_wait_data));
@@ -599,20 +570,21 @@
data->handle = handle;
data->signal = signal;
data->abort = abort;
- data->mutex = mutex;
/* launch waiting thread */
- thread = CreateThread(NULL, 0,
- &select_ws_wait_thread,
- data, 0, NULL);
+#ifdef _WIN32_WCE
+ thread = CreateThread(NULL, 0, &select_ws_wait_thread, data, 0, NULL);
+#else
+ thread = _beginthreadex(NULL, 0, &select_ws_wait_thread, data, 0, NULL);
+#endif
/* free data if thread failed to launch */
if(!thread) {
free(data);
}
+ return (HANDLE)thread;
}
-
- return thread;
+ return NULL;
}
struct select_ws_data {
int fd; /* provided file descriptor (indexed by nfd) */
@@ -625,8 +597,8 @@
static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *tv)
{
- HANDLE abort, mutex, signal, handle, *handles;
DWORD timeout_ms, wait, nfd, nth, nws, i;
+ HANDLE abort, signal, handle, *handles;
fd_set readsock, writesock, exceptsock;
struct select_ws_data *data;
WSANETWORKEVENTS wsaevents;
@@ -661,19 +633,10 @@
return -1;
}
- /* create internal mutex to lock event handling in threads */
- mutex = CreateMutex(NULL, FALSE, NULL);
- if(!mutex) {
- CloseHandle(abort);
- errno = ENOMEM;
- return -1;
- }
-
/* allocate internal array for the internal data */
data = calloc(nfds, sizeof(struct select_ws_data));
if(!data) {
CloseHandle(abort);
- CloseHandle(mutex);
errno = ENOMEM;
return -1;
}
@@ -682,7 +645,6 @@
handles = calloc(nfds + 1, sizeof(HANDLE));
if(!handles) {
CloseHandle(abort);
- CloseHandle(mutex);
free(data);
errno = ENOMEM;
return -1;
@@ -723,7 +685,7 @@
signal = CreateEvent(NULL, TRUE, FALSE, NULL);
if(signal) {
handle = GetStdHandle(STD_INPUT_HANDLE);
- handle = select_ws_wait(handle, signal, abort, mutex);
+ handle = select_ws_wait(handle, signal, abort);
if(handle) {
handles[nfd] = signal;
data[nth].signal = signal;
@@ -777,7 +739,7 @@
signal = CreateEvent(NULL, TRUE, FALSE, NULL);
if(signal) {
handle = (HANDLE)wsasock;
- handle = select_ws_wait(handle, signal, abort, mutex);
+ handle = select_ws_wait(handle, signal, abort);
if(handle) {
handles[nfd] = signal;
data[nth].signal = signal;
@@ -808,8 +770,12 @@
/* wait for one of the internal handles to trigger */
wait = WaitForMultipleObjectsEx(wait, handles, FALSE, timeout_ms, FALSE);
- /* wait for internal mutex to lock event handling in threads */
- WaitForSingleObjectEx(mutex, INFINITE, FALSE);
+ /* signal the abort event handle and join the other waiting threads */
+ SetEvent(abort);
+ for(i = 0; i < nth; i++) {
+ WaitForSingleObjectEx(data[i].thread, INFINITE, FALSE);
+ CloseHandle(data[i].thread);
+ }
/* loop over the internal handles returned in the descriptors */
ret = 0; /* number of ready file descriptors */
@@ -868,9 +834,6 @@
}
}
- /* signal the event handle for the other waiting threads */
- SetEvent(abort);
-
for(fd = 0; fd < nfds; fd++) {
if(FD_ISSET(fd, readfds))
logmsg("[select_ws] %d is readable", fd);
@@ -886,13 +849,9 @@
}
for(i = 0; i < nth; i++) {
- WaitForSingleObjectEx(data[i].thread, INFINITE, FALSE);
- CloseHandle(data[i].thread);
CloseHandle(data[i].signal);
}
-
CloseHandle(abort);
- CloseHandle(mutex);
free(handles);
free(data);
@@ -1132,7 +1091,7 @@
if(CURL_SOCKET_BAD == newfd) {
error = SOCKERRNO;
logmsg("accept(%d, NULL, NULL) failed with error: (%d) %s",
- sockfd, error, strerror(error));
+ sockfd, error, sstrerror(error));
}
else {
logmsg("====> Client connect");
@@ -1196,7 +1155,7 @@
if(rc) {
error = SOCKERRNO;
logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
if(maxretr) {
rc = wait_ms(delay);
if(rc) {
@@ -1248,7 +1207,7 @@
if(rc) {
error = SOCKERRNO;
logmsg("Error binding socket on port %hu: (%d) %s",
- *listenport, error, strerror(error));
+ *listenport, error, sstrerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
}
@@ -1270,7 +1229,7 @@
if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
error = SOCKERRNO;
logmsg("getsockname() failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
}
@@ -1308,7 +1267,7 @@
if(0 != rc) {
error = SOCKERRNO;
logmsg("listen(%d, 5) failed with error: (%d) %s",
- sock, error, strerror(error));
+ sock, error, sstrerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
}
@@ -1455,8 +1414,7 @@
if(CURL_SOCKET_BAD == sock) {
error = SOCKERRNO;
- logmsg("Error creating socket: (%d) %s",
- error, strerror(error));
+ logmsg("Error creating socket: (%d) %s", error, sstrerror(error));
write_stdout("FAIL\n", 5);
goto sockfilt_cleanup;
}
@@ -1492,7 +1450,7 @@
if(rc) {
error = SOCKERRNO;
logmsg("Error connecting to port %hu: (%d) %s",
- connectport, error, strerror(error));
+ connectport, error, sstrerror(error));
write_stdout("FAIL\n", 5);
goto sockfilt_cleanup;
}
diff --git a/tests/server/socksd.c b/tests/server/socksd.c
index d49efcf..e53001d 100644
--- a/tests/server/socksd.c
+++ b/tests/server/socksd.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -304,7 +304,7 @@
if(rc) {
int error = SOCKERRNO;
logmsg("Error connecting to %s:%hu: (%d) %s",
- connectaddr, connectport, error, strerror(error));
+ connectaddr, connectport, error, sstrerror(error));
return CURL_SOCKET_BAD;
}
logmsg("Connected fine to %s:%d", connectaddr, connectport);
@@ -740,7 +740,7 @@
if(CURL_SOCKET_BAD == newfd) {
error = SOCKERRNO;
logmsg("accept(%d, NULL, NULL) failed with error: (%d) %s",
- sockfd, error, strerror(error));
+ sockfd, error, sstrerror(error));
}
else {
curl_socket_t remotefd;
@@ -810,7 +810,7 @@
if(rc) {
error = SOCKERRNO;
logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
if(maxretr) {
rc = wait_ms(delay);
if(rc) {
@@ -866,8 +866,14 @@
if(rc) {
error = SOCKERRNO;
- logmsg("Error binding socket on port %hu: (%d) %s",
- *listenport, error, strerror(error));
+#ifdef USE_UNIX_SOCKETS
+ if(socket_domain == AF_UNIX)
+ logmsg("Error binding socket on path %s: (%d) %s",
+ unix_socket, error, sstrerror(error));
+ else
+#endif
+ logmsg("Error binding socket on port %hu: (%d) %s",
+ *listenport, error, sstrerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
}
@@ -891,7 +897,7 @@
if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
error = SOCKERRNO;
logmsg("getsockname() failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
}
@@ -923,7 +929,7 @@
if(0 != rc) {
error = SOCKERRNO;
logmsg("listen(%d, 5) failed with error: (%d) %s",
- sock, error, strerror(error));
+ sock, error, sstrerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
}
@@ -1017,8 +1023,8 @@
unix_socket = argv[arg];
if(strlen(unix_socket) >= sizeof(sau.sun_path)) {
fprintf(stderr,
- "socksd: socket path must be shorter than %zu chars\n",
- sizeof(sau.sun_path));
+ "socksd: socket path must be shorter than %zu chars: %s\n",
+ sizeof(sau.sun_path), unix_socket);
return 0;
}
socket_domain = AF_UNIX;
@@ -1071,7 +1077,7 @@
if(CURL_SOCKET_BAD == sock) {
error = SOCKERRNO;
logmsg("Error creating socket: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
goto socks5_cleanup;
}
@@ -1095,7 +1101,7 @@
#ifdef USE_UNIX_SOCKETS
if(socket_domain == AF_UNIX)
- logmsg("Listening on unix socket %s", unix_socket);
+ logmsg("Listening on unix socket %s", unix_socket);
else
#endif
logmsg("Listening on port %hu", port);
diff --git a/tests/server/sws.c b/tests/server/sws.c
index 9f8c4a8..bf2c6f9 100644
--- a/tests/server/sws.c
+++ b/tests/server/sws.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -124,7 +124,7 @@
bool skipall; /* skip all incoming data */
bool noexpect; /* refuse Expect: (don't read the body) */
bool connmon; /* monitor the state of the connection, log disconnects */
- bool upgrade; /* test case allows upgrade to http2 */
+ bool upgrade; /* test case allows upgrade */
bool upgrade_request; /* upgrade request found and allowed */
bool close; /* similar to swsclose in response: close connection after
response is sent */
@@ -146,19 +146,21 @@
#endif
const char *serverlogfile = DEFAULT_LOGFILE;
+static const char *logdir = "log";
+static char loglockfile[256];
#define SWSVERSION "curl test suite HTTP server/0.1"
-#define REQUEST_DUMP "log/server.input"
-#define RESPONSE_DUMP "log/server.response"
+#define REQUEST_DUMP "server.input"
+#define RESPONSE_DUMP "server.response"
/* when told to run as proxy, we store the logs in different files so that
they can co-exist with the same program running as a "server" */
-#define REQUEST_PROXY_DUMP "log/proxy.input"
-#define RESPONSE_PROXY_DUMP "log/proxy.response"
+#define REQUEST_PROXY_DUMP "proxy.input"
+#define RESPONSE_PROXY_DUMP "proxy.response"
/* file in which additional instructions may be found */
-#define DEFAULT_CMDFILE "log/ftpserver.cmd"
+#define DEFAULT_CMDFILE "log/server.cmd"
const char *cmdfile = DEFAULT_CMDFILE;
/* very-big-path support */
@@ -182,7 +184,7 @@
proper point - like with NTLM */
#define CMD_CONNECTIONMONITOR "connection-monitor"
-/* upgrade to http2 */
+/* upgrade to http2/websocket/xxxx */
#define CMD_UPGRADE "upgrade"
/* close connection */
@@ -262,7 +264,7 @@
FILE *stream;
int error;
- stream = test2fopen(req->testno);
+ stream = test2fopen(req->testno, logdir);
req->close = FALSE;
req->connmon = FALSE;
@@ -311,7 +313,7 @@
req->connmon = TRUE;
}
else if(!strncmp(CMD_UPGRADE, cmd, strlen(CMD_UPGRADE))) {
- logmsg("enabled upgrade to http2");
+ logmsg("enabled upgrade");
req->upgrade = TRUE;
}
else if(!strncmp(CMD_SWSCLOSE, cmd, strlen(CMD_SWSCLOSE))) {
@@ -541,8 +543,9 @@
parse_servercmd(req);
}
else if((req->offset >= 3)) {
+ unsigned char *l = (unsigned char *)line;
logmsg("** Unusual request. Starts with %02x %02x %02x (%c%c%c)",
- line[0], line[1], line[2], line[0], line[1], line[2]);
+ l[0], l[1], l[2], l[0], l[1], l[2]);
}
}
@@ -601,10 +604,10 @@
/* **** Persistence ****
*
- * If the request is a HTTP/1.0 one, we close the connection unconditionally
+ * If the request is an HTTP/1.0 one, we close the connection unconditionally
* when we're done.
*
- * If the request is a HTTP/1.1 one, we MUST check for a "Connection:"
+ * If the request is an HTTP/1.1 one, we MUST check for a "Connection:"
* header that might say "close". If it does, we close a connection when
* this request is processed. Otherwise, we keep the connection alive for X
* seconds.
@@ -763,8 +766,9 @@
if(req->upgrade && strstr(req->reqbuf, "Upgrade:")) {
/* we allow upgrade and there was one! */
- logmsg("Found Upgrade: in request and allows it");
+ logmsg("Found Upgrade: in request and allow it");
req->upgrade_request = TRUE;
+ return 0; /* not done */
}
if(req->cl > 0) {
@@ -785,7 +789,10 @@
size_t written;
size_t writeleft;
FILE *dump;
- const char *dumpfile = is_proxy?REQUEST_PROXY_DUMP:REQUEST_DUMP;
+ char dumpfile[256];
+
+ msnprintf(dumpfile, sizeof(dumpfile), "%s/%s",
+ logdir, is_proxy?REQUEST_PROXY_DUMP:REQUEST_DUMP);
if(!reqbuf)
return;
@@ -857,6 +864,8 @@
req->upgrade_request = 0;
}
+static int send_doc(curl_socket_t sock, struct httprequest *req);
+
/* returns 1 if the connection should be serviced again immediately, 0 if there
is no data waiting, or < 0 if it should be closed */
static int get_request(curl_socket_t sock, struct httprequest *req)
@@ -866,6 +875,62 @@
ssize_t got = 0;
int overflow = 0;
+ if(req->upgrade_request) {
+ /* upgraded connection, work it differently until end of connection */
+ logmsg("Upgraded connection, this is no longer HTTP/1");
+ send_doc(sock, req);
+
+ /* dump the request received so far to the external file */
+ reqbuf[req->offset] = '\0';
+ storerequest(reqbuf, req->offset);
+ req->offset = 0;
+
+ /* read websocket traffic */
+ if(req->open) {
+ logmsg("wait for websocket traffic");
+ do {
+ got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset);
+ if(got > 0) {
+ req->offset += got;
+ logmsg("Got %zu bytes from client", got);
+ }
+
+ if((got == -1) && ((EAGAIN == errno) || (EWOULDBLOCK == errno))) {
+ int rc;
+ fd_set input;
+ fd_set output;
+ struct timeval timeout = {1, 0}; /* 1000 ms */
+
+ logmsg("Got EAGAIN from sread");
+ FD_ZERO(&input);
+ FD_ZERO(&output);
+ got = 0;
+ FD_SET(sock, &input);
+ do {
+ logmsg("Wait until readable");
+ rc = select((int)sock + 1, &input, &output, NULL, &timeout);
+ } while(rc < 0 && errno == EINTR && !got_exit_signal);
+ logmsg("readable %d", rc);
+ if(rc)
+ got = 1;
+ }
+ } while(got > 0);
+ }
+ else {
+ logmsg("NO wait for websocket traffic");
+ }
+ if(req->offset) {
+ logmsg("log the websocket traffic");
+ /* dump the incoming websocket traffic to the external file */
+ reqbuf[req->offset] = '\0';
+ storerequest(reqbuf, req->offset);
+ req->offset = 0;
+ }
+ init_httprequest(req);
+
+ return -1;
+ }
+
if(req->offset >= REQBUFSIZ-1) {
/* buffer is already full; do nothing */
overflow = 1;
@@ -891,7 +956,7 @@
/* nothing to read at the moment */
return 0;
}
- logmsg("recv() returned error: (%d) %s", error, strerror(error));
+ logmsg("recv() returned error: (%d) %s", error, sstrerror(error));
fail = 1;
}
if(fail) {
@@ -951,8 +1016,11 @@
size_t responsesize;
int error = 0;
int res;
- const char *responsedump = is_proxy?RESPONSE_PROXY_DUMP:RESPONSE_DUMP;
static char weare[256];
+ char responsedump[256];
+
+ msnprintf(responsedump, sizeof(responsedump), "%s/%s",
+ logdir, is_proxy?RESPONSE_PROXY_DUMP:RESPONSE_DUMP);
switch(req->rcmd) {
default:
@@ -1024,7 +1092,7 @@
logmsg("Send response test%ld section <%s>", req->testno, partbuf);
- stream = test2fopen(req->testno);
+ stream = test2fopen(req->testno, logdir);
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1046,7 +1114,7 @@
}
/* re-open the same file again */
- stream = test2fopen(req->testno);
+ stream = test2fopen(req->testno, logdir);
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1104,7 +1172,7 @@
if(num > 20)
num = 20;
- retry:
+retry:
written = swrite(sock, buffer, num);
if(written < 0) {
if((EWOULDBLOCK == SOCKERRNO) || (EAGAIN == SOCKERRNO)) {
@@ -1236,7 +1304,7 @@
if(CURL_SOCKET_BAD == serverfd) {
error = SOCKERRNO;
logmsg("Error creating socket for server connection: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
return CURL_SOCKET_BAD;
}
@@ -1292,7 +1360,7 @@
if(rc) {
error = SOCKERRNO;
logmsg("Error connecting to server port %hu: (%d) %s",
- port, error, strerror(error));
+ port, error, sstrerror(error));
sclose(serverfd);
return CURL_SOCKET_BAD;
}
@@ -1323,7 +1391,8 @@
static void http_connect(curl_socket_t *infdp,
curl_socket_t rootfd,
const char *ipaddr,
- unsigned short ipport)
+ unsigned short ipport,
+ int keepalive_secs)
{
curl_socket_t serverfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD};
curl_socket_t clientfd[2] = {CURL_SOCKET_BAD, CURL_SOCKET_BAD};
@@ -1679,7 +1748,7 @@
} /* (rc > 0) */
else {
timeout_count++;
- if(timeout_count > 5) {
+ if(timeout_count > keepalive_secs) {
logmsg("CONNECT proxy timeout after %d idle seconds!", timeout_count);
break;
}
@@ -1708,10 +1777,10 @@
*infdp = CURL_SOCKET_BAD;
}
-static void http2(struct httprequest *req)
+static void http_upgrade(struct httprequest *req)
{
(void)req;
- logmsg("switched to http2");
+ logmsg("Upgraded to ... %u", req->upgrade_request);
/* left to implement */
}
@@ -1744,14 +1813,14 @@
return 0;
}
logmsg("MAJOR ERROR: accept() failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
return CURL_SOCKET_BAD;
}
if(0 != curlx_nonblock(msgsock, TRUE)) {
error = SOCKERRNO;
logmsg("curlx_nonblock failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
sclose(msgsock);
return CURL_SOCKET_BAD;
}
@@ -1760,7 +1829,7 @@
(void *)&flag, sizeof(flag))) {
error = SOCKERRNO;
logmsg("setsockopt(SO_KEEPALIVE) failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
sclose(msgsock);
return CURL_SOCKET_BAD;
}
@@ -1772,7 +1841,7 @@
*/
if(!serverlogslocked)
- set_advisor_read_lock(SERVERLOGS_LOCK);
+ set_advisor_read_lock(loglockfile);
serverlogslocked += 1;
logmsg("====> Client connect");
@@ -1799,7 +1868,8 @@
is no data waiting, or < 0 if it should be closed */
static int service_connection(curl_socket_t msgsock, struct httprequest *req,
curl_socket_t listensock,
- const char *connecthost)
+ const char *connecthost,
+ int keepalive_secs)
{
if(got_exit_signal)
return -1;
@@ -1846,15 +1916,16 @@
return 1;
}
else {
- http_connect(&msgsock, listensock, connecthost, req->connect_port);
+ http_connect(&msgsock, listensock, connecthost, req->connect_port,
+ keepalive_secs);
return -1;
}
}
if(req->upgrade_request) {
- /* an upgrade request, switch to http2 here */
- http2(req);
- return -1;
+ /* an upgrade request, switch to another protocol here */
+ http_upgrade(req);
+ return 1;
}
/* if we got a CONNECT, loop and get another request as well! */
@@ -1863,6 +1934,9 @@
logmsg("=> persistent connection request ended, awaits new request\n");
return 1;
}
+ else {
+ logmsg("=> NOT a persistent connection, close close CLOSE\n");
+ }
return -1;
}
@@ -1889,6 +1963,8 @@
const char *socket_type = "IPv4";
char port_str[11];
const char *location_str = port_str;
+ int keepalive_secs = 5;
+ const char *protocol_type = "HTTP";
/* a default CONNECT port is basically pointless but still ... */
size_t socket_idx;
@@ -1920,6 +1996,11 @@
if(argc>arg)
serverlogfile = argv[arg++];
}
+ else if(!strcmp("--logdir", argv[arg])) {
+ arg++;
+ if(argc>arg)
+ logdir = argv[arg++];
+ }
else if(!strcmp("--cmdfile", argv[arg])) {
arg++;
if(argc>arg)
@@ -1928,6 +2009,7 @@
else if(!strcmp("--gopher", argv[arg])) {
arg++;
use_gopher = TRUE;
+ protocol_type = "GOPHER";
end_of_headers = "\r\n"; /* gopher style is much simpler */
}
else if(!strcmp("--ipv4", argv[arg])) {
@@ -1950,8 +2032,9 @@
#ifdef USE_UNIX_SOCKETS
unix_socket = argv[arg];
if(strlen(unix_socket) >= sizeof(me.sau.sun_path)) {
- fprintf(stderr, "sws: socket path must be shorter than %zu chars\n",
- sizeof(me.sau.sun_path));
+ fprintf(stderr,
+ "sws: socket path must be shorter than %zu chars: %s\n",
+ sizeof(me.sau.sun_path), unix_socket);
return 0;
}
socket_type = "unix";
@@ -1983,6 +2066,21 @@
arg++;
}
}
+ else if(!strcmp("--keepalive", argv[arg])) {
+ arg++;
+ if(argc>arg) {
+ char *endptr;
+ unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
+ if((endptr != argv[arg] + strlen(argv[arg])) ||
+ (ulnum && (ulnum > 65535UL))) {
+ fprintf(stderr, "sws: invalid --keepalive argument (%s), must "
+ "be number of seconds\n", argv[arg]);
+ return 0;
+ }
+ keepalive_secs = curlx_ultous(ulnum);
+ arg++;
+ }
+ }
else if(!strcmp("--connect", argv[arg])) {
/* The connect host IP number that the proxy will connect to no matter
what the client asks for, but also use this as a hint that we run as
@@ -1999,6 +2097,7 @@
puts("Usage: sws [option]\n"
" --version\n"
" --logfile [file]\n"
+ " --logdir [directory]\n"
" --pidfile [file]\n"
" --portfile [file]\n"
" --ipv4\n"
@@ -2012,6 +2111,10 @@
}
}
+ msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/sws-%s%s-%s.lock",
+ logdir, SERVERLOGS_LOCKDIR, protocol_type,
+ is_proxy ? "-proxy" : "", socket_type);
+
#ifdef WIN32
win32_init();
atexit(win32_cleanup);
@@ -2030,8 +2133,7 @@
if(CURL_SOCKET_BAD == sock) {
error = SOCKERRNO;
- logmsg("Error creating socket: (%d) %s",
- error, strerror(error));
+ logmsg("Error creating socket: (%d) %s", error, sstrerror(error));
goto sws_cleanup;
}
@@ -2040,13 +2142,13 @@
(void *)&flag, sizeof(flag))) {
error = SOCKERRNO;
logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
goto sws_cleanup;
}
if(0 != curlx_nonblock(sock, TRUE)) {
error = SOCKERRNO;
logmsg("curlx_nonblock failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
goto sws_cleanup;
}
@@ -2074,7 +2176,14 @@
}
if(0 != rc) {
error = SOCKERRNO;
- logmsg("Error binding socket: (%d) %s", error, strerror(error));
+#ifdef USE_UNIX_SOCKETS
+ if(socket_domain == AF_UNIX)
+ logmsg("Error binding socket on path %s: (%d) %s",
+ unix_socket, error, sstrerror(error));
+ else
+#endif
+ logmsg("Error binding socket on port %hu: (%d) %s",
+ port, error, sstrerror(error));
goto sws_cleanup;
}
@@ -2095,7 +2204,7 @@
if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
error = SOCKERRNO;
logmsg("getsockname() failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
sclose(sock);
goto sws_cleanup;
}
@@ -2127,14 +2236,13 @@
msnprintf(port_str, sizeof(port_str), "port %hu", port);
logmsg("Running %s %s version on %s",
- use_gopher?"GOPHER":"HTTP", socket_type, location_str);
+ protocol_type, socket_type, location_str);
/* start accepting connections */
rc = listen(sock, 5);
if(0 != rc) {
error = SOCKERRNO;
- logmsg("listen() failed with error: (%d) %s",
- error, strerror(error));
+ logmsg("listen() failed with error: (%d) %s", error, sstrerror(error));
goto sws_cleanup;
}
@@ -2206,8 +2314,7 @@
if(rc < 0) {
error = SOCKERRNO;
- logmsg("select() failed with error: (%d) %s",
- error, strerror(error));
+ logmsg("select() failed with error: (%d) %s", error, sstrerror(error));
goto sws_cleanup;
}
@@ -2240,7 +2347,7 @@
/* Service this connection until it has nothing available */
do {
rc = service_connection(all_sockets[socket_idx], req, sock,
- connecthost);
+ connecthost, keepalive_secs);
if(got_exit_signal)
goto sws_cleanup;
@@ -2266,14 +2373,14 @@
serverlogslocked -= 1;
if(!serverlogslocked)
- clear_advisor_read_lock(SERVERLOGS_LOCK);
+ clear_advisor_read_lock(loglockfile);
if(req->testno == DOCNUMBER_QUIT)
goto sws_cleanup;
}
/* Reset the request, unless we're still in the middle of reading */
- if(rc)
+ if(rc && !req->upgrade_request)
init_httprequest(req);
} while(rc > 0);
}
@@ -2312,7 +2419,7 @@
if(serverlogslocked) {
serverlogslocked = 0;
- clear_advisor_read_lock(SERVERLOGS_LOCK);
+ clear_advisor_read_lock(loglockfile);
}
restore_signal_handlers(false);
diff --git a/tests/server/testpart.c b/tests/server/testpart.c
index f54c712..489b218 100644
--- a/tests/server/testpart.c
+++ b/tests/server/testpart.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/server/tftp.h b/tests/server/tftp.h
index d8328dc..70e2197 100644
--- a/tests/server/tftp.h
+++ b/tests/server/tftp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,7 +34,7 @@
((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7)))
# define PACKED_STRUCT __attribute__((__packed__))
#else
-# define PACKED_STRUCT /*NOTHING*/
+# define PACKED_STRUCT /* NOTHING */
#endif
/* Using a packed struct as binary in a program is begging for problems, but
diff --git a/tests/server/tftpd.c b/tests/server/tftpd.c
index 10f99d9..ef45c48 100644
--- a/tests/server/tftpd.c
+++ b/tests/server/tftpd.c
@@ -15,7 +15,7 @@
*/
/*
- * Copyright (C) 2005 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (c) 1983, Regents of the University of California.
* All rights reserved.
*
@@ -88,6 +88,8 @@
#include <pwd.h>
#endif
+#include <ctype.h>
+
#define ENABLE_CURLX_PRINTF
/* make the curlx header define all printf() functions to use the curlx_*
versions instead */
@@ -161,7 +163,7 @@
#define DEFAULT_LOGFILE "log/tftpd.log"
#endif
-#define REQUEST_DUMP "log/server.input"
+#define REQUEST_DUMP "server.input"
#define DEFAULT_PORT 8999 /* UDP */
@@ -213,6 +215,8 @@
static const char *ipv_inuse = "IPv4";
const char *serverlogfile = DEFAULT_LOGFILE;
+const char *logdir = "log";
+char loglockfile[256];
static const char *pidname = ".tftpd.pid";
static const char *portname = NULL; /* none by default */
static int serverlogslocked = 0;
@@ -298,7 +302,7 @@
}
if(serverlogslocked) {
serverlogslocked = 0;
- clear_advisor_read_lock(SERVERLOGS_LOCK);
+ clear_advisor_read_lock(loglockfile);
}
exit(1);
}
@@ -456,7 +460,7 @@
if(!test->ofile) {
char outfile[256];
- msnprintf(outfile, sizeof(outfile), "log/upload.%ld", test->testno);
+ msnprintf(outfile, sizeof(outfile), "%s/upload.%ld", logdir, test->testno);
#ifdef WIN32
test->ofile = open(outfile, O_CREAT|O_RDWR|O_BINARY, 0777);
#else
@@ -496,7 +500,7 @@
putc(c, file); */
if(1 != write(test->ofile, &c, 1))
break;
- skipit:
+skipit:
prevchar = c;
}
return count;
@@ -593,6 +597,11 @@
if(argc>arg)
serverlogfile = argv[arg++];
}
+ else if(!strcmp("--logdir", argv[arg])) {
+ arg++;
+ if(argc>arg)
+ logdir = argv[arg++];
+ }
else if(!strcmp("--ipv4", argv[arg])) {
#ifdef ENABLE_IPV6
ipv_inuse = "IPv4";
@@ -627,6 +636,7 @@
puts("Usage: tftpd [option]\n"
" --version\n"
" --logfile [file]\n"
+ " --logdir [directory]\n"
" --pidfile [file]\n"
" --portfile [file]\n"
" --ipv4\n"
@@ -637,6 +647,9 @@
}
}
+ msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/tftp-%s.lock",
+ logdir, SERVERLOGS_LOCKDIR, ipv_inuse);
+
#ifdef WIN32
win32_init();
atexit(win32_cleanup);
@@ -655,8 +668,7 @@
if(CURL_SOCKET_BAD == sock) {
error = SOCKERRNO;
- logmsg("Error creating socket: (%d) %s",
- error, strerror(error));
+ logmsg("Error creating socket: (%d) %s", error, sstrerror(error));
result = 1;
goto tftpd_cleanup;
}
@@ -666,7 +678,7 @@
(void *)&flag, sizeof(flag))) {
error = SOCKERRNO;
logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
result = 1;
goto tftpd_cleanup;
}
@@ -691,8 +703,8 @@
#endif /* ENABLE_IPV6 */
if(0 != rc) {
error = SOCKERRNO;
- logmsg("Error binding socket on port %hu: (%d) %s",
- port, error, strerror(error));
+ logmsg("Error binding socket on port %hu: (%d) %s", port, error,
+ sstrerror(error));
result = 1;
goto tftpd_cleanup;
}
@@ -714,7 +726,7 @@
if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
error = SOCKERRNO;
logmsg("getsockname() failed with error: (%d) %s",
- error, strerror(error));
+ error, sstrerror(error));
sclose(sock);
goto tftpd_cleanup;
}
@@ -777,7 +789,7 @@
break;
}
- set_advisor_read_lock(SERVERLOGS_LOCK);
+ set_advisor_read_lock(loglockfile);
serverlogslocked = 1;
#ifdef ENABLE_IPV6
@@ -831,7 +843,7 @@
if(serverlogslocked) {
serverlogslocked = 0;
- clear_advisor_read_lock(SERVERLOGS_LOCK);
+ clear_advisor_read_lock(loglockfile);
}
logmsg("end of one transfer");
@@ -859,7 +871,7 @@
if(serverlogslocked) {
serverlogslocked = 0;
- clear_advisor_read_lock(SERVERLOGS_LOCK);
+ clear_advisor_read_lock(loglockfile);
}
restore_signal_handlers(true);
@@ -893,13 +905,17 @@
#endif
const char *option = "mode"; /* mode is implicit */
int toggle = 1;
+ FILE *server;
+ char dumpfile[256];
+
+ msnprintf(dumpfile, sizeof(dumpfile), "%s/%s", logdir, REQUEST_DUMP);
/* Open request dump file. */
- FILE *server = fopen(REQUEST_DUMP, "ab");
+ server = fopen(dumpfile, "ab");
if(!server) {
int error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
- logmsg("Error opening file: %s", REQUEST_DUMP);
+ logmsg("Error opening file: %s", dumpfile);
return -1;
}
@@ -1002,7 +1018,7 @@
FILE *stream;
int error;
- stream = test2fopen(req->testno);
+ stream = test2fopen(req->testno, logdir);
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1113,7 +1129,7 @@
(void)parse_servercmd(test);
- stream = test2fopen(testno);
+ stream = test2fopen(testno, logdir);
if(0 != partno)
msnprintf(partbuf, sizeof(partbuf), "data%ld", partno);
@@ -1184,7 +1200,7 @@
wait_ms(1000*test->writedelay);
}
- send_data:
+send_data:
logmsg("write");
if(swrite(peer, sdp, size + 4) != size + 4) {
logmsg("write: fail");
diff --git a/tests/server/util.c b/tests/server/util.c
index 9af7305..d18c225 100644
--- a/tests/server/util.c
+++ b/tests/server/util.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -67,7 +67,7 @@
((__W32API_MAJOR_VERSION == 3) && (__W32API_MINOR_VERSION < 6))
const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
#endif /* w32api < 3.6 */
-#endif /* ENABLE_IPV6 && __MINGW32__*/
+#endif /* ENABLE_IPV6 && __MINGW32__ */
static struct timeval tvnow(void);
@@ -147,16 +147,22 @@
}
#ifdef WIN32
+/* use instead of strerror() on generic Windows */
+static const char *win32_strerror(int err, char *buf, size_t buflen)
+{
+ if(!FormatMessageA((FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
+ LANG_NEUTRAL, buf, (DWORD)buflen, NULL))
+ msnprintf(buf, buflen, "Unknown error %lu (%#lx)", err, err);
+ return buf;
+}
+
/* use instead of perror() on generic windows */
void win32_perror(const char *msg)
{
char buf[512];
DWORD err = SOCKERRNO;
-
- if(!FormatMessageA((FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
- LANG_NEUTRAL, buf, sizeof(buf), NULL))
- msnprintf(buf, sizeof(buf), "Unknown error %lu (%#lx)", err, err);
+ win32_strerror(err, buf, sizeof(buf));
if(msg)
fprintf(stderr, "%s: ", msg);
fprintf(stderr, "%s\n", buf);
@@ -197,17 +203,24 @@
/* flush buffers of all streams regardless of their mode */
_flushall();
}
+
+/* socket-safe strerror (works on WinSock errors, too */
+const char *sstrerror(int err)
+{
+ static char buf[512];
+ return win32_strerror(err, buf, sizeof(buf));
+}
#endif /* WIN32 */
/* set by the main code to point to where the test dir is */
const char *path = ".";
-FILE *test2fopen(long testno)
+FILE *test2fopen(long testno, const char *logdir)
{
FILE *stream;
char filename[256];
/* first try the alternative, preprocessed, file */
- msnprintf(filename, sizeof(filename), ALTTEST_DATA_PATH, ".", testno);
+ msnprintf(filename, sizeof(filename), ALTTEST_DATA_PATH, logdir, testno);
stream = fopen(filename, "rb");
if(stream)
return stream;
@@ -367,31 +380,6 @@
}
-/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
- its behavior is altered by the current locale. */
-static char raw_toupper(char in)
-{
- if(in >= 'a' && in <= 'z')
- return (char)('A' + in - 'a');
- return in;
-}
-
-int strncasecompare(const char *first, const char *second, size_t max)
-{
- while(*first && *second && max) {
- if(raw_toupper(*first) != raw_toupper(*second)) {
- break;
- }
- max--;
- first++;
- second++;
- }
- if(0 == max)
- return 1; /* they are equal this far */
-
- return raw_toupper(*first) == raw_toupper(*second);
-}
-
#if defined(WIN32) && !defined(MSDOS)
static struct timeval tvnow(void)
@@ -521,7 +509,11 @@
#endif
#ifdef WIN32
+#ifdef _WIN32_WCE
static DWORD thread_main_id = 0;
+#else
+static unsigned int thread_main_id = 0;
+#endif
static HANDLE thread_main_window = NULL;
static HWND hidden_main_window = NULL;
#endif
@@ -624,7 +616,12 @@
}
/* Window message queue loop for hidden main window, details see above.
*/
+#ifdef _WIN32_WCE
static DWORD WINAPI main_window_loop(LPVOID lpParameter)
+#else
+#include <process.h>
+static unsigned int WINAPI main_window_loop(void *lpParameter)
+#endif
{
WNDCLASS wc;
BOOL ret;
@@ -705,6 +702,14 @@
void install_signal_handlers(bool keep_sigalrm)
{
#ifdef WIN32
+#ifdef _WIN32_WCE
+ typedef HANDLE curl_win_thread_handle_t;
+#elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+ typedef unsigned long curl_win_thread_handle_t;
+#else
+ typedef uintptr_t curl_win_thread_handle_t;
+#endif
+ curl_win_thread_handle_t thread;
/* setup windows exit event before any signal can trigger */
exit_event = CreateEvent(NULL, TRUE, FALSE, NULL);
if(!exit_event)
@@ -753,10 +758,14 @@
#ifdef WIN32
if(!SetConsoleCtrlHandler(ctrl_event_handler, TRUE))
logmsg("cannot install CTRL event handler");
- thread_main_window = CreateThread(NULL, 0,
- &main_window_loop,
- (LPVOID)GetModuleHandle(NULL),
- 0, &thread_main_id);
+#ifdef _WIN32_WCE
+ thread = CreateThread(NULL, 0, &main_window_loop,
+ (LPVOID)GetModuleHandle(NULL), 0, &thread_main_id);
+#else
+ thread = _beginthreadex(NULL, 0, &main_window_loop,
+ (void *)GetModuleHandle(NULL), 0, &thread_main_id);
+#endif
+ thread_main_window = (HANDLE)thread;
if(!thread_main_window || !thread_main_id)
logmsg("cannot start main window loop");
#endif
@@ -823,23 +832,22 @@
sau->sun_family = AF_UNIX;
strncpy(sau->sun_path, unix_socket, sizeof(sau->sun_path) - 1);
rc = bind(sock, (struct sockaddr*)sau, sizeof(struct sockaddr_un));
- if(0 != rc && errno == EADDRINUSE) {
+ if(0 != rc && SOCKERRNO == EADDRINUSE) {
struct_stat statbuf;
/* socket already exists. Perhaps it is stale? */
curl_socket_t unixfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(CURL_SOCKET_BAD == unixfd) {
- error = SOCKERRNO;
- logmsg("Error binding socket, failed to create socket at %s: (%d) %s",
- unix_socket, error, strerror(error));
- return rc;
+ logmsg("Failed to create socket at %s: (%d) %s",
+ unix_socket, SOCKERRNO, sstrerror(SOCKERRNO));
+ return -1;
}
/* check whether the server is alive */
rc = connect(unixfd, (struct sockaddr*)sau, sizeof(struct sockaddr_un));
- error = errno;
+ error = SOCKERRNO;
sclose(unixfd);
- if(ECONNREFUSED != error) {
- logmsg("Error binding socket, failed to connect to %s: (%d) %s",
- unix_socket, error, strerror(error));
+ if(0 != rc && ECONNREFUSED != error) {
+ logmsg("Failed to connect to %s: (%d) %s",
+ unix_socket, error, sstrerror(error));
return rc;
}
/* socket server is not alive, now check if it was actually a socket. */
@@ -856,9 +864,8 @@
}
#ifdef S_IFSOCK
if((statbuf.st_mode & S_IFSOCK) != S_IFSOCK) {
- logmsg("Error binding socket, failed to stat %s: (%d) %s",
- unix_socket, error, strerror(error));
- return rc;
+ logmsg("Error binding socket, failed to stat %s", unix_socket);
+ return -1;
}
#endif
/* dead socket, cleanup and retry bind */
diff --git a/tests/server/util.h b/tests/server/util.h
index 2c29fd0..a12f4db 100644
--- a/tests/server/util.h
+++ b/tests/server/util.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,9 +30,8 @@
long timediff(struct timeval newer, struct timeval older);
#define TEST_DATA_PATH "%s/data/test%ld"
-#define ALTTEST_DATA_PATH "%s/log/test%ld"
-
-#define SERVERLOGS_LOCK "log/serverlogs.lock"
+#define ALTTEST_DATA_PATH "%s/test%ld"
+#define SERVERLOGS_LOCKDIR "lock" /* within logdir */
/* global variable, where to find the 'data' dir */
extern const char *path;
@@ -54,10 +53,14 @@
void win32_init(void);
void win32_cleanup(void);
+const char *sstrerror(int err);
+#else /* WIN32 */
+
+#define sstrerror(e) strerror(e)
#endif /* WIN32 */
/* fopens the test case file */
-FILE *test2fopen(long testno);
+FILE *test2fopen(long testno, const char *logdir);
int wait_ms(int timeout_ms);
curl_off_t our_getpid(void);
@@ -83,6 +86,8 @@
#ifdef USE_UNIX_SOCKETS
+#include <curl/curl.h> /* for curl_socket_t */
+
#ifdef HAVE_SYS_UN_H
#include <sys/un.h> /* for sockaddr_un */
#endif /* HAVE_SYS_UN_H */
diff --git a/tests/serverhelp.pm b/tests/serverhelp.pm
index 7d312cc..502b6eb 100644
--- a/tests/serverhelp.pm
+++ b/tests/serverhelp.pm
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -22,48 +22,45 @@
#
#***************************************************************************
+# This perl module contains functions useful in writing test servers.
+
package serverhelp;
use strict;
use warnings;
-use Exporter;
+BEGIN {
+ use base qw(Exporter);
-#***************************************************************************
-# Global symbols allowed without explicit package name
-#
-use vars qw(
- @ISA
- @EXPORT_OK
+ our @EXPORT_OK = qw(
+ logmsg
+ $logfile
+ serverfactors
+ servername_id
+ servername_str
+ servername_canon
+ server_pidfilename
+ server_portfilename
+ server_logfilename
+ server_cmdfilename
+ server_inputfilename
+ server_outputfilename
+ mainsockf_pidfilename
+ mainsockf_logfilename
+ datasockf_pidfilename
+ datasockf_logfilename
);
-
-#***************************************************************************
-# Inherit Exporter's capabilities
-#
-@ISA = qw(Exporter);
+ # sub second timestamping needs Time::HiRes
+ eval {
+ no warnings "all";
+ require Time::HiRes;
+ import Time::HiRes qw( gettimeofday );
+ }
+}
-#***************************************************************************
-# Global symbols this module will export upon request
-#
-@EXPORT_OK = qw(
- serverfactors
- servername_id
- servername_str
- servername_canon
- server_pidfilename
- server_portfilename
- server_logfilename
- server_cmdfilename
- server_inputfilename
- server_outputfilename
- mainsockf_pidfilename
- mainsockf_logfilename
- datasockf_pidfilename
- datasockf_logfilename
- );
-
+our $logfile; # server log file name, for logmsg
#***************************************************************************
# Just for convenience, test harness uses 'https' and 'httptls' literals as
@@ -71,6 +68,31 @@
# 'https' literal is used for stunnel based https test servers, and 'httptls'
# is used for non-stunnel https test servers.
+#**********************************************************************
+# logmsg is general message logging subroutine for our test servers.
+#
+sub logmsg {
+ my $now;
+ # sub second timestamping needs Time::HiRes
+ if($Time::HiRes::VERSION) {
+ my ($seconds, $usec) = gettimeofday();
+ my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
+ localtime($seconds);
+ $now = sprintf("%02d:%02d:%02d.%06d ", $hour, $min, $sec, $usec);
+ }
+ else {
+ my $seconds = time();
+ my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
+ localtime($seconds);
+ $now = sprintf("%02d:%02d:%02d ", $hour, $min, $sec);
+ }
+ if(open(my $logfilefh, ">>", "$logfile")) {
+ print $logfilefh $now;
+ print $logfilefh @_;
+ close($logfilefh);
+ }
+}
+
#***************************************************************************
# Return server characterization factors given a server id string.
@@ -108,7 +130,7 @@
$proto = uc($proto) if($proto);
die "unsupported protocol: '$proto'" unless($proto &&
- ($proto =~ /^(((FTP|HTTP|HTTP\/2|IMAP|POP3|GOPHER|SMTP|HTTP-PIPE)S?)|(TFTP|SFTP|SOCKS|SSH|RTSP|HTTPTLS|DICT|SMB|SMBS|TELNET|MQTT))$/));
+ ($proto =~ /^(((FTP|HTTP|HTTP\/2|HTTP\/3|IMAP|POP3|GOPHER|SMTP|HTTP-PIPE)S?)|(TFTP|SFTP|SOCKS|SSH|RTSP|HTTPTLS|DICT|SMB|SMBS|TELNET|MQTT))$/));
$ipver = (not $ipver) ? 'ipv4' : lc($ipver);
die "unsupported IP version: '$ipver'" unless($ipver &&
@@ -118,7 +140,7 @@
$idnum = 1 if(not $idnum);
die "unsupported ID number: '$idnum'" unless($idnum &&
($idnum =~ /^(\d+)$/));
- $idnum = '' unless($idnum > 1);
+ $idnum = '' if($idnum <= 1);
return "${proto}${idnum}${ipver}";
}
@@ -149,18 +171,18 @@
# Return file name for server pid file.
#
sub server_pidfilename {
- my ($proto, $ipver, $idnum) = @_;
+ my ($piddir, $proto, $ipver, $idnum) = @_;
my $trailer = '_server.pid';
- return '.'. servername_canon($proto, $ipver, $idnum) ."$trailer";
+ return "${piddir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
}
#***************************************************************************
# Return file name for server port file.
#
sub server_portfilename {
- my ($proto, $ipver, $idnum) = @_;
+ my ($piddir, $proto, $ipver, $idnum) = @_;
my $trailer = '_server.port';
- return '.'. servername_canon($proto, $ipver, $idnum) ."$trailer";
+ return "${piddir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
}
@@ -209,11 +231,11 @@
# Return file name for main or primary sockfilter pid file.
#
sub mainsockf_pidfilename {
- my ($proto, $ipver, $idnum) = @_;
+ my ($piddir, $proto, $ipver, $idnum) = @_;
die "unsupported protocol: '$proto'" unless($proto &&
(lc($proto) =~ /^(ftp|imap|pop3|smtp)s?$/));
my $trailer = (lc($proto) =~ /^ftps?$/) ? '_sockctrl.pid':'_sockfilt.pid';
- return '.'. servername_canon($proto, $ipver, $idnum) ."$trailer";
+ return "${piddir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
}
@@ -233,11 +255,11 @@
# Return file name for data or secondary sockfilter pid file.
#
sub datasockf_pidfilename {
- my ($proto, $ipver, $idnum) = @_;
+ my ($piddir, $proto, $ipver, $idnum) = @_;
die "unsupported protocol: '$proto'" unless($proto &&
(lc($proto) =~ /^ftps?$/));
my $trailer = '_sockdata.pid';
- return '.'. servername_canon($proto, $ipver, $idnum) ."$trailer";
+ return "${piddir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
}
diff --git a/tests/servers.pm b/tests/servers.pm
new file mode 100644
index 0000000..d6f96f4
--- /dev/null
+++ b/tests/servers.pm
@@ -0,0 +1,3002 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+# This module contains functions that are useful for managing the lifecycle of
+# test servers required when running tests. It is not intended for use within
+# those servers, but rather for starting and stopping them.
+
+package servers;
+
+use IO::Socket;
+use strict;
+use warnings;
+
+BEGIN {
+ use base qw(Exporter);
+
+ our @EXPORT = (
+ # variables
+ qw(
+ $SOCKSIN
+ $err_unexpected
+ $debugprotocol
+ $stunnel
+ ),
+
+ # functions
+ qw(
+ initserverconfig
+ )
+ );
+
+ our @EXPORT_OK = (
+ # functions
+ qw(
+ checkcmd
+ clearlocks
+ serverfortest
+ stopserver
+ stopservers
+ subvariables
+ ),
+
+ # for debugging only
+ qw(
+ protoport
+ )
+ );
+}
+
+use serverhelp qw(
+ serverfactors
+ servername_id
+ servername_str
+ servername_canon
+ server_pidfilename
+ server_portfilename
+ server_logfilename
+ );
+
+use sshhelp qw(
+ $hstpubmd5f
+ $hstpubsha256f
+ $sshexe
+ $sftpexe
+ $sftpconfig
+ $sshdlog
+ $sftplog
+ $sftpcmds
+ display_sshdconfig
+ display_sftpconfig
+ display_sshdlog
+ display_sftplog
+ find_sshd
+ find_ssh
+ find_sftp
+ find_httptlssrv
+ sshversioninfo
+ );
+
+use pathhelp qw(
+ exe_ext
+ os_is_win
+ sys_native_abs_path
+ );
+
+use processhelp;
+use globalconfig;
+use testutil qw(
+ logmsg
+ runclient
+ runclientoutput
+ );
+
+
+my %serverpidfile; # all server pid file names, identified by server id
+my %serverportfile;# all server port file names, identified by server id
+my $sshdvernum; # for socks server, ssh daemon version number
+my $sshdverstr; # for socks server, ssh daemon version string
+my $sshderror; # for socks server, ssh daemon version error
+my %doesntrun; # servers that don't work, identified by pidfile
+my %PORT = (nolisten => 47); # port we use for a local non-listening service
+my $server_response_maxtime=13;
+my $httptlssrv = find_httptlssrv();
+my %run; # running server
+my %runcert; # cert file currently in use by an ssl running server
+my $CLIENTIP="127.0.0.1"; # address which curl uses for incoming connections
+my $CLIENT6IP="[::1]"; # address which curl uses for incoming connections
+my $posix_pwd=$pwd; # current working directory
+my $h2cver = "h2c"; # this version is decided by the nghttp2 lib being used
+my $portrange = 999; # space from which to choose a random port
+ # don't increase without making sure generated port
+ # numbers will always be valid (<=65535)
+my $HOSTIP="127.0.0.1"; # address on which the test server listens
+my $HOST6IP="[::1]"; # address on which the test server listens
+my $HTTPUNIXPATH; # HTTP server Unix domain socket path
+my $SOCKSUNIXPATH; # socks server Unix domain socket path
+my $SSHSRVMD5 = "[uninitialized]"; # MD5 of ssh server public key
+my $SSHSRVSHA256 = "[uninitialized]"; # SHA256 of ssh server public key
+my $USER; # name of the current user
+my $sshdid; # for socks server, ssh daemon version id
+my $ftpchecktime=1; # time it took to verify our test FTP server
+
+# Variables shared with runtests.pl
+our $SOCKSIN="socksd-request.log"; # what curl sent to the SOCKS proxy
+our $err_unexpected; # error instead of warning on server unexpectedly alive
+our $debugprotocol; # nonzero for verbose server logs
+our $stunnel; # path to stunnel command
+
+
+#######################################################################
+# Check for a command in the PATH of the test server.
+#
+sub checkcmd {
+ my ($cmd, @extrapaths)=@_;
+ my @paths=(split(m/[:]/, $ENV{'PATH'}), "/usr/sbin", "/usr/local/sbin",
+ "/sbin", "/usr/bin", "/usr/local/bin", @extrapaths);
+ for(@paths) {
+ if( -x "$_/$cmd" && ! -d "$_/$cmd") {
+ # executable bit but not a directory!
+ return "$_/$cmd";
+ }
+ }
+ return "";
+}
+
+#######################################################################
+# Create a server socket on a random (unused) port, then close it and
+# return the port number
+#
+sub getfreeport {
+ my ($ipnum) = @_;
+ my $server = IO::Socket->new(LocalPort => 0,
+ Domain => $ipnum == 6 ? AF_INET6 : AF_INET,
+ Type => SOCK_STREAM,
+ Reuse => 1,
+ Listen => 10 )
+ or die "Couldn't create tcp server socket: $@\n";
+
+ return $server->sockport();
+}
+
+use File::Temp qw/ tempfile/;
+
+#######################################################################
+# Initialize configuration variables
+sub initserverconfig {
+ my ($fh, $socks) = tempfile("/tmp/curl-socksd-XXXXXXXX");
+ close($fh);
+ unlink($socks);
+ my ($f2, $http) = tempfile("/tmp/curl-http-XXXXXXXX");
+ close($f2);
+ unlink($http);
+ $SOCKSUNIXPATH = $socks; # SOCKS Unix domain socket
+ $HTTPUNIXPATH = $http; # HTTP Unix domain socket
+ $stunnel = checkcmd("stunnel4") || checkcmd("tstunnel") || checkcmd("stunnel");
+
+ # get the name of the current user
+ $USER = $ENV{USER}; # Linux
+ if (!$USER) {
+ $USER = $ENV{USERNAME}; # Windows
+ if (!$USER) {
+ $USER = $ENV{LOGNAME}; # Some Unix (I think)
+ }
+ }
+ init_serverpidfile_hash();
+}
+
+#######################################################################
+# Load serverpidfile and serverportfile hashes with file names for all
+# possible servers.
+#
+sub init_serverpidfile_hash {
+ for my $proto (('ftp', 'gopher', 'http', 'imap', 'pop3', 'smtp', 'http/2', 'http/3')) {
+ for my $ssl (('', 's')) {
+ for my $ipvnum ((4, 6)) {
+ for my $idnum ((1, 2, 3)) {
+ my $serv = servername_id("$proto$ssl", $ipvnum, $idnum);
+ my $pidf = server_pidfilename("$LOGDIR/$PIDDIR", "$proto$ssl",
+ $ipvnum, $idnum);
+ $serverpidfile{$serv} = $pidf;
+ my $portf = server_portfilename("$LOGDIR/$PIDDIR", "$proto$ssl",
+ $ipvnum, $idnum);
+ $serverportfile{$serv} = $portf;
+ }
+ }
+ }
+ }
+ for my $proto (('tftp', 'sftp', 'socks', 'ssh', 'rtsp', 'httptls',
+ 'dict', 'smb', 'smbs', 'telnet', 'mqtt')) {
+ for my $ipvnum ((4, 6)) {
+ for my $idnum ((1, 2)) {
+ my $serv = servername_id($proto, $ipvnum, $idnum);
+ my $pidf = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
+ $idnum);
+ $serverpidfile{$serv} = $pidf;
+ my $portf = server_portfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
+ $idnum);
+ $serverportfile{$serv} = $portf;
+ }
+ }
+ }
+ for my $proto (('http', 'imap', 'pop3', 'smtp', 'http/2', 'http/3')) {
+ for my $ssl (('', 's')) {
+ my $serv = servername_id("$proto$ssl", "unix", 1);
+ my $pidf = server_pidfilename("$LOGDIR/$PIDDIR", "$proto$ssl",
+ "unix", 1);
+ $serverpidfile{$serv} = $pidf;
+ my $portf = server_portfilename("$LOGDIR/$PIDDIR", "$proto$ssl",
+ "unix", 1);
+ $serverportfile{$serv} = $portf;
+ }
+ }
+}
+
+
+#######################################################################
+# Kill the processes that still have lock files in a directory
+#
+sub clearlocks {
+ my $dir = $_[0];
+ my $done = 0;
+
+ if(os_is_win()) {
+ $dir = sys_native_abs_path($dir);
+ $dir =~ s/\//\\\\/g;
+ my $handle = "handle.exe";
+ if($ENV{"PROCESSOR_ARCHITECTURE"} =~ /64$/) {
+ $handle = "handle64.exe";
+ }
+ my @handles = `$handle $dir -accepteula -nobanner`;
+ for my $tryhandle (@handles) {
+ if($tryhandle =~ /^(\S+)\s+pid:\s+(\d+)\s+type:\s+(\w+)\s+([0-9A-F]+):\s+(.+)\r\r/) {
+ logmsg "Found $3 lock of '$5' ($4) by $1 ($2)\n";
+ # Ignore stunnel since we cannot do anything about its locks
+ if("$3" eq "File" && "$1" ne "tstunnel.exe") {
+ logmsg "Killing IMAGENAME eq $1 and PID eq $2\n";
+ system("taskkill.exe -f -fi \"IMAGENAME eq $1\" -fi \"PID eq $2\" >nul 2>&1");
+ $done = 1;
+ }
+ }
+ }
+ }
+ return $done;
+}
+
+#######################################################################
+# Check if a given child process has just died. Reaps it if so.
+#
+sub checkdied {
+ my $pid = $_[0];
+ if((not defined $pid) || $pid <= 0) {
+ return 0;
+ }
+ use POSIX ":sys_wait_h";
+ my $rc = pidwait($pid, &WNOHANG);
+ return ($rc == $pid)?1:0;
+}
+
+
+##############################################################################
+# This function makes sure the right set of server is running for the
+# specified test case. This is a useful design when we run single tests as not
+# all servers need to run then!
+#
+# Returns: a string, blank if everything is fine or a reason why it failed, and
+# an integer:
+# 0 for success
+# 1 for an error starting the server
+# 2 for not the first time getting an error starting the server
+# 3 for a failure to stop a server in order to restart it
+# 4 for an unsupported server type
+#
+sub serverfortest {
+ my (@what)=@_;
+
+ for(my $i = scalar(@what) - 1; $i >= 0; $i--) {
+ my $srvrline = $what[$i];
+ chomp $srvrline if($srvrline);
+ if($srvrline =~ /^(\S+)((\s*)(.*))/) {
+ my $server = "${1}";
+ my $lnrest = "${2}";
+ my $tlsext;
+ if($server =~ /^(httptls)(\+)(ext|srp)(\d*)(-ipv6|)$/) {
+ $server = "${1}${4}${5}";
+ $tlsext = uc("TLS-${3}");
+ }
+ if(! grep /^\Q$server\E$/, @protocols) {
+ if(substr($server,0,5) ne "socks") {
+ if($tlsext) {
+ return ("curl lacks $tlsext support", 4);
+ }
+ else {
+ return ("curl lacks $server server support", 4);
+ }
+ }
+ }
+ $what[$i] = "$server$lnrest" if($tlsext);
+ }
+ }
+
+ return &startservers(@what);
+}
+
+
+#######################################################################
+# Start a new thread/process and run the given command line in there.
+# Return the pids (yes plural) of the new child process to the parent.
+#
+sub startnew {
+ my ($cmd, $pidfile, $timeout, $fakepidfile)=@_;
+
+ logmsg "startnew: $cmd\n" if ($verbose);
+
+ my $child = fork();
+
+ if(not defined $child) {
+ logmsg "startnew: fork() failure detected\n";
+ return (-1,-1);
+ }
+
+ if(0 == $child) {
+ # Here we are the child. Run the given command.
+
+ # Flush output.
+ $| = 1;
+
+ # Put an "exec" in front of the command so that the child process
+ # keeps this child's process ID.
+ exec("exec $cmd") || die "Can't exec() $cmd: $!";
+
+ # exec() should never return back here to this process. We protect
+ # ourselves by calling die() just in case something goes really bad.
+ die "error: exec() has returned";
+ }
+
+ # Ugly hack but ssh client and gnutls-serv don't support pid files
+ if ($fakepidfile) {
+ if(open(my $out, ">", "$pidfile")) {
+ print $out $child . "\n";
+ close($out) || die "Failure writing pidfile";
+ logmsg "startnew: $pidfile faked with pid=$child\n" if($verbose);
+ }
+ else {
+ logmsg "startnew: failed to write fake $pidfile with pid=$child\n";
+ }
+ # could/should do a while connect fails sleep a bit and loop
+ portable_sleep($timeout);
+ if (checkdied($child)) {
+ logmsg "startnew: child process has failed to start\n" if($verbose);
+ return (-1,-1);
+ }
+ }
+
+ my $pid2 = 0;
+ my $count = $timeout;
+ while($count--) {
+ $pid2 = pidfromfile($pidfile);
+ if(($pid2 > 0) && pidexists($pid2)) {
+ # if $pid2 is valid, then make sure this pid is alive, as
+ # otherwise it is just likely to be the _previous_ pidfile or
+ # similar!
+ last;
+ }
+ if (checkdied($child)) {
+ logmsg "startnew: child process has died, server might start up\n"
+ if($verbose);
+ # We can't just abort waiting for the server with a
+ # return (-1,-1);
+ # because the server might have forked and could still start
+ # up normally. Instead, just reduce the amount of time we remain
+ # waiting.
+ $count >>= 2;
+ }
+ sleep(1);
+ }
+
+ # Return two PIDs, the one for the child process we spawned and the one
+ # reported by the server itself (in case it forked again on its own).
+ # Both (potentially) need to be killed at the end of the test.
+ return ($child, $pid2);
+}
+
+
+#######################################################################
+# Return the port to use for the given protocol.
+#
+sub protoport {
+ my ($proto) = @_;
+ return $PORT{$proto} || "[not running]";
+}
+
+
+#######################################################################
+# Stop a test server along with pids which aren't in the %run hash yet.
+# This also stops all servers which are relative to the given one.
+#
+sub stopserver {
+ my ($server, $pidlist) = @_;
+
+ #
+ # kill sockfilter processes for pingpong relative server
+ #
+ if($server =~ /^(ftp|imap|pop3|smtp)s?(\d*)(-ipv6|)$/) {
+ my $proto = $1;
+ my $idnum = ($2 && ($2 > 1)) ? $2 : 1;
+ my $ipvnum = ($3 && ($3 =~ /6$/)) ? 6 : 4;
+ killsockfilters("$LOGDIR/$PIDDIR", $proto, $ipvnum, $idnum, $verbose);
+ }
+ #
+ # All servers relative to the given one must be stopped also
+ #
+ my @killservers;
+ if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
+ # given a stunnel based ssl server, also kill non-ssl underlying one
+ push @killservers, "${1}${2}";
+ }
+ elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|-unix|))$/) {
+ # given a non-ssl server, also kill stunnel based ssl piggybacking one
+ push @killservers, "${1}s${2}";
+ }
+ elsif($server =~ /^(socks)((\d*)(-ipv6|))$/) {
+ # given a socks server, also kill ssh underlying one
+ push @killservers, "ssh${2}";
+ }
+ elsif($server =~ /^(ssh)((\d*)(-ipv6|))$/) {
+ # given a ssh server, also kill socks piggybacking one
+ push @killservers, "socks${2}";
+ }
+ if($server eq "http" or $server eq "https") {
+ # since the http2+3 server is a proxy that needs to know about the
+ # dynamic http port it too needs to get restarted when the http server
+ # is killed
+ push @killservers, "http/2";
+ push @killservers, "http/3";
+ }
+ push @killservers, $server;
+ #
+ # kill given pids and server relative ones clearing them in %run hash
+ #
+ foreach my $server (@killservers) {
+ if($run{$server}) {
+ # we must prepend a space since $pidlist may already contain a pid
+ $pidlist .= " $run{$server}";
+ $run{$server} = 0;
+ }
+ $runcert{$server} = 0 if($runcert{$server});
+ }
+ killpid($verbose, $pidlist);
+ #
+ # cleanup server pid files
+ #
+ my $result = 0;
+ foreach my $server (@killservers) {
+ my $pidfile = $serverpidfile{$server};
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ if($err_unexpected) {
+ logmsg "ERROR: ";
+ $result = -1;
+ }
+ else {
+ logmsg "Warning: ";
+ }
+ logmsg "$server server unexpectedly alive\n";
+ killpid($verbose, $pid);
+ }
+ unlink($pidfile) if(-f $pidfile);
+ }
+
+ return $result;
+}
+
+
+#######################################################################
+# Return flags to let curl use an external HTTP proxy
+#
+sub getexternalproxyflags {
+ return " --proxy $proxy_address ";
+}
+
+#######################################################################
+# Verify that the server that runs on $ip, $port is our server. This also
+# implies that we can speak with it, as there might be occasions when the
+# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
+# assign requested address")
+#
+sub verifyhttp {
+ my ($proto, $ipvnum, $idnum, $ip, $port_or_path) = @_;
+ my $server = servername_id($proto, $ipvnum, $idnum);
+ my $bonus="";
+ # $port_or_path contains a path for Unix sockets, sws ignores the port
+ my $port = ($ipvnum eq "unix") ? 80 : $port_or_path;
+
+ my $verifyout = "$LOGDIR/".
+ servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
+ unlink($verifyout) if(-f $verifyout);
+
+ my $verifylog = "$LOGDIR/".
+ servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
+ unlink($verifylog) if(-f $verifylog);
+
+ if($proto eq "gopher") {
+ # gopher is funny
+ $bonus="1/";
+ }
+
+ my $flags = "--max-time $server_response_maxtime ";
+ $flags .= "--output $verifyout ";
+ $flags .= "--silent ";
+ $flags .= "--verbose ";
+ $flags .= "--globoff ";
+ $flags .= "--unix-socket '$port_or_path' " if $ipvnum eq "unix";
+ $flags .= "--insecure " if($proto eq 'https');
+ if($proxy_address) {
+ $flags .= getexternalproxyflags();
+ }
+ $flags .= "\"$proto://$ip:$port/${bonus}verifiedserver\"";
+
+ my $cmd = "$VCURL $flags 2>$verifylog";
+
+ # verify if our/any server is running on this port
+ logmsg "RUN: $cmd\n" if($verbose);
+ my $res = runclient($cmd);
+
+ $res >>= 8; # rotate the result
+ if($res & 128) {
+ logmsg "RUN: curl command died with a coredump\n";
+ return -1;
+ }
+
+ if($res && $verbose) {
+ logmsg "RUN: curl command returned $res\n";
+ if(open(my $file, "<", "$verifylog")) {
+ while(my $string = <$file>) {
+ logmsg "RUN: $string" if($string !~ /^([ \t]*)$/);
+ }
+ close($file);
+ }
+ }
+
+ my $data;
+ if(open(my $file, "<", "$verifyout")) {
+ while(my $string = <$file>) {
+ $data = $string;
+ last; # only want first line
+ }
+ close($file);
+ }
+
+ my $pid = 0;
+ if($data && ($data =~ /WE ROOLZ: (\d+)/)) {
+ $pid = 0+$1;
+ }
+ elsif($res == 6) {
+ # curl: (6) Couldn't resolve host '::1'
+ logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n";
+ return -1;
+ }
+ elsif($data || ($res && ($res != 7))) {
+ logmsg "RUN: Unknown server on our $server port: $port ($res)\n";
+ return -1;
+ }
+ return $pid;
+}
+
+#######################################################################
+# Verify that the server that runs on $ip, $port is our server. This also
+# implies that we can speak with it, as there might be occasions when the
+# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
+# assign requested address")
+#
+sub verifyftp {
+ my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
+ my $server = servername_id($proto, $ipvnum, $idnum);
+ my $time=time();
+ my $extra="";
+
+ my $verifylog = "$LOGDIR/".
+ servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
+ unlink($verifylog) if(-f $verifylog);
+
+ if($proto eq "ftps") {
+ $extra .= "--insecure --ftp-ssl-control ";
+ }
+
+ my $flags = "--max-time $server_response_maxtime ";
+ $flags .= "--silent ";
+ $flags .= "--verbose ";
+ $flags .= "--globoff ";
+ $flags .= $extra;
+ if($proxy_address) {
+ $flags .= getexternalproxyflags();
+ }
+ $flags .= "\"$proto://$ip:$port/verifiedserver\"";
+
+ my $cmd = "$VCURL $flags 2>$verifylog";
+
+ # check if this is our server running on this port:
+ logmsg "RUN: $cmd\n" if($verbose);
+ my @data = runclientoutput($cmd);
+
+ my $res = $? >> 8; # rotate the result
+ if($res & 128) {
+ logmsg "RUN: curl command died with a coredump\n";
+ return -1;
+ }
+
+ my $pid = 0;
+ foreach my $line (@data) {
+ if($line =~ /WE ROOLZ: (\d+)/) {
+ # this is our test server with a known pid!
+ $pid = 0+$1;
+ last;
+ }
+ }
+ if($pid <= 0 && @data && $data[0]) {
+ # this is not a known server
+ logmsg "RUN: Unknown server on our $server port: $port\n";
+ return 0;
+ }
+ # we can/should use the time it took to verify the FTP server as a measure
+ # on how fast/slow this host/FTP is.
+ my $took = int(0.5+time()-$time);
+
+ if($verbose) {
+ logmsg "RUN: Verifying our test $server server took $took seconds\n";
+ }
+ $ftpchecktime = $took>=1?$took:1; # make sure it never is below 1
+
+ return $pid;
+}
+
+#######################################################################
+# Verify that the server that runs on $ip, $port is our server. This also
+# implies that we can speak with it, as there might be occasions when the
+# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
+# assign requested address")
+#
+sub verifyrtsp {
+ my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $verifyout = "$LOGDIR/".
+ servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
+ unlink($verifyout) if(-f $verifyout);
+
+ my $verifylog = "$LOGDIR/".
+ servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
+ unlink($verifylog) if(-f $verifylog);
+
+ my $flags = "--max-time $server_response_maxtime ";
+ $flags .= "--output $verifyout ";
+ $flags .= "--silent ";
+ $flags .= "--verbose ";
+ $flags .= "--globoff ";
+ if($proxy_address) {
+ $flags .= getexternalproxyflags();
+ }
+ # currently verification is done using http
+ $flags .= "\"http://$ip:$port/verifiedserver\"";
+
+ my $cmd = "$VCURL $flags 2>$verifylog";
+
+ # verify if our/any server is running on this port
+ logmsg "RUN: $cmd\n" if($verbose);
+ my $res = runclient($cmd);
+
+ $res >>= 8; # rotate the result
+ if($res & 128) {
+ logmsg "RUN: curl command died with a coredump\n";
+ return -1;
+ }
+
+ if($res && $verbose) {
+ logmsg "RUN: curl command returned $res\n";
+ if(open(my $file, "<", "$verifylog")) {
+ while(my $string = <$file>) {
+ logmsg "RUN: $string" if($string !~ /^[ \t]*$/);
+ }
+ close($file);
+ }
+ }
+
+ my $data;
+ if(open(my $file, "<", "$verifyout")) {
+ while(my $string = <$file>) {
+ $data = $string;
+ last; # only want first line
+ }
+ close($file);
+ }
+
+ my $pid = 0;
+ if($data && ($data =~ /RTSP_SERVER WE ROOLZ: (\d+)/)) {
+ $pid = 0+$1;
+ }
+ elsif($res == 6) {
+ # curl: (6) Couldn't resolve host '::1'
+ logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n";
+ return -1;
+ }
+ elsif($data || ($res != 7)) {
+ logmsg "RUN: Unknown server on our $server port: $port\n";
+ return -1;
+ }
+ return $pid;
+}
+
+#######################################################################
+# Verify that the ssh server has written out its pidfile, recovering
+# the pid from the file and returning it if a process with that pid is
+# actually alive, or a negative value if the process is dead.
+#
+sub verifyssh {
+ my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
+ my $pidfile = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
+ $idnum);
+ my $pid = processexists($pidfile);
+ if($pid < 0) {
+ logmsg "RUN: SSH server has died after starting up\n";
+ }
+ return $pid;
+}
+
+#######################################################################
+# Verify that we can connect to the sftp server, properly authenticate
+# with generated config and key files and run a simple remote pwd.
+#
+sub verifysftp {
+ my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
+ my $server = servername_id($proto, $ipvnum, $idnum);
+ my $verified = 0;
+ # Find out sftp client canonical file name
+ my $sftp = find_sftp();
+ if(!$sftp) {
+ logmsg "RUN: SFTP server cannot find $sftpexe\n";
+ return -1;
+ }
+ # Find out ssh client canonical file name
+ my $ssh = find_ssh();
+ if(!$ssh) {
+ logmsg "RUN: SFTP server cannot find $sshexe\n";
+ return -1;
+ }
+ # Connect to sftp server, authenticate and run a remote pwd
+ # command using our generated configuration and key files
+ my $cmd = "\"$sftp\" -b $LOGDIR/$PIDDIR/$sftpcmds -F $LOGDIR/$PIDDIR/$sftpconfig -S \"$ssh\" $ip > $sftplog 2>&1";
+ my $res = runclient($cmd);
+ # Search for pwd command response in log file
+ if(open(my $sftplogfile, "<", "$sftplog")) {
+ while(<$sftplogfile>) {
+ if(/^Remote working directory: /) {
+ $verified = 1;
+ last;
+ }
+ }
+ close($sftplogfile);
+ }
+ return $verified;
+}
+
+#######################################################################
+# Verify that the non-stunnel HTTP TLS extensions capable server that runs
+# on $ip, $port is our server. This also implies that we can speak with it,
+# as there might be occasions when the server runs fine but we cannot talk
+# to it ("Failed to connect to ::1: Can't assign requested address")
+#
+sub verifyhttptls {
+ my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
+ my $server = servername_id($proto, $ipvnum, $idnum);
+ my $pidfile = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
+ $idnum);
+
+ my $verifyout = "$LOGDIR/".
+ servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
+ unlink($verifyout) if(-f $verifyout);
+
+ my $verifylog = "$LOGDIR/".
+ servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
+ unlink($verifylog) if(-f $verifylog);
+
+ my $flags = "--max-time $server_response_maxtime ";
+ $flags .= "--output $verifyout ";
+ $flags .= "--verbose ";
+ $flags .= "--globoff ";
+ $flags .= "--insecure ";
+ $flags .= "--tlsauthtype SRP ";
+ $flags .= "--tlsuser jsmith ";
+ $flags .= "--tlspassword abc ";
+ if($proxy_address) {
+ $flags .= getexternalproxyflags();
+ }
+ $flags .= "\"https://$ip:$port/verifiedserver\"";
+
+ my $cmd = "$VCURL $flags 2>$verifylog";
+
+ # verify if our/any server is running on this port
+ logmsg "RUN: $cmd\n" if($verbose);
+ my $res = runclient($cmd);
+
+ $res >>= 8; # rotate the result
+ if($res & 128) {
+ logmsg "RUN: curl command died with a coredump\n";
+ return -1;
+ }
+
+ if($res && $verbose) {
+ logmsg "RUN: curl command returned $res\n";
+ if(open(my $file, "<", "$verifylog")) {
+ while(my $string = <$file>) {
+ logmsg "RUN: $string" if($string !~ /^([ \t]*)$/);
+ }
+ close($file);
+ }
+ }
+
+ my $data;
+ if(open(my $file, "<", "$verifyout")) {
+ while(my $string = <$file>) {
+ $data .= $string;
+ }
+ close($file);
+ }
+
+ my $pid = 0;
+ if($data && ($data =~ /(GNUTLS|GnuTLS)/) && ($pid = processexists($pidfile))) {
+ if($pid < 0) {
+ logmsg "RUN: $server server has died after starting up\n";
+ }
+ return $pid;
+ }
+ elsif($res == 6) {
+ # curl: (6) Couldn't resolve host '::1'
+ logmsg "RUN: failed to resolve host (https://$ip:$port/verifiedserver)\n";
+ return -1;
+ }
+ elsif($data || ($res && ($res != 7))) {
+ logmsg "RUN: Unknown server on our $server port: $port ($res)\n";
+ return -1;
+ }
+ return $pid;
+}
+
+#######################################################################
+# STUB for verifying socks
+#
+sub verifysocks {
+ my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
+ my $pidfile = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
+ $idnum);
+ my $pid = processexists($pidfile);
+ if($pid < 0) {
+ logmsg "RUN: SOCKS server has died after starting up\n";
+ }
+ return $pid;
+}
+
+#######################################################################
+# Verify that the server that runs on $ip, $port is our server. This also
+# implies that we can speak with it, as there might be occasions when the
+# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
+# assign requested address")
+#
+sub verifysmb {
+ my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
+ my $server = servername_id($proto, $ipvnum, $idnum);
+ my $time=time();
+ my $extra="";
+
+ my $verifylog = "$LOGDIR/".
+ servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
+ unlink($verifylog) if(-f $verifylog);
+
+ my $flags = "--max-time $server_response_maxtime ";
+ $flags .= "--silent ";
+ $flags .= "--verbose ";
+ $flags .= "--globoff ";
+ $flags .= "-u 'curltest:curltest' ";
+ $flags .= $extra;
+ $flags .= "\"$proto://$ip:$port/SERVER/verifiedserver\"";
+
+ my $cmd = "$VCURL $flags 2>$verifylog";
+
+ # check if this is our server running on this port:
+ logmsg "RUN: $cmd\n" if($verbose);
+ my @data = runclientoutput($cmd);
+
+ my $res = $? >> 8; # rotate the result
+ if($res & 128) {
+ logmsg "RUN: curl command died with a coredump\n";
+ return -1;
+ }
+
+ my $pid = 0;
+ foreach my $line (@data) {
+ if($line =~ /WE ROOLZ: (\d+)/) {
+ # this is our test server with a known pid!
+ $pid = 0+$1;
+ last;
+ }
+ }
+ if($pid <= 0 && @data && $data[0]) {
+ # this is not a known server
+ logmsg "RUN: Unknown server on our $server port: $port\n";
+ return 0;
+ }
+ # we can/should use the time it took to verify the server as a measure
+ # on how fast/slow this host is.
+ my $took = int(0.5+time()-$time);
+
+ if($verbose) {
+ logmsg "RUN: Verifying our test $server server took $took seconds\n";
+ }
+
+ return $pid;
+}
+
+#######################################################################
+# Verify that the server that runs on $ip, $port is our server. This also
+# implies that we can speak with it, as there might be occasions when the
+# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
+# assign requested address")
+#
+sub verifytelnet {
+ my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
+ my $server = servername_id($proto, $ipvnum, $idnum);
+ my $time=time();
+ my $extra="";
+
+ my $verifylog = "$LOGDIR/".
+ servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
+ unlink($verifylog) if(-f $verifylog);
+
+ my $flags = "--max-time $server_response_maxtime ";
+ $flags .= "--silent ";
+ $flags .= "--verbose ";
+ $flags .= "--globoff ";
+ $flags .= "--upload-file - ";
+ $flags .= $extra;
+ $flags .= "\"$proto://$ip:$port\"";
+
+ my $cmd = "echo 'verifiedserver' | $VCURL $flags 2>$verifylog";
+
+ # check if this is our server running on this port:
+ logmsg "RUN: $cmd\n" if($verbose);
+ my @data = runclientoutput($cmd);
+
+ my $res = $? >> 8; # rotate the result
+ if($res & 128) {
+ logmsg "RUN: curl command died with a coredump\n";
+ return -1;
+ }
+
+ my $pid = 0;
+ foreach my $line (@data) {
+ if($line =~ /WE ROOLZ: (\d+)/) {
+ # this is our test server with a known pid!
+ $pid = 0+$1;
+ last;
+ }
+ }
+ if($pid <= 0 && @data && $data[0]) {
+ # this is not a known server
+ logmsg "RUN: Unknown server on our $server port: $port\n";
+ return 0;
+ }
+ # we can/should use the time it took to verify the server as a measure
+ # on how fast/slow this host is.
+ my $took = int(0.5+time()-$time);
+
+ if($verbose) {
+ logmsg "RUN: Verifying our test $server server took $took seconds\n";
+ }
+
+ return $pid;
+}
+
+#######################################################################
+# Verify that the server that runs on $ip, $port is our server.
+# Retry over several seconds before giving up. The ssh server in
+# particular can take a long time to start if it needs to generate
+# keys on a slow or loaded host.
+#
+# Just for convenience, test harness uses 'https' and 'httptls' literals
+# as values for 'proto' variable in order to differentiate different
+# servers. 'https' literal is used for stunnel based https test servers,
+# and 'httptls' is used for non-stunnel https test servers.
+#
+
+my %protofunc = ('http' => \&verifyhttp,
+ 'https' => \&verifyhttp,
+ 'rtsp' => \&verifyrtsp,
+ 'ftp' => \&verifyftp,
+ 'pop3' => \&verifyftp,
+ 'imap' => \&verifyftp,
+ 'smtp' => \&verifyftp,
+ 'ftps' => \&verifyftp,
+ 'pop3s' => \&verifyftp,
+ 'imaps' => \&verifyftp,
+ 'smtps' => \&verifyftp,
+ 'tftp' => \&verifyftp,
+ 'ssh' => \&verifyssh,
+ 'socks' => \&verifysocks,
+ 'socks5unix' => \&verifysocks,
+ 'gopher' => \&verifyhttp,
+ 'httptls' => \&verifyhttptls,
+ 'dict' => \&verifyftp,
+ 'smb' => \&verifysmb,
+ 'telnet' => \&verifytelnet);
+
+sub verifyserver {
+ my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
+
+ my $count = 30; # try for this many seconds
+ my $pid;
+
+ while($count--) {
+ my $fun = $protofunc{$proto};
+
+ $pid = &$fun($proto, $ipvnum, $idnum, $ip, $port);
+
+ if($pid > 0) {
+ last;
+ }
+ elsif($pid < 0) {
+ # a real failure, stop trying and bail out
+ return 0;
+ }
+ sleep(1);
+ }
+ return $pid;
+}
+
+#######################################################################
+# Single shot server responsiveness test. This should only be used
+# to verify that a server present in %run hash is still functional
+#
+sub responsiveserver {
+ my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
+ my $prev_verbose = $verbose;
+
+ $verbose = 0;
+ my $fun = $protofunc{$proto};
+ my $pid = &$fun($proto, $ipvnum, $idnum, $ip, $port);
+ $verbose = $prev_verbose;
+
+ if($pid > 0) {
+ return 1; # responsive
+ }
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ logmsg " server precheck FAILED (unresponsive $srvrname server)\n";
+ return 0;
+}
+
+
+#######################################################################
+# start the http server
+#
+sub runhttpserver {
+ my ($proto, $verb, $alt, $port_or_path) = @_;
+ my $ip = $HOSTIP;
+ my $ipvnum = 4;
+ my $idnum = 1;
+ my $exe = "$perl $srcdir/http-server.pl";
+ my $verbose_flag = "--verbose ";
+ my $keepalive_secs = 30; # forwarded to sws, was 5 by default which
+ # led to pukes in CI jobs
+
+ if($alt eq "ipv6") {
+ # if IPv6, use a different setup
+ $ipvnum = 6;
+ $ip = $HOST6IP;
+ }
+ elsif($alt eq "proxy") {
+ # basically the same, but another ID
+ $idnum = 2;
+ }
+ elsif($alt eq "unix") {
+ # IP (protocol) is mutually exclusive with Unix sockets
+ $ipvnum = "unix";
+ }
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $portfile = $serverportfile{$server};
+
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--gopher " if($proto eq "gopher");
+ $flags .= "--connect $HOSTIP " if($alt eq "proxy");
+ $flags .= "--keepalive $keepalive_secs ";
+ $flags .= $verbose_flag if($debugprotocol);
+ $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
+ $flags .= "--logdir \"$LOGDIR\" ";
+ $flags .= "--portfile $portfile ";
+ $flags .= "--config $LOGDIR/$SERVERCMD ";
+ $flags .= "--id $idnum " if($idnum > 1);
+ if($ipvnum eq "unix") {
+ $flags .= "--unix-socket '$port_or_path' ";
+ } else {
+ $flags .= "--ipv$ipvnum --port 0 ";
+ }
+ $flags .= "--srcdir \"$srcdir\"";
+
+ my $cmd = "$exe $flags";
+ my ($httppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
+
+ if($httppid <= 0 || !pidexists($httppid)) {
+ # it is NOT alive
+ logmsg "RUN: failed to start the $srvrname server\n";
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ return (1, 0, 0, 0);
+ }
+
+ # where is it?
+ my $port = 0;
+ if(!$port_or_path) {
+ $port = $port_or_path = pidfromfile($portfile);
+ }
+
+ # Server is up. Verify that we can speak to it.
+ my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
+ if(!$pid3) {
+ logmsg "RUN: $srvrname server failed verification\n";
+ # failed to talk to it properly. Kill the server and return failure
+ stopserver($server, "$httppid $pid2");
+ $doesntrun{$pidfile} = 1;
+ return (1, 0, 0, 0);
+ }
+ $pid2 = $pid3;
+
+ if($verb) {
+ logmsg "RUN: $srvrname server is on PID $httppid port $port_or_path\n";
+ }
+
+ return (0, $httppid, $pid2, $port);
+}
+
+
+#######################################################################
+# start the http2 server
+#
+sub runhttp2server {
+ my ($verb) = @_;
+ my $proto="http/2";
+ my $ipvnum = 4;
+ my $idnum = 0;
+ my $exe = "$perl $srcdir/http2-server.pl";
+ my $verbose_flag = "--verbose ";
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--nghttpx \"$ENV{'NGHTTPX'}\" ";
+ $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
+ $flags .= "--logdir \"$LOGDIR\" ";
+ $flags .= "--connect $HOSTIP:" . protoport("http") . " ";
+ $flags .= $verbose_flag if($debugprotocol);
+
+ my $port = getfreeport($ipvnum);
+ my $port2 = getfreeport($ipvnum);
+ my $aflags = "--port $port --port2 $port2 $flags";
+ my $cmd = "$exe $aflags";
+ my ($http2pid, $pid2) = startnew($cmd, $pidfile, 15, 0);
+
+ if($http2pid <= 0 || !pidexists($http2pid)) {
+ # it is NOT alive
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ $http2pid = $pid2 = 0;
+ logmsg "RUN: failed to start the $srvrname server\n";
+ return (3, 0, 0, 0, 0);
+ }
+ $doesntrun{$pidfile} = 0;
+
+ if($verb) {
+ logmsg "RUN: $srvrname server PID $http2pid ".
+ "http-port $port https-port $port2 ".
+ "backend $HOSTIP:" . protoport("http") . "\n";
+ }
+
+ return (0+!$http2pid, $http2pid, $pid2, $port, $port2);
+}
+
+#######################################################################
+# start the http3 server
+#
+sub runhttp3server {
+ my ($verb, $cert) = @_;
+ my $proto="http/3";
+ my $ipvnum = 4;
+ my $idnum = 0;
+ my $exe = "$perl $srcdir/http3-server.pl";
+ my $verbose_flag = "--verbose ";
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--nghttpx \"$ENV{'NGHTTPX'}\" ";
+ $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
+ $flags .= "--logdir \"$LOGDIR\" ";
+ $flags .= "--connect $HOSTIP:" . protoport("http") . " ";
+ $flags .= "--cert \"$cert\" " if($cert);
+ $flags .= $verbose_flag if($debugprotocol);
+
+ my $port = getfreeport($ipvnum);
+ my $aflags = "--port $port $flags";
+ my $cmd = "$exe $aflags";
+ my ($http3pid, $pid3) = startnew($cmd, $pidfile, 15, 0);
+
+ if($http3pid <= 0 || !pidexists($http3pid)) {
+ # it is NOT alive
+ stopserver($server, "$pid3");
+ $doesntrun{$pidfile} = 1;
+ $http3pid = $pid3 = 0;
+ logmsg "RUN: failed to start the $srvrname server\n";
+ return (3, 0, 0, 0);
+ }
+ $doesntrun{$pidfile} = 0;
+
+ if($verb) {
+ logmsg "RUN: $srvrname server PID $http3pid port $port\n";
+ }
+
+ return (0+!$http3pid, $http3pid, $pid3, $port);
+}
+
+#######################################################################
+# start the https stunnel based server
+#
+sub runhttpsserver {
+ my ($verb, $proto, $proxy, $certfile) = @_;
+ my $ip = $HOSTIP;
+ my $ipvnum = 4;
+ my $idnum = 1;
+
+ if($proxy eq "proxy") {
+ # the https-proxy runs as https2
+ $idnum = 2;
+ }
+
+ if(!$stunnel) {
+ return (4, 0, 0, 0);
+ }
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ $certfile = 'stunnel.pem' unless($certfile);
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--verbose " if($debugprotocol);
+ $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
+ $flags .= "--logdir \"$LOGDIR\" ";
+ $flags .= "--id $idnum " if($idnum > 1);
+ $flags .= "--ipv$ipvnum --proto $proto ";
+ $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
+ $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
+ if($proto eq "gophers") {
+ $flags .= "--connect " . protoport("gopher");
+ }
+ elsif(!$proxy) {
+ $flags .= "--connect " . protoport("http");
+ }
+ else {
+ # for HTTPS-proxy we connect to the HTTP proxy
+ $flags .= "--connect " . protoport("httpproxy");
+ }
+
+ my $port = getfreeport($ipvnum);
+ my $options = "$flags --accept $port";
+ my $cmd = "$perl $srcdir/secureserver.pl $options";
+ my ($httpspid, $pid2) = startnew($cmd, $pidfile, 15, 0);
+
+ if($httpspid <= 0 || !pidexists($httpspid)) {
+ # it is NOT alive
+ # don't call stopserver since that will also kill the dependent
+ # server that has already been started properly
+ $doesntrun{$pidfile} = 1;
+ $httpspid = $pid2 = 0;
+ logmsg "RUN: failed to start the $srvrname server\n";
+ return (3, 0, 0, 0);
+ }
+
+ $doesntrun{$pidfile} = 0;
+ # we have a server!
+ if($verb) {
+ logmsg "RUN: $srvrname server is PID $httpspid port $port\n";
+ }
+
+ $runcert{$server} = $certfile;
+
+ return (0+!$httpspid, $httpspid, $pid2, $port);
+}
+
+#######################################################################
+# start the non-stunnel HTTP TLS extensions capable server
+#
+sub runhttptlsserver {
+ my ($verb, $ipv6) = @_;
+ my $proto = "httptls";
+ my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
+ my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
+ my $idnum = 1;
+
+ if(!$httptlssrv) {
+ return (4, 0, 0);
+ }
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--http ";
+ $flags .= "--debug 1 " if($debugprotocol);
+ $flags .= "--priority NORMAL:+SRP ";
+ $flags .= "--srppasswd $srcdir/certs/srp-verifier-db ";
+ $flags .= "--srppasswdconf $srcdir/certs/srp-verifier-conf";
+
+ my $port = getfreeport($ipvnum);
+ my $allflags = "--port $port $flags";
+ my $cmd = "$httptlssrv $allflags > $logfile 2>&1";
+ my ($httptlspid, $pid2) = startnew($cmd, $pidfile, 10, 1);
+
+ if($httptlspid <= 0 || !pidexists($httptlspid)) {
+ # it is NOT alive
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ $httptlspid = $pid2 = 0;
+ logmsg "RUN: failed to start the $srvrname server\n";
+ return (3, 0, 0, 0);
+ }
+ $doesntrun{$pidfile} = 0;
+
+ if($verb) {
+ logmsg "RUN: $srvrname server PID $httptlspid port $port\n";
+ }
+ return (0+!$httptlspid, $httptlspid, $pid2, $port);
+}
+
+#######################################################################
+# start the pingpong server (FTP, POP3, IMAP, SMTP)
+#
+sub runpingpongserver {
+ my ($proto, $id, $verb, $ipv6) = @_;
+
+ # Check the requested server
+ if($proto !~ /^(?:ftp|imap|pop3|smtp)$/) {
+ logmsg "Unsupported protocol $proto!!\n";
+ return (4, 0, 0);
+ }
+
+ my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
+ my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
+ my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+ my $portfile = $serverportfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--verbose " if($debugprotocol);
+ $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
+ $flags .= "--logdir \"$LOGDIR\" ";
+ $flags .= "--portfile \"$portfile\" ";
+ $flags .= "--srcdir \"$srcdir\" --proto $proto ";
+ $flags .= "--id $idnum " if($idnum > 1);
+ $flags .= "--ipv$ipvnum --port 0 --addr \"$ip\"";
+
+ my $cmd = "$perl $srcdir/ftpserver.pl $flags";
+ my ($ftppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
+
+ if($ftppid <= 0 || !pidexists($ftppid)) {
+ # it is NOT alive
+ logmsg "RUN: failed to start the $srvrname server\n";
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ return (1, 0, 0);
+ }
+
+ # where is it?
+ my $port = pidfromfile($portfile);
+
+ logmsg "PINGPONG runs on port $port ($portfile)\n" if($verb);
+
+ # Server is up. Verify that we can speak to it.
+ my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
+ if(!$pid3) {
+ logmsg "RUN: $srvrname server failed verification\n";
+ # failed to talk to it properly. Kill the server and return failure
+ stopserver($server, "$ftppid $pid2");
+ $doesntrun{$pidfile} = 1;
+ return (1, 0, 0);
+ }
+ $pid2 = $pid3;
+
+ logmsg "RUN: $srvrname server is PID $ftppid port $port\n" if($verb);
+
+ # Assign the correct port variable!
+ $PORT{$proto . ($ipvnum == 6? '6': '')} = $port;
+
+ return (0, $pid2, $ftppid);
+}
+
+#######################################################################
+# start the ftps/imaps/pop3s/smtps server (or rather, tunnel)
+#
+sub runsecureserver {
+ my ($verb, $ipv6, $certfile, $proto, $clearport) = @_;
+ my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
+ my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
+ my $idnum = 1;
+
+ if(!$stunnel) {
+ return (4, 0, 0, 0);
+ }
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ $certfile = 'stunnel.pem' unless($certfile);
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--verbose " if($debugprotocol);
+ $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
+ $flags .= "--logdir \"$LOGDIR\" ";
+ $flags .= "--id $idnum " if($idnum > 1);
+ $flags .= "--ipv$ipvnum --proto $proto ";
+ $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
+ $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
+ $flags .= "--connect $clearport";
+
+ my $port = getfreeport($ipvnum);
+ my $options = "$flags --accept $port";
+
+ my $cmd = "$perl $srcdir/secureserver.pl $options";
+ my ($protospid, $pid2) = startnew($cmd, $pidfile, 15, 0);
+
+ if($protospid <= 0 || !pidexists($protospid)) {
+ # it is NOT alive
+ # don't call stopserver since that will also kill the dependent
+ # server that has already been started properly
+ $doesntrun{$pidfile} = 1;
+ $protospid = $pid2 = 0;
+ logmsg "RUN: failed to start the $srvrname server\n";
+ return (3, 0, 0, 0);
+ }
+
+ $doesntrun{$pidfile} = 0;
+ $runcert{$server} = $certfile;
+
+ if($verb) {
+ logmsg "RUN: $srvrname server is PID $protospid port $port\n";
+ }
+
+ return (0+!$protospid, $protospid, $pid2, $port);
+}
+
+#######################################################################
+# start the tftp server
+#
+sub runtftpserver {
+ my ($id, $verb, $ipv6) = @_;
+ my $ip = $HOSTIP;
+ my $proto = 'tftp';
+ my $ipvnum = 4;
+ my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
+
+ if($ipv6) {
+ # if IPv6, use a different setup
+ $ipvnum = 6;
+ $ip = $HOST6IP;
+ }
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $portfile = $serverportfile{$server};
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--verbose " if($debugprotocol);
+ $flags .= "--pidfile \"$pidfile\" ";
+ $flags .= "--portfile \"$portfile\" ";
+ $flags .= "--logfile \"$logfile\" ";
+ $flags .= "--logdir \"$LOGDIR\" ";
+ $flags .= "--id $idnum " if($idnum > 1);
+ $flags .= "--ipv$ipvnum --port 0 --srcdir \"$srcdir\"";
+
+ my $cmd = "$perl $srcdir/tftpserver.pl $flags";
+ my ($tftppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
+
+ if($tftppid <= 0 || !pidexists($tftppid)) {
+ # it is NOT alive
+ logmsg "RUN: failed to start the $srvrname server\n";
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ return (1, 0, 0, 0);
+ }
+
+ my $port = pidfromfile($portfile);
+
+ # Server is up. Verify that we can speak to it.
+ my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
+ if(!$pid3) {
+ logmsg "RUN: $srvrname server failed verification\n";
+ # failed to talk to it properly. Kill the server and return failure
+ stopserver($server, "$tftppid $pid2");
+ $doesntrun{$pidfile} = 1;
+ return (1, 0, 0, 0);
+ }
+ $pid2 = $pid3;
+
+ if($verb) {
+ logmsg "RUN: $srvrname server on PID $tftppid port $port\n";
+ }
+
+ return (0, $pid2, $tftppid, $port);
+}
+
+
+#######################################################################
+# start the rtsp server
+#
+sub runrtspserver {
+ my ($verb, $ipv6) = @_;
+ my $ip = $HOSTIP;
+ my $proto = 'rtsp';
+ my $ipvnum = 4;
+ my $idnum = 1;
+
+ if($ipv6) {
+ # if IPv6, use a different setup
+ $ipvnum = 6;
+ $ip = $HOST6IP;
+ }
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+ my $portfile = $serverportfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--verbose " if($debugprotocol);
+ $flags .= "--pidfile \"$pidfile\" ";
+ $flags .= "--portfile \"$portfile\" ";
+ $flags .= "--logfile \"$logfile\" ";
+ $flags .= "--logdir \"$LOGDIR\" ";
+ $flags .= "--id $idnum " if($idnum > 1);
+ $flags .= "--ipv$ipvnum --port 0 --srcdir \"$srcdir\"";
+
+ my $cmd = "$perl $srcdir/rtspserver.pl $flags";
+ my ($rtsppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
+
+ if($rtsppid <= 0 || !pidexists($rtsppid)) {
+ # it is NOT alive
+ logmsg "RUN: failed to start the $srvrname server\n";
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ return (1, 0, 0, 0);
+ }
+
+ my $port = pidfromfile($portfile);
+
+ # Server is up. Verify that we can speak to it.
+ my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
+ if(!$pid3) {
+ logmsg "RUN: $srvrname server failed verification\n";
+ # failed to talk to it properly. Kill the server and return failure
+ stopserver($server, "$rtsppid $pid2");
+ $doesntrun{$pidfile} = 1;
+ return (1, 0, 0, 0);
+ }
+ $pid2 = $pid3;
+
+ if($verb) {
+ logmsg "RUN: $srvrname server PID $rtsppid port $port\n";
+ }
+
+ return (0, $rtsppid, $pid2, $port);
+}
+
+
+#######################################################################
+# Start the ssh (scp/sftp) server
+#
+sub runsshserver {
+ my ($id, $verb, $ipv6) = @_;
+ my $ip=$HOSTIP;
+ my $proto = 'ssh';
+ my $ipvnum = 4;
+ my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
+
+ if(!$USER) {
+ logmsg "Can't start ssh server due to lack of USER name\n";
+ return (4, 0, 0, 0);
+ }
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0);
+ }
+
+ my $sshd = find_sshd();
+ if($sshd) {
+ ($sshdid,$sshdvernum,$sshdverstr,$sshderror) = sshversioninfo($sshd);
+ logmsg $sshderror if($sshderror);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--verbose " if($verb);
+ $flags .= "--debugprotocol " if($debugprotocol);
+ $flags .= "--pidfile \"$pidfile\" ";
+ $flags .= "--logdir \"$LOGDIR\" ";
+ $flags .= "--id $idnum " if($idnum > 1);
+ $flags .= "--ipv$ipvnum --addr \"$ip\" ";
+ $flags .= "--user \"$USER\"";
+
+ my @tports;
+ my $port = getfreeport($ipvnum);
+
+ push @tports, $port;
+
+ my $options = "$flags --sshport $port";
+
+ my $cmd = "$perl $srcdir/sshserver.pl $options";
+ my ($sshpid, $pid2) = startnew($cmd, $pidfile, 60, 0);
+
+ # on loaded systems sshserver start up can take longer than the
+ # timeout passed to startnew, when this happens startnew completes
+ # without being able to read the pidfile and consequently returns a
+ # zero pid2 above.
+ if($sshpid <= 0 || !pidexists($sshpid)) {
+ # it is NOT alive
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ $sshpid = $pid2 = 0;
+ logmsg "RUN: failed to start the $srvrname server on $port\n";
+ return (3, 0, 0, 0);
+ }
+
+ # once it is known that the ssh server is alive, sftp server
+ # verification is performed actually connecting to it, authenticating
+ # and performing a very simple remote command. This verification is
+ # tried only one time.
+
+ $sshdlog = server_logfilename($LOGDIR, 'ssh', $ipvnum, $idnum);
+ $sftplog = server_logfilename($LOGDIR, 'sftp', $ipvnum, $idnum);
+
+ if(verifysftp('sftp', $ipvnum, $idnum, $ip, $port) < 1) {
+ logmsg "RUN: SFTP server failed verification\n";
+ # failed to talk to it properly. Kill the server and return failure
+ display_sftplog();
+ display_sftpconfig();
+ display_sshdlog();
+ display_sshdconfig();
+ stopserver($server, "$sshpid $pid2");
+ $doesntrun{$pidfile} = 1;
+ $sshpid = $pid2 = 0;
+ logmsg "RUN: failed to verifty the $srvrname server on $port\n";
+ return (5, 0, 0, 0);
+ }
+ # we're happy, no need to loop anymore!
+ $doesntrun{$pidfile} = 0;
+
+ my $hostfile;
+ if(!open($hostfile, "<", "$LOGDIR/$PIDDIR/$hstpubmd5f") ||
+ (read($hostfile, $SSHSRVMD5, 32) != 32) ||
+ !close($hostfile) ||
+ ($SSHSRVMD5 !~ /^[a-f0-9]{32}$/i))
+ {
+ my $msg = "Fatal: $srvrname pubkey md5 missing : \"$hstpubmd5f\" : $!";
+ logmsg "$msg\n";
+ stopservers($verb);
+ die $msg;
+ }
+
+ if(!open($hostfile, "<", "$LOGDIR/$PIDDIR/$hstpubsha256f") ||
+ (read($hostfile, $SSHSRVSHA256, 48) == 0) ||
+ !close($hostfile))
+ {
+ my $msg = "Fatal: $srvrname pubkey sha256 missing : \"$hstpubsha256f\" : $!";
+ logmsg "$msg\n";
+ stopservers($verb);
+ die $msg;
+ }
+
+ logmsg "RUN: $srvrname on PID $pid2 port $port\n" if($verb);
+
+ return (0, $pid2, $sshpid, $port);
+}
+
+#######################################################################
+# Start the MQTT server
+#
+sub runmqttserver {
+ my ($id, $verb, $ipv6) = @_;
+ my $ip=$HOSTIP;
+ my $proto = 'mqtt';
+ my $port = protoport($proto);
+ my $ipvnum = 4;
+ my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+ my $pidfile = $serverpidfile{$server};
+ my $portfile = $serverportfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ # start our MQTT server - on a random port!
+ my $cmd="server/mqttd".exe_ext('SRV').
+ " --port 0 ".
+ " --pidfile $pidfile".
+ " --portfile $portfile".
+ " --config $LOGDIR/$SERVERCMD".
+ " --logfile $logfile".
+ " --logdir $LOGDIR";
+ my ($sockspid, $pid2) = startnew($cmd, $pidfile, 30, 0);
+
+ if($sockspid <= 0 || !pidexists($sockspid)) {
+ # it is NOT alive
+ logmsg "RUN: failed to start the $srvrname server\n";
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ return (1, 0, 0);
+ }
+
+ my $mqttport = pidfromfile($portfile);
+ $PORT{"mqtt"} = $mqttport;
+
+ if($verb) {
+ logmsg "RUN: $srvrname server is now running PID $pid2 on PORT $mqttport\n";
+ }
+
+ return (0, $pid2, $sockspid);
+}
+
+#######################################################################
+# Start the socks server
+#
+sub runsocksserver {
+ my ($id, $verb, $ipv6, $is_unix) = @_;
+ my $ip=$HOSTIP;
+ my $proto = 'socks';
+ my $ipvnum = 4;
+ my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $portfile = $serverportfile{$server};
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ # start our socks server, get commands from the FTP cmd file
+ my $cmd="";
+ if($is_unix) {
+ $cmd="server/socksd".exe_ext('SRV').
+ " --pidfile $pidfile".
+ " --reqfile $LOGDIR/$SOCKSIN".
+ " --logfile $logfile".
+ " --unix-socket $SOCKSUNIXPATH".
+ " --backend $HOSTIP".
+ " --config $LOGDIR/$SERVERCMD";
+ } else {
+ $cmd="server/socksd".exe_ext('SRV').
+ " --port 0 ".
+ " --pidfile $pidfile".
+ " --portfile $portfile".
+ " --reqfile $LOGDIR/$SOCKSIN".
+ " --logfile $logfile".
+ " --backend $HOSTIP".
+ " --config $LOGDIR/$SERVERCMD";
+ }
+ my ($sockspid, $pid2) = startnew($cmd, $pidfile, 30, 0);
+
+ if($sockspid <= 0 || !pidexists($sockspid)) {
+ # it is NOT alive
+ logmsg "RUN: failed to start the $srvrname server\n";
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ return (1, 0, 0, 0);
+ }
+
+ my $port = pidfromfile($portfile);
+
+ if($verb) {
+ logmsg "RUN: $srvrname server is now running PID $pid2\n";
+ }
+
+ return (0, $pid2, $sockspid, $port);
+}
+
+#######################################################################
+# start the dict server
+#
+sub rundictserver {
+ my ($verb, $alt) = @_;
+ my $proto = "dict";
+ my $ip = $HOSTIP;
+ my $ipvnum = 4;
+ my $idnum = 1;
+
+ if($alt eq "ipv6") {
+ # No IPv6
+ }
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--verbose 1 " if($debugprotocol);
+ $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
+ $flags .= "--id $idnum " if($idnum > 1);
+ $flags .= "--srcdir \"$srcdir\" ";
+ $flags .= "--host $HOSTIP";
+
+ my $port = getfreeport($ipvnum);
+ my $aflags = "--port $port $flags";
+ my $cmd = "$srcdir/dictserver.py $aflags";
+ my ($dictpid, $pid2) = startnew($cmd, $pidfile, 15, 0);
+
+ if($dictpid <= 0 || !pidexists($dictpid)) {
+ # it is NOT alive
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ $dictpid = $pid2 = 0;
+ logmsg "RUN: failed to start the $srvrname server\n";
+ return (3, 0, 0, 0);
+ }
+ $doesntrun{$pidfile} = 0;
+
+ if($verb) {
+ logmsg "RUN: $srvrname server PID $dictpid port $port\n";
+ }
+
+ return (0+!$dictpid, $dictpid, $pid2, $port);
+}
+
+#######################################################################
+# start the SMB server
+#
+sub runsmbserver {
+ my ($verb, $alt) = @_;
+ my $proto = "smb";
+ my $ip = $HOSTIP;
+ my $ipvnum = 4;
+ my $idnum = 1;
+
+ if($alt eq "ipv6") {
+ # No IPv6
+ }
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--verbose 1 " if($debugprotocol);
+ $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
+ $flags .= "--id $idnum " if($idnum > 1);
+ $flags .= "--srcdir \"$srcdir\" ";
+ $flags .= "--host $HOSTIP";
+
+ my $port = getfreeport($ipvnum);
+ my $aflags = "--port $port $flags";
+ my $cmd = "$srcdir/smbserver.py $aflags";
+ my ($smbpid, $pid2) = startnew($cmd, $pidfile, 15, 0);
+
+ if($smbpid <= 0 || !pidexists($smbpid)) {
+ # it is NOT alive
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ $smbpid = $pid2 = 0;
+ logmsg "RUN: failed to start the $srvrname server\n";
+ return (3, 0, 0, 0);
+ }
+ $doesntrun{$pidfile} = 0;
+
+ if($verb) {
+ logmsg "RUN: $srvrname server PID $smbpid port $port\n";
+ }
+
+ return (0+!$smbpid, $smbpid, $pid2, $port);
+}
+
+#######################################################################
+# start the telnet server
+#
+sub runnegtelnetserver {
+ my ($verb, $alt) = @_;
+ my $proto = "telnet";
+ my $ip = $HOSTIP;
+ my $ipvnum = 4;
+ my $idnum = 1;
+
+ if($alt eq "ipv6") {
+ # No IPv6
+ }
+
+ my $server = servername_id($proto, $ipvnum, $idnum);
+
+ my $pidfile = $serverpidfile{$server};
+
+ # don't retry if the server doesn't work
+ if ($doesntrun{$pidfile}) {
+ return (2, 0, 0, 0);
+ }
+
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ stopserver($server, "$pid");
+ }
+ unlink($pidfile) if(-f $pidfile);
+
+ my $srvrname = servername_str($proto, $ipvnum, $idnum);
+ my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+
+ my $flags = "";
+ $flags .= "--verbose 1 " if($debugprotocol);
+ $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
+ $flags .= "--id $idnum " if($idnum > 1);
+ $flags .= "--srcdir \"$srcdir\"";
+
+ my $port = getfreeport($ipvnum);
+ my $aflags = "--port $port $flags";
+ my $cmd = "$srcdir/negtelnetserver.py $aflags";
+ my ($ntelpid, $pid2) = startnew($cmd, $pidfile, 15, 0);
+
+ if($ntelpid <= 0 || !pidexists($ntelpid)) {
+ # it is NOT alive
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ $ntelpid = $pid2 = 0;
+ logmsg "RUN: failed to start the $srvrname server\n";
+ return (3, 0, 0, 0);
+ }
+ $doesntrun{$pidfile} = 0;
+
+ if($verb) {
+ logmsg "RUN: $srvrname server PID $ntelpid port $port\n";
+ }
+
+ return (0+!$ntelpid, $ntelpid, $pid2, $port);
+}
+
+
+
+
+#######################################################################
+# Single shot http and gopher server responsiveness test. This should only
+# be used to verify that a server present in %run hash is still functional
+#
+sub responsive_http_server {
+ my ($proto, $verb, $alt, $port_or_path) = @_;
+ my $ip = $HOSTIP;
+ my $ipvnum = 4;
+ my $idnum = 1;
+
+ if($alt eq "ipv6") {
+ # if IPv6, use a different setup
+ $ipvnum = 6;
+ $ip = $HOST6IP;
+ }
+ elsif($alt eq "proxy") {
+ $idnum = 2;
+ }
+ elsif($alt eq "unix") {
+ # IP (protocol) is mutually exclusive with Unix sockets
+ $ipvnum = "unix";
+ }
+
+ return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
+}
+
+#######################################################################
+# Single shot pingpong server responsiveness test. This should only be
+# used to verify that a server present in %run hash is still functional
+#
+sub responsive_pingpong_server {
+ my ($proto, $id, $verb, $ipv6) = @_;
+ my $port;
+ my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
+ my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
+ my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
+ my $protoip = $proto . ($ipvnum == 6? '6': '');
+
+ if($proto =~ /^(?:ftp|imap|pop3|smtp)$/) {
+ $port = protoport($protoip);
+ }
+ else {
+ logmsg "Unsupported protocol $proto!!\n";
+ return 0;
+ }
+
+ return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
+}
+
+#######################################################################
+# Single shot rtsp server responsiveness test. This should only be
+# used to verify that a server present in %run hash is still functional
+#
+sub responsive_rtsp_server {
+ my ($verb, $ipv6) = @_;
+ my $proto = 'rtsp';
+ my $port = protoport($proto);
+ my $ip = $HOSTIP;
+ my $ipvnum = 4;
+ my $idnum = 1;
+
+ if($ipv6) {
+ # if IPv6, use a different setup
+ $ipvnum = 6;
+ $port = protoport('rtsp6');
+ $ip = $HOST6IP;
+ }
+
+ return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
+}
+
+#######################################################################
+# Single shot tftp server responsiveness test. This should only be
+# used to verify that a server present in %run hash is still functional
+#
+sub responsive_tftp_server {
+ my ($id, $verb, $ipv6) = @_;
+ my $proto = 'tftp';
+ my $port = protoport($proto);
+ my $ip = $HOSTIP;
+ my $ipvnum = 4;
+ my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
+
+ if($ipv6) {
+ # if IPv6, use a different setup
+ $ipvnum = 6;
+ $port = protoport('tftp6');
+ $ip = $HOST6IP;
+ }
+
+ return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
+}
+
+#######################################################################
+# Single shot non-stunnel HTTP TLS extensions capable server
+# responsiveness test. This should only be used to verify that a
+# server present in %run hash is still functional
+#
+sub responsive_httptls_server {
+ my ($verb, $ipv6) = @_;
+ my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
+ my $proto = "httptls";
+ my $port = protoport($proto);
+ my $ip = "$HOSTIP";
+ my $idnum = 1;
+
+ if ($ipvnum == 6) {
+ $port = protoport("httptls6");
+ $ip = "$HOST6IP";
+ }
+
+ return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
+}
+
+#######################################################################
+# startservers() starts all the named servers
+#
+# Returns: string with error reason or blank for success, and an integer:
+# 0 for success
+# 1 for an error starting the server
+# 2 for not the first time getting an error starting the server
+# 3 for a failure to stop a server in order to restart it
+# 4 for an unsupported server type
+#
+sub startservers {
+ my @what = @_;
+ my ($pid, $pid2);
+ my $serr; # error while starting a server (as as the return enumerations)
+ for(@what) {
+ my (@whatlist) = split(/\s+/,$_);
+ my $what = lc($whatlist[0]);
+ $what =~ s/[^a-z0-9\/-]//g;
+
+ my $certfile;
+ if($what =~ /^(ftp|gopher|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
+ $certfile = ($whatlist[1]) ? $whatlist[1] : 'stunnel.pem';
+ }
+
+ if(($what eq "pop3") ||
+ ($what eq "ftp") ||
+ ($what eq "imap") ||
+ ($what eq "smtp")) {
+ if($torture && $run{$what} &&
+ !responsive_pingpong_server($what, "", $verbose)) {
+ if(stopserver($what)) {
+ return ("failed stopping unresponsive ".uc($what)." server", 3);
+ }
+ }
+ if(!$run{$what}) {
+ ($serr, $pid, $pid2) = runpingpongserver($what, "", $verbose);
+ if($pid <= 0) {
+ return ("failed starting ". uc($what) ." server", $serr);
+ }
+ logmsg sprintf("* pid $what => %d %d\n", $pid, $pid2) if($verbose);
+ $run{$what}="$pid $pid2";
+ }
+ }
+ elsif($what eq "ftp-ipv6") {
+ if($torture && $run{'ftp-ipv6'} &&
+ !responsive_pingpong_server("ftp", "", $verbose, "ipv6")) {
+ if(stopserver('ftp-ipv6')) {
+ return ("failed stopping unresponsive FTP-IPv6 server", 3);
+ }
+ }
+ if(!$run{'ftp-ipv6'}) {
+ ($serr, $pid, $pid2) = runpingpongserver("ftp", "", $verbose, "ipv6");
+ if($pid <= 0) {
+ return ("failed starting FTP-IPv6 server", $serr);
+ }
+ logmsg sprintf("* pid ftp-ipv6 => %d %d\n", $pid,
+ $pid2) if($verbose);
+ $run{'ftp-ipv6'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "gopher") {
+ if($torture && $run{'gopher'} &&
+ !responsive_http_server("gopher", $verbose, 0,
+ protoport("gopher"))) {
+ if(stopserver('gopher')) {
+ return ("failed stopping unresponsive GOPHER server", 3);
+ }
+ }
+ if(!$run{'gopher'}) {
+ ($serr, $pid, $pid2, $PORT{'gopher'}) =
+ runhttpserver("gopher", $verbose, 0);
+ if($pid <= 0) {
+ return ("failed starting GOPHER server", $serr);
+ }
+ logmsg sprintf ("* pid gopher => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'gopher'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "gopher-ipv6") {
+ if($torture && $run{'gopher-ipv6'} &&
+ !responsive_http_server("gopher", $verbose, "ipv6",
+ protoport("gopher"))) {
+ if(stopserver('gopher-ipv6')) {
+ return ("failed stopping unresponsive GOPHER-IPv6 server", 3);
+ }
+ }
+ if(!$run{'gopher-ipv6'}) {
+ ($serr, $pid, $pid2, $PORT{"gopher6"}) =
+ runhttpserver("gopher", $verbose, "ipv6");
+ if($pid <= 0) {
+ return ("failed starting GOPHER-IPv6 server", $serr);
+ }
+ logmsg sprintf("* pid gopher-ipv6 => %d %d\n", $pid,
+ $pid2) if($verbose);
+ $run{'gopher-ipv6'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "http/3") {
+ if(!$run{'http/3'}) {
+ ($serr, $pid, $pid2, $PORT{"http3"}) = runhttp3server($verbose);
+ if($pid <= 0) {
+ return ("failed starting HTTP/3 server", $serr);
+ }
+ logmsg sprintf ("* pid http/3 => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'http/3'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "http/2") {
+ if(!$run{'http/2'}) {
+ ($serr, $pid, $pid2, $PORT{"http2"}, $PORT{"http2tls"}) =
+ runhttp2server($verbose);
+ if($pid <= 0) {
+ return ("failed starting HTTP/2 server", $serr);
+ }
+ logmsg sprintf ("* pid http/2 => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'http/2'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "http") {
+ if($torture && $run{'http'} &&
+ !responsive_http_server("http", $verbose, 0, protoport('http'))) {
+ if(stopserver('http')) {
+ return ("failed stopping unresponsive HTTP server", 3);
+ }
+ }
+ if(!$run{'http'}) {
+ ($serr, $pid, $pid2, $PORT{'http'}) =
+ runhttpserver("http", $verbose, 0);
+ if($pid <= 0) {
+ return ("failed starting HTTP server", $serr);
+ }
+ logmsg sprintf ("* pid http => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'http'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "http-proxy") {
+ if($torture && $run{'http-proxy'} &&
+ !responsive_http_server("http", $verbose, "proxy",
+ protoport("httpproxy"))) {
+ if(stopserver('http-proxy')) {
+ return ("failed stopping unresponsive HTTP-proxy server", 3);
+ }
+ }
+ if(!$run{'http-proxy'}) {
+ ($serr, $pid, $pid2, $PORT{"httpproxy"}) =
+ runhttpserver("http", $verbose, "proxy");
+ if($pid <= 0) {
+ return ("failed starting HTTP-proxy server", $serr);
+ }
+ logmsg sprintf ("* pid http-proxy => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'http-proxy'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "http-ipv6") {
+ if($torture && $run{'http-ipv6'} &&
+ !responsive_http_server("http", $verbose, "ipv6",
+ protoport("http6"))) {
+ if(stopserver('http-ipv6')) {
+ return ("failed stopping unresponsive HTTP-IPv6 server", 3);
+ }
+ }
+ if(!$run{'http-ipv6'}) {
+ ($serr, $pid, $pid2, $PORT{"http6"}) =
+ runhttpserver("http", $verbose, "ipv6");
+ if($pid <= 0) {
+ return ("failed starting HTTP-IPv6 server", $serr);
+ }
+ logmsg sprintf("* pid http-ipv6 => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'http-ipv6'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "rtsp") {
+ if($torture && $run{'rtsp'} &&
+ !responsive_rtsp_server($verbose)) {
+ if(stopserver('rtsp')) {
+ return ("failed stopping unresponsive RTSP server", 3);
+ }
+ }
+ if(!$run{'rtsp'}) {
+ ($serr, $pid, $pid2, $PORT{'rtsp'}) = runrtspserver($verbose);
+ if($pid <= 0) {
+ return ("failed starting RTSP server", $serr);
+ }
+ logmsg sprintf("* pid rtsp => %d %d\n", $pid, $pid2) if($verbose);
+ $run{'rtsp'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "rtsp-ipv6") {
+ if($torture && $run{'rtsp-ipv6'} &&
+ !responsive_rtsp_server($verbose, "ipv6")) {
+ if(stopserver('rtsp-ipv6')) {
+ return ("failed stopping unresponsive RTSP-IPv6 server", 3);
+ }
+ }
+ if(!$run{'rtsp-ipv6'}) {
+ ($serr, $pid, $pid2, $PORT{'rtsp6'}) = runrtspserver($verbose, "ipv6");
+ if($pid <= 0) {
+ return ("failed starting RTSP-IPv6 server", $serr);
+ }
+ logmsg sprintf("* pid rtsp-ipv6 => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'rtsp-ipv6'}="$pid $pid2";
+ }
+ }
+ elsif($what =~ /^(ftp|imap|pop3|smtp)s$/) {
+ my $cproto = $1;
+ if(!$stunnel) {
+ # we can't run ftps tests without stunnel
+ return ("no stunnel", 4);
+ }
+ if($runcert{$what} && ($runcert{$what} ne $certfile)) {
+ # stop server when running and using a different cert
+ if(stopserver($what)) {
+ return ("failed stopping $what server with different cert", 3);
+ }
+ }
+ if($torture && $run{$cproto} &&
+ !responsive_pingpong_server($cproto, "", $verbose)) {
+ if(stopserver($cproto)) {
+ return ("failed stopping unresponsive $cproto server", 3);
+ }
+ }
+ if(!$run{$cproto}) {
+ ($serr, $pid, $pid2) = runpingpongserver($cproto, "", $verbose);
+ if($pid <= 0) {
+ return ("failed starting $cproto server", $serr);
+ }
+ logmsg sprintf("* pid $cproto => %d %d\n", $pid, $pid2) if($verbose);
+ $run{$cproto}="$pid $pid2";
+ }
+ if(!$run{$what}) {
+ ($serr, $pid, $pid2, $PORT{$what}) =
+ runsecureserver($verbose, "", $certfile, $what,
+ protoport($cproto));
+ if($pid <= 0) {
+ return ("failed starting $what server (stunnel)", $serr);
+ }
+ logmsg sprintf("* pid $what => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{$what}="$pid $pid2";
+ }
+ }
+ elsif($what eq "file") {
+ # we support it but have no server!
+ }
+ elsif($what eq "https") {
+ if(!$stunnel) {
+ # we can't run https tests without stunnel
+ return ("no stunnel", 4);
+ }
+ if($runcert{'https'} && ($runcert{'https'} ne $certfile)) {
+ # stop server when running and using a different cert
+ if(stopserver('https')) {
+ return ("failed stopping HTTPS server with different cert", 3);
+ }
+ }
+ if($torture && $run{'http'} &&
+ !responsive_http_server("http", $verbose, 0,
+ protoport('http'))) {
+ if(stopserver('http')) {
+ return ("failed stopping unresponsive HTTP server", 3);
+ }
+ }
+ if(!$run{'http'}) {
+ ($serr, $pid, $pid2, $PORT{'http'}) =
+ runhttpserver("http", $verbose, 0);
+ if($pid <= 0) {
+ return ("failed starting HTTP server", $serr);
+ }
+ logmsg sprintf("* pid http => %d %d\n", $pid, $pid2) if($verbose);
+ $run{'http'}="$pid $pid2";
+ }
+ if(!$run{'https'}) {
+ ($serr, $pid, $pid2, $PORT{'https'}) =
+ runhttpsserver($verbose, "https", "", $certfile);
+ if($pid <= 0) {
+ return ("failed starting HTTPS server (stunnel)", $serr);
+ }
+ logmsg sprintf("* pid https => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'https'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "gophers") {
+ if(!$stunnel) {
+ # we can't run TLS tests without stunnel
+ return ("no stunnel", 4);
+ }
+ if($runcert{'gophers'} && ($runcert{'gophers'} ne $certfile)) {
+ # stop server when running and using a different cert
+ if(stopserver('gophers')) {
+ return ("failed stopping GOPHERS server with different cert", 3);
+ }
+ }
+ if($torture && $run{'gopher'} &&
+ !responsive_http_server("gopher", $verbose, 0,
+ protoport('gopher'))) {
+ if(stopserver('gopher')) {
+ return ("failed stopping unresponsive GOPHER server", 3);
+ }
+ }
+ if(!$run{'gopher'}) {
+ my $port;
+ ($serr, $pid, $pid2, $port) =
+ runhttpserver("gopher", $verbose, 0);
+ $PORT{'gopher'} = $port;
+ if($pid <= 0) {
+ return ("failed starting GOPHER server", $serr);
+ }
+ logmsg sprintf("* pid gopher => %d %d\n", $pid, $pid2) if($verbose);
+ logmsg "GOPHERPORT => $port\n" if($verbose);
+ $run{'gopher'}="$pid $pid2";
+ }
+ if(!$run{'gophers'}) {
+ my $port;
+ ($serr, $pid, $pid2, $port) =
+ runhttpsserver($verbose, "gophers", "", $certfile);
+ $PORT{'gophers'} = $port;
+ if($pid <= 0) {
+ return ("failed starting GOPHERS server (stunnel)", $serr);
+ }
+ logmsg sprintf("* pid gophers => %d %d\n", $pid, $pid2)
+ if($verbose);
+ logmsg "GOPHERSPORT => $port\n" if($verbose);
+ $run{'gophers'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "https-proxy") {
+ if(!$stunnel) {
+ # we can't run https-proxy tests without stunnel
+ return ("no stunnel", 4);
+ }
+ if($runcert{'https-proxy'} &&
+ ($runcert{'https-proxy'} ne $certfile)) {
+ # stop server when running and using a different cert
+ if(stopserver('https-proxy')) {
+ return ("failed stopping HTTPS-proxy with different cert", 3);
+ }
+ }
+
+ # we front the http-proxy with stunnel so we need to make sure the
+ # proxy runs as well
+ my ($f, $e) = startservers("http-proxy");
+ if($f) {
+ return ($f, $e);
+ }
+
+ if(!$run{'https-proxy'}) {
+ ($serr, $pid, $pid2, $PORT{"httpsproxy"}) =
+ runhttpsserver($verbose, "https", "proxy", $certfile);
+ if($pid <= 0) {
+ return ("failed starting HTTPS-proxy (stunnel)", $serr);
+ }
+ logmsg sprintf("* pid https-proxy => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'https-proxy'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "httptls") {
+ if(!$httptlssrv) {
+ # for now, we can't run http TLS-EXT tests without gnutls-serv
+ return ("no gnutls-serv (with SRP support)", 4);
+ }
+ if($torture && $run{'httptls'} &&
+ !responsive_httptls_server($verbose, "IPv4")) {
+ if(stopserver('httptls')) {
+ return ("failed stopping unresponsive HTTPTLS server", 3);
+ }
+ }
+ if(!$run{'httptls'}) {
+ ($serr, $pid, $pid2, $PORT{'httptls'}) =
+ runhttptlsserver($verbose, "IPv4");
+ if($pid <= 0) {
+ return ("failed starting HTTPTLS server (gnutls-serv)", $serr);
+ }
+ logmsg sprintf("* pid httptls => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'httptls'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "httptls-ipv6") {
+ if(!$httptlssrv) {
+ # for now, we can't run http TLS-EXT tests without gnutls-serv
+ return ("no gnutls-serv", 4);
+ }
+ if($torture && $run{'httptls-ipv6'} &&
+ !responsive_httptls_server($verbose, "ipv6")) {
+ if(stopserver('httptls-ipv6')) {
+ return ("failed stopping unresponsive HTTPTLS-IPv6 server", 3);
+ }
+ }
+ if(!$run{'httptls-ipv6'}) {
+ ($serr, $pid, $pid2, $PORT{"httptls6"}) =
+ runhttptlsserver($verbose, "ipv6");
+ if($pid <= 0) {
+ return ("failed starting HTTPTLS-IPv6 server (gnutls-serv)", $serr);
+ }
+ logmsg sprintf("* pid httptls-ipv6 => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'httptls-ipv6'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "tftp") {
+ if($torture && $run{'tftp'} &&
+ !responsive_tftp_server("", $verbose)) {
+ if(stopserver('tftp')) {
+ return ("failed stopping unresponsive TFTP server", 3);
+ }
+ }
+ if(!$run{'tftp'}) {
+ ($serr, $pid, $pid2, $PORT{'tftp'}) =
+ runtftpserver("", $verbose);
+ if($pid <= 0) {
+ return ("failed starting TFTP server", $serr);
+ }
+ logmsg sprintf("* pid tftp => %d %d\n", $pid, $pid2) if($verbose);
+ $run{'tftp'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "tftp-ipv6") {
+ if($torture && $run{'tftp-ipv6'} &&
+ !responsive_tftp_server("", $verbose, "ipv6")) {
+ if(stopserver('tftp-ipv6')) {
+ return ("failed stopping unresponsive TFTP-IPv6 server", 3);
+ }
+ }
+ if(!$run{'tftp-ipv6'}) {
+ ($serr, $pid, $pid2, $PORT{'tftp6'}) =
+ runtftpserver("", $verbose, "ipv6");
+ if($pid <= 0) {
+ return ("failed starting TFTP-IPv6 server", $serr);
+ }
+ logmsg sprintf("* pid tftp-ipv6 => %d %d\n", $pid, $pid2) if($verbose);
+ $run{'tftp-ipv6'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "sftp" || $what eq "scp") {
+ if(!$run{'ssh'}) {
+ ($serr, $pid, $pid2, $PORT{'ssh'}) = runsshserver("", $verbose);
+ if($pid <= 0) {
+ return ("failed starting SSH server", $serr);
+ }
+ logmsg sprintf("* pid ssh => %d %d\n", $pid, $pid2) if($verbose);
+ $run{'ssh'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "socks4" || $what eq "socks5" ) {
+ if(!$run{'socks'}) {
+ ($serr, $pid, $pid2, $PORT{"socks"}) = runsocksserver("", $verbose);
+ if($pid <= 0) {
+ return ("failed starting socks server", $serr);
+ }
+ logmsg sprintf("* pid socks => %d %d\n", $pid, $pid2) if($verbose);
+ $run{'socks'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "socks5unix") {
+ if(!$run{'socks5unix'}) {
+ ($serr, $pid, $pid2) = runsocksserver("2", $verbose, "", "unix");
+ if($pid <= 0) {
+ return ("failed starting socks5unix server", $serr);
+ }
+ logmsg sprintf("* pid socks5unix => %d %d\n", $pid, $pid2) if($verbose);
+ $run{'socks5unix'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "mqtt" ) {
+ if(!$run{'mqtt'}) {
+ ($serr, $pid, $pid2) = runmqttserver("", $verbose);
+ if($pid <= 0) {
+ return ("failed starting mqtt server", $serr);
+ }
+ logmsg sprintf("* pid mqtt => %d %d\n", $pid, $pid2) if($verbose);
+ $run{'mqtt'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "http-unix") {
+ if($torture && $run{'http-unix'} &&
+ !responsive_http_server("http", $verbose, "unix", $HTTPUNIXPATH)) {
+ if(stopserver('http-unix')) {
+ return ("failed stopping unresponsive HTTP-unix server", 3);
+ }
+ }
+ if(!$run{'http-unix'}) {
+ my $unused;
+ ($serr, $pid, $pid2, $unused) =
+ runhttpserver("http", $verbose, "unix", $HTTPUNIXPATH);
+ if($pid <= 0) {
+ return ("failed starting HTTP-unix server", $serr);
+ }
+ logmsg sprintf("* pid http-unix => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'http-unix'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "dict") {
+ if(!$run{'dict'}) {
+ ($serr, $pid, $pid2, $PORT{"dict"}) = rundictserver($verbose, "");
+ if($pid <= 0) {
+ return ("failed starting DICT server", $serr);
+ }
+ logmsg sprintf ("* pid DICT => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'dict'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "smb") {
+ if(!$run{'smb'}) {
+ ($serr, $pid, $pid2, $PORT{"smb"}) = runsmbserver($verbose, "");
+ if($pid <= 0) {
+ return ("failed starting SMB server", $serr);
+ }
+ logmsg sprintf ("* pid SMB => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'smb'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "telnet") {
+ if(!$run{'telnet'}) {
+ ($serr, $pid, $pid2, $PORT{"telnet"}) =
+ runnegtelnetserver($verbose, "");
+ if($pid <= 0) {
+ return ("failed starting neg TELNET server", $serr);
+ }
+ logmsg sprintf ("* pid neg TELNET => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'telnet'}="$pid $pid2";
+ }
+ }
+ elsif($what eq "none") {
+ logmsg "* starts no server\n" if ($verbose);
+ }
+ else {
+ warn "we don't support a server for $what";
+ return ("no server for $what", 4);
+ }
+ }
+ return ("", 0);
+}
+
+#######################################################################
+# Stop all running test servers
+#
+sub stopservers {
+ my $verb = $_[0];
+ #
+ # kill sockfilter processes for all pingpong servers
+ #
+ killallsockfilters("$LOGDIR/$PIDDIR", $verb);
+ #
+ # kill all server pids from %run hash clearing them
+ #
+ my $pidlist;
+ foreach my $server (keys %run) {
+ if($run{$server}) {
+ if($verb) {
+ my $prev = 0;
+ my $pids = $run{$server};
+ foreach my $pid (split(' ', $pids)) {
+ if($pid != $prev) {
+ logmsg sprintf("* kill pid for %s => %d\n",
+ $server, $pid);
+ $prev = $pid;
+ }
+ }
+ }
+ $pidlist .= "$run{$server} ";
+ $run{$server} = 0;
+ }
+ $runcert{$server} = 0 if($runcert{$server});
+ }
+ killpid($verb, $pidlist);
+ #
+ # cleanup all server pid files
+ #
+ my $result = 0;
+ foreach my $server (keys %serverpidfile) {
+ my $pidfile = $serverpidfile{$server};
+ my $pid = processexists($pidfile);
+ if($pid > 0) {
+ if($err_unexpected) {
+ logmsg "ERROR: ";
+ $result = -1;
+ }
+ else {
+ logmsg "Warning: ";
+ }
+ logmsg "$server server unexpectedly alive\n";
+ killpid($verb, $pid);
+ }
+ unlink($pidfile) if(-f $pidfile);
+ }
+
+ return $result;
+}
+
+
+#######################################################################
+# substitute the variable stuff into either a joined up file or
+# a command, in either case passed by reference
+#
+sub subvariables {
+ my ($thing, $testnum, $prefix) = @_;
+ my $port;
+
+ if(!$prefix) {
+ $prefix = "%";
+ }
+
+ # test server ports
+ # Substitutes variables like %HTTPPORT and %SMTP6PORT with the server ports
+ foreach my $proto ('DICT',
+ 'FTP', 'FTP6', 'FTPS',
+ 'GOPHER', 'GOPHER6', 'GOPHERS',
+ 'HTTP', 'HTTP6', 'HTTPS',
+ 'HTTPSPROXY', 'HTTPTLS', 'HTTPTLS6',
+ 'HTTP2', 'HTTP2TLS',
+ 'HTTP3',
+ 'IMAP', 'IMAP6', 'IMAPS',
+ 'MQTT',
+ 'NOLISTEN',
+ 'POP3', 'POP36', 'POP3S',
+ 'RTSP', 'RTSP6',
+ 'SMB', 'SMBS',
+ 'SMTP', 'SMTP6', 'SMTPS',
+ 'SOCKS',
+ 'SSH',
+ 'TELNET',
+ 'TFTP', 'TFTP6') {
+ $port = protoport(lc $proto);
+ $$thing =~ s/${prefix}(?:$proto)PORT/$port/g;
+ }
+ # Special case: for PROXYPORT substitution, use httpproxy.
+ $port = protoport('httpproxy');
+ $$thing =~ s/${prefix}PROXYPORT/$port/g;
+
+ # server Unix domain socket paths
+ $$thing =~ s/${prefix}HTTPUNIXPATH/$HTTPUNIXPATH/g;
+ $$thing =~ s/${prefix}SOCKSUNIXPATH/$SOCKSUNIXPATH/g;
+
+ # client IP addresses
+ $$thing =~ s/${prefix}CLIENT6IP/$CLIENT6IP/g;
+ $$thing =~ s/${prefix}CLIENTIP/$CLIENTIP/g;
+
+ # server IP addresses
+ $$thing =~ s/${prefix}HOST6IP/$HOST6IP/g;
+ $$thing =~ s/${prefix}HOSTIP/$HOSTIP/g;
+
+ # misc
+ $$thing =~ s/${prefix}CURL/$CURL/g;
+ $$thing =~ s/${prefix}LOGDIR/$LOGDIR/g;
+ $$thing =~ s/${prefix}PWD/$pwd/g;
+ $$thing =~ s/${prefix}POSIX_PWD/$posix_pwd/g;
+ $$thing =~ s/${prefix}VERSION/$CURLVERSION/g;
+ $$thing =~ s/${prefix}TESTNUMBER/$testnum/g;
+
+ my $file_pwd = $pwd;
+ if($file_pwd !~ /^\//) {
+ $file_pwd = "/$file_pwd";
+ }
+ my $ssh_pwd = $posix_pwd;
+ # this only works after the SSH server has been started
+ # TODO: call sshversioninfo early and store $sshdid so this substitution
+ # always works
+ if ($sshdid && $sshdid =~ /OpenSSH-Windows/) {
+ $ssh_pwd = $file_pwd;
+ }
+
+ $$thing =~ s/${prefix}FILE_PWD/$file_pwd/g;
+ $$thing =~ s/${prefix}SSH_PWD/$ssh_pwd/g;
+ $$thing =~ s/${prefix}SRCDIR/$srcdir/g;
+ $$thing =~ s/${prefix}USER/$USER/g;
+
+ $$thing =~ s/${prefix}SSHSRVMD5/$SSHSRVMD5/g;
+ $$thing =~ s/${prefix}SSHSRVSHA256/$SSHSRVSHA256/g;
+
+ # The purpose of FTPTIME2 and FTPTIME3 is to provide times that can be
+ # used for time-out tests and that would work on most hosts as these
+ # adjust for the startup/check time for this particular host. We needed to
+ # do this to make the test suite run better on very slow hosts.
+ my $ftp2 = $ftpchecktime * 2;
+ my $ftp3 = $ftpchecktime * 3;
+
+ $$thing =~ s/${prefix}FTPTIME2/$ftp2/g;
+ $$thing =~ s/${prefix}FTPTIME3/$ftp3/g;
+
+ # HTTP2
+ $$thing =~ s/${prefix}H2CVER/$h2cver/g;
+}
+
+
+1;
diff --git a/tests/smbserver.py b/tests/smbserver.py
index 62f2d7a..3de8d69 100755
--- a/tests/smbserver.py
+++ b/tests/smbserver.py
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2017 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -29,8 +29,10 @@
import argparse
import logging
import os
+import signal
import sys
import tempfile
+import threading
# Import our curl test data helper
from util import ClosingFileHandler, TestData
@@ -59,6 +61,49 @@
VERIFIED_RSP = "WE ROOLZ: {pid}\n"
+class ShutdownHandler(threading.Thread):
+ """Cleanly shut down the SMB server
+
+ This can only be done from another thread while the server is in
+ serve_forever(), so a thread is spawned here that waits for a shutdown
+ signal before doing its thing. Use in a with statement around the
+ serve_forever() call.
+ """
+
+ def __init__(self, server):
+ super(ShutdownHandler, self).__init__()
+ self.server = server
+ self.shutdown_event = threading.Event()
+
+ def __enter__(self):
+ self.start()
+ signal.signal(signal.SIGINT, self._sighandler)
+ signal.signal(signal.SIGTERM, self._sighandler)
+
+ def __exit__(self, *_):
+ # Call for shutdown just in case it wasn't done already
+ self.shutdown_event.set()
+ # Wait for thread, and therefore also the server, to finish
+ self.join()
+ # Uninstall our signal handlers
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ signal.signal(signal.SIGTERM, signal.SIG_DFL)
+ # Delete any temporary files created by the server during its run
+ log.info("Deleting %d temporary files", len(self.server.tmpfiles))
+ for f in self.server.tmpfiles:
+ os.unlink(f)
+
+ def _sighandler(self, _signum, _frame):
+ # Wake up the cleanup task
+ self.shutdown_event.set()
+
+ def run(self):
+ # Wait for shutdown signal
+ self.shutdown_event.wait()
+ # Notify the server to shut down
+ self.server.shutdown()
+
+
def smbserver(options):
"""Start up a TCP SMB server that serves forever
@@ -105,7 +150,12 @@
test_data_directory=test_data_dir)
log.info("[SMB] setting up SMB server on port %s", options.port)
smb_server.processConfigFile()
- smb_server.serve_forever()
+
+ # Start a thread that cleanly shuts down the server on a signal
+ with ShutdownHandler(smb_server):
+ # This will block until smb_server.shutdown() is called
+ smb_server.serve_forever()
+
return 0
@@ -122,6 +172,7 @@
imp_smbserver.SMBSERVER.__init__(self,
address,
config_parser=config_parser)
+ self.tmpfiles = []
# Set up a test data object so we can get test data later.
self.ctd = TestData(test_data_directory)
@@ -182,6 +233,8 @@
assert (path == TESTS_MAGIC)
fid, full_path = self.get_test_path(requested_file)
+ self.tmpfiles.append(full_path)
+
resp_parms = imp_smb.SMBNtCreateAndXResponse_Parameters()
resp_data = ""
diff --git a/tests/sshhelp.pm b/tests/sshhelp.pm
index 2d419c1..c8df594 100644
--- a/tests/sshhelp.pm
+++ b/tests/sshhelp.pm
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -26,118 +26,82 @@
use strict;
use warnings;
-use Exporter;
+
+BEGIN {
+ use base qw(Exporter);
+
+ our @EXPORT_OK = qw(
+ $sshdexe
+ $sshexe
+ $sftpsrvexe
+ $sftpexe
+ $sshkeygenexe
+ $sshdconfig
+ $sshconfig
+ $sftpconfig
+ $knownhosts
+ $sshdlog
+ $sshlog
+ $sftplog
+ $sftpcmds
+ $hstprvkeyf
+ $hstpubkeyf
+ $hstpubmd5f
+ $hstpubsha256f
+ $cliprvkeyf
+ $clipubkeyf
+ display_sshdconfig
+ display_sshconfig
+ display_sftpconfig
+ display_sshdlog
+ display_sshlog
+ display_sftplog
+ dump_array
+ find_sshd
+ find_ssh
+ find_sftpsrv
+ find_sftp
+ find_sshkeygen
+ find_httptlssrv
+ sshversioninfo
+ );
+}
+
use File::Spec;
-
-#***************************************************************************
-# Global symbols allowed without explicit package name
-#
-use vars qw(
- @ISA
- @EXPORT_OK
- $sshdexe
- $sshexe
- $sftpsrvexe
- $sftpexe
- $sshkeygenexe
- $httptlssrvexe
- $sshdconfig
- $sshconfig
- $sftpconfig
- $knownhosts
- $sshdlog
- $sshlog
- $sftplog
- $sftpcmds
- $hstprvkeyf
- $hstpubkeyf
- $hstpubmd5f
- $hstpubsha256f
- $cliprvkeyf
- $clipubkeyf
- @sftppath
- @httptlssrvpath
- );
-
-
-#***************************************************************************
-# Inherit Exporter's capabilities
-#
-@ISA = qw(Exporter);
-
-
-#***************************************************************************
-# Global symbols this module will export upon request
-#
-@EXPORT_OK = qw(
- $sshdexe
- $sshexe
- $sftpsrvexe
- $sftpexe
- $sshkeygenexe
- $sshdconfig
- $sshconfig
- $sftpconfig
- $knownhosts
- $sshdlog
- $sshlog
- $sftplog
- $sftpcmds
- $hstprvkeyf
- $hstpubkeyf
- $hstpubmd5f
- $hstpubsha256f
- $cliprvkeyf
- $clipubkeyf
- display_sshdconfig
- display_sshconfig
- display_sftpconfig
- display_sshdlog
- display_sshlog
- display_sftplog
- dump_array
+use pathhelp qw(
exe_ext
- find_sshd
- find_ssh
- find_sftpsrv
- find_sftp
- find_sshkeygen
- find_httptlssrv
- logmsg
- sshversioninfo
);
-
#***************************************************************************
# Global variables initialization
#
-$sshdexe = 'sshd' .exe_ext('SSH'); # base name and ext of ssh daemon
-$sshexe = 'ssh' .exe_ext('SSH'); # base name and ext of ssh client
-$sftpsrvexe = 'sftp-server' .exe_ext('SSH'); # base name and ext of sftp-server
-$sftpexe = 'sftp' .exe_ext('SSH'); # base name and ext of sftp client
-$sshkeygenexe = 'ssh-keygen' .exe_ext('SSH'); # base name and ext of ssh-keygen
-$httptlssrvexe = 'gnutls-serv' .exe_ext('SSH'); # base name and ext of gnutls-serv
-$sshdconfig = 'curl_sshd_config'; # ssh daemon config file
-$sshconfig = 'curl_ssh_config'; # ssh client config file
-$sftpconfig = 'curl_sftp_config'; # sftp client config file
-$sshdlog = undef; # ssh daemon log file
-$sshlog = undef; # ssh client log file
-$sftplog = undef; # sftp client log file
-$sftpcmds = 'curl_sftp_cmds'; # sftp client commands batch file
-$knownhosts = 'curl_client_knownhosts'; # ssh knownhosts file
-$hstprvkeyf = 'curl_host_rsa_key'; # host private key file
-$hstpubkeyf = 'curl_host_rsa_key.pub'; # host public key file
-$hstpubmd5f = 'curl_host_rsa_key.pub_md5'; # md5 hash of host public key
-$hstpubsha256f = 'curl_host_rsa_key.pub_sha256'; # sha256 hash of host public key
-$cliprvkeyf = 'curl_client_key'; # client private key file
-$clipubkeyf = 'curl_client_key.pub'; # client public key file
+our $sshdexe = 'sshd' .exe_ext('SSH'); # base name and ext of ssh daemon
+our $sshexe = 'ssh' .exe_ext('SSH'); # base name and ext of ssh client
+our $sftpsrvexe = 'sftp-server' .exe_ext('SSH'); # base name and ext of sftp-server
+our $sftpexe = 'sftp' .exe_ext('SSH'); # base name and ext of sftp client
+our $sshkeygenexe = 'ssh-keygen' .exe_ext('SSH'); # base name and ext of ssh-keygen
+our $httptlssrvexe = 'gnutls-serv' .exe_ext('SSH'); # base name and ext of gnutls-serv
+our $sshdconfig = 'curl_sshd_config'; # ssh daemon config file
+our $sshconfig = 'curl_ssh_config'; # ssh client config file
+our $sftpconfig = 'curl_sftp_config'; # sftp client config file
+our $sshdlog = undef; # ssh daemon log file
+our $sshlog = undef; # ssh client log file
+our $sftplog = undef; # sftp client log file
+our $sftpcmds = 'curl_sftp_cmds'; # sftp client commands batch file
+our $knownhosts = 'curl_client_knownhosts'; # ssh knownhosts file
+our $hstprvkeyf = 'curl_host_rsa_key'; # host private key file
+our $hstpubkeyf = 'curl_host_rsa_key.pub'; # host public key file
+our $hstpubmd5f = 'curl_host_rsa_key.pub_md5'; # md5 hash of host public key
+our $hstpubsha256f = 'curl_host_rsa_key.pub_sha256'; # sha256 hash of host public key
+our $cliprvkeyf = 'curl_client_key'; # client private key file
+our $clipubkeyf = 'curl_client_key.pub'; # client public key file
#***************************************************************************
# Absolute paths where to look for sftp-server plugin, when not in PATH
#
-@sftppath = qw(
+our @sftppath = qw(
/usr/lib/openssh
/usr/libexec/openssh
/usr/libexec
@@ -163,7 +127,7 @@
#***************************************************************************
# Absolute paths where to look for httptlssrv (gnutls-serv), when not in PATH
#
-@httptlssrvpath = qw(
+our @httptlssrvpath = qw(
/usr/sbin
/usr/libexec
/usr/lib
@@ -185,24 +149,6 @@
#***************************************************************************
-# Return file extension for executable files on this operating system
-#
-sub exe_ext {
- my ($component, @arr) = @_;
- if ($ENV{'CURL_TEST_EXE_EXT'}) {
- return $ENV{'CURL_TEST_EXE_EXT'};
- }
- if ($ENV{'CURL_TEST_EXE_EXT_'.$component}) {
- return $ENV{'CURL_TEST_EXE_EXT_'.$component};
- }
- if ($^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys' ||
- $^O eq 'dos' || $^O eq 'os2') {
- return '.exe';
- }
-}
-
-
-#***************************************************************************
# Create or overwrite the given file with lines from an array of strings
#
sub dump_array {
@@ -212,12 +158,12 @@
if(!$filename) {
$error = 'Error: Missing argument 1 for dump_array()';
}
- elsif(open(TEXTFH, ">$filename")) {
+ elsif(open(my $textfh, ">", $filename)) {
foreach my $line (@arr) {
- $line .= "\n" unless($line =~ /\n$/);
- print TEXTFH $line;
+ $line .= "\n" if($line !~ /\n$/);
+ print $textfh $line;
}
- if(!close(TEXTFH)) {
+ if(!close($textfh)) {
$error = "Error: cannot close file $filename";
}
}
@@ -229,27 +175,16 @@
#***************************************************************************
-# Display a message
-#
-sub logmsg {
- my ($line) = @_;
- chomp $line if($line);
- $line .= "\n";
- print "$line";
-}
-
-
-#***************************************************************************
# Display contents of the given file
#
sub display_file {
my $filename = $_[0];
print "=== Start of file $filename\n";
- if(open(DISPLAYFH, "<$filename")) {
- while(my $line = <DISPLAYFH>) {
+ if(open(my $displayfh, "<", "$filename")) {
+ while(my $line = <$displayfh>) {
print "$line";
}
- close DISPLAYFH;
+ close $displayfh;
}
print "=== End of file $filename\n";
}
@@ -319,6 +254,7 @@
return $file;
}
}
+ return "";
}
@@ -337,6 +273,7 @@
return $file if(($xext) && (lc($file) =~ /\Q$xext\E$/));
}
}
+ return "";
}
@@ -408,7 +345,19 @@
# Find httptlssrv (gnutls-serv) and return canonical filename
#
sub find_httptlssrv {
- return find_exe_file_hpath($httptlssrvexe);
+ my $p = find_exe_file_hpath($httptlssrvexe);
+ if($p) {
+ my @o = `"$p" -l`;
+ my $found;
+ for(@o) {
+ if(/Key exchange: SRP/) {
+ $found = 1;
+ last;
+ }
+ }
+ return $p if($found);
+ }
+ return "";
}
diff --git a/tests/sshserver.pl b/tests/sshserver.pl
old mode 100644
new mode 100755
index 576b706..2a69561
--- a/tests/sshserver.pl
+++ b/tests/sshserver.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -35,6 +35,7 @@
use Digest::SHA;
use Digest::SHA 'sha256_base64';
use MIME::Base64;
+use File::Basename;
#***************************************************************************
# Variables and subs imported from sshhelp module
@@ -71,7 +72,6 @@
find_sftpsrv
find_sftp
find_sshkeygen
- logmsg
sshversioninfo
);
@@ -79,6 +79,8 @@
# Subs imported from serverhelp module
#
use serverhelp qw(
+ logmsg
+ $logfile
server_pidfilename
server_logfilename
);
@@ -96,6 +98,7 @@
my $proto = 'ssh'; # protocol the ssh daemon speaks
my $path = getcwd(); # current working directory
my $logdir = $path .'/log'; # directory for log files
+my $piddir; # directory for server config files
my $username = $ENV{USER}; # default user
my $pidfile; # ssh daemon pid file
my $identity = 'curl_client_key'; # default identity file
@@ -103,6 +106,14 @@
my $error;
my @cfgarr;
+#***************************************************************************
+# Returns a path of the given file name in the log directory (PiddirPath)
+#
+sub pp {
+ my $file = $_[0];
+ return "$piddir/$file";
+ # TODO: do Windows path conversion here
+}
#***************************************************************************
# Parse command line options
@@ -157,6 +168,12 @@
shift @ARGV;
}
}
+ elsif($ARGV[0] eq '--logdir') {
+ if($ARGV[1]) {
+ $logdir = "$path/". $ARGV[1];
+ shift @ARGV;
+ }
+ }
elsif($ARGV[0] eq '--sshport') {
if($ARGV[1]) {
if($ARGV[1] =~ /^(\d+)$/) {
@@ -171,21 +188,29 @@
shift @ARGV;
}
+#***************************************************************************
+# Initialize command line option dependent variables
+#
#***************************************************************************
-# Default ssh daemon pid file name
+# Default ssh daemon pid file name & directory
#
-if(!$pidfile) {
- $pidfile = "$path/". server_pidfilename($proto, $ipvnum, $idnum);
+if($pidfile) {
+ # Use our pidfile directory to store server config files
+ $piddir = dirname($pidfile);
}
-
+else {
+ # Use the current directory to store server config files
+ $piddir = $path;
+ $pidfile = server_pidfilename($piddir, $proto, $ipvnum, $idnum);
+}
#***************************************************************************
# ssh and sftp server log file names
#
$sshdlog = server_logfilename($logdir, 'ssh', $ipvnum, $idnum);
$sftplog = server_logfilename($logdir, 'sftp', $ipvnum, $idnum);
-
+$logfile = "$logdir/sshserver.log"; # used by logmsg
#***************************************************************************
# Logging level for ssh server and client
@@ -203,7 +228,7 @@
$error = 'Will not run ssh server as root to mitigate security risks';
}
if($error) {
- logmsg $error;
+ logmsg "$error\n";
exit 1;
}
@@ -213,7 +238,7 @@
#
my $sshd = find_sshd();
if(!$sshd) {
- logmsg "cannot find $sshdexe";
+ logmsg "cannot find $sshdexe\n";
exit 1;
}
@@ -224,11 +249,11 @@
my ($sshdid, $sshdvernum, $sshdverstr, $sshderror) = sshversioninfo($sshd);
if(!$sshdid) {
# Not an OpenSSH or SunSSH ssh daemon
- logmsg $sshderror if($verbose);
- logmsg 'SCP and SFTP tests require OpenSSH 2.9.9 or later';
+ logmsg "$sshderror\n" if($verbose);
+ logmsg "SCP and SFTP tests require OpenSSH 2.9.9 or later\n";
exit 1;
}
-logmsg "ssh server found $sshd is $sshdverstr" if($verbose);
+logmsg "ssh server found $sshd is $sshdverstr\n" if($verbose);
#***************************************************************************
@@ -254,7 +279,7 @@
#
if((($sshdid =~ /OpenSSH/) && ($sshdvernum < 299)) ||
(($sshdid =~ /SunSSH/) && ($sshdvernum < 100))) {
- logmsg 'SCP and SFTP tests require OpenSSH 2.9.9 or later';
+ logmsg "SCP and SFTP tests require OpenSSH 2.9.9 or later\n";
exit 1;
}
@@ -264,10 +289,10 @@
#
my $sftpsrv = find_sftpsrv();
if(!$sftpsrv) {
- logmsg "cannot find $sftpsrvexe";
+ logmsg "cannot find $sftpsrvexe\n";
exit 1;
}
-logmsg "sftp server plugin found $sftpsrv" if($verbose);
+logmsg "sftp server plugin found $sftpsrv\n" if($verbose);
#***************************************************************************
@@ -275,10 +300,10 @@
#
my $sftp = find_sftp();
if(!$sftp) {
- logmsg "cannot find $sftpexe";
+ logmsg "cannot find $sftpexe\n";
exit 1;
}
-logmsg "sftp client found $sftp" if($verbose);
+logmsg "sftp client found $sftp\n" if($verbose);
#***************************************************************************
@@ -286,10 +311,10 @@
#
my $sshkeygen = find_sshkeygen();
if(!$sshkeygen) {
- logmsg "cannot find $sshkeygenexe";
+ logmsg "cannot find $sshkeygenexe\n";
exit 1;
}
-logmsg "ssh keygen found $sshkeygen" if($verbose);
+logmsg "ssh keygen found $sshkeygen\n" if($verbose);
#***************************************************************************
@@ -297,7 +322,7 @@
#
my $ssh = find_ssh();
if(!$ssh) {
- logmsg "cannot find $sshexe";
+ logmsg "cannot find $sshexe\n";
exit 1;
}
@@ -308,11 +333,11 @@
my ($sshid, $sshvernum, $sshverstr, $ssherror) = sshversioninfo($ssh);
if(!$sshid) {
# Not an OpenSSH or SunSSH ssh client
- logmsg $ssherror if($verbose);
- logmsg 'SCP and SFTP tests require OpenSSH 2.9.9 or later';
+ logmsg "$ssherror\n" if($verbose);
+ logmsg "SCP and SFTP tests require OpenSSH 2.9.9 or later\n";
exit 1;
}
-logmsg "ssh client found $ssh is $sshverstr" if($verbose);
+logmsg "ssh client found $ssh is $sshverstr\n" if($verbose);
#***************************************************************************
@@ -340,7 +365,7 @@
#
if((($sshid =~ /OpenSSH/) && ($sshvernum < 299)) ||
(($sshid =~ /SunSSH/) && ($sshvernum < 100))) {
- logmsg 'SCP and SFTP tests require OpenSSH 2.9.9 or later';
+ logmsg "SCP and SFTP tests require OpenSSH 2.9.9 or later\n";
exit 1;
}
@@ -364,48 +389,48 @@
#***************************************************************************
# Generate host and client key files for curl's tests
#
-if((! -e $hstprvkeyf) || (! -s $hstprvkeyf) ||
- (! -e $hstpubkeyf) || (! -s $hstpubkeyf) ||
- (! -e $hstpubmd5f) || (! -s $hstpubmd5f) ||
- (! -e $hstpubsha256f) || (! -s $hstpubsha256f) ||
- (! -e $cliprvkeyf) || (! -s $cliprvkeyf) ||
- (! -e $clipubkeyf) || (! -s $clipubkeyf)) {
+if((! -e pp($hstprvkeyf)) || (! -s pp($hstprvkeyf)) ||
+ (! -e pp($hstpubkeyf)) || (! -s pp($hstpubkeyf)) ||
+ (! -e pp($hstpubmd5f)) || (! -s pp($hstpubmd5f)) ||
+ (! -e pp($hstpubsha256f)) || (! -s pp($hstpubsha256f)) ||
+ (! -e pp($cliprvkeyf)) || (! -s pp($cliprvkeyf)) ||
+ (! -e pp($clipubkeyf)) || (! -s pp($clipubkeyf))) {
# Make sure all files are gone so ssh-keygen doesn't complain
- unlink($hstprvkeyf, $hstpubkeyf, $hstpubmd5f, $hstpubsha256f,
- $cliprvkeyf, $clipubkeyf);
- logmsg 'generating host keys...' if($verbose);
- if(system "\"$sshkeygen\" -q -t rsa -f $hstprvkeyf -C 'curl test server' -N ''") {
- logmsg 'Could not generate host key';
+ unlink(pp($hstprvkeyf), pp($hstpubkeyf), pp($hstpubmd5f),
+ pp($hstpubsha256f), pp($cliprvkeyf), pp($clipubkeyf));
+ logmsg "generating host keys...\n" if($verbose);
+ if(system "\"$sshkeygen\" -q -t rsa -f " . pp($hstprvkeyf) . " -C 'curl test server' -N ''") {
+ logmsg "Could not generate host key\n";
exit 1;
}
- logmsg 'generating client keys...' if($verbose);
- if(system "\"$sshkeygen\" -q -t rsa -f $cliprvkeyf -C 'curl test client' -N ''") {
- logmsg 'Could not generate client key';
+ logmsg "generating client keys...\n" if($verbose);
+ if(system "\"$sshkeygen\" -q -t rsa -f " . pp($cliprvkeyf) . " -C 'curl test client' -N ''") {
+ logmsg "Could not generate client key\n";
exit 1;
}
# Make sure that permissions are restricted so openssh doesn't complain
- system "chmod 600 $hstprvkeyf";
- system "chmod 600 $cliprvkeyf";
+ system "chmod 600 " . pp($hstprvkeyf);
+ system "chmod 600 " . pp($cliprvkeyf);
# Save md5 and sha256 hashes of public host key
- open(RSAKEYFILE, "<$hstpubkeyf");
- my @rsahostkey = do { local $/ = ' '; <RSAKEYFILE> };
- close(RSAKEYFILE);
+ open(my $rsakeyfile, "<", pp($hstpubkeyf));
+ my @rsahostkey = do { local $/ = ' '; <$rsakeyfile> };
+ close($rsakeyfile);
if(!$rsahostkey[1]) {
- logmsg 'Failed parsing base64 encoded RSA host key';
+ logmsg "Failed parsing base64 encoded RSA host key\n";
exit 1;
}
- open(PUBMD5FILE, ">$hstpubmd5f");
- print PUBMD5FILE md5_hex(decode_base64($rsahostkey[1]));
- close(PUBMD5FILE);
- if((! -e $hstpubmd5f) || (! -s $hstpubmd5f)) {
- logmsg 'Failed writing md5 hash of RSA host key';
+ open(my $pubmd5file, ">", pp($hstpubmd5f));
+ print $pubmd5file md5_hex(decode_base64($rsahostkey[1]));
+ close($pubmd5file);
+ if((! -e pp($hstpubmd5f)) || (! -s pp($hstpubmd5f))) {
+ logmsg "Failed writing md5 hash of RSA host key\n";
exit 1;
}
- open(PUBSHA256FILE, ">$hstpubsha256f");
- print PUBSHA256FILE sha256_base64(decode_base64($rsahostkey[1]));
- close(PUBSHA256FILE);
- if((! -e $hstpubsha256f) || (! -s $hstpubsha256f)) {
- logmsg 'Failed writing sha256 hash of RSA host key';
+ open(my $pubsha256file, ">", pp($hstpubsha256f));
+ print $pubsha256file sha256_base64(decode_base64($rsahostkey[1]));
+ close($pubsha256file);
+ if((! -e pp($hstpubsha256f)) || (! -s pp($hstpubsha256f))) {
+ logmsg "Failed writing sha256 hash of RSA host key\n";
exit 1;
}
}
@@ -414,29 +439,31 @@
#***************************************************************************
# Convert paths for curl's tests running on Windows with Cygwin/Msys OpenSSH
#
-my $clipubkeyf_config = abs_path("$path/$clipubkeyf");
-my $hstprvkeyf_config = abs_path("$path/$hstprvkeyf");
-my $pidfile_config = $pidfile;
-my $sftpsrv_config = $sftpsrv;
-
-if (pathhelp::os_is_win()) {
+my $clipubkeyf_config;
+my $hstprvkeyf_config;
+my $pidfile_config;
+my $sftpsrv_config;
+if ($sshdid =~ /OpenSSH-Windows/) {
+ # Ensure to use native Windows paths with OpenSSH for Windows
+ $clipubkeyf_config = pathhelp::sys_native_abs_path(pp($clipubkeyf));
+ $hstprvkeyf_config = pathhelp::sys_native_abs_path(pp($hstprvkeyf));
+ $pidfile_config = pathhelp::sys_native_abs_path($pidfile);
+ $sftpsrv_config = pathhelp::sys_native_abs_path($sftpsrv);
+}
+elsif (pathhelp::os_is_win()) {
# Ensure to use MinGW/Cygwin paths
$clipubkeyf_config = pathhelp::build_sys_abs_path($clipubkeyf_config);
$hstprvkeyf_config = pathhelp::build_sys_abs_path($hstprvkeyf_config);
$pidfile_config = pathhelp::build_sys_abs_path($pidfile_config);
$sftpsrv_config = "internal-sftp";
}
-if ($sshdid =~ /OpenSSH-Windows/) {
- # Ensure to use native Windows paths with OpenSSH for Windows
- $clipubkeyf_config = pathhelp::sys_native_abs_path($clipubkeyf);
- $hstprvkeyf_config = pathhelp::sys_native_abs_path($hstprvkeyf);
- $pidfile_config = pathhelp::sys_native_abs_path($pidfile);
- $sftpsrv_config = pathhelp::sys_native_abs_path($sftpsrv);
-
- $sshdconfig = pathhelp::sys_native_abs_path($sshdconfig);
- $sshconfig = pathhelp::sys_native_abs_path($sshconfig);
- $sftpconfig = pathhelp::sys_native_abs_path($sftpconfig);
+else {
+ $clipubkeyf_config = abs_path(pp($clipubkeyf));
+ $hstprvkeyf_config = abs_path(pp($hstprvkeyf));
+ $pidfile_config = $pidfile;
+ $sftpsrv_config = $sftpsrv;
}
+my $sshdconfig_abs = pathhelp::sys_native_abs_path(pp($sshdconfig));
#***************************************************************************
# ssh daemon configuration file options we might use and version support
@@ -523,7 +550,7 @@
#***************************************************************************
# Initialize sshd config with options actually supported in OpenSSH 2.9.9
#
-logmsg 'generating ssh server config file...' if($verbose);
+logmsg "generating ssh server config file...\n" if($verbose);
@cfgarr = ();
push @cfgarr, '# This is a generated file. Do not edit.';
push @cfgarr, "# $sshdverstr sshd configuration file for curl testing";
@@ -550,6 +577,11 @@
push @cfgarr, "HostKey $hstprvkeyf_config";
if ($sshdid !~ /OpenSSH-Windows/) {
push @cfgarr, "PidFile $pidfile_config";
+ push @cfgarr, '#';
+}
+if(($sshdid =~ /OpenSSH/) && ($sshdvernum >= 880)) {
+ push @cfgarr, 'HostKeyAlgorithms +ssh-rsa';
+ push @cfgarr, 'PubkeyAcceptedKeyTypes +ssh-rsa';
}
push @cfgarr, '#';
push @cfgarr, "Port $port";
@@ -590,9 +622,9 @@
#***************************************************************************
# Write out initial sshd configuration file for curl's tests
#
-$error = dump_array($sshdconfig, @cfgarr);
+$error = dump_array(pp($sshdconfig), @cfgarr);
if($error) {
- logmsg $error;
+ logmsg "$error\n";
exit 1;
}
@@ -608,19 +640,19 @@
($sshdid =~ /SunSSH/)) {
# ssh daemon supports command line options -t -f and -o
$err = grep /((Unsupported)|(Bad configuration)|(Deprecated)) option.*$option/,
- qx("$sshd" -t -f $sshdconfig -o "$option=$value" 2>&1);
+ `\"$sshd\" -t -f $sshdconfig_abs -o \"$option=$value\" 2>&1`;
return !$err;
}
if(($sshdid =~ /OpenSSH/) && ($sshdvernum >= 299)) {
# ssh daemon supports command line options -t and -f
- $err = dump_array($sshdconfig, (@cfgarr, "$option $value"));
+ $err = dump_array(pp($sshdconfig), (@cfgarr, "$option $value"));
if($err) {
- logmsg $err;
+ logmsg "$err\n";
return 0;
}
$err = grep /((Unsupported)|(Bad configuration)|(Deprecated)) option.*$option/,
- qx("$sshd" -t -f $sshdconfig 2>&1);
- unlink $sshdconfig;
+ `\"$sshd\" -t -f $sshdconfig_abs 2>&1`;
+ unlink pp($sshdconfig);
return !$err;
}
return 0;
@@ -694,7 +726,7 @@
#
if(sshd_supports_opt('AddressFamily','any')) {
# Address family must be specified before ListenAddress
- splice @cfgarr, 14, 0, 'AddressFamily any';
+ splice @cfgarr, 11, 0, 'AddressFamily any';
}
if(sshd_supports_opt('Compression','no')) {
push @cfgarr, 'Compression no';
@@ -752,9 +784,9 @@
#***************************************************************************
# Write out resulting sshd configuration file for curl's tests
#
-$error = dump_array($sshdconfig, @cfgarr);
+$error = dump_array(pp($sshdconfig), @cfgarr);
if($error) {
- logmsg $error;
+ logmsg "$error\n";
exit 1;
}
@@ -762,8 +794,8 @@
#***************************************************************************
# Verify that sshd actually supports our generated configuration file
#
-if(system "\"$sshd\" -t -f $sshdconfig > $sshdlog 2>&1") {
- logmsg "sshd configuration file $sshdconfig failed verification";
+if(system "\"$sshd\" -t -f $sshdconfig_abs > $sshdlog 2>&1") {
+ logmsg "sshd configuration file $sshdconfig failed verification\n";
display_sshdlog();
display_sshdconfig();
exit 1;
@@ -773,15 +805,15 @@
#***************************************************************************
# Generate ssh client host key database file for curl's tests
#
-if((! -e $knownhosts) || (! -s $knownhosts)) {
- logmsg 'generating ssh client known hosts file...' if($verbose);
- unlink($knownhosts);
- if(open(RSAKEYFILE, "<$hstpubkeyf")) {
- my @rsahostkey = do { local $/ = ' '; <RSAKEYFILE> };
- if(close(RSAKEYFILE)) {
- if(open(KNOWNHOSTS, ">$knownhosts")) {
- print KNOWNHOSTS "$listenaddr ssh-rsa $rsahostkey[1]\n";
- if(!close(KNOWNHOSTS)) {
+if((! -e pp($knownhosts)) || (! -s pp($knownhosts))) {
+ logmsg "generating ssh client known hosts file...\n" if($verbose);
+ unlink(pp($knownhosts));
+ if(open(my $rsakeyfile, "<", pp($hstpubkeyf))) {
+ my @rsahostkey = do { local $/ = ' '; <$rsakeyfile> };
+ if(close($rsakeyfile)) {
+ if(open(my $knownhostsh, ">", pp($knownhosts))) {
+ print $knownhostsh "$listenaddr ssh-rsa $rsahostkey[1]\n";
+ if(!close($knownhostsh)) {
$error = "Error: cannot close file $knownhosts";
}
}
@@ -797,7 +829,7 @@
$error = "Error: cannot read file $hstpubkeyf";
}
if($error) {
- logmsg $error;
+ logmsg "$error\n";
exit 1;
}
}
@@ -806,20 +838,24 @@
#***************************************************************************
# Convert paths for curl's tests running on Windows using Cygwin OpenSSH
#
-my $identity_config = abs_path("$path/$identity");
-my $knownhosts_config = abs_path("$path/$knownhosts");
-
-if (pathhelp::os_is_win()) {
+my $identity_config;
+my $knownhosts_config;
+if ($sshdid =~ /OpenSSH-Windows/) {
+ # Ensure to use native Windows paths with OpenSSH for Windows
+ $identity_config = pathhelp::sys_native_abs_path(pp($identity));
+ $knownhosts_config = pathhelp::sys_native_abs_path(pp($knownhosts));
+}
+elsif (pathhelp::os_is_win()) {
# Ensure to use MinGW/Cygwin paths
$identity_config = pathhelp::build_sys_abs_path($identity_config);
$knownhosts_config = pathhelp::build_sys_abs_path($knownhosts_config);
}
-if ($sshdid =~ /OpenSSH-Windows/) {
- # Ensure to use native Windows paths with OpenSSH for Windows
- $identity_config = pathhelp::sys_native_abs_path($identity);
- $knownhosts_config = pathhelp::sys_native_abs_path($knownhosts);
+else {
+ $identity_config = abs_path(pp($identity));
+ $knownhosts_config = abs_path(pp($knownhosts));
}
+
#***************************************************************************
# ssh client configuration file options we might use and version support
#
@@ -900,7 +936,7 @@
#***************************************************************************
# Initialize ssh config with options actually supported in OpenSSH 2.9.9
#
-logmsg 'generating ssh client config file...' if($verbose);
+logmsg "generating ssh client config file...\n" if($verbose);
@cfgarr = ();
push @cfgarr, '# This is a generated file. Do not edit.';
push @cfgarr, "# $sshverstr ssh client configuration file for curl testing";
@@ -1056,9 +1092,9 @@
#***************************************************************************
# Write out resulting ssh client configuration file for curl's tests
#
-$error = dump_array($sshconfig, @cfgarr);
+$error = dump_array(pp($sshconfig), @cfgarr);
if($error) {
- logmsg $error;
+ logmsg "$error\n";
exit 1;
}
@@ -1066,7 +1102,7 @@
#***************************************************************************
# Initialize client sftp config with options actually supported.
#
-logmsg 'generating sftp client config file...' if($verbose);
+logmsg "generating sftp client config file...\n" if($verbose);
splice @cfgarr, 1, 1, "# $sshverstr sftp client configuration file for curl testing";
#
for(my $i = scalar(@cfgarr) - 1; $i > 0; $i--) {
@@ -1084,9 +1120,9 @@
#***************************************************************************
# Write out resulting sftp client configuration file for curl's tests
#
-$error = dump_array($sftpconfig, @cfgarr);
+$error = dump_array(pp($sftpconfig), @cfgarr);
if($error) {
- logmsg $error;
+ logmsg "$error\n";
exit 1;
}
@cfgarr = ();
@@ -1095,12 +1131,12 @@
#***************************************************************************
# Generate client sftp commands batch file for sftp server verification
#
-logmsg 'generating sftp client commands file...' if($verbose);
+logmsg "generating sftp client commands file...\n" if($verbose);
push @cfgarr, 'pwd';
push @cfgarr, 'quit';
-$error = dump_array($sftpcmds, @cfgarr);
+$error = dump_array(pp($sftpcmds), @cfgarr);
if($error) {
- logmsg $error;
+ logmsg "$error\n";
exit 1;
}
@cfgarr = ();
@@ -1108,18 +1144,18 @@
#***************************************************************************
# Prepare command line of ssh server daemon
#
-my $cmd = "\"$sshd\" -e -D -f $sshdconfig > $sshdlog 2>&1";
-logmsg "SCP/SFTP server listening on port $port" if($verbose);
-logmsg "RUN: $cmd" if($verbose);
+my $cmd = "\"$sshd\" -e -D -f $sshdconfig_abs > $sshdlog 2>&1";
+logmsg "SCP/SFTP server listening on port $port\n" if($verbose);
+logmsg "RUN: $cmd\n" if($verbose);
#***************************************************************************
# Start the ssh server daemon on Windows without forking it
#
if ($sshdid =~ /OpenSSH-Windows/) {
# Fake pidfile for ssh server on Windows.
- if(open(OUT, ">$pidfile")) {
- print OUT $$ . "\n";
- close(OUT);
+ if(open(my $out, ">", "$pidfile")) {
+ print $out $$ . "\n";
+ close($out);
}
# Flush output.
@@ -1141,22 +1177,22 @@
#
my $rc = system($cmd);
if($rc == -1) {
- logmsg "\"$sshd\" failed with: $!";
+ logmsg "\"$sshd\" failed with: $!\n";
}
elsif($rc & 127) {
- logmsg sprintf("\"$sshd\" died with signal %d, and %s coredump",
+ logmsg sprintf("\"$sshd\" died with signal %d, and %s coredump\n",
($rc & 127), ($rc & 128)?'a':'no');
}
elsif($verbose && ($rc >> 8)) {
- logmsg sprintf("\"$sshd\" exited with %d", $rc >> 8);
+ logmsg sprintf("\"$sshd\" exited with %d\n", $rc >> 8);
}
#***************************************************************************
# Clean up once the server has stopped
#
-unlink($hstprvkeyf, $hstpubkeyf, $hstpubmd5f, $hstpubsha256f,
- $cliprvkeyf, $clipubkeyf, $knownhosts,
- $sshdconfig, $sshconfig, $sftpconfig);
+unlink(pp($hstprvkeyf), pp($hstpubkeyf), pp($hstpubmd5f), pp($hstpubsha256f),
+ pp($cliprvkeyf), pp($clipubkeyf), pp($knownhosts),
+ pp($sshdconfig), pp($sshconfig), pp($sftpconfig));
exit 0;
diff --git a/tests/stunnel.pem b/tests/stunnel.pem
index 2a05941..b7dd1e8 100644
--- a/tests/stunnel.pem
+++ b/tests/stunnel.pem
@@ -1,172 +1,165 @@
-#
-# This file contains a private key and a certificate used for stunnel.
-# The certificate contains a number of extensions essentially being
-# used in the 509 test. The certificate has been generated using
-# openssl with the parameters listed below up to the line
-# contain [something], after that you find the result.
-#
-#
extensions = x509v3
[ x509v3 ]
-subjectAltName = DNS:localhost
-nsCertType = server
-nsComment = "CURL stunnel server test certificate"
-keyUsage = digitalSignature,keyEncipherment
+subjectAltName = DNS:localhost
+keyUsage = keyEncipherment,digitalSignature,keyAgreement
extendedKeyUsage = serverAuth
-basicConstraints = CA:false
subjectKeyIdentifier = hash
-subjectInfoAccess = AD_DVCS;URI:"https://localhost:8433/509"
-authorityInfoAccess = AD_DVCS;URI:"https://localhost:8433/509"
+authorityKeyIdentifier = keyid
+basicConstraints = CA:false
+authorityInfoAccess = @issuer_info
+crlDistributionPoints = @crl_info
+
+[ crl_ext ]
+authorityKeyIdentifier = keyid:always
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+caIssuers;URI.0 = http://test.curl.se/ca/EdelCurlRoot.cer
+
+[ crl_info ]
+URI.0 = http://test.curl.se/ca/EdelCurlRoot.crl
+
[ req ]
-default_bits = 1234
+default_bits = 12048
distinguished_name = req_DN
-default_md = sha1
-string_mask = pkix
+default_md = sha256
+string_mask = utf8only
[ req_DN ]
-countryName = "1. Country Name (2 letter code)"
-countryName_value = SE
-stateOrProvinceName = "2. State or Province Name (full name) "
-stateOrProvinceName_value = Solna
-localityName = "3. Locality Name (eg, city) "
-localityName_value = Mooo
-0.organizationName = "4. Organization Name (eg, company) "
-0.organizationName_value = Haxx
-organizationalUnitName = "5. Organizational Unit Name (eg, section) "
-organizationalUnitName_value = Coolx
-commonName = "6. Common Name (eg, FQDN) "
-commonName_value = "storbror"
-1.commonName = "6. Common Name (eg, FQDN) "
-1.commonName_value = "localhost"
+countryName = "Country Name is Northern Nowhere"
+countryName_value = NN
+organizationName = "Organization Name"
+organizationName_value = Edel Curl Arctic Illudium Research Cloud
+commonName = "Common Name"
+commonName_value = localhost
+
[something]
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEA4m+wAdU3ml4EGud+/rx3ZY9VnNIfRZo6yDGogOk/Pg1NM7zo
-+cXsRhQZuFNskxOgiYv9vTLJCocPXGJBRhosnCkUXypbaismZLGXBxyvUNvI4cNi
-/icPnq9RHwWCbX9UpSn6nsjcVyHacQeHEza8pC5MnFDC8tTTy3rCpWe2LKSp3X6g
-E4vKRiLFbXAZshrtk8wKiRuDuiNhxUyYcVs3s5+Il8Y9yu/kGkY6U15SizO+o224
-kfOHL6W9Ut4l2xY7aRZLWhqjyihlaHSLFEiLkR9fPMVDTOF6j/g2fFAjNePw6+9Y
-VbVq0PQF1cY0ew6wMNvu7cVLZo+xz5toebOH4wIDAQABAoIBAGLf1CIowVvVm8NH
-vIttLlGZkg+lLOSOoQZTsLmBoAzvb/ucjLqsMyyykDyNqQZb9qi5CTY5W9IOAaYc
-fVYoDbyur2eSrlIgv2YOqd0AKImNPx1d3PcPhWGMOkbqd/ZqOELansYA/T3K2YCr
-gc7hAuRKF0fWeBni1wyt8Rqau9Cn0AK/aAf/Fn28bCaS5DrkqvsM2wOIRWelGgCM
-3zfn+RbhcLbBPIyP6iC+8Gm39pK8JZznJXC0rhN05edvh0+ILlB7lMJ4t5lnLSxF
-vsfkxLGl5pMXWthJ0VYl+H5JIsD+7+dc45HjX21GLs6eTW0hMxPcrqaNlWgQPMxG
-DQNriPECgYEA8tfVQiyzT7rM2HI562BlV5b0PEafq2F7WAzNWMGiBxxRUpMnAtmn
-VVsWiRrHch4Y4nlbmjvQDhrvDOzpGuEPAi+FtePk23y87q8lB8VjOSDR86TPvSXK
-QqMDZ8ffYvRIh7MKYO8gvIYrjMEDeSQNzGxiyw3e0EIGuuQt+42t8JkCgYEA7rRL
-4sl3fl/npxacrtFNnqZP+R/KKBbdbeOgJPDPknMfzd6/B5Pyznz6dG3N3QwivPPF
-uAjPgqI8Pt+7SFW8Rw7XRVWZP9fZGPWrDdqdP/0lzDLYmmHXICqCVQXQapKofZbI
-HfV0HZSGuJtEiLG3bzjQiQx5jJlXtegMHHpMfdsCgYAzVrvIDKkv3t71l1h1UWC7
-XrdtksSot6ga2kIDVJRLiooKuf9SU+9TVTlzbMzjbEd4gY2DEsgOY1VMVz2EqDXD
-EYbkCDTWzg0nLLHYbbtnVW/tYVdltnqHEe1jYFbylZBL1+cGzScPlBHa5Oc2EhA0
-umk8YkdLodnIYvrxpmcyaQKBgQCd6UJGblcRkCp0e939PFNn/8fqG6ClsrKbjrkT
-lwcKcAR7Mb8YKUS4Wy9otHc6o1ubunxzScjVN7Q5N9LygF1EeMnqgT0XYhipjWOy
-j4v1l+dYVc67Gryw984upuEAj7LNGmGaiBVfuDEDkRvefgrGlkRGVa1XWN4QZckV
-UcamfwKBgQDO9xGun8Q97KonBRih4aNBM+89/8/deZNPAc8MAImzFHyTMNTD06C/
-3wnJwMiyNbZEUfKavapNz3+oe0fXMbgjfEypbaP7jKHSxr2tKwJV+MK1RVF4Sd3l
-ou6XtlnToLp/LO1X3E/IcYameT5VLi/4OyFOMKe9K0Woxvhz42PDww==
------END RSA PRIVATE KEY-----
+# The key
+# the certificate
+# some dhparam
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCrCrAD0Hb+Xs4V
+3mHV45FvfNa7yiaOeL4mNdGmWfHVPFU+CSzsoNSvDjxaorWweFGVYoCAcchOn1lZ
+k0ASsqnOss0Xi58n8+PPI3gG0gYjX5sg7EJ3Zq2kXoK0TZRy6hNkcvzLgyzXoYv1
+LkzTwYiyyJgZX++Y/GKAs2fMHyP8XzjNgm4tltk1k/4pomllwN9Fqz+sFxgAgEq3
+ybq4Xym7xKwWl8xXNBDJNmVsPtiJRcilQoR8Xs0a6PE+VbMhD9A2E/LEL7lzQfqH
+qtxE1mSW5FpQ+Uqf4KLnafStWs86IOWnCeLP6BmhAK6ouyICNFyzz7UkTHa/renx
+uNOGun2TAgMBAAECggEAH0BsKb5Ax7h90jwYRzL141d9isFkaxq/r46c2FbN24bT
+EmstxKycP8ILoAnjxbMuQOvHC/D+RvNRqY7Aocn4Qdakp50wvuWOpc3Ww/RC/9qb
+pxfUCyn9Jy/HlPcp3RdM5MknzG2S13Fid7F2gyh0+CmztMs1JZBT1S0ylXbJJfbY
+1pdlHcf9oEbYo36vGd9rtJHAFzsFfwua0idl76XYuOnR3bpOkHl1B5cJ8jpOliPv
+VTmzn0cIgAmk7IByHHqGQ0u30PFiElI9kEbkKWoxAM1hq1pFU58jQhvp0ZkjVENL
+bSFB2B4DbyosxPlbUgvJCN4B7nclqzYqBdrrk6/ZLQKBgQC1lDrPSGIGXLwvkZYS
+xc0wtaCC7u6m7zV8rzh5HGcEoVvtmya/VyoZR8KGIpSor8COIkZqFtan6C77C3MH
+wClbu2Kn3FkGb76D5U2Xwl38zepzjn8Z5qXc3bZfccrsDY1gXPicgsmcKUY9xV5/
+T0RjESDKB+xxkJpCjia6klm2NQKBgQDxJNuqB6frDYKaj7mW/rvyHqkeT94J6eDY
+BcMZVKeHRNWcBMOvJDChVmpsCjJPOWHhHOlAE755NxWn8wpgyiUcac3BiysMgvTT
+pyH8UVWaP/DWYOfpuhtcLPkIjKnPijOvshpyWBxfXNIejiovoT6E3IXKOxr5g5yq
+U/9a5+I9pwKBgDyJG4YpkoyedBrDxa2ihkL7+nRMZgH/c+yKmiA+aNXxWa2AcU2P
+KLje5KpFcxw948s/AAy0aoH19Vu6uHHYDbHIah6eZouvy2s7kj/LC/yRRd2anyMq
+cxeMTxXI4ScLaZu7wyKis8Y9OG61k0iMS7dfaXgRZjGCTPttWtoOmpwVAoGAd2k+
+EXuLDl15UBpd18S6wxGlw2nfVN9oxPBNhUyjTNusP38oe6EbJ7mIJ4oBEbQjoPrV
+EjL0vkelxK4YdIeFSwWlqvLEVYS/wdNgg/auwhxpoW8JSHctNz7Z7v7g0/Hm2FkE
+uZyiKCLptdHGWCGruNUOt27/U5F10e6YY6ayJL8CgYEAoE/ddHIlrKFzcZ0cu47R
+ky4D4x32ceC2au4eGPLMDItPjceXe8I6zgB5P8/U5U3PRw5oWabpAf5lAcRwa12c
+23xgy9O5QNlyps/rAdnVjwxqGwEd5E2LrZ2+JDflPRGunx2VO5v9CxXvsxu9F3Rj
+tREtebHe2H7u5jNsIQArnRI=
+-----END PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 17862059579548371559 (0xf7e2c88ce3d80a67)
- Signature Algorithm: sha256WithRSAEncryption
- Issuer: C=SE, ST=Solna, L=Mooo, O=Haxx, OU=Coolx, CN=storbror, CN=localhost
+ Serial Number: 16717980999635 (0xf3475519fd3)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer:
+ countryName = NN
+ organizationName = Edel Curl Arctic Illudium Research Cloud
+ commonName = Northern Nowhere Trust Anchor
Validity
- Not Before: Aug 31 23:39:18 2018 GMT
- Not After : Aug 28 23:39:18 2028 GMT
- Subject: C=SE, ST=Solna, L=Mooo, O=Haxx, OU=Coolx, CN=storbror, CN=localhost
+ Not Before: Dec 23 12:21:39 2022 GMT
+ Not After : Mar 11 12:21:39 2031 GMT
+ Subject:
+ countryName = NN
+ organizationName = Edel Curl Arctic Illudium Research Cloud
+ commonName = localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:e2:6f:b0:01:d5:37:9a:5e:04:1a:e7:7e:fe:bc:
- 77:65:8f:55:9c:d2:1f:45:9a:3a:c8:31:a8:80:e9:
- 3f:3e:0d:4d:33:bc:e8:f9:c5:ec:46:14:19:b8:53:
- 6c:93:13:a0:89:8b:fd:bd:32:c9:0a:87:0f:5c:62:
- 41:46:1a:2c:9c:29:14:5f:2a:5b:6a:2b:26:64:b1:
- 97:07:1c:af:50:db:c8:e1:c3:62:fe:27:0f:9e:af:
- 51:1f:05:82:6d:7f:54:a5:29:fa:9e:c8:dc:57:21:
- da:71:07:87:13:36:bc:a4:2e:4c:9c:50:c2:f2:d4:
- d3:cb:7a:c2:a5:67:b6:2c:a4:a9:dd:7e:a0:13:8b:
- ca:46:22:c5:6d:70:19:b2:1a:ed:93:cc:0a:89:1b:
- 83:ba:23:61:c5:4c:98:71:5b:37:b3:9f:88:97:c6:
- 3d:ca:ef:e4:1a:46:3a:53:5e:52:8b:33:be:a3:6d:
- b8:91:f3:87:2f:a5:bd:52:de:25:db:16:3b:69:16:
- 4b:5a:1a:a3:ca:28:65:68:74:8b:14:48:8b:91:1f:
- 5f:3c:c5:43:4c:e1:7a:8f:f8:36:7c:50:23:35:e3:
- f0:eb:ef:58:55:b5:6a:d0:f4:05:d5:c6:34:7b:0e:
- b0:30:db:ee:ed:c5:4b:66:8f:b1:cf:9b:68:79:b3:
- 87:e3
+ 00:ab:0a:b0:03:d0:76:fe:5e:ce:15:de:61:d5:e3:
+ 91:6f:7c:d6:bb:ca:26:8e:78:be:26:35:d1:a6:59:
+ f1:d5:3c:55:3e:09:2c:ec:a0:d4:af:0e:3c:5a:a2:
+ b5:b0:78:51:95:62:80:80:71:c8:4e:9f:59:59:93:
+ 40:12:b2:a9:ce:b2:cd:17:8b:9f:27:f3:e3:cf:23:
+ 78:06:d2:06:23:5f:9b:20:ec:42:77:66:ad:a4:5e:
+ 82:b4:4d:94:72:ea:13:64:72:fc:cb:83:2c:d7:a1:
+ 8b:f5:2e:4c:d3:c1:88:b2:c8:98:19:5f:ef:98:fc:
+ 62:80:b3:67:cc:1f:23:fc:5f:38:cd:82:6e:2d:96:
+ d9:35:93:fe:29:a2:69:65:c0:df:45:ab:3f:ac:17:
+ 18:00:80:4a:b7:c9:ba:b8:5f:29:bb:c4:ac:16:97:
+ cc:57:34:10:c9:36:65:6c:3e:d8:89:45:c8:a5:42:
+ 84:7c:5e:cd:1a:e8:f1:3e:55:b3:21:0f:d0:36:13:
+ f2:c4:2f:b9:73:41:fa:87:aa:dc:44:d6:64:96:e4:
+ 5a:50:f9:4a:9f:e0:a2:e7:69:f4:ad:5a:cf:3a:20:
+ e5:a7:09:e2:cf:e8:19:a1:00:ae:a8:bb:22:02:34:
+ 5c:b3:cf:b5:24:4c:76:bf:ad:e9:f1:b8:d3:86:ba:
+ 7d:93
Exponent: 65537 (0x10001)
X509v3 extensions:
- X509v3 Subject Alternative Name:
+ X509v3 Subject Alternative Name:
DNS:localhost
- Netscape Cert Type:
- SSL Server
- Netscape Comment:
- CURL stunnel server test certificate
- X509v3 Key Usage:
- Digital Signature, Key Encipherment
- X509v3 Extended Key Usage:
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment, Key Agreement
+ X509v3 Extended Key Usage:
TLS Web Server Authentication
- X509v3 Basic Constraints:
+ X509v3 Subject Key Identifier:
+ 9C:97:B0:3D:B3:50:B1:F6:D4:71:E2:EB:CB:80:EA:93:7C:98:CC:72
+ X509v3 Authority Key Identifier:
+ 87:CB:B1:33:2E:C1:67:7E:71:E3:E5:2B:4C:4D:A4:B3:6E:D2:5B:A9
+ X509v3 Basic Constraints:
CA:FALSE
- X509v3 Subject Key Identifier:
- 5D:A5:DB:5A:C8:6D:31:A6:B0:E3:4D:47:50:AA:87:A9:B2:DE:9F:37
- Subject Information Access:
- ad dvcs - URI:https://localhost:8433/509
-
- Authority Information Access:
- ad dvcs - URI:https://localhost:8433/509
-
+ Authority Information Access:
+ CA Issuers - URI:http://test.curl.se/ca/EdelCurlRoot.cer
+ X509v3 CRL Distribution Points:
+ Full Name:
+ URI:http://test.curl.se/ca/EdelCurlRoot.crl
Signature Algorithm: sha256WithRSAEncryption
- 63:26:72:df:c4:68:af:f1:30:60:4e:ac:94:bd:37:3e:c4:1f:
- 6b:43:6e:0f:1c:67:49:f4:fb:19:83:23:b6:75:46:a0:84:bd:
- 8b:61:21:00:05:6b:d6:09:16:94:8f:5b:9d:98:98:d6:1e:86:
- 23:26:1e:e8:39:ac:0a:89:ea:17:b5:4f:60:20:9a:2b:4a:d4:
- 9f:4e:3d:d4:ac:05:db:25:94:56:e3:87:13:ea:ab:83:57:18:
- ff:26:e3:46:0c:e6:49:7e:74:2e:77:98:54:52:30:ea:6f:58:
- 35:dc:63:fb:e4:a2:c3:12:87:dd:e9:2a:18:5c:9c:cf:a4:d3:
- 58:7f:d0:50:50:0f:b9:b7:cb:a8:d9:bd:b8:7c:e4:29:d5:f3:
- fd:6f:3f:ea:fc:0f:21:3f:ad:2f:ac:3c:28:e3:74:87:43:a9:
- f0:46:81:4b:c8:a5:75:50:5b:e2:d5:75:0a:98:af:2c:6d:6b:
- 6a:cc:c6:37:5f:04:52:c4:d8:6a:a0:f6:99:76:c3:3b:3b:50:
- c8:bc:ea:50:04:a1:c0:54:82:b4:2f:09:b8:6e:ac:cc:64:12:
- ce:b8:24:7a:5a:e5:f5:e5:79:9f:28:da:a2:11:45:f5:2a:cb:
- e3:b0:96:6a:ac:2b:d3:02:01:21:6d:38:ef:52:60:5e:50:b1:
- 25:e5:4f:69
+ Signature Value:
+ 0b:8a:ed:6a:87:fa:71:15:88:25:58:85:1b:4a:09:bf:43:00:
+ 35:93:78:0d:72:14:30:51:e2:93:83:a1:da:1b:2f:a9:31:ae:
+ b7:c7:4c:72:c2:5e:32:24:f1:96:93:70:d5:3f:b5:85:80:13:
+ 75:32:cf:0e:f8:5d:c4:a2:29:84:43:2c:75:81:26:12:6a:a0:
+ cb:7b:57:c1:92:78:85:08:fa:64:50:c2:7b:83:02:4d:79:13:
+ bc:61:64:4d:b8:6b:d5:f1:84:6b:12:5c:69:90:ad:40:47:c0:
+ ed:dd:ea:8a:66:7e:87:85:19:aa:89:d3:3c:08:72:08:a1:4d:
+ 63:60:5b:9b:17:9e:00:12:a1:00:52:ca:78:01:88:18:c7:ed:
+ 5b:c7:e4:d9:eb:bd:3f:af:92:53:3f:fe:58:57:0d:fc:f4:7b:
+ 7b:a2:4f:e9:b9:5c:b5:a4:52:50:b4:56:5a:44:8e:d9:d0:ed:
+ de:8f:7e:ac:1c:58:76:5b:a8:79:c9:95:ab:85:1d:db:4c:13:
+ 82:4a:a5:41:1b:29:f5:d3:96:df:80:d1:1e:00:7d:ba:35:94:
+ 57:81:e1:08:2a:81:6b:1c:30:50:37:01:1a:0e:26:4f:6b:ed:
+ c9:50:17:37:2b:33:3f:68:fe:c6:f0:21:8c:e7:b2:79:55:f2:
+ 42:bd:2f:b0
-----BEGIN CERTIFICATE-----
-MIIEhzCCA2+gAwIBAgIJAPfiyIzj2ApnMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNV
-BAYTAlNFMQ4wDAYDVQQIEwVTb2xuYTENMAsGA1UEBxMETW9vbzENMAsGA1UEChME
-SGF4eDEOMAwGA1UECxMFQ29vbHgxETAPBgNVBAMTCHN0b3Jicm9yMRIwEAYDVQQD
-Ewlsb2NhbGhvc3QwHhcNMTgwODMxMjMzOTE4WhcNMjgwODI4MjMzOTE4WjByMQsw
-CQYDVQQGEwJTRTEOMAwGA1UECBMFU29sbmExDTALBgNVBAcTBE1vb28xDTALBgNV
-BAoTBEhheHgxDjAMBgNVBAsTBUNvb2x4MREwDwYDVQQDEwhzdG9yYnJvcjESMBAG
-A1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
-4m+wAdU3ml4EGud+/rx3ZY9VnNIfRZo6yDGogOk/Pg1NM7zo+cXsRhQZuFNskxOg
-iYv9vTLJCocPXGJBRhosnCkUXypbaismZLGXBxyvUNvI4cNi/icPnq9RHwWCbX9U
-pSn6nsjcVyHacQeHEza8pC5MnFDC8tTTy3rCpWe2LKSp3X6gE4vKRiLFbXAZshrt
-k8wKiRuDuiNhxUyYcVs3s5+Il8Y9yu/kGkY6U15SizO+o224kfOHL6W9Ut4l2xY7
-aRZLWhqjyihlaHSLFEiLkR9fPMVDTOF6j/g2fFAjNePw6+9YVbVq0PQF1cY0ew6w
-MNvu7cVLZo+xz5toebOH4wIDAQABo4IBHjCCARowFAYDVR0RBA0wC4IJbG9jYWxo
-b3N0MBEGCWCGSAGG+EIBAQQEAwIGQDAzBglghkgBhvhCAQ0EJhYkQ1VSTCBzdHVu
-bmVsIHNlcnZlciB0ZXN0IGNlcnRpZmljYXRlMAsGA1UdDwQEAwIFoDATBgNVHSUE
-DDAKBggrBgEFBQcDATAJBgNVHRMEAjAAMB0GA1UdDgQWBBRdpdtayG0xprDjTUdQ
-qoepst6fNzA2BggrBgEFBQcBCwQqMCgwJgYIKwYBBQUHMASGGmh0dHBzOi8vbG9j
-YWxob3N0Ojg0MzMvNTA5MDYGCCsGAQUFBwEBBCowKDAmBggrBgEFBQcwBIYaaHR0
-cHM6Ly9sb2NhbGhvc3Q6ODQzMy81MDkwDQYJKoZIhvcNAQELBQADggEBAGMmct/E
-aK/xMGBOrJS9Nz7EH2tDbg8cZ0n0+xmDI7Z1RqCEvYthIQAFa9YJFpSPW52YmNYe
-hiMmHug5rAqJ6he1T2AgmitK1J9OPdSsBdsllFbjhxPqq4NXGP8m40YM5kl+dC53
-mFRSMOpvWDXcY/vkosMSh93pKhhcnM+k01h/0FBQD7m3y6jZvbh85CnV8/1vP+r8
-DyE/rS+sPCjjdIdDqfBGgUvIpXVQW+LVdQqYryxta2rMxjdfBFLE2Gqg9pl2wzs7
-UMi86lAEocBUgrQvCbhurMxkEs64JHpa5fXleZ8o2qIRRfUqy+OwlmqsK9MCASFt
-OO9SYF5QsSXlT2k=
+MIIERDCCAyygAwIBAgIGDzR1UZ/TMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYT
+Ak5OMTEwLwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNo
+IENsb3VkMSYwJAYDVQQDDB1Ob3J0aGVybiBOb3doZXJlIFRydXN0IEFuY2hvcjAe
+Fw0yMjEyMjMxMjIxMzlaFw0zMTAzMTExMjIxMzlaMFQxCzAJBgNVBAYTAk5OMTEw
+LwYDVQQKDChFZGVsIEN1cmwgQXJjdGljIElsbHVkaXVtIFJlc2VhcmNoIENsb3Vk
+MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQCrCrAD0Hb+Xs4V3mHV45FvfNa7yiaOeL4mNdGmWfHVPFU+CSzsoNSvDjxa
+orWweFGVYoCAcchOn1lZk0ASsqnOss0Xi58n8+PPI3gG0gYjX5sg7EJ3Zq2kXoK0
+TZRy6hNkcvzLgyzXoYv1LkzTwYiyyJgZX++Y/GKAs2fMHyP8XzjNgm4tltk1k/4p
+omllwN9Fqz+sFxgAgEq3ybq4Xym7xKwWl8xXNBDJNmVsPtiJRcilQoR8Xs0a6PE+
+VbMhD9A2E/LEL7lzQfqHqtxE1mSW5FpQ+Uqf4KLnafStWs86IOWnCeLP6BmhAK6o
+uyICNFyzz7UkTHa/renxuNOGun2TAgMBAAGjggEGMIIBAjAUBgNVHREEDTALggls
+b2NhbGhvc3QwCwYDVR0PBAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1Ud
+DgQWBBScl7A9s1Cx9tRx4uvLgOqTfJjMcjAfBgNVHSMEGDAWgBSHy7EzLsFnfnHj
+5StMTaSzbtJbqTAJBgNVHRMEAjAAMEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcw
+AoYnaHR0cDovL3Rlc3QuY3VybC5zZS9jYS9FZGVsQ3VybFJvb3QuY2VyMDgGA1Ud
+HwQxMC8wLaAroCmGJ2h0dHA6Ly90ZXN0LmN1cmwuc2UvY2EvRWRlbEN1cmxSb290
+LmNybDANBgkqhkiG9w0BAQsFAAOCAQEAC4rtaof6cRWIJViFG0oJv0MANZN4DXIU
+MFHik4Oh2hsvqTGut8dMcsJeMiTxlpNw1T+1hYATdTLPDvhdxKIphEMsdYEmEmqg
+y3tXwZJ4hQj6ZFDCe4MCTXkTvGFkTbhr1fGEaxJcaZCtQEfA7d3qimZ+h4UZqonT
+PAhyCKFNY2BbmxeeABKhAFLKeAGIGMftW8fk2eu9P6+SUz/+WFcN/PR7e6JP6blc
+taRSULRWWkSO2dDt3o9+rBxYdluoecmVq4Ud20wTgkqlQRsp9dOW34DRHgB9ujWU
+V4HhCCqBaxwwUDcBGg4mT2vtyVAXNyszP2j+xvAhjOeyeVXyQr0vsA==
-----END CERTIFICATE-----
------BEGIN DH PARAMETERS-----
-MIIBCAKCAQEA5H4005OFRDtVlHgJ5AGLRMAqvc+f4g7fApALq/1qJCwF7xq3POya
-hFr/O+9WtdlaiXLi0tqJzj5Cfv0ChIUcSOD7qBfUpIYcDFqQhYaRexMP6h0Ugk9x
-sIs2tcUfix7xemGLdawkGD041MJW8SK0+iY/s2wIXH/Pp5w7/e/RmTcjTa3QnL8O
-zbyXnZVvCEpDhRefgYrY5lR4SeZHl8+A6qe+M37g9Lai+ASCDuGfiynRW8JqAA3n
-5ozPhlQF3HaHglvEONUM0Qxd5a4jVjTXQYfV+hqvkz/Ykv8rZa8rVjx/bi1sKM66
-+WwPhqnjh31d+nFezqDJC4j0wLmxorDkMwIBAg==
------END DH PARAMETERS-----
\ No newline at end of file
diff --git a/tests/symbol-scan.pl b/tests/symbol-scan.pl
index 92dc0f0..5c4f337 100755
--- a/tests/symbol-scan.pl
+++ b/tests/symbol-scan.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -53,15 +53,11 @@
# need an include directory when building out-of-tree
my $i = ($ARGV[1]) ? "-I$ARGV[1] " : '';
-my $h = "$root/include/curl/curl.h";
-my $mh = "$root/include/curl/multi.h";
-my $ua = "$root/include/curl/urlapi.h";
-my $hd = "$root/include/curl/header.h";
-
my $verbose=0;
my $summary=0;
my $misses=0;
+my @manrefs;
my @syms;
my %doc;
my %rem;
@@ -70,40 +66,82 @@
# included by it, which *should* be all headers
sub scanenum {
my ($file) = @_;
- open H_IN, "-|", "$Cpreprocessor $i$file" || die "Cannot preprocess $file";
- while ( <H_IN> ) {
+ open my $h_in, "-|", "$Cpreprocessor $i$file" || die "Cannot preprocess $file";
+ while ( <$h_in> ) {
if ( /enum\s+(\S+\s+)?{/ .. /}/ ) {
s/^\s+//;
next unless /^CURL/;
chomp;
s/[,\s].*//;
push @syms, $_;
- print STDERR "$_\n";
}
}
- close H_IN || die "Error preprocessing $file";
+ close $h_in || die "Error preprocessing $file";
}
sub scanheader {
my ($f)=@_;
- open H, "<$f";
- while(<H>) {
- if (/^#define (CURL[A-Za-z0-9_]*)/) {
+ open my $h, "<", "$f";
+ while(<$h>) {
+ if (/^#define ((LIB|)CURL[A-Za-z0-9_]*)/) {
push @syms, $1;
}
}
- close H;
+ close $h;
}
-scanenum($h);
-scanheader($h);
-scanheader($mh);
-scanheader($ua);
-scanheader($hd);
+sub scanallheaders {
+ my $d = "$root/include/curl";
+ opendir(my $dh, $d) ||
+ die "Can't opendir: $!";
+ my @headers = grep { /.h\z/ } readdir($dh);
+ closedir $dh;
+ foreach my $h (@headers) {
+ scanenum("$d/$h");
+ scanheader("$d/$h");
+ }
+}
-open S, "<$root/docs/libcurl/symbols-in-versions";
-while(<S>) {
- if(/(^CURL[^ \n]*) *(.*)/) {
+sub checkmanpage {
+ my ($m) = @_;
+
+ open(my $mh, "<", "$m");
+ my $line = 1;
+ while(<$mh>) {
+ # strip off formatting
+ $_ =~ s/\\f[BPRI]//;
+ # detect global-looking 'CURL[BLABLA]_*' symbols
+ while(s/\W(CURL(AUTH|E|H|MOPT|OPT|SHOPT|UE|M|SSH|SSLBACKEND|HEADER|FORM|FTP|PIPE|MIMEOPT|GSSAPI|ALTSVC|PROTO|PROXY|UPART|USESSL|_READFUNC|_WRITEFUNC|_CSELECT|_FORMADD|_IPRESOLVE|_REDIR|_RTSPREQ|_TIMECOND|_VERSION)_[a-zA-Z0-9_]+)//) {
+ my $s = $1;
+ # skip two "special" ones
+ if($s !~ /^(CURLE_OBSOLETE|CURLOPT_TEMPLATE)/) {
+ push @manrefs, "$1:$m:$line";
+ }
+ }
+ $line++;
+ }
+ close($mh);
+}
+
+sub scanman3dir {
+ my ($d) = @_;
+ opendir(my $dh, $d) ||
+ die "Can't opendir: $!";
+ my @mans = grep { /.3\z/ } readdir($dh);
+ closedir $dh;
+ for my $m (@mans) {
+ checkmanpage("$d/$m");
+ }
+}
+
+
+scanallheaders();
+scanman3dir("$root/docs/libcurl");
+scanman3dir("$root/docs/libcurl/opts");
+
+open my $s, "<", "$root/docs/libcurl/symbols-in-versions";
+while(<$s>) {
+ if(/(^[^ \n]+) +(.*)/) {
my ($sym, $rest)=($1, $2);
if($doc{$sym}) {
print "Detected duplicate symbol: $sym\n";
@@ -119,7 +157,7 @@
}
}
}
-close S;
+close $s;
my $ignored=0;
for my $e (sort @syms) {
@@ -176,6 +214,17 @@
}
}
+my %warned;
+for my $r (@manrefs) {
+ if($r =~ /^([^:]+):(.*)/) {
+ my ($sym, $file)=($1, $2);
+ if(!$doc{$sym} && !$warned{$sym, $file}) {
+ print "$file: $sym is not a public symbol\n";
+ $warned{$sym, $file} = 1;
+ }
+ }
+}
+
if($summary) {
print "Summary:\n";
printf "%d symbols in headers (out of which %d are ignored)\n", scalar(@syms),
diff --git a/tests/testcurl.1 b/tests/testcurl.1
index ed4b5b5..c88b275 100644
--- a/tests/testcurl.1
+++ b/tests/testcurl.1
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH testcurl.pl 1 "24 Mar 2010" "Curl 7.20.1" "testcurl"
+.TH testcurl.pl 1 "24 Mar 2010" testcurl testcurl
.SH NAME
testcurl.pl \- (automatically) test curl
.SH SYNOPSIS
diff --git a/tests/testcurl.pl b/tests/testcurl.pl
index acf2c6b..09b0d98 100755
--- a/tests/testcurl.pl
+++ b/tests/testcurl.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -77,7 +77,7 @@
$timestamp $notes);
# version of this script
-$version='2014-11-25';
+$version='2023-03-28';
$fixed=0;
# Determine if we're running from git or a canned copy of curl,
@@ -195,14 +195,14 @@
sub grepfile($$) {
my ($target, $fn) = @_;
- open(F, $fn) or die;
- while (<F>) {
+ open(my $fh, "<", $fn) or die;
+ while (<$fh>) {
if (/$target/) {
- close(F);
+ close($fh);
return 1;
}
}
- close(F);
+ close($fh);
return 0;
}
@@ -243,14 +243,14 @@
my $triplet;
my $configfile = "$pwd/$build/lib/curl_config.h";
- if(-f $configfile && -s $configfile && open(LIBCONFIGH, "<$configfile")) {
- while(<LIBCONFIGH>) {
+ if(-f $configfile && -s $configfile && open(my $libconfigh, "<", "$configfile")) {
+ while(<$libconfigh>) {
if($_ =~ /^\#define\s+OS\s+"*([^"][^"]*)"*\s*/) {
$triplet = $1;
last;
}
}
- close(LIBCONFIGH);
+ close($libconfigh);
}
return $triplet;
}
@@ -261,13 +261,13 @@
$infixed=4;
$fixed=4;
}
-elsif (open(F, "$setupfile")) {
- while (<F>) {
+elsif (open(my $f, "<", "$setupfile")) {
+ while (<$f>) {
if (/(\w+)=(.*)/) {
eval "\$$1=$2;";
}
}
- close(F);
+ close($f);
$infixed=$fixed;
}
else {
@@ -307,14 +307,14 @@
if ($fixed < 4) {
$fixed=4;
- open(F, ">$setupfile") or die;
- print F "name='$name'\n";
- print F "email='$email'\n";
- print F "desc='$desc'\n";
- print F "confopts='$confopts'\n";
- print F "notes='$notes'\n";
- print F "fixed='$fixed'\n";
- close(F);
+ open(my $f, ">", "$setupfile") or die;
+ print $f "name='$name'\n";
+ print $f "email='$email'\n";
+ print $f "desc='$desc'\n";
+ print $f "confopts='$confopts'\n";
+ print $f "notes='$notes'\n";
+ print $f "fixed='$fixed'\n";
+ close($f);
}
# Enable picky compiler warnings unless explicitly disabled
@@ -469,15 +469,15 @@
# generate the build files
logit "invoke autoreconf";
- open(F, "autoreconf -fi 2>&1 |") or die;
- open(LOG, ">$buildlog") or die;
- while (<F>) {
+ open(my $f, "-|", "autoreconf -fi 2>&1") or die;
+ open(my $log, ">", "$buildlog") or die;
+ while (<$f>) {
my $ll = $_;
print $ll;
- print LOG $ll;
+ print $log $ll;
}
- close(F);
- close(LOG);
+ close($f);
+ close($log);
logit "buildconf was successful";
}
@@ -488,8 +488,8 @@
# Set timestamp to the one in curlver.h if this isn't a git test build.
if ((-f "include/curl/curlver.h") &&
- (open(F, "<include/curl/curlver.h"))) {
- while (<F>) {
+ (open(my $f, "<", "include/curl/curlver.h"))) {
+ while (<$f>) {
chomp;
if ($_ =~ /^\#define\s+LIBCURL_TIMESTAMP\s+\"(.+)\".*$/) {
my $stampstring = $1;
@@ -500,7 +500,7 @@
last;
}
}
- close(F);
+ close($f);
}
# Show timestamp we are using for this test build.
@@ -572,21 +572,21 @@
if(-f "./libcurl.pc") {
logit_spaced "display libcurl.pc";
- if(open(F, "<./libcurl.pc")) {
- while(<F>) {
+ if(open(my $f, "<", "libcurl.pc")) {
+ while(<$f>) {
my $ll = $_;
print $ll if(($ll !~ /^ *#/) && ($ll !~ /^ *$/));
}
- close(F);
+ close($f);
}
}
logit_spaced "display lib/$confheader";
-open(F, "lib/$confheader") or die "lib/$confheader: $!";
-while (<F>) {
+open(my $f, "<", "lib/$confheader") or die "lib/$confheader: $!";
+while (<$f>) {
print if /^ *#/;
}
-close(F);
+close($f);
if (($have_embedded_ares) &&
(grepfile("^#define USE_ARES", "lib/$confheader"))) {
@@ -595,23 +595,23 @@
if(-f "./ares/libcares.pc") {
logit_spaced "display ares/libcares.pc";
- if(open(F, "<./ares/libcares.pc")) {
- while(<F>) {
+ if(open($f, "<", "ares/libcares.pc")) {
+ while(<$f>) {
my $ll = $_;
print $ll if(($ll !~ /^ *#/) && ($ll !~ /^ *$/));
}
- close(F);
+ close($f);
}
}
if(-f "./ares/ares_build.h") {
logit_spaced "display ares/ares_build.h";
- if(open(F, "<./ares/ares_build.h")) {
- while(<F>) {
+ if(open($f, "<", "ares/ares_build.h")) {
+ while(<$f>) {
my $ll = $_;
print $ll if(($ll =~ /^ *# *define *CARES_/) && ($ll !~ /__CARES_BUILD_H/));
}
- close(F);
+ close($f);
}
}
else {
@@ -620,11 +620,11 @@
$confheader =~ s/curl/ares/;
logit_spaced "display ares/$confheader";
- if(open(F, "ares/$confheader")) {
- while (<F>) {
+ if(open($f, "<", "ares/$confheader")) {
+ while (<$f>) {
print if /^ *#/;
}
- close(F);
+ close($f);
}
print "\n";
@@ -633,17 +633,17 @@
if ($targetos && !$configurebuild) {
logit "$make -f Makefile.$targetos";
- open(F, "$make -f Makefile.$targetos 2>&1 |") or die;
+ open($f, "-|", "$make -f Makefile.$targetos 2>&1") or die;
}
else {
logit "$make";
- open(F, "$make 2>&1 |") or die;
+ open($f, "-|", "$make 2>&1") or die;
}
- while (<F>) {
+ while (<$f>) {
s/$pwd//g;
print;
}
- close(F);
+ close($f);
if (-f "libcares$libext") {
logit "ares is now built successfully (libcares$libext)";
@@ -657,12 +657,12 @@
my $mkcmd = "$make -i" . ($targetos && !$configurebuild ? " $targetos" : "");
logit "$mkcmd";
-open(F, "$mkcmd 2>&1 |") or die;
-while (<F>) {
+open(my $f, "-|", "$mkcmd 2>&1") or die;
+while (<$f>) {
s/$pwd//g;
print;
}
-close(F);
+close($f);
if (-f "lib/libcurl$libext") {
logit "libcurl was created fine (libcurl$libext)";
@@ -681,13 +681,13 @@
if (!$crosscompile || (($extvercmd ne '') && (-x $extvercmd))) {
logit "display curl${binext} --version output";
my $cmd = ($extvercmd ne '' ? $extvercmd.' ' : '')."./src/curl${binext} --version|";
- open(F, $cmd);
- while(<F>) {
+ open($f, "<", $cmd);
+ while(<$f>) {
# strip CR from output on non-win32 platforms (wine on Linux)
s/\r// if ($^O ne 'MSWin32');
print;
}
- close(F);
+ close($f);
}
if ($configurebuild && !$crosscompile) {
@@ -699,15 +699,15 @@
($host_triplet =~ /([^-]+)-([^-]+)-solaris2(.*)/)) {
chdir "$pwd/$build/docs/examples";
logit_spaced "build examples";
- open(F, "$make -i 2>&1 |") or die;
- open(LOG, ">$buildlog") or die;
- while (<F>) {
+ open($f, "-|", "$make -i 2>&1") or die;
+ open(my $log, ">", "$buildlog") or die;
+ while (<$f>) {
s/$pwd//g;
print;
- print LOG;
+ print $log $_;
}
- close(F);
- close(LOG);
+ close($f);
+ close($log);
chdir "$pwd/$build";
}
# build and run full test suite
@@ -716,15 +716,15 @@
$o = "TEST_F=\"$runtestopts\" ";
}
logit "$make -k ${o}test-full";
- open(F, "$make -k ${o}test-full 2>&1 |") or die;
- open(LOG, ">$buildlog") or die;
- while (<F>) {
+ open($f, "-|", "$make -k ${o}test-full 2>&1") or die;
+ open(my $log, ">", "$buildlog") or die;
+ while (<$f>) {
s/$pwd//g;
print;
- print LOG;
+ print $log $_;
}
- close(F);
- close(LOG);
+ close($f);
+ close($log);
if (grepfile("^TEST", $buildlog)) {
logit "tests were run";
@@ -746,30 +746,30 @@
($host_triplet =~ /([^-]+)-([^-]+)-android(.*)/)) {
chdir "$pwd/$build/docs/examples";
logit_spaced "build examples";
- open(F, "$make -i 2>&1 |") or die;
- open(LOG, ">$buildlog") or die;
- while (<F>) {
+ open($f, "-|", "$make -i 2>&1") or die;
+ open(my $log, ">", "$buildlog") or die;
+ while (<$f>) {
s/$pwd//g;
print;
- print LOG;
+ print $log $_;
}
- close(F);
- close(LOG);
+ close($f);
+ close($log);
chdir "$pwd/$build";
}
# build test harness programs for selected cross-compiles
if($host_triplet =~ /([^-]+)-([^-]+)-mingw(.*)/) {
chdir "$pwd/$build/tests";
logit_spaced "build test harness";
- open(F, "$make -i 2>&1 |") or die;
- open(LOG, ">$buildlog") or die;
- while (<F>) {
+ open(my $f, "-|", "$make -i 2>&1") or die;
+ open(my $log, ">", "$buildlog") or die;
+ while (<$f>) {
s/$pwd//g;
print;
- print LOG;
+ print $log $_;
}
- close(F);
- close(LOG);
+ close($f);
+ close($log);
chdir "$pwd/$build";
}
logit_spaced "cross-compiling, can't run tests";
diff --git a/tests/testutil.pm b/tests/testutil.pm
new file mode 100644
index 0000000..ece0b6e
--- /dev/null
+++ b/tests/testutil.pm
@@ -0,0 +1,204 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+# This module contains miscellaneous functions needed in several parts of
+# the test suite.
+
+package testutil;
+
+use strict;
+use warnings;
+
+BEGIN {
+ use base qw(Exporter);
+
+ our @EXPORT = qw(
+ runclient
+ runclientoutput
+ setlogfunc
+ shell_quote
+ subbase64
+ subnewlines
+ );
+
+ our @EXPORT_OK = qw(
+ clearlogs
+ logmsg
+ );
+}
+
+use MIME::Base64;
+
+use globalconfig qw(
+ $torture
+ $verbose
+);
+
+my $logfunc; # optional reference to function for logging
+my @logmessages; # array holding logged messages
+
+
+#######################################################################
+# Log an informational message
+# If a log callback function was set in setlogfunc, it is called. If not,
+# then the log message is buffered until retrieved by clearlogs.
+#
+# logmsg must only be called by one of the runner_* entry points and functions
+# called by them, or else logs risk being lost, since those are the only
+# functions that know about and will return buffered logs.
+sub logmsg {
+ if(!scalar(@_)) {
+ return;
+ }
+ if(defined $logfunc) {
+ &$logfunc(@_);
+ return;
+ }
+ push @logmessages, @_;
+}
+
+#######################################################################
+# Set the function to use for logging
+sub setlogfunc {
+ ($logfunc)=@_;
+}
+
+#######################################################################
+# Clear the buffered log messages after returning them
+sub clearlogs {
+ my $loglines = join('', @logmessages);
+ undef @logmessages;
+ return $loglines;
+}
+
+
+#######################################################################
+sub subbase64 {
+ my ($thing) = @_;
+
+ # cut out the base64 piece
+ while($$thing =~ s/%b64\[(.*?)\]b64%/%%B64%%/i) {
+ my $d = $1;
+ # encode %NN characters
+ $d =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+ my $enc = encode_base64($d, "");
+ # put the result into there
+ $$thing =~ s/%%B64%%/$enc/;
+ }
+ # hex decode
+ while($$thing =~ s/%hex\[(.*?)\]hex%/%%HEX%%/i) {
+ # decode %NN characters
+ my $d = $1;
+ $d =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+ $$thing =~ s/%%HEX%%/$d/;
+ }
+ while($$thing =~ s/%repeat\[(\d+) x (.*?)\]%/%%REPEAT%%/i) {
+ # decode %NN characters
+ my ($d, $n) = ($2, $1);
+ $d =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+ my $all = $d x $n;
+ $$thing =~ s/%%REPEAT%%/$all/;
+ }
+}
+
+my $prevupdate; # module scope so it remembers the last value
+sub subnewlines {
+ my ($force, $thing) = @_;
+
+ if($force) {
+ # enforce CRLF newline
+ $$thing =~ s/\x0d*\x0a/\x0d\x0a/;
+ return;
+ }
+
+ # When curl is built with Hyper, it gets all response headers delivered as
+ # name/value pairs and curl "invents" the newlines when it saves the
+ # headers. Therefore, curl will always save headers with CRLF newlines
+ # when built to use Hyper. By making sure we deliver all tests using CRLF
+ # as well, all test comparisons will survive without knowing about this
+ # little quirk.
+
+ if(($$thing =~ /^HTTP\/(1.1|1.0|2|3) [1-5][^\x0d]*\z/) ||
+ ($$thing =~ /^(GET|POST|PUT|DELETE) \S+ HTTP\/\d+(\.\d+)?/) ||
+ (($$thing =~ /^[a-z0-9_-]+: [^\x0d]*\z/i) &&
+ # skip curl error messages
+ ($$thing !~ /^curl: \(\d+\) /))) {
+ # enforce CRLF newline
+ $$thing =~ s/\x0d*\x0a/\x0d\x0a/;
+ $prevupdate = 1;
+ }
+ else {
+ if(($$thing =~ /^\n\z/) && $prevupdate) {
+ # if there's a blank link after a line we update, we hope it is
+ # the empty line following headers
+ $$thing =~ s/\x0a/\x0d\x0a/;
+ }
+ $prevupdate = 0;
+ }
+}
+
+#######################################################################
+# Run the application under test and return its return code
+#
+sub runclient {
+ my ($cmd)=@_;
+ my $ret = system($cmd);
+ print "CMD ($ret): $cmd\n" if($verbose && !$torture);
+ return $ret;
+
+# This is one way to test curl on a remote machine
+# my $out = system("ssh $CLIENTIP cd \'$pwd\' \\; \'$cmd\'");
+# sleep 2; # time to allow the NFS server to be updated
+# return $out;
+}
+
+#######################################################################
+# Run the application under test and return its stdout
+#
+sub runclientoutput {
+ my ($cmd)=@_;
+ return `$cmd 2>/dev/null`;
+
+# This is one way to test curl on a remote machine
+# my @out = `ssh $CLIENTIP cd \'$pwd\' \\; \'$cmd\'`;
+# sleep 2; # time to allow the NFS server to be updated
+# return @out;
+}
+
+
+#######################################################################
+# Quote an argument for passing safely to a Bourne shell
+# This does the same thing as String::ShellQuote but doesn't need a package.
+#
+sub shell_quote {
+ my ($s)=@_;
+ if($s !~ m/^[-+=.,_\/:a-zA-Z0-9]+$/) {
+ # string contains a "dangerous" character--quote it
+ $s =~ s/'/'"'"'/g;
+ $s = "'" . $s . "'";
+ }
+ return $s;
+}
+
+1;
diff --git a/tests/tftpserver.pl b/tests/tftpserver.pl
index 9db7343..52ad01f 100755
--- a/tests/tftpserver.pl
+++ b/tests/tftpserver.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -23,20 +23,20 @@
#
#***************************************************************************
+use strict;
+use warnings;
+
BEGIN {
push(@INC, $ENV{'srcdir'}) if(defined $ENV{'srcdir'});
push(@INC, ".");
}
-use strict;
-use warnings;
-
use serverhelp qw(
server_pidfilename
server_logfilename
);
-use sshhelp qw(
+use pathhelp qw(
exe_ext
);
@@ -74,6 +74,12 @@
shift @ARGV;
}
}
+ elsif($ARGV[0] eq '--logdir') {
+ if($ARGV[1]) {
+ $logdir = $ARGV[1];
+ shift @ARGV;
+ }
+ }
elsif($ARGV[0] eq '--srcdir') {
if($ARGV[1]) {
$srcdir = $ARGV[1];
@@ -111,7 +117,7 @@
$srcdir = $ENV{'srcdir'} || '.';
}
if(!$pidfile) {
- $pidfile = "$path/". server_pidfilename($proto, $ipvnum, $idnum);
+ $pidfile = server_pidfilename($path, $proto, $ipvnum, $idnum);
}
if(!$logfile) {
$logfile = server_logfilename($logdir, $proto, $ipvnum, $idnum);
@@ -119,7 +125,8 @@
$flags .= "--pidfile \"$pidfile\" ".
"--portfile \"$portfile\" ".
- "--logfile \"$logfile\" ";
+ "--logfile \"$logfile\" ".
+ "--logdir \"$logdir\" ";
$flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\"";
$| = 1;
diff --git a/tests/unit/.gitignore b/tests/unit/.gitignore
index d4fa007..8f0bb90 100644
--- a/tests/unit/.gitignore
+++ b/tests/unit/.gitignore
@@ -1,5 +1,5 @@
-# Copyright (C) 2011 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
-/unit1[36][0-9][0-9]
+/unit[0-9][0-9][0-9][0-9]
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index 8798165..9ca9a97 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -22,36 +22,9 @@
#
###########################################################################
-# TODO build a special libcurlu library for unittests.
-return()
+transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
+include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake)
-set(UT_SRC
- unit1300.c
- unit1301.c
- unit1302.c
- unit1303.c
- unit1304.c
- unit1305.c
- unit1307.c
- unit1308.c
- unit1309.c
- unit1330.c
-# Broken link on Linux
-# unit1394.c
- unit1395.c
- unit1396.c
- unit1397.c
- unit1398.c
- unit1600.c
- unit1601.c
- unit1603.c
-# Broken link on Linux
-# unit1604.c
- unit1620.c
- unit1655.c
- )
-
-set(UT_COMMON_FILES ../libtest/first.c ../libtest/test.h curlcheck.h)
include_directories(
${CURL_SOURCE_DIR}/lib # To be able to reach "curl_setup_once.h"
${CURL_SOURCE_DIR}/tests/libtest
@@ -60,12 +33,10 @@
${CURL_BINARY_DIR}/include # To be able to reach "curl/curl.h"
)
-foreach(_testfile ${UT_SRC})
-
- get_filename_component(_testname ${_testfile} NAME_WE)
- add_executable(${_testname} EXCLUDE_FROM_ALL ${_testfile} ${UT_COMMON_FILES})
- #add_dependencies(testdeps ${_testname})
- target_link_libraries(${_testname} libcurl ${CURL_LIBS})
- set_target_properties(${_testname}
- PROPERTIES COMPILE_DEFINITIONS "UNITTESTS")
-endforeach()
+if (ENABLE_CURLDEBUG) # running unittests require curl to compiled with CURLDEBUG
+ foreach(_testfile ${UNITPROGS})
+ add_executable(${_testfile} EXCLUDE_FROM_ALL ${_testfile}.c ${UNITFILES})
+ add_dependencies(testdeps ${_testfile})
+ target_link_libraries(${_testfile} curltool curlu)
+ endforeach()
+endif()
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index a0d7a94..e7a6aa4 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -51,9 +51,6 @@
AM_CPPFLAGS += -DCURL_STATICLIB -DUNITTESTS
-# Makefile.inc provides neat definitions
-include Makefile.inc
-
CHECKSRC = $(CS_$(V))
CS_0 = @echo " RUN " $@;
CS_1 =
@@ -62,6 +59,9 @@
checksrc:
$(CHECKSRC)@PERL@ $(top_srcdir)/scripts/checksrc.pl $(srcdir)/*.[ch]
+# Makefile.inc provides neat definitions
+include Makefile.inc
+
if BUILD_UNITTESTS
noinst_PROGRAMS = $(UNITPROGS)
else
diff --git a/tests/unit/Makefile.inc b/tests/unit/Makefile.inc
index f86cb7c..36e922b 100644
--- a/tests/unit/Makefile.inc
+++ b/tests/unit/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -29,136 +29,104 @@
../libtest/first.c
# These are all unit test programs
-UNITPROGS = unit1300 unit1301 unit1302 unit1303 unit1304 unit1305 unit1307 \
+UNITPROGS = unit1300 unit1302 unit1303 unit1304 unit1305 unit1307 \
unit1308 unit1309 unit1323 \
unit1330 unit1394 unit1395 unit1396 unit1397 unit1398 \
unit1399 \
unit1600 unit1601 unit1602 unit1603 unit1604 unit1605 unit1606 unit1607 \
- unit1608 unit1609 unit1610 unit1611 unit1612 \
+ unit1608 unit1609 unit1610 unit1611 unit1612 unit1614 \
unit1620 unit1621 \
unit1650 unit1651 unit1652 unit1653 unit1654 unit1655 \
- unit1660 unit1661
+ unit1660 unit1661 \
+ unit2600 unit2601 unit2602 unit2603 \
+ unit3200
unit1300_SOURCES = unit1300.c $(UNITFILES)
-unit1300_CPPFLAGS = $(AM_CPPFLAGS)
-
-unit1301_SOURCES = unit1301.c $(UNITFILES)
-unit1301_CPPFLAGS = $(AM_CPPFLAGS)
unit1302_SOURCES = unit1302.c $(UNITFILES)
-unit1302_CPPFLAGS = $(AM_CPPFLAGS)
unit1303_SOURCES = unit1303.c $(UNITFILES)
-unit1303_CPPFLAGS = $(AM_CPPFLAGS)
unit1304_SOURCES = unit1304.c $(UNITFILES)
-unit1304_CPPFLAGS = $(AM_CPPFLAGS)
unit1305_SOURCES = unit1305.c $(UNITFILES)
-unit1305_CPPFLAGS = $(AM_CPPFLAGS)
unit1307_SOURCES = unit1307.c $(UNITFILES)
-unit1307_CPPFLAGS = $(AM_CPPFLAGS)
unit1308_SOURCES = unit1308.c $(UNITFILES)
-unit1308_CPPFLAGS = $(AM_CPPFLAGS)
unit1309_SOURCES = unit1309.c $(UNITFILES)
-unit1309_CPPFLAGS = $(AM_CPPFLAGS)
unit1323_SOURCES = unit1323.c $(UNITFILES)
-unit1323_CPPFLAGS = $(AM_CPPFLAGS)
unit1330_SOURCES = unit1330.c $(UNITFILES)
-unit1330_CPPFLAGS = $(AM_CPPFLAGS)
unit1394_SOURCES = unit1394.c $(UNITFILES)
-unit1394_CPPFLAGS = $(AM_CPPFLAGS)
-unit1394_LDADD = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@
-unit1394_LDFLAGS = $(top_builddir)/src/libcurltool.la
-unit1394_LIBS =
unit1395_SOURCES = unit1395.c $(UNITFILES)
-unit1395_CPPFLAGS = $(AM_CPPFLAGS)
unit1396_SOURCES = unit1396.c $(UNITFILES)
-unit1396_CPPFLAGS = $(AM_CPPFLAGS)
unit1397_SOURCES = unit1397.c $(UNITFILES)
-unit1397_CPPFLAGS = $(AM_CPPFLAGS)
unit1398_SOURCES = unit1398.c $(UNITFILES)
-unit1398_CPPFLAGS = $(AM_CPPFLAGS)
unit1399_SOURCES = unit1399.c $(UNITFILES)
-unit1399_CPPFLAGS = $(AM_CPPFLAGS)
unit1600_SOURCES = unit1600.c $(UNITFILES)
-unit1600_CPPFLAGS = $(AM_CPPFLAGS)
unit1601_SOURCES = unit1601.c $(UNITFILES)
-unit1601_CPPFLAGS = $(AM_CPPFLAGS)
unit1602_SOURCES = unit1602.c $(UNITFILES)
-unit1602_CPPFLAGS = $(AM_CPPFLAGS)
unit1603_SOURCES = unit1603.c $(UNITFILES)
-unit1603_CPPFLAGS = $(AM_CPPFLAGS)
unit1604_SOURCES = unit1604.c $(UNITFILES)
-unit1604_CPPFLAGS = $(AM_CPPFLAGS)
unit1605_SOURCES = unit1605.c $(UNITFILES)
-unit1605_CPPFLAGS = $(AM_CPPFLAGS)
unit1606_SOURCES = unit1606.c $(UNITFILES)
-unit1606_CPPFLAGS = $(AM_CPPFLAGS)
unit1607_SOURCES = unit1607.c $(UNITFILES)
-unit1607_CPPFLAGS = $(AM_CPPFLAGS)
unit1608_SOURCES = unit1608.c $(UNITFILES)
-unit1608_CPPFLAGS = $(AM_CPPFLAGS)
unit1609_SOURCES = unit1609.c $(UNITFILES)
-unit1609_CPPFLAGS = $(AM_CPPFLAGS)
unit1610_SOURCES = unit1610.c $(UNITFILES)
-unit1610_CPPFLAGS = $(AM_CPPFLAGS)
unit1611_SOURCES = unit1611.c $(UNITFILES)
-unit1611_CPPFLAGS = $(AM_CPPFLAGS)
unit1612_SOURCES = unit1612.c $(UNITFILES)
-unit1612_CPPFLAGS = $(AM_CPPFLAGS)
+
+unit1614_SOURCES = unit1614.c $(UNITFILES)
unit1620_SOURCES = unit1620.c $(UNITFILES)
-unit1620_CPPFLAGS = $(AM_CPPFLAGS)
unit1621_SOURCES = unit1621.c $(UNITFILES)
-unit1621_CPPFLAGS = $(AM_CPPFLAGS)
-unit1621_LDADD = $(top_builddir)/src/libcurltool.la $(top_builddir)/lib/libcurl.la @NSS_LIBS@
unit1650_SOURCES = unit1650.c $(UNITFILES)
-unit1650_CPPFLAGS = $(AM_CPPFLAGS)
unit1651_SOURCES = unit1651.c $(UNITFILES)
-unit1651_CPPFLAGS = $(AM_CPPFLAGS)
unit1652_SOURCES = unit1652.c $(UNITFILES)
-unit1652_CPPFLAGS = $(AM_CPPFLAGS)
unit1653_SOURCES = unit1653.c $(UNITFILES)
-unit1653_CPPFLAGS = $(AM_CPPFLAGS)
unit1654_SOURCES = unit1654.c $(UNITFILES)
-unit1654_CPPFLAGS = $(AM_CPPFLAGS)
unit1655_SOURCES = unit1655.c $(UNITFILES)
-unit1655_CPPFLAGS = $(AM_CPPFLAGS)
unit1660_SOURCES = unit1660.c $(UNITFILES)
-unit1660_CPPFLAGS = $(AM_CPPFLAGS)
unit1661_SOURCES = unit1661.c $(UNITFILES)
-unit1661_CPPFLAGS = $(AM_CPPFLAGS)
+
+unit2600_SOURCES = unit2600.c $(UNITFILES)
+
+unit2601_SOURCES = unit2601.c $(UNITFILES)
+
+unit2602_SOURCES = unit2602.c $(UNITFILES)
+
+unit2603_SOURCES = unit2603.c $(UNITFILES)
+
+unit3200_SOURCES = unit3200.c $(UNITFILES)
diff --git a/tests/unit/README.md b/tests/unit/README.md
index 29bd3f3..f111190 100644
--- a/tests/unit/README.md
+++ b/tests/unit/README.md
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 1998 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
@@ -26,47 +26,48 @@
## Debug Unit Tests
If a specific test fails you will get told. The test case then has output left
-in the log/ subdirectory, but most importantly you can re-run the test again
+in the %LOGDIR subdirectory, but most importantly you can re-run the test again
using gdb by doing `./runtests.pl -g NNNN`. That is, add a `-g` to make it
start up gdb and run the same case using that.
## Write Unit Tests
We put tests that focus on an area or a specific function into a single C
-source file. The source file should be named 'unitNNNN.c' where NNNN is a
+source file. The source file should be named `unitNNNN.c` where `NNNN` is a
previously unused number.
-Add your test to `tests/unit/Makefile.inc` (if it is a unit test). Add your
+Add your test to `tests/unit/Makefile.inc` (if it is a unit test). Add your
test data file name to `tests/data/Makefile.inc`
You also need a separate file called `tests/data/testNNNN` (using the same
number) that describes your test case. See the test1300 file for inspiration
and the `tests/FILEFORMAT.md` documentation.
-For the actual C file, here's a very simple example:
+For the actual C file, here's a simple example:
~~~c
-#include "curlcheck.h"
-#include "a libcurl header.h" /* from the lib dir */
+ #include "curlcheck.h"
-static CURLcode unit_setup( void )
-{
- /* whatever you want done first */
- return CURLE_OK;
-}
+ #include "a libcurl header.h" /* from the lib dir */
-static void unit_stop( void )
-{
- /* done before shutting down and exiting */
-}
+ static CURLcode unit_setup( void )
+ {
+ /* whatever you want done first */
+ return CURLE_OK;
+ }
-UNITTEST_START
+ static void unit_stop( void )
+ {
+ /* done before shutting down and exiting */
+ }
- /* here you start doing things and checking that the results are good */
+ UNITTEST_START
- fail_unless( size == 0 , "initial size should be zero" );
- fail_if( head == NULL , "head should not be initiated to NULL" );
+ /* here you start doing things and checking that the results are good */
- /* you end the test code like this: */
+ fail_unless( size == 0 , "initial size should be zero" );
+ fail_if( head == NULL , "head should not be initiated to NULL" );
-UNITTEST_STOP
+ /* you end the test code like this: */
+
+ UNITTEST_STOP
diff --git a/tests/unit/curlcheck.h b/tests/unit/curlcheck.h
index 1e8ca0e..7c0ac4f 100644
--- a/tests/unit/curlcheck.h
+++ b/tests/unit/curlcheck.h
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/unit/unit1300.c b/tests/unit/unit1300.c
index 493a2f1..acbf89b 100644
--- a/tests/unit/unit1300.c
+++ b/tests/unit/unit1300.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -93,10 +93,10 @@
fail_unless(Curl_llist_count(&llist) == 1,
"List size should be 1 after adding a new element");
- /*test that the list head data holds my unusedData */
+ /* test that the list head data holds my unusedData */
fail_unless(llist.head->ptr == &unusedData_case1,
"head ptr should be first entry");
- /*same goes for the list tail */
+ /* same goes for the list tail */
fail_unless(llist.tail == llist.head,
"tail and head should be the same");
diff --git a/tests/unit/unit1301.c b/tests/unit/unit1301.c
deleted file mode 100644
index 17b2700..0000000
--- a/tests/unit/unit1301.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the 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 "curlcheck.h"
-
-#include "strcase.h"
-
-static CURLcode unit_setup(void) {return CURLE_OK;}
-static void unit_stop(void) {}
-
-UNITTEST_START
-
-int rc;
-
-rc = curl_strequal("iii", "III");
-fail_unless(rc != 0, "return code should be non-zero");
-
-rc = curl_strequal("iiia", "III");
-fail_unless(rc == 0, "return code should be zero");
-
-rc = curl_strequal("iii", "IIIa");
-fail_unless(rc == 0, "return code should be zero");
-
-rc = curl_strequal("iiiA", "IIIa");
-fail_unless(rc != 0, "return code should be non-zero");
-
-rc = curl_strnequal("iii", "III", 3);
-fail_unless(rc != 0, "return code should be non-zero");
-
-rc = curl_strnequal("iiiABC", "IIIcba", 3);
-fail_unless(rc != 0, "return code should be non-zero");
-
-rc = curl_strnequal("ii", "II", 3);
-fail_unless(rc != 0, "return code should be non-zero");
-
-UNITTEST_STOP
diff --git a/tests/unit/unit1302.c b/tests/unit/unit1302.c
index 77c8b1a..cf3c9b0 100644
--- a/tests/unit/unit1302.c
+++ b/tests/unit/unit1302.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -32,7 +32,7 @@
static CURLcode unit_setup(void)
{
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
data = curl_easy_init();
@@ -89,14 +89,14 @@
rc = Curl_base64url_encode("\xff\x01\xfe\x02", 4, &output, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-fail_unless(size == 8, "size should be 8");
-verify_memory(output, "_wH-Ag==", 8);
+fail_unless(size == 6, "size should be 6");
+verify_memory(output, "_wH-Ag", 6);
Curl_safefree(output);
rc = Curl_base64url_encode("iiii", 4, &output, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
-fail_unless(size == 8, "size should be 8");
-verify_memory(output, "aWlpaQ==", 8);
+fail_unless(size == 6, "size should be 6");
+verify_memory(output, "aWlpaQ", 6);
Curl_safefree(output);
/* 0 length makes it do strlen() */
@@ -106,6 +106,18 @@
verify_memory(output, "aWlpaQ==", 8);
Curl_safefree(output);
+rc = Curl_base64_encode("", 0, &output, &size);
+fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
+fail_unless(size == 0, "size should be 0");
+fail_unless(output && !output[0], "output should be a zero-length string");
+Curl_safefree(output);
+
+rc = Curl_base64url_encode("", 0, &output, &size);
+fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
+fail_unless(size == 0, "size should be 0");
+fail_unless(output && !output[0], "output should be a zero-length string");
+Curl_safefree(output);
+
rc = Curl_base64_decode("aWlpaQ==", &decoded, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
fail_unless(size == 4, "size should be 4");
@@ -157,6 +169,15 @@
fail_unless(size == 0, "size should be 0");
fail_if(decoded, "returned pointer should be NULL");
+/* This is also illegal input as it contains a padding character mid input */
+size = 1; /* not zero */
+decoded = &anychar; /* not NULL */
+rc = Curl_base64_decode("aWlpa=Q=", &decoded, &size);
+fail_unless(rc == CURLE_BAD_CONTENT_ENCODING,
+ "return code should be CURLE_BAD_CONTENT_ENCODING");
+fail_unless(size == 0, "size should be 0");
+fail_if(decoded, "returned pointer should be NULL");
+
/* This is garbage input as it contains an illegal base64 character */
size = 1; /* not zero */
decoded = &anychar; /* not NULL */
@@ -166,4 +187,5 @@
fail_unless(size == 0, "size should be 0");
fail_if(decoded, "returned pointer should be NULL");
+
UNITTEST_STOP
diff --git a/tests/unit/unit1303.c b/tests/unit/unit1303.c
index 59b4d2e..c022496 100644
--- a/tests/unit/unit1303.c
+++ b/tests/unit/unit1303.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
static CURLcode unit_setup(void)
{
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
data = curl_easy_init();
@@ -101,10 +101,10 @@
{BASE + 12, 0, 10000, 0, FALSE, -2000, "-2000, overdue 2 seconds"},
/* no connect timeout set, connecting */
- {BASE + 4, 0, 10000, 0, FALSE, 6000, "6 seconds should be left"},
- {BASE + 4, 990000, 10000, 0, FALSE, 5010, "5010 ms should be left"},
- {BASE + 10, 0, 10000, 0, FALSE, -1, "timeout is -1, expired"},
- {BASE + 12, 0, 10000, 0, FALSE, -2000, "-2000, overdue 2 seconds"},
+ {BASE + 4, 0, 10000, 0, TRUE, 6000, "6 seconds should be left"},
+ {BASE + 4, 990000, 10000, 0, TRUE, 5010, "5010 ms should be left"},
+ {BASE + 10, 0, 10000, 0, TRUE, -1, "timeout is -1, expired"},
+ {BASE + 12, 0, 10000, 0, TRUE, -2000, "-2000, overdue 2 seconds"},
/* only connect timeout set, not connecting */
{BASE + 4, 0, 0, 10000, FALSE, 0, "no timeout active"},
diff --git a/tests/unit/unit1304.c b/tests/unit/unit1304.c
index 090e8ad..cb7f7bb 100644
--- a/tests/unit/unit1304.c
+++ b/tests/unit/unit1304.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,7 +27,6 @@
static char *login;
static char *password;
-static char filename[64];
static CURLcode unit_setup(void)
{
@@ -49,17 +48,11 @@
UNITTEST_START
int result;
- bool login_changed;
- bool password_changed;
-
- static const char * const filename1 = "log/netrc1304";
- memcpy(filename, filename1, strlen(filename1));
/*
* Test a non existent host in our netrc file.
*/
- result = Curl_parsenetrc("test.example.com", &login, &password,
- &login_changed, &password_changed, filename);
+ result = Curl_parsenetrc("test.example.com", &login, &password, arg);
fail_unless(result == 1, "Host not found should return 1");
abort_unless(password != NULL, "returned NULL!");
fail_unless(password[0] == 0, "password should not have been changed");
@@ -72,16 +65,13 @@
free(login);
login = strdup("me");
abort_unless(login != NULL, "returned NULL!");
- result = Curl_parsenetrc("example.com", &login, &password,
- &login_changed, &password_changed, filename);
+ result = Curl_parsenetrc("example.com", &login, &password, arg);
fail_unless(result == 0, "Host should have been found");
abort_unless(password != NULL, "returned NULL!");
fail_unless(password[0] == 0, "password should not have been changed");
- fail_unless(!password_changed, "password should not have been changed");
abort_unless(login != NULL, "returned NULL!");
fail_unless(strncmp(login, "me", 2) == 0,
"login should not have been changed");
- fail_unless(!login_changed, "login should not have been changed");
/*
* Test a non existent login and host in our netrc file.
@@ -89,8 +79,7 @@
free(login);
login = strdup("me");
abort_unless(login != NULL, "returned NULL!");
- result = Curl_parsenetrc("test.example.com", &login, &password,
- &login_changed, &password_changed, filename);
+ result = Curl_parsenetrc("test.example.com", &login, &password, arg);
fail_unless(result == 1, "Host not found should return 1");
abort_unless(password != NULL, "returned NULL!");
fail_unless(password[0] == 0, "password should not have been changed");
@@ -105,16 +94,13 @@
free(login);
login = strdup("admi");
abort_unless(login != NULL, "returned NULL!");
- result = Curl_parsenetrc("example.com", &login, &password,
- &login_changed, &password_changed, filename);
+ result = Curl_parsenetrc("example.com", &login, &password, arg);
fail_unless(result == 0, "Host should have been found");
abort_unless(password != NULL, "returned NULL!");
fail_unless(password[0] == 0, "password should not have been changed");
- fail_unless(!password_changed, "password should not have been changed");
abort_unless(login != NULL, "returned NULL!");
fail_unless(strncmp(login, "admi", 4) == 0,
"login should not have been changed");
- fail_unless(!login_changed, "login should not have been changed");
/*
* Test a non existent login (superstring of an existing one)
@@ -123,16 +109,13 @@
free(login);
login = strdup("adminn");
abort_unless(login != NULL, "returned NULL!");
- result = Curl_parsenetrc("example.com", &login, &password,
- &login_changed, &password_changed, filename);
+ result = Curl_parsenetrc("example.com", &login, &password, arg);
fail_unless(result == 0, "Host should have been found");
abort_unless(password != NULL, "returned NULL!");
fail_unless(password[0] == 0, "password should not have been changed");
- fail_unless(!password_changed, "password should not have been changed");
abort_unless(login != NULL, "returned NULL!");
fail_unless(strncmp(login, "adminn", 6) == 0,
"login should not have been changed");
- fail_unless(!login_changed, "login should not have been changed");
/*
* Test for the first existing host in our netrc file
@@ -141,16 +124,13 @@
free(login);
login = strdup("");
abort_unless(login != NULL, "returned NULL!");
- result = Curl_parsenetrc("example.com", &login, &password,
- &login_changed, &password_changed, filename);
+ result = Curl_parsenetrc("example.com", &login, &password, arg);
fail_unless(result == 0, "Host should have been found");
abort_unless(password != NULL, "returned NULL!");
fail_unless(strncmp(password, "passwd", 6) == 0,
"password should be 'passwd'");
- fail_unless(password_changed, "password should have been changed");
abort_unless(login != NULL, "returned NULL!");
fail_unless(strncmp(login, "admin", 5) == 0, "login should be 'admin'");
- fail_unless(login_changed, "login should have been changed");
/*
* Test for the first existing host in our netrc file
@@ -159,16 +139,13 @@
free(password);
password = strdup("");
abort_unless(password != NULL, "returned NULL!");
- result = Curl_parsenetrc("example.com", &login, &password,
- &login_changed, &password_changed, filename);
+ result = Curl_parsenetrc("example.com", &login, &password, arg);
fail_unless(result == 0, "Host should have been found");
abort_unless(password != NULL, "returned NULL!");
fail_unless(strncmp(password, "passwd", 6) == 0,
"password should be 'passwd'");
- fail_unless(password_changed, "password should have been changed");
abort_unless(login != NULL, "returned NULL!");
fail_unless(strncmp(login, "admin", 5) == 0, "login should be 'admin'");
- fail_unless(!login_changed, "login should not have been changed");
/*
* Test for the second existing host in our netrc file
@@ -180,16 +157,13 @@
free(login);
login = strdup("");
abort_unless(login != NULL, "returned NULL!");
- result = Curl_parsenetrc("curl.example.com", &login, &password,
- &login_changed, &password_changed, filename);
+ result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
fail_unless(result == 0, "Host should have been found");
abort_unless(password != NULL, "returned NULL!");
fail_unless(strncmp(password, "none", 4) == 0,
"password should be 'none'");
- fail_unless(password_changed, "password should have been changed");
abort_unless(login != NULL, "returned NULL!");
fail_unless(strncmp(login, "none", 4) == 0, "login should be 'none'");
- fail_unless(login_changed, "login should have been changed");
/*
* Test for the second existing host in our netrc file
@@ -198,15 +172,12 @@
free(password);
password = strdup("");
abort_unless(password != NULL, "returned NULL!");
- result = Curl_parsenetrc("curl.example.com", &login, &password,
- &login_changed, &password_changed, filename);
+ result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
fail_unless(result == 0, "Host should have been found");
abort_unless(password != NULL, "returned NULL!");
fail_unless(strncmp(password, "none", 4) == 0,
"password should be 'none'");
- fail_unless(password_changed, "password should have been changed");
abort_unless(login != NULL, "returned NULL!");
fail_unless(strncmp(login, "none", 4) == 0, "login should be 'none'");
- fail_unless(!login_changed, "login should not have been changed");
UNITTEST_STOP
diff --git a/tests/unit/unit1305.c b/tests/unit/unit1305.c
index c35d448..19cc62c 100644
--- a/tests/unit/unit1305.c
+++ b/tests/unit/unit1305.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -54,7 +54,7 @@
return CURLE_OUT_OF_MEMORY;
}
- Curl_init_dnscache(&hp);
+ Curl_init_dnscache(&hp, 7);
return CURLE_OK;
}
@@ -75,7 +75,7 @@
{
static struct Curl_addrinfo *ai;
static const char dummy[]="dummy";
- size_t namelen = sizeof(dummy); /* including the zero terminator */
+ size_t namelen = sizeof(dummy); /* including the null-terminator */
ai = calloc(1, sizeof(struct Curl_addrinfo) + sizeof(struct sockaddr_in) +
namelen);
diff --git a/tests/unit/unit1307.c b/tests/unit/unit1307.c
index d8fcb80..440b390 100644
--- a/tests/unit/unit1307.c
+++ b/tests/unit/unit1307.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -316,10 +316,6 @@
#else
UNITTEST_START
-{
- /* nothing to do, just fail */
- return 1;
-}
UNITTEST_STOP
#endif
diff --git a/tests/unit/unit1308.c b/tests/unit/unit1308.c
index 2a866e7..3e2cf4b 100644
--- a/tests/unit/unit1308.c
+++ b/tests/unit/unit1308.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,6 +21,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
+#define CURL_DISABLE_DEPRECATION /* Testing the form api */
#include "curlcheck.h"
#include <curl/curl.h>
@@ -82,7 +83,7 @@
rc = curl_formadd(&post, &last,
CURLFORM_PTRNAME, "name of file field",
- CURLFORM_FILE, "log/test-1308",
+ CURLFORM_FILE, arg,
CURLFORM_FILENAME, "custom named file",
CURLFORM_END);
diff --git a/tests/unit/unit1309.c b/tests/unit/unit1309.c
index 121dfed..5c5801a 100644
--- a/tests/unit/unit1309.c
+++ b/tests/unit/unit1309.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/unit/unit1323.c b/tests/unit/unit1323.c
index b089282..26498ed 100644
--- a/tests/unit/unit1323.c
+++ b/tests/unit/unit1323.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/unit/unit1330.c b/tests/unit/unit1330.c
index ea6f996..2e27e80 100644
--- a/tests/unit/unit1330.c
+++ b/tests/unit/unit1330.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/unit/unit1394.c b/tests/unit/unit1394.c
index f4f05a0..e4e9981 100644
--- a/tests/unit/unit1394.c
+++ b/tests/unit/unit1394.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/unit/unit1395.c b/tests/unit/unit1395.c
index 79115dd..d01403f 100644
--- a/tests/unit/unit1395.c
+++ b/tests/unit/unit1395.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,8 @@
***************************************************************************/
#include "curlcheck.h"
-#include "dotdot.h"
+/* copied from urlapi.c */
+extern int dedotdotify(const char *input, size_t clen, char **out);
#include "memdebug.h"
@@ -57,35 +58,43 @@
{ "/1/./..", "/" },
{ "/1/./../2", "/2" },
{ "/hello/1/./../2", "/hello/2" },
- { "test/this", "test/this" },
+ { "test/this", NULL },
{ "test/this/../now", "test/now" },
{ "/1../moo../foo", "/1../moo../foo"},
{ "/../../moo", "/moo"},
- { "/../../moo?andnot/../yay", "/moo?andnot/../yay"},
- { "/123?foo=/./&bar=/../", "/123?foo=/./&bar=/../"},
- { "/../moo/..?what", "/?what" },
- { "/", "/" },
- { "", "" },
+ { "/../../moo?", "/moo?"},
+ { "/123?", NULL},
+ { "/../moo/..?", "/" },
+ { "/", NULL },
+ { "", NULL },
{ "/.../", "/.../" },
{ "./moo", "moo" },
{ "../moo", "moo" },
{ "/.", "/" },
{ "/..", "/" },
{ "/moo/..", "/" },
- { "..", "" },
- { ".", "" },
+ { "/..", "/" },
+ { "/.", "/" },
};
for(i = 0; i < sizeof(pairs)/sizeof(pairs[0]); i++) {
- char *out = Curl_dedotdotify(pairs[i].input);
- abort_unless(out != NULL, "returned NULL!");
+ char *out;
+ int err = dedotdotify(pairs[i].input, strlen(pairs[i].input), &out);
+ abort_unless(err == 0, "returned error");
+ abort_if(err && out, "returned error with output");
- if(strcmp(out, pairs[i].output)) {
+ if(out && strcmp(out, pairs[i].output)) {
fprintf(stderr, "Test %u: '%s' gave '%s' instead of '%s'\n",
i, pairs[i].input, out, pairs[i].output);
fail("Test case output mismatched");
fails++;
}
+ else if(!out && pairs[i].output) {
+ fprintf(stderr, "Test %u: '%s' gave '%s' instead of NULL\n",
+ i, pairs[i].input, out);
+ fail("Test case output mismatched");
+ fails++;
+ }
else
fprintf(stderr, "Test %u: OK\n", i);
free(out);
diff --git a/tests/unit/unit1396.c b/tests/unit/unit1396.c
index edf3a3e..43f9c86 100644
--- a/tests/unit/unit1396.c
+++ b/tests/unit/unit1396.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,7 +27,7 @@
static CURLcode unit_setup(void)
{
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
return res;
diff --git a/tests/unit/unit1397.c b/tests/unit/unit1397.c
index 90ec31c..3ae7561 100644
--- a/tests/unit/unit1397.c
+++ b/tests/unit/unit1397.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,7 +23,6 @@
***************************************************************************/
#include "curlcheck.h"
-#include "vtls/hostcheck.h" /* from the lib dir */
static CURLcode unit_setup(void)
{
@@ -32,63 +31,94 @@
static void unit_stop(void)
{
- /* done before shutting down and exiting */
}
+/* only these backends define the tested functions */
+#if defined(USE_OPENSSL) || defined(USE_GSKIT) || defined(USE_SCHANNEL)
+#include "vtls/hostcheck.h"
+struct testcase {
+ const char *host;
+ const char *pattern;
+ bool match;
+};
+
+static struct testcase tests[] = {
+ {"", "", FALSE},
+ {"a", "", FALSE},
+ {"", "b", FALSE},
+ {"a", "b", FALSE},
+ {"aa", "bb", FALSE},
+ {"\xff", "\xff", TRUE},
+ {"aa.aa.aa", "aa.aa.bb", FALSE},
+ {"aa.aa.aa", "aa.aa.aa", TRUE},
+ {"aa.aa.aa", "*.aa.bb", FALSE},
+ {"aa.aa.aa", "*.aa.aa", TRUE},
+ {"192.168.0.1", "192.168.0.1", TRUE},
+ {"192.168.0.1", "*.168.0.1", FALSE},
+ {"192.168.0.1", "*.0.1", FALSE},
+ {"h.ello", "*.ello", FALSE},
+ {"h.ello.", "*.ello", FALSE},
+ {"h.ello", "*.ello.", FALSE},
+ {"h.e.llo", "*.e.llo", TRUE},
+ {"h.e.llo", " *.e.llo", FALSE},
+ {" h.e.llo", "*.e.llo", TRUE},
+ {"h.e.llo.", "*.e.llo", TRUE},
+ {"*.e.llo.", "*.e.llo", TRUE},
+ {"************.e.llo.", "*.e.llo", TRUE},
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
+ "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
+ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
+ "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
+ ".e.llo.", "*.e.llo", TRUE},
+ {"\xfe\xfe.e.llo.", "*.e.llo", TRUE},
+ {"h.e.llo.", "*.e.llo.", TRUE},
+ {"h.e.llo", "*.e.llo.", TRUE},
+ {".h.e.llo", "*.e.llo.", FALSE},
+ {"h.e.llo", "*.*.llo.", FALSE},
+ {"h.e.llo", "h.*.llo", FALSE},
+ {"h.e.llo", "h.e.*", FALSE},
+ {"hello", "*.ello", FALSE},
+ {"hello", "**llo", FALSE},
+ {"bar.foo.example.com", "*.example.com", FALSE},
+ {"foo.example.com", "*.example.com", TRUE},
+ {"baz.example.net", "b*z.example.net", FALSE},
+ {"foobaz.example.net", "*baz.example.net", FALSE},
+ {"xn--l8j.example.local", "x*.example.local", FALSE},
+ {"xn--l8j.example.net", "*.example.net", TRUE},
+ {"xn--l8j.example.net", "*j.example.net", FALSE},
+ {"xn--l8j.example.net", "xn--l8j.example.net", TRUE},
+ {"xn--l8j.example.net", "xn--l8j.*.net", FALSE},
+ {"xl8j.example.net", "*.example.net", TRUE},
+ {"fe80::3285:a9ff:fe46:b619", "*::3285:a9ff:fe46:b619", FALSE},
+ {"fe80::3285:a9ff:fe46:b619", "fe80::3285:a9ff:fe46:b619", TRUE},
+ {NULL, NULL, FALSE}
+};
+
+UNITTEST_START
+{
+ int i;
+ for(i = 0; tests[i].host; i++) {
+ if(tests[i].match != Curl_cert_hostcheck(tests[i].pattern,
+ strlen(tests[i].pattern),
+ tests[i].host,
+ strlen(tests[i].host))) {
+ fprintf(stderr,
+ "HOST: %s\n"
+ "PTRN: %s\n"
+ "did %sMATCH\n",
+ tests[i].host,
+ tests[i].pattern,
+ tests[i].match ? "NOT ": "");
+ unitfail++;
+ }
+ }
+}
+
+UNITTEST_STOP
+#else
+
UNITTEST_START
-/* only these backends define the tested functions */
-#if defined(USE_OPENSSL) || defined(USE_GSKIT)
-
- /* here you start doing things and checking that the results are good */
-
-fail_unless(Curl_cert_hostcheck(STRCONST("www.example.com"),
- STRCONST("www.example.com")), "good 1");
-fail_unless(Curl_cert_hostcheck(STRCONST("*.example.com"),
- STRCONST("www.example.com")),
- "good 2");
-fail_unless(Curl_cert_hostcheck(STRCONST("xxx*.example.com"),
- STRCONST("xxxwww.example.com")), "good 3");
-fail_unless(Curl_cert_hostcheck(STRCONST("f*.example.com"),
- STRCONST("foo.example.com")), "good 4");
-fail_unless(Curl_cert_hostcheck(STRCONST("192.168.0.0"),
- STRCONST("192.168.0.0")), "good 5");
-
-fail_if(Curl_cert_hostcheck(STRCONST("xxx.example.com"),
- STRCONST("www.example.com")), "bad 1");
-fail_if(Curl_cert_hostcheck(STRCONST("*"),
- STRCONST("www.example.com")),"bad 2");
-fail_if(Curl_cert_hostcheck(STRCONST("*.*.com"),
- STRCONST("www.example.com")), "bad 3");
-fail_if(Curl_cert_hostcheck(STRCONST("*.example.com"),
- STRCONST("baa.foo.example.com")), "bad 4");
-fail_if(Curl_cert_hostcheck(STRCONST("f*.example.com"),
- STRCONST("baa.example.com")), "bad 5");
-fail_if(Curl_cert_hostcheck(STRCONST("*.com"),
- STRCONST("example.com")), "bad 6");
-fail_if(Curl_cert_hostcheck(STRCONST("*fail.com"),
- STRCONST("example.com")), "bad 7");
-fail_if(Curl_cert_hostcheck(STRCONST("*.example."),
- STRCONST("www.example.")), "bad 8");
-fail_if(Curl_cert_hostcheck(STRCONST("*.example."),
- STRCONST("www.example")), "bad 9");
-fail_if(Curl_cert_hostcheck(STRCONST(""), STRCONST("www")), "bad 10");
-fail_if(Curl_cert_hostcheck(STRCONST("*"), STRCONST("www")), "bad 11");
-fail_if(Curl_cert_hostcheck(STRCONST("*.168.0.0"),
- STRCONST("192.168.0.0")), "bad 12");
-fail_if(Curl_cert_hostcheck(STRCONST("www.example.com"),
- STRCONST("192.168.0.0")), "bad 13");
-
-#ifdef ENABLE_IPV6
-fail_if(Curl_cert_hostcheck(STRCONST("*::3285:a9ff:fe46:b619"),
- STRCONST("fe80::3285:a9ff:fe46:b619")), "bad 14");
-fail_unless(Curl_cert_hostcheck(STRCONST("fe80::3285:a9ff:fe46:b619"),
- STRCONST("fe80::3285:a9ff:fe46:b619")),
- "good 6");
-#endif
-
-#endif
-
- /* you end the test code like this: */
-
UNITTEST_STOP
+#endif
diff --git a/tests/unit/unit1398.c b/tests/unit/unit1398.c
index f68e43e..184489c 100644
--- a/tests/unit/unit1398.c
+++ b/tests/unit/unit1398.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -89,4 +89,8 @@
fail_unless(rc == 15, "return code should be 15");
fail_unless(!strcmp(output, " 1234 567"), "wrong output");
+/* double precision */
+rc = curl_msnprintf(output, 24, "%.*1$.99d", 3, 5678);
+fail_unless(rc == 0, "return code should be 0");
+
UNITTEST_STOP
diff --git a/tests/unit/unit1399.c b/tests/unit/unit1399.c
index c364650..1a293ac 100644
--- a/tests/unit/unit1399.c
+++ b/tests/unit/unit1399.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -76,7 +76,7 @@
}
/* Scenario: simulate a redirect. When a redirect occurs, t_nslookup,
- * t_connect, t_appconnect, t_pretransfer, and t_starttransfer are addative.
+ * t_connect, t_appconnect, t_pretransfer, and t_starttransfer are additive.
* E.g., if t_starttransfer took 2 seconds initially and took another 1
* second for the redirect request, then the resulting t_starttransfer should
* be 3 seconds. */
diff --git a/tests/unit/unit1600.c b/tests/unit/unit1600.c
index a640718..ee36c5e 100644
--- a/tests/unit/unit1600.c
+++ b/tests/unit/unit1600.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,7 +30,7 @@
static CURLcode unit_setup(void)
{
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
easy = curl_easy_init();
diff --git a/tests/unit/unit1601.c b/tests/unit/unit1601.c
index c598c0c..0bea388 100644
--- a/tests/unit/unit1601.c
+++ b/tests/unit/unit1601.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/unit/unit1602.c b/tests/unit/unit1602.c
index aa2b463..f7dc4a2 100644
--- a/tests/unit/unit1602.c
+++ b/tests/unit/unit1602.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/unit/unit1603.c b/tests/unit/unit1603.c
index e8640a7..004fdbc 100644
--- a/tests/unit/unit1603.c
+++ b/tests/unit/unit1603.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2015 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/unit/unit1604.c b/tests/unit/unit1604.c
index f7f8cee..411b94a 100644
--- a/tests/unit/unit1604.c
+++ b/tests/unit/unit1604.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/unit/unit1605.c b/tests/unit/unit1605.c
index cc58394..d0006d2 100644
--- a/tests/unit/unit1605.c
+++ b/tests/unit/unit1605.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,7 +29,7 @@
static CURLcode unit_setup(void)
{
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
easy = curl_easy_init();
diff --git a/tests/unit/unit1606.c b/tests/unit/unit1606.c
index 44f4c99..faa8941 100644
--- a/tests/unit/unit1606.c
+++ b/tests/unit/unit1606.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,7 +30,7 @@
static CURLcode unit_setup(void)
{
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
easy = curl_easy_init();
diff --git a/tests/unit/unit1607.c b/tests/unit/unit1607.c
index 7b93032..83af9c8 100644
--- a/tests/unit/unit1607.c
+++ b/tests/unit/unit1607.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,7 +36,7 @@
static CURLcode unit_setup(void)
{
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
@@ -227,7 +227,7 @@
continue;
}
}
- error:
+error:
curl_easy_cleanup(easy);
curl_multi_cleanup(multi);
curl_slist_free_all(list);
diff --git a/tests/unit/unit1608.c b/tests/unit/unit1608.c
index 64ef90f..31c6912 100644
--- a/tests/unit/unit1608.c
+++ b/tests/unit/unit1608.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,7 +47,7 @@
}
UNITTEST_START
-{
+
int i;
CURLcode code;
struct Curl_addrinfo *addrhead = addrs;
@@ -71,6 +71,4 @@
abort_unless(addrhead != addrs, "addresses are not being reordered");
- return 0;
-}
UNITTEST_STOP
diff --git a/tests/unit/unit1609.c b/tests/unit/unit1609.c
index 1b041f2..9f48394 100644
--- a/tests/unit/unit1609.c
+++ b/tests/unit/unit1609.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,7 +36,7 @@
static CURLcode unit_setup(void)
{
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
@@ -212,7 +212,7 @@
}
}
goto unit_test_abort;
- error:
+error:
curl_easy_cleanup(easy);
curl_multi_cleanup(multi);
curl_slist_free_all(list);
diff --git a/tests/unit/unit1610.c b/tests/unit/unit1610.c
index 3be61de..5624df8 100644
--- a/tests/unit/unit1610.c
+++ b/tests/unit/unit1610.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,7 +27,7 @@
static CURLcode unit_setup(void)
{
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
return res;
}
diff --git a/tests/unit/unit1611.c b/tests/unit/unit1611.c
index 46f9aa8..0062ac6 100644
--- a/tests/unit/unit1611.c
+++ b/tests/unit/unit1611.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@
UNITTEST_START
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+#ifdef USE_CURL_NTLM_CORE
const char string1[] = "1";
const char string2[] = "hello-you-fool";
unsigned char output[MD4_DIGEST_LENGTH];
diff --git a/tests/unit/unit1612.c b/tests/unit/unit1612.c
index d0e221c..1e99eeb 100644
--- a/tests/unit/unit1612.c
+++ b/tests/unit/unit1612.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/unit/unit1614.c b/tests/unit/unit1614.c
new file mode 100644
index 0000000..ef03e3b
--- /dev/null
+++ b/tests/unit/unit1614.c
@@ -0,0 +1,164 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 "curlcheck.h"
+
+#include "noproxy.h"
+
+static CURLcode unit_setup(void)
+{
+ return CURLE_OK;
+}
+
+static void unit_stop(void)
+{
+
+}
+
+struct check {
+ const char *a;
+ const char *n;
+ unsigned int bits;
+ bool match;
+};
+
+struct noproxy {
+ const char *a;
+ const char *n;
+ bool match;
+ bool space; /* space separated */
+};
+
+UNITTEST_START
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_PROXY)
+{
+ int i;
+ int err = 0;
+ struct check list4[]= {
+ { "192.160.0.1", "192.160.0.1", 33, FALSE},
+ { "192.160.0.1", "192.160.0.1", 32, TRUE},
+ { "192.160.0.1", "192.160.0.1", 0, TRUE},
+ { "192.160.0.1", "192.160.0.1", 24, TRUE},
+ { "192.160.0.1", "192.160.0.1", 26, TRUE},
+ { "192.160.0.1", "192.160.0.1", 20, TRUE},
+ { "192.160.0.1", "192.160.0.1", 18, TRUE},
+ { "192.160.0.1", "192.160.0.1", 12, TRUE},
+ { "192.160.0.1", "192.160.0.1", 8, TRUE},
+ { "192.160.0.1", "10.0.0.1", 8, FALSE},
+ { "192.160.0.1", "10.0.0.1", 32, FALSE},
+ { "192.160.0.1", "10.0.0.1", 0, FALSE},
+ { NULL, NULL, 0, FALSE} /* end marker */
+ };
+ struct check list6[]= {
+ { "::1", "::1", 0, TRUE},
+ { "::1", "::1", 128, TRUE},
+ { "::1", "0:0::1", 128, TRUE},
+ { "::1", "0:0::1", 129, FALSE},
+ { "fe80::ab47:4396:55c9:8474", "fe80::ab47:4396:55c9:8474", 64, TRUE},
+ { NULL, NULL, 0, FALSE} /* end marker */
+ };
+ struct noproxy list[]= {
+ { "www.example.com", "localhost .example.com .example.de", TRUE, TRUE},
+ { "www.example.com", "localhost,.example.com,.example.de", TRUE, FALSE},
+ { "www.example.com.", "localhost,.example.com,.example.de", TRUE, FALSE},
+ { "example.com", "localhost,.example.com,.example.de", TRUE, FALSE},
+ { "example.com.", "localhost,.example.com,.example.de", TRUE, FALSE},
+ { "www.example.com", "localhost,.example.com.,.example.de", TRUE, FALSE},
+ { "www.example.com", "localhost,www.example.com.,.example.de",
+ TRUE, FALSE},
+ { "example.com", "localhost,example.com,.example.de", TRUE, FALSE},
+ { "example.com.", "localhost,example.com,.example.de", TRUE, FALSE},
+ { "nexample.com", "localhost,example.com,.example.de", FALSE, FALSE},
+ { "www.example.com", "localhost,example.com,.example.de", TRUE, FALSE},
+ { "127.0.0.1", "127.0.0.1,localhost", TRUE, FALSE},
+ { "127.0.0.1", "127.0.0.1,localhost,", TRUE, FALSE},
+ { "127.0.0.1", "127.0.0.1/8,localhost,", TRUE, FALSE},
+ { "127.0.0.1", "127.0.0.1/28,localhost,", TRUE, FALSE},
+ { "127.0.0.1", "127.0.0.1/31,localhost,", TRUE, FALSE},
+ { "127.0.0.1", "localhost,127.0.0.1", TRUE, FALSE},
+ { "127.0.0.1", "localhost,127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1."
+ "127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1.127."
+ "0.0.1.127.0.0.1.127.0.0." /* 128 bytes "address" */, FALSE, FALSE},
+ { "127.0.0.1", "localhost,127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1."
+ "127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1.127."
+ "0.0.1.127.0.0.1.127.0.0" /* 127 bytes "address" */, FALSE, FALSE},
+ { "localhost", "localhost,127.0.0.1", TRUE, FALSE},
+ { "localhost", "127.0.0.1,localhost", TRUE, FALSE},
+ { "foobar", "barfoo", FALSE, FALSE},
+ { "foobar", "foobar", TRUE, FALSE},
+ { "192.168.0.1", "foobar", FALSE, FALSE},
+ { "192.168.0.1", "192.168.0.0/16", TRUE, FALSE},
+ { "192.168.0.1", "192.168.0.0/24", TRUE, FALSE},
+ { "192.168.0.1", "192.168.0.0/32", FALSE, FALSE},
+ { "192.168.0.1", "192.168.0.0", FALSE, FALSE},
+ { "192.168.1.1", "192.168.0.0/24", FALSE, FALSE},
+ { "192.168.1.1", "foo, bar, 192.168.0.0/24", FALSE, FALSE},
+ { "192.168.1.1", "foo, bar, 192.168.0.0/16", TRUE, FALSE},
+ { "[::1]", "foo, bar, 192.168.0.0/16", FALSE, FALSE},
+ { "[::1]", "foo, bar, ::1/64", TRUE, FALSE},
+ { "bar", "foo, bar, ::1/64", TRUE, FALSE},
+ { "BAr", "foo, bar, ::1/64", TRUE, FALSE},
+ { "BAr", "foo,,,,, bar, ::1/64", TRUE, FALSE},
+ { "www.example.com", "foo, .example.com", TRUE, FALSE},
+ { "www.example.com", "www2.example.com, .example.net", FALSE, FALSE},
+ { "example.com", ".example.com, .example.net", TRUE, FALSE},
+ { "nonexample.com", ".example.com, .example.net", FALSE, FALSE},
+ { NULL, NULL, FALSE, FALSE}
+ };
+ for(i = 0; list4[i].a; i++) {
+ bool match = Curl_cidr4_match(list4[i].a, list4[i].n, list4[i].bits);
+ if(match != list4[i].match) {
+ fprintf(stderr, "%s in %s/%u should %smatch\n",
+ list4[i].a, list4[i].n, list4[i].bits,
+ list4[i].match ? "": "not ");
+ err++;
+ }
+ }
+ for(i = 0; list6[i].a; i++) {
+ bool match = Curl_cidr6_match(list6[i].a, list6[i].n, list6[i].bits);
+ if(match != list6[i].match) {
+ fprintf(stderr, "%s in %s/%u should %smatch\n",
+ list6[i].a, list6[i].n, list6[i].bits,
+ list6[i].match ? "": "not ");
+ err++;
+ }
+ }
+ for(i = 0; list[i].a; i++) {
+ bool spacesep = FALSE;
+ bool match = Curl_check_noproxy(list[i].a, list[i].n, &spacesep);
+ if(match != list[i].match) {
+ fprintf(stderr, "%s in %s should %smatch\n",
+ list[i].a, list[i].n,
+ list[i].match ? "": "not ");
+ err++;
+ }
+ if(spacesep != list[i].space) {
+ fprintf(stderr, "%s is claimed to be %sspace separated\n",
+ list[i].n, list[i].space?"":"NOT ");
+ err++;
+ }
+ }
+ fail_if(err, "errors");
+}
+#endif
+UNITTEST_STOP
diff --git a/tests/unit/unit1620.c b/tests/unit/unit1620.c
index 572affe..8b6f34c 100644
--- a/tests/unit/unit1620.c
+++ b/tests/unit/unit1620.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,7 +30,7 @@
static CURLcode unit_setup(void)
{
- int res = CURLE_OK;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
return res;
}
diff --git a/tests/unit/unit1621.c b/tests/unit/unit1621.c
index 0e6705d..c384e04 100644
--- a/tests/unit/unit1621.c
+++ b/tests/unit/unit1621.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -41,13 +41,10 @@
(!defined(HAVE_FSETXATTR) && \
(!defined(__FreeBSD_version) || (__FreeBSD_version < 500000)))
UNITTEST_START
-{
- return 0;
-}
UNITTEST_STOP
#else
-bool stripcredentials(char **url);
+char *stripcredentials(const char *url);
struct checkthis {
const char *input;
@@ -67,27 +64,18 @@
UNITTEST_START
{
- bool cleanup;
- char *url;
int i;
- int rc = 0;
for(i = 0; tests[i].input; i++) {
- url = (char *)tests[i].input;
- cleanup = stripcredentials(&url);
+ const char *url = tests[i].input;
+ char *stripped = stripcredentials(url);
printf("Test %u got input \"%s\", output: \"%s\"\n",
- i, tests[i].input, url);
+ i, tests[i].input, stripped);
- if(strcmp(tests[i].output, url)) {
- fprintf(stderr, "Test %u got input \"%s\", expected output \"%s\"\n"
- " Actual output: \"%s\"\n", i, tests[i].input, tests[i].output,
- url);
- rc++;
- }
- if(cleanup)
- curl_free(url);
+ fail_if(stripped && strcmp(tests[i].output, stripped),
+ tests[i].output);
+ curl_free(stripped);
}
- return rc;
}
UNITTEST_STOP
#endif
diff --git a/tests/unit/unit1650.c b/tests/unit/unit1650.c
index ae748a9..1993616 100644
--- a/tests/unit/unit1650.c
+++ b/tests/unit/unit1650.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -159,25 +159,27 @@
unsigned char buffer[256];
size_t i;
unsigned char *p;
+
for(i = 0; i < sizeof(req) / sizeof(req[0]); i++) {
int rc = doh_encode(req[i].name, req[i].type,
buffer, sizeof(buffer), &size);
if(rc != req[i].rc) {
fprintf(stderr, "req %zu: Expected return code %d got %d\n", i,
req[i].rc, rc);
- return 1;
+ abort_if(rc != req[i].rc, "return code");
}
- else if(size != req[i].size) {
+ if(size != req[i].size) {
fprintf(stderr, "req %zu: Expected size %zu got %zu\n", i,
req[i].size, size);
fprintf(stderr, "DNS encode made: %s\n", hexdump(buffer, size));
- return 2;
+ abort_if(size != req[i].size, "size");
}
- else if(req[i].packet && memcmp(req[i].packet, buffer, size)) {
+ if(req[i].packet && memcmp(req[i].packet, buffer, size)) {
fprintf(stderr, "DNS encode made: %s\n", hexdump(buffer, size));
fprintf(stderr, "... instead of: %s\n",
hexdump((unsigned char *)req[i].packet, size));
- return 3;
+ abort_if(req[i].packet && memcmp(req[i].packet, buffer, size),
+ "contents");
}
}
@@ -193,7 +195,7 @@
if(rc != resp[i].rc) {
fprintf(stderr, "resp %zu: Expected return code %d got %d\n", i,
resp[i].rc, rc);
- return 4;
+ abort_if(rc != resp[i].rc, "return code");
}
len = sizeof(buffer);
ptr = (char *)buffer;
@@ -234,63 +236,61 @@
if(resp[i].out && strcmp((char *)buffer, resp[i].out)) {
fprintf(stderr, "resp %zu: Expected %s got %s\n", i,
resp[i].out, buffer);
- return 1;
+ abort_if(resp[i].out && strcmp((char *)buffer, resp[i].out), "content");
+ }
+ }
+
+ /* pass all sizes into the decoder until full */
+ for(i = 0; i < sizeof(full49)-1; i++) {
+ struct dohentry d;
+ int rc;
+ memset(&d, 0, sizeof(d));
+ rc = doh_decode((const unsigned char *)full49, i, DNS_TYPE_A, &d);
+ if(!rc) {
+ /* none of them should work */
+ fprintf(stderr, "%zu: %d\n", i, rc);
+ abort_if(!rc, "error rc");
+ }
+ }
+
+ /* and try all pieces from the other end of the packet */
+ for(i = 1; i < sizeof(full49); i++) {
+ struct dohentry d;
+ int rc;
+ memset(&d, 0, sizeof(d));
+ rc = doh_decode((const unsigned char *)&full49[i], sizeof(full49)-i-1,
+ DNS_TYPE_A, &d);
+ if(!rc) {
+ /* none of them should work */
+ fprintf(stderr, "2 %zu: %d\n", i, rc);
+ abort_if(!rc, "error rc");
}
}
{
- /* pass all sizes into the decoder until full */
- for(i = 0; i < sizeof(full49)-1; i++) {
- struct dohentry d;
- int rc;
- memset(&d, 0, sizeof(d));
- rc = doh_decode((const unsigned char *)full49, i, DNS_TYPE_A, &d);
- if(!rc) {
- /* none of them should work */
- fprintf(stderr, "%zu: %d\n", i, rc);
- return 5;
- }
+ int rc;
+ struct dohentry d;
+ struct dohaddr *a;
+ memset(&d, 0, sizeof(d));
+ rc = doh_decode((const unsigned char *)full49, sizeof(full49)-1,
+ DNS_TYPE_A, &d);
+ fail_if(d.numaddr != 1, "missing address");
+ a = &d.addr[0];
+ p = &a->ip.v4[0];
+ msnprintf((char *)buffer, sizeof(buffer),
+ "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
+ if(rc || strcmp((char *)buffer, "127.0.0.1")) {
+ fprintf(stderr, "bad address decoded: %s, rc == %d\n", buffer, rc);
+ abort_if(rc || strcmp((char *)buffer, "127.0.0.1"), "bad address");
}
- /* and try all pieces from the other end of the packet */
- for(i = 1; i < sizeof(full49); i++) {
- struct dohentry d;
- int rc;
- memset(&d, 0, sizeof(d));
- rc = doh_decode((const unsigned char *)&full49[i], sizeof(full49)-i-1,
- DNS_TYPE_A, &d);
- if(!rc) {
- /* none of them should work */
- fprintf(stderr, "2 %zu: %d\n", i, rc);
- return 7;
- }
- }
- {
- int rc;
- struct dohentry d;
- struct dohaddr *a;
- memset(&d, 0, sizeof(d));
- rc = doh_decode((const unsigned char *)full49, sizeof(full49)-1,
- DNS_TYPE_A, &d);
- fail_if(d.numaddr != 1, "missing address");
- a = &d.addr[0];
- p = &a->ip.v4[0];
- msnprintf((char *)buffer, sizeof(buffer),
- "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
- if(rc || strcmp((char *)buffer, "127.0.0.1")) {
- fprintf(stderr, "bad address decoded: %s, rc == %d\n", buffer, rc);
- return 7;
- }
- fail_if(d.numcname, "bad cname counter");
- }
+ fail_if(d.numcname, "bad cname counter");
}
}
UNITTEST_STOP
#else /* CURL_DISABLE_DOH */
UNITTEST_START
-{
- return 1; /* nothing to do, just fail */
-}
+/* nothing to do, just succeed */
UNITTEST_STOP
diff --git a/tests/unit/unit1651.c b/tests/unit/unit1651.c
index 3f92f82..dd1f3cb 100644
--- a/tests/unit/unit1651.c
+++ b/tests/unit/unit1651.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/unit/unit1652.c b/tests/unit/unit1652.c
index e77e432..ef27262 100644
--- a/tests/unit/unit1652.c
+++ b/tests/unit/unit1652.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -61,7 +61,7 @@
static CURLcode
unit_setup(void)
{
- int res = 0;
+ CURLcode res = CURLE_OK;
global_init(CURL_GLOBAL_ALL);
data = curl_easy_init();
@@ -71,7 +71,7 @@
}
curl_easy_setopt(data, CURLOPT_DEBUGFUNCTION, debugf_cb);
curl_easy_setopt(data, CURLOPT_VERBOSE, 1L);
- return CURLE_OK;
+ return res;
}
static void
diff --git a/tests/unit/unit1653.c b/tests/unit/unit1653.c
index 5b6e0a1..d543fb0 100644
--- a/tests/unit/unit1653.c
+++ b/tests/unit/unit1653.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,6 +44,19 @@
#define free_and_clear(x) free(x); x = NULL
+static CURLUcode parse_port(CURLU *url,
+ char *h, bool has_scheme)
+{
+ struct dynbuf host;
+ CURLUcode ret;
+ Curl_dyn_init(&host, 10000);
+ if(Curl_dyn_add(&host, h))
+ return CURLUE_OUT_OF_MEMORY;
+ ret = Curl_parse_port(url, &host, has_scheme);
+ Curl_dyn_free(&host);
+ return ret;
+}
+
UNITTEST_START
{
CURLUcode ret;
@@ -57,8 +70,8 @@
ipv6port = strdup("[fe80::250:56ff:fea7:da15]");
if(!ipv6port)
goto fail;
- ret = Curl_parse_port(u, ipv6port, FALSE);
- fail_unless(ret == CURLUE_OK, "Curl_parse_port returned error");
+ ret = parse_port(u, ipv6port, FALSE);
+ fail_unless(ret == CURLUE_OK, "parse_port returned error");
ret = curl_url_get(u, CURLUPART_PORT, &portnum, CURLU_NO_DEFAULT_PORT);
fail_unless(ret != CURLUE_OK, "curl_url_get portnum returned something");
free_and_clear(ipv6port);
@@ -71,19 +84,24 @@
ipv6port = strdup("[fe80::250:56ff:fea7:da15|");
if(!ipv6port)
goto fail;
- ret = Curl_parse_port(u, ipv6port, FALSE);
- fail_unless(ret != CURLUE_OK, "Curl_parse_port true on error");
+ ret = parse_port(u, ipv6port, FALSE);
+ fail_unless(ret != CURLUE_OK, "parse_port true on error");
free_and_clear(ipv6port);
curl_url_cleanup(u);
u = curl_url();
if(!u)
goto fail;
- ipv6port = strdup("[fe80::250:56ff;fea7:da15]:80");
+ ipv6port = strdup("[fe80::250:56ff;fea7:da15]:808");
if(!ipv6port)
goto fail;
- ret = Curl_parse_port(u, ipv6port, FALSE);
- fail_unless(ret != CURLUE_OK, "Curl_parse_port true on error");
+ ret = parse_port(u, ipv6port, FALSE);
+ fail_unless(ret == CURLUE_OK, "parse_port returned error");
+ ret = curl_url_get(u, CURLUPART_PORT, &portnum, 0);
+ fail_unless(ret == CURLUE_OK, "curl_url_get portnum returned error");
+ fail_unless(portnum && !strcmp(portnum, "808"), "Check portnumber");
+
+ curl_free(portnum);
free_and_clear(ipv6port);
curl_url_cleanup(u);
@@ -94,8 +112,8 @@
ipv6port = strdup("[fe80::250:56ff:fea7:da15%25eth3]:80");
if(!ipv6port)
goto fail;
- ret = Curl_parse_port(u, ipv6port, FALSE);
- fail_unless(ret == CURLUE_OK, "Curl_parse_port returned error");
+ ret = parse_port(u, ipv6port, FALSE);
+ fail_unless(ret == CURLUE_OK, "parse_port returned error");
ret = curl_url_get(u, CURLUPART_PORT, &portnum, 0);
fail_unless(ret == CURLUE_OK, "curl_url_get portnum returned error");
fail_unless(portnum && !strcmp(portnum, "80"), "Check portnumber");
@@ -110,8 +128,8 @@
ipv6port = strdup("[fe80::250:56ff:fea7:da15%25eth3]");
if(!ipv6port)
goto fail;
- ret = Curl_parse_port(u, ipv6port, FALSE);
- fail_unless(ret == CURLUE_OK, "Curl_parse_port returned error");
+ ret = parse_port(u, ipv6port, FALSE);
+ fail_unless(ret == CURLUE_OK, "parse_port returned error");
free_and_clear(ipv6port);
curl_url_cleanup(u);
@@ -122,8 +140,8 @@
ipv6port = strdup("[fe80::250:56ff:fea7:da15]:81");
if(!ipv6port)
goto fail;
- ret = Curl_parse_port(u, ipv6port, FALSE);
- fail_unless(ret == CURLUE_OK, "Curl_parse_port returned error");
+ ret = parse_port(u, ipv6port, FALSE);
+ fail_unless(ret == CURLUE_OK, "parse_port returned error");
ret = curl_url_get(u, CURLUPART_PORT, &portnum, 0);
fail_unless(ret == CURLUE_OK, "curl_url_get portnum returned error");
fail_unless(portnum && !strcmp(portnum, "81"), "Check portnumber");
@@ -138,8 +156,8 @@
ipv6port = strdup("[fe80::250:56ff:fea7:da15];81");
if(!ipv6port)
goto fail;
- ret = Curl_parse_port(u, ipv6port, FALSE);
- fail_unless(ret != CURLUE_OK, "Curl_parse_port true on error");
+ ret = parse_port(u, ipv6port, FALSE);
+ fail_unless(ret != CURLUE_OK, "parse_port true on error");
free_and_clear(ipv6port);
curl_url_cleanup(u);
@@ -149,8 +167,8 @@
ipv6port = strdup("[fe80::250:56ff:fea7:da15]80");
if(!ipv6port)
goto fail;
- ret = Curl_parse_port(u, ipv6port, FALSE);
- fail_unless(ret != CURLUE_OK, "Curl_parse_port true on error");
+ ret = parse_port(u, ipv6port, FALSE);
+ fail_unless(ret != CURLUE_OK, "parse_port true on error");
free_and_clear(ipv6port);
curl_url_cleanup(u);
@@ -162,20 +180,24 @@
ipv6port = strdup("[fe80::250:56ff:fea7:da15]:");
if(!ipv6port)
goto fail;
- ret = Curl_parse_port(u, ipv6port, TRUE);
- fail_unless(ret == CURLUE_OK, "Curl_parse_port returned error");
+ ret = parse_port(u, ipv6port, TRUE);
+ fail_unless(ret == CURLUE_OK, "parse_port returned error");
free_and_clear(ipv6port);
curl_url_cleanup(u);
- /* Incorrect zone index syntax */
+ /* Incorrect zone index syntax, but the port extractor doesn't care */
u = curl_url();
if(!u)
goto fail;
- ipv6port = strdup("[fe80::250:56ff:fea7:da15!25eth3]:80");
+ ipv6port = strdup("[fe80::250:56ff:fea7:da15!25eth3]:180");
if(!ipv6port)
goto fail;
- ret = Curl_parse_port(u, ipv6port, FALSE);
- fail_unless(ret != CURLUE_OK, "Curl_parse_port returned non-error");
+ ret = parse_port(u, ipv6port, FALSE);
+ fail_unless(ret == CURLUE_OK, "parse_port returned error");
+ ret = curl_url_get(u, CURLUPART_PORT, &portnum, 0);
+ fail_unless(ret == CURLUE_OK, "curl_url_get portnum returned error");
+ fail_unless(portnum && !strcmp(portnum, "180"), "Check portnumber");
+ curl_free(portnum);
free_and_clear(ipv6port);
curl_url_cleanup(u);
@@ -186,8 +208,8 @@
ipv6port = strdup("[fe80::250:56ff:fea7:da15%eth3]:80");
if(!ipv6port)
goto fail;
- ret = Curl_parse_port(u, ipv6port, FALSE);
- fail_unless(ret == CURLUE_OK, "Curl_parse_port returned error");
+ ret = parse_port(u, ipv6port, FALSE);
+ fail_unless(ret == CURLUE_OK, "parse_port returned error");
free_and_clear(ipv6port);
curl_url_cleanup(u);
@@ -200,9 +222,9 @@
"aaaaaaaaaaaaaaaaaaaaaa:");
if(!ipv6port)
goto fail;
- ret = Curl_parse_port(u, ipv6port, FALSE);
- fail_unless(ret == CURLUE_BAD_PORT_NUMBER, "Curl_parse_port did wrong");
- fail:
+ ret = parse_port(u, ipv6port, FALSE);
+ fail_unless(ret == CURLUE_BAD_PORT_NUMBER, "parse_port did wrong");
+fail:
free(ipv6port);
curl_url_cleanup(u);
diff --git a/tests/unit/unit1654.c b/tests/unit/unit1654.c
index 1e4a535..f7ca391 100644
--- a/tests/unit/unit1654.c
+++ b/tests/unit/unit1654.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -38,105 +38,76 @@
curl_global_cleanup();
}
-#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_ALTSVC)
UNITTEST_START
-{
- return 0; /* nothing to do when HTTP or alt-svc is disabled */
-}
-UNITTEST_STOP
-#else
-UNITTEST_START
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_ALTSVC)
{
char outname[256];
CURL *curl;
CURLcode result;
struct altsvcinfo *asi = Curl_altsvc_init();
- if(!asi)
- return 1;
+ abort_if(!asi, "Curl_altsvc_i");
result = Curl_altsvc_load(asi, arg);
if(result) {
- Curl_altsvc_cleanup(&asi);
- return result;
+ fail_if(result, "Curl_altsvc_load");
+ goto fail;
}
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
- if(!curl)
+ if(!curl) {
+ fail_if(!curl, "curl_easy_init");
goto fail;
+ }
fail_unless(asi->list.size == 4, "wrong number of entries");
msnprintf(outname, sizeof(outname), "%s-out", arg);
result = Curl_altsvc_parse(curl, asi, "h2=\"example.com:8080\"\r\n",
ALPN_h1, "example.org", 8080);
- if(result) {
- fprintf(stderr, "Curl_altsvc_parse() failed!\n");
- unitfail++;
- }
+ fail_if(result, "Curl_altsvc_parse() failed!");
fail_unless(asi->list.size == 5, "wrong number of entries");
result = Curl_altsvc_parse(curl, asi, "h3=\":8080\"\r\n",
ALPN_h1, "2.example.org", 8080);
- if(result) {
- fprintf(stderr, "Curl_altsvc_parse(2) failed!\n");
- unitfail++;
- }
+ fail_if(result, "Curl_altsvc_parse(2) failed!");
fail_unless(asi->list.size == 6, "wrong number of entries");
result = Curl_altsvc_parse(curl, asi,
"h2=\"example.com:8080\", h3=\"yesyes.com\"\r\n",
ALPN_h1, "3.example.org", 8080);
- if(result) {
- fprintf(stderr, "Curl_altsvc_parse(3) failed!\n");
- unitfail++;
- }
+ fail_if(result, "Curl_altsvc_parse(3) failed!");
/* that one should make two entries */
fail_unless(asi->list.size == 8, "wrong number of entries");
result = Curl_altsvc_parse(curl, asi,
"h2=\"example.com:443\"; ma = 120;\r\n",
ALPN_h2, "example.org", 80);
- if(result) {
- fprintf(stderr, "Curl_altsvc_parse(4) failed!\n");
- unitfail++;
- }
+ fail_if(result, "Curl_altsvc_parse(4) failed!");
fail_unless(asi->list.size == 9, "wrong number of entries");
/* quoted 'ma' value */
result = Curl_altsvc_parse(curl, asi,
"h2=\"example.net:443\"; ma=\"180\";\r\n",
ALPN_h2, "example.net", 80);
- if(result) {
- fprintf(stderr, "Curl_altsvc_parse(4) failed!\n");
- unitfail++;
- }
+ fail_if(result, "Curl_altsvc_parse(4) failed!");
fail_unless(asi->list.size == 10, "wrong number of entries");
result =
Curl_altsvc_parse(curl, asi,
"h2=\":443\", h3=\":443\"; ma = 120; persist = 1\r\n",
ALPN_h1, "curl.se", 80);
- if(result) {
- fprintf(stderr, "Curl_altsvc_parse(5) failed!\n");
- unitfail++;
- }
+ fail_if(result, "Curl_altsvc_parse(5) failed!");
fail_unless(asi->list.size == 12, "wrong number of entries");
/* clear that one again and decrease the counter */
result = Curl_altsvc_parse(curl, asi, "clear;\r\n",
ALPN_h1, "curl.se", 80);
- if(result) {
- fprintf(stderr, "Curl_altsvc_parse(6) failed!\n");
- unitfail++;
- }
+ fail_if(result, "Curl_altsvc_parse(6) failed!");
fail_unless(asi->list.size == 10, "wrong number of entries");
Curl_altsvc_save(curl, asi, outname);
curl_easy_cleanup(curl);
- curl_global_cleanup();
- fail:
+fail:
Curl_altsvc_cleanup(&asi);
- curl_global_cleanup();
- return unitfail;
}
-UNITTEST_STOP
#endif
+UNITTEST_STOP
diff --git a/tests/unit/unit1655.c b/tests/unit/unit1655.c
index 1f5a6c9..ca88f71 100644
--- a/tests/unit/unit1655.c
+++ b/tests/unit/unit1655.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,7 +47,7 @@
* Prove detection of other invalid input.
*/
do {
- const char *max =
+ static const char max[] =
/* ..|....1.........2.........3.........4.........5.........6... */
/* 3456789012345678901234567890123456789012345678901234567890123 */
"this.is.a.maximum-length.hostname." /* 34: 34 */
@@ -59,7 +59,7 @@
"that.is.two-hundred.and.fifty-six." /* 34: 231 */
"including.the.last.null." /* 24: 255 */
"";
- const char *toolong =
+ static const char toolong[] =
/* ..|....1.........2.........3.........4.........5.........6... */
/* 3456789012345678901234567890123456789012345678901234567890123 */
"here.is.a.hostname.which.is.just.barely.too.long." /* 49: 49 */
@@ -70,10 +70,10 @@
"a.trailing.dot.may.have.up.to." /* 30: 230 */
"255.characters.never.more." /* 26: 256 */
"";
- const char *emptylabel =
+ static const char emptylabel[] =
"this.is.an.otherwise-valid.hostname."
".with.an.empty.label.";
- const char *outsizelabel =
+ static const char outsizelabel[] =
"this.is.an.otherwise-valid.hostname."
"with-a-label-of-greater-length-than-the-sixty-three-characters-"
"specified.in.the.RFCs.";
@@ -105,7 +105,7 @@
struct demo victim;
DOHcode d;
- victim.canary1 = 87; /* magic numbers, arbritrarily picked */
+ victim.canary1 = 87; /* magic numbers, arbitrarily picked */
victim.canary2 = 35;
victim.canary3 = 41;
d = doh_encode(name, DNS_TYPE_A, victim.dohbuffer,
@@ -184,9 +184,7 @@
#else /* CURL_DISABLE_DOH */
UNITTEST_START
-{
- return 1; /* nothing to do, just fail */
-}
+/* nothing to do, just succeed */
UNITTEST_STOP
#endif
diff --git a/tests/unit/unit1660.c b/tests/unit/unit1660.c
index c7b46f5..938d1a1 100644
--- a/tests/unit/unit1660.c
+++ b/tests/unit/unit1660.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -103,7 +103,7 @@
/* make this live for 7 seconds */
{ "expire.example", NULL, "max-age=\"7\"\r\n", CURLE_OK },
- { NULL, NULL, NULL, 0 }
+ { NULL, NULL, NULL, CURLE_OK }
};
static void showsts(struct stsentry *e, const char *chost)
@@ -118,25 +118,25 @@
}
UNITTEST_START
-{
CURLcode result;
struct stsentry *e;
struct hsts *h = Curl_hsts_init();
int i;
const char *chost;
CURL *easy;
- if(!h)
- return 1;
+ char savename[256];
+
+ abort_unless(h, "Curl_hsts_init()");
curl_global_init(CURL_GLOBAL_ALL);
easy = curl_easy_init();
if(!easy) {
Curl_hsts_cleanup(&h);
curl_global_cleanup();
- return 1;
+ abort_unless(easy, "curl_easy_init()");
}
- Curl_hsts_loadfile(easy, h, "log/input1660");
+ Curl_hsts_loadfile(easy, h, arg);
for(i = 0; headers[i].host ; i++) {
if(headers[i].hdr) {
@@ -169,11 +169,11 @@
deltatime++; /* another second passed */
}
- (void)Curl_hsts_save(easy, h, "log/hsts1660");
+ msnprintf(savename, sizeof(savename), "%s.save", arg);
+ (void)Curl_hsts_save(easy, h, savename);
Curl_hsts_cleanup(&h);
curl_easy_cleanup(easy);
curl_global_cleanup();
- return unitfail;
-}
+
UNITTEST_STOP
#endif
diff --git a/tests/unit/unit1661.c b/tests/unit/unit1661.c
index 59cc5a9..265e483 100644
--- a/tests/unit/unit1661.c
+++ b/tests/unit/unit1661.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/tests/unit/unit2600.c b/tests/unit/unit2600.c
new file mode 100644
index 0000000..260ce6e
--- /dev/null
+++ b/tests/unit/unit2600.c
@@ -0,0 +1,413 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 "curlcheck.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_SETJMP_H
+#include <setjmp.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#include "urldata.h"
+#include "connect.h"
+#include "cfilters.h"
+#include "curl_log.h"
+
+/* copied from hostip.c to switch using SIGALARM for timeouts.
+ * SIGALARM has only seconds resolution, so our tests will not work
+ * here. */
+#if defined(CURLRES_SYNCH) && \
+ defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP)
+#define USE_ALARM_TIMEOUT
+#endif
+
+
+static CURL *easy;
+
+static CURLcode unit_setup(void)
+{
+ CURLcode res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
+ easy = curl_easy_init();
+ if(!easy) {
+ curl_global_cleanup();
+ return CURLE_OUT_OF_MEMORY;
+ }
+ curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L);
+ return res;
+}
+
+static void unit_stop(void)
+{
+ curl_easy_cleanup(easy);
+ curl_global_cleanup();
+}
+
+#ifdef DEBUGBUILD
+
+struct test_case {
+ int id;
+ const char *url;
+ const char *resolve_info;
+ unsigned char ip_version;
+ timediff_t connect_timeout_ms;
+ timediff_t he_timeout_ms;
+ timediff_t cf4_fail_delay_ms;
+ timediff_t cf6_fail_delay_ms;
+
+ int exp_cf4_creations;
+ int exp_cf6_creations;
+ timediff_t min_duration_ms;
+ timediff_t max_duration_ms;
+ CURLcode exp_result;
+ const char *pref_family;
+};
+
+struct ai_family_stats {
+ const char *family;
+ int creations;
+ timediff_t first_created;
+ timediff_t last_created;
+};
+
+struct test_result {
+ CURLcode result;
+ struct curltime started;
+ struct curltime ended;
+ struct ai_family_stats cf4;
+ struct ai_family_stats cf6;
+};
+
+static struct test_case *current_tc;
+static struct test_result *current_tr;
+
+struct cf_test_ctx {
+ int ai_family;
+ int transport;
+ char id[16];
+ struct curltime started;
+ timediff_t fail_delay_ms;
+ struct ai_family_stats *stats;
+};
+
+static void cf_test_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_test_ctx *ctx = cf->ctx;
+
+ infof(data, "%04dms: cf[%s] destroyed",
+ (int)Curl_timediff(Curl_now(), current_tr->started), ctx->id);
+ free(ctx);
+ cf->ctx = NULL;
+}
+
+static CURLcode cf_test_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct cf_test_ctx *ctx = cf->ctx;
+ struct curltime now;
+
+ (void)data;
+ (void)blocking;
+ *done = FALSE;
+ now = Curl_now();
+ if(Curl_timediff(now, ctx->started) >= ctx->fail_delay_ms) {
+ infof(data, "%04dms: cf[%s] fail delay reached",
+ (int)Curl_timediff(Curl_now(), current_tr->started), ctx->id);
+ return CURLE_COULDNT_CONNECT;
+ }
+ infof(data, "%04dms: cf[%s] continuing",
+ (int)Curl_timediff(Curl_now(), current_tr->started), ctx->id);
+ return CURLE_OK;
+}
+
+static struct Curl_cftype cft_test = {
+ "TEST",
+ CF_TYPE_IP_CONNECT,
+ CURL_LOG_DEFAULT,
+ cf_test_destroy,
+ cf_test_connect,
+ Curl_cf_def_close,
+ Curl_cf_def_get_host,
+ Curl_cf_def_get_select_socks,
+ Curl_cf_def_data_pending,
+ Curl_cf_def_send,
+ Curl_cf_def_recv,
+ Curl_cf_def_cntrl,
+ Curl_cf_def_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ Curl_cf_def_query,
+};
+
+static CURLcode cf_test_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai,
+ int transport)
+{
+ struct cf_test_ctx *ctx = NULL;
+ struct Curl_cfilter *cf = NULL;
+ timediff_t created_at;
+ CURLcode result;
+
+ (void)data;
+ (void)conn;
+ ctx = calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ ctx->ai_family = ai->ai_family;
+ ctx->transport = transport;
+ ctx->started = Curl_now();
+#ifdef ENABLE_IPV6
+ if(ctx->ai_family == AF_INET6) {
+ ctx->stats = ¤t_tr->cf6;
+ ctx->fail_delay_ms = current_tc->cf6_fail_delay_ms;
+ curl_msprintf(ctx->id, "v6-%d", ctx->stats->creations);
+ ctx->stats->creations++;
+ }
+ else
+#endif
+ {
+ ctx->stats = ¤t_tr->cf4;
+ ctx->fail_delay_ms = current_tc->cf4_fail_delay_ms;
+ curl_msprintf(ctx->id, "v4-%d", ctx->stats->creations);
+ ctx->stats->creations++;
+ }
+
+ created_at = Curl_timediff(ctx->started, current_tr->started);
+ if(ctx->stats->creations == 1)
+ ctx->stats->first_created = created_at;
+ ctx->stats->last_created = created_at;
+ infof(data, "%04dms: cf[%s] created", (int)created_at, ctx->id);
+
+ result = Curl_cf_create(&cf, &cft_test, ctx);
+
+out:
+ *pcf = (!result)? cf : NULL;
+ if(result) {
+ free(cf);
+ free(ctx);
+ }
+ return result;
+}
+
+static void check_result(struct test_case *tc,
+ struct test_result *tr)
+{
+ char msg[256];
+ timediff_t duration_ms = 0;
+
+ if(tr->result != tc->exp_result
+ && CURLE_OPERATION_TIMEDOUT != tr->result) {
+ /* on CI we encounter the TIMEOUT result, since images get less CPU
+ * and events are not as sharply timed. */
+ curl_msprintf(msg, "%d: expected result %d but got %d",
+ tc->id, tc->exp_result, tr->result);
+ fail(msg);
+ }
+ if(tr->cf4.creations != tc->exp_cf4_creations) {
+ curl_msprintf(msg, "%d: expected %d ipv4 creations, but got %d",
+ tc->id, tc->exp_cf4_creations, tr->cf4.creations);
+ fail(msg);
+ }
+ if(tr->cf6.creations != tc->exp_cf6_creations) {
+ curl_msprintf(msg, "%d: expected %d ipv6 creations, but got %d",
+ tc->id, tc->exp_cf6_creations, tr->cf6.creations);
+ fail(msg);
+ }
+
+ (void)duration_ms;
+#ifndef USE_ALARM_TIMEOUT
+ duration_ms = Curl_timediff(tr->ended, tr->started);
+ if(duration_ms < tc->min_duration_ms) {
+ curl_msprintf(msg, "%d: expected min duration of %dms, but took %dms",
+ tc->id, (int)tc->min_duration_ms, (int)duration_ms);
+ fail(msg);
+ }
+ if(duration_ms > tc->max_duration_ms) {
+ curl_msprintf(msg, "%d: expected max duration of %dms, but took %dms",
+ tc->id, (int)tc->max_duration_ms, (int)duration_ms);
+ fail(msg);
+ }
+#endif
+ if(tr->cf6.creations && tr->cf4.creations && tc->pref_family) {
+ /* did ipv4 and ipv6 both, expect the preferred family to start right arway
+ * with the other being delayed by the happy_eyeball_timeout */
+ struct ai_family_stats *stats1 = !strcmp(tc->pref_family, "v6")?
+ &tr->cf6 : &tr->cf4;
+ struct ai_family_stats *stats2 = !strcmp(tc->pref_family, "v6")?
+ &tr->cf4 : &tr->cf6;
+
+ if(stats1->first_created > 100) {
+ curl_msprintf(msg, "%d: expected ip%s to start right away, instead "
+ "first attempt made after %dms",
+ tc->id, stats1->family, (int)stats1->first_created);
+ fail(msg);
+ }
+#ifndef USE_ALARM_TIMEOUT
+ if(stats2->first_created < tc->he_timeout_ms) {
+#else
+ if(stats2->first_created < 1000) {
+#endif
+ curl_msprintf(msg, "%d: expected ip%s to start delayed after %dms, "
+ "instead first attempt made after %dms",
+ tc->id, stats2->family, (int)tc->he_timeout_ms,
+ (int)stats2->first_created);
+ fail(msg);
+ }
+ }
+}
+
+static void test_connect(struct test_case *tc)
+{
+ struct test_result tr;
+ struct curl_slist *list = NULL;
+
+ Curl_debug_set_transport_provider(TRNSPRT_TCP, cf_test_create);
+ current_tc = tc;
+ current_tr = &tr;
+
+ list = curl_slist_append(NULL, tc->resolve_info);
+ fail_unless(list, "error allocating resolve list entry");
+ curl_easy_setopt(easy, CURLOPT_RESOLVE, list);
+ curl_easy_setopt(easy, CURLOPT_IPRESOLVE, (long)tc->ip_version);
+#ifdef USE_ALARM_TIMEOUT
+ curl_easy_setopt(easy, CURLOPT_CONNECTTIMEOUT_MS, 2000L);
+ curl_easy_setopt(easy, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS,
+ (tc->he_timeout_ms > tc->connect_timeout_ms)?
+ 3000L : 1000L);
+#else
+ curl_easy_setopt(easy, CURLOPT_CONNECTTIMEOUT_MS,
+ (long)tc->connect_timeout_ms);
+ curl_easy_setopt(easy, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS,
+ (long)tc->he_timeout_ms);
+#endif
+
+ curl_easy_setopt(easy, CURLOPT_URL, tc->url);
+ memset(&tr, 0, sizeof(tr));
+ tr.cf6.family = "v6";
+ tr.cf4.family = "v4";
+
+ tr.started = Curl_now();
+ tr.result = curl_easy_perform(easy);
+ tr.ended = Curl_now();
+
+ curl_easy_setopt(easy, CURLOPT_RESOLVE, NULL);
+ curl_slist_free_all(list);
+ list = NULL;
+ current_tc = NULL;
+ current_tr = NULL;
+
+ check_result(tc, &tr);
+}
+
+#endif /* DEBUGBUILD */
+
+/*
+ * How these test cases work:
+ * - replace the creation of the TCP socket filter with our test filter
+ * - test filter does nothing and reports failure after configured delay
+ * - we feed addresses into the resolve cache to simulate different cases
+ * - we monitor how many instances of ipv4/v6 attempts are made and when
+ * - for mixed families, we expect HAPPY_EYEBALLS_TIMEOUT to trigger
+ *
+ * Max Duration checks needs to be conservative since CI jobs are not
+ * as sharp.
+ */
+#define TURL "http://test.com:123"
+
+#define R_FAIL CURLE_COULDNT_CONNECT
+
+static struct test_case TEST_CASES[] = {
+ /* TIMEOUT_MS, FAIL_MS CREATED DURATION Result, HE_PREF */
+ /* CNCT HE v4 v6 v4 v6 MIN MAX */
+ { 1, TURL, "test.com:123:192.0.2.1", CURL_IPRESOLVE_WHATEVER,
+ 250, 150, 200, 200, 1, 0, 200, 600, R_FAIL, NULL },
+ /* 1 ipv4, fails after ~200ms, reports COULDNT_CONNECT */
+ { 2, TURL, "test.com:123:192.0.2.1,192.0.2.2", CURL_IPRESOLVE_WHATEVER,
+ 500, 150, 200, 200, 2, 0, 400, 800, R_FAIL, NULL },
+ /* 2 ipv4, fails after ~400ms, reports COULDNT_CONNECT */
+#ifdef ENABLE_IPV6
+ { 3, TURL, "test.com:123:::1", CURL_IPRESOLVE_WHATEVER,
+ 250, 150, 200, 200, 0, 1, 200, 500, R_FAIL, NULL },
+ /* 1 ipv6, fails after ~200ms, reports COULDNT_CONNECT */
+ { 4, TURL, "test.com:123:::1,::2", CURL_IPRESOLVE_WHATEVER,
+ 500, 150, 200, 200, 0, 2, 400, 800, R_FAIL, NULL },
+ /* 2 ipv6, fails after ~400ms, reports COULDNT_CONNECT */
+
+ { 5, TURL, "test.com:123:192.0.2.1,::1", CURL_IPRESOLVE_WHATEVER,
+ 500, 150, 200, 200, 1, 1, 350, 800, R_FAIL, "v4" },
+ /* mixed ip4+6, v4 starts, v6 kicks in on HE, fails after ~350ms */
+ { 6, TURL, "test.com:123:::1,192.0.2.1", CURL_IPRESOLVE_WHATEVER,
+ 500, 150, 200, 200, 1, 1, 350, 800, R_FAIL, "v6" },
+ /* mixed ip6+4, v6 starts, v4 kicks in on HE, fails after ~350ms */
+ { 7, TURL, "test.com:123:::1,192.0.2.1,::2,::3", CURL_IPRESOLVE_WHATEVER,
+ 500, 600, 200, 200, 0, 3, 350, 800, R_FAIL, "v6" },
+ /* mixed ip6+4, v6 starts, v4 never starts due to high HE, TIMEOUT */
+ { 8, TURL, "test.com:123:192.0.2.1,::1", CURL_IPRESOLVE_V4,
+ 400, 150, 500, 500, 1, 0, 400, 600, R_FAIL, NULL },
+ /* mixed ip4+6, but only use v4, check it uses full connect timeout,
+ although another address of the 'wrong' family is available */
+ { 9, TURL, "test.com:123:::1,192.0.2.1", CURL_IPRESOLVE_V6,
+ 400, 150, 500, 500, 0, 1, 400, 600, R_FAIL, NULL },
+ /* mixed ip4+6, but only use v6, check it uses full connect timeout,
+ although another address of the 'wrong' family is available */
+#endif
+};
+
+UNITTEST_START
+
+#if defined(DEBUGBUILD)
+ size_t i;
+
+ for(i = 0; i < sizeof(TEST_CASES)/sizeof(TEST_CASES[0]); ++i) {
+ test_connect(&TEST_CASES[i]);
+ }
+#else
+ (void)TEST_CASES;
+ (void)test_connect;
+#endif
+
+UNITTEST_STOP
diff --git a/tests/unit/unit2601.c b/tests/unit/unit2601.c
new file mode 100644
index 0000000..de2a9f9
--- /dev/null
+++ b/tests/unit/unit2601.c
@@ -0,0 +1,246 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 "curlcheck.h"
+
+#include "urldata.h"
+#include "bufq.h"
+#include "curl_log.h"
+
+static CURLcode unit_setup(void)
+{
+ CURLcode res = CURLE_OK;
+ return res;
+}
+
+static void unit_stop(void)
+{
+}
+
+static const char *tail_err(struct bufq *q)
+{
+ struct buf_chunk *chunk;
+
+ if(!q->tail) {
+ return q->head? "tail is NULL, but head is not" : NULL;
+ }
+
+ chunk = q->head;
+ while(chunk) {
+ if(chunk == q->tail) {
+ if(chunk->next) {
+ return "tail points to queue, but not at the end";
+ }
+ return NULL;
+ }
+ chunk = chunk->next;
+ }
+ return "tail not part of queue";
+}
+
+static void dump_bufq(struct bufq *q, const char *msg)
+{
+ struct buf_chunk *chunk;
+ const char *terr;
+ size_t n;
+
+ fprintf(stderr, "bufq[chunk_size=%zu, max_chunks=%zu] %s\n",
+ q->chunk_size, q->max_chunks, msg);
+ fprintf(stderr, "- queue[\n");
+ chunk = q->head;
+ while(chunk) {
+ fprintf(stderr, " chunk[len=%zu, roff=%zu, woff=%zu]\n",
+ chunk->dlen, chunk->r_offset, chunk->w_offset);
+ chunk = chunk->next;
+ }
+ fprintf(stderr, " ]\n");
+ terr = tail_err(q);
+ fprintf(stderr, "- tail: %s\n", terr? terr : "ok");
+ n = 0;
+ chunk = q->spare;
+ while(chunk) {
+ ++n;
+ chunk = chunk->next;
+ }
+ fprintf(stderr, "- chunks: %zu\n", q->chunk_count);
+ fprintf(stderr, "- spares: %zu\n", n);
+}
+
+static unsigned char test_data[32*1024];
+
+static void check_bufq(size_t pool_spares,
+ size_t chunk_size, size_t max_chunks,
+ size_t wsize, size_t rsize, int opts)
+{
+ struct bufq q;
+ struct bufc_pool pool;
+ size_t max_len = chunk_size * max_chunks;
+ CURLcode result;
+ ssize_t n, i;
+ size_t nwritten, nread;
+
+ if(pool_spares > 0) {
+ Curl_bufcp_init(&pool, chunk_size, pool_spares);
+ Curl_bufq_initp(&q, &pool, max_chunks, opts);
+ }
+ else {
+ Curl_bufq_init2(&q, chunk_size, max_chunks, opts);
+ }
+
+ fail_unless(q.chunk_size == chunk_size, "chunk_size init wrong");
+ fail_unless(q.max_chunks == max_chunks, "max_chunks init wrong");
+ fail_unless(q.head == NULL, "init: head not NULL");
+ fail_unless(q.tail == NULL, "init: tail not NULL");
+ fail_unless(q.spare == NULL, "init: spare not NULL");
+ fail_unless(Curl_bufq_len(&q) == 0, "init: bufq length != 0");
+
+ n = Curl_bufq_write(&q, test_data, wsize, &result);
+ fail_unless(n >= 0, "write: negative size returned");
+ fail_unless((size_t)n <= wsize, "write: wrong size returned");
+ fail_unless(result == CURLE_OK, "write: wrong result returned");
+
+ /* write empty bufq full */
+ nwritten = 0;
+ Curl_bufq_reset(&q);
+ while(!Curl_bufq_is_full(&q)) {
+ n = Curl_bufq_write(&q, test_data, wsize, &result);
+ if(n >= 0) {
+ nwritten += (size_t)n;
+ }
+ else if(result != CURLE_AGAIN) {
+ fail_unless(result == CURLE_AGAIN, "write-loop: unexpected result");
+ break;
+ }
+ }
+ if(nwritten != max_len) {
+ fprintf(stderr, "%zu bytes written, but max_len=%zu\n",
+ nwritten, max_len);
+ dump_bufq(&q, "after writing full");
+ fail_if(TRUE, "write: bufq full but nwritten wrong");
+ }
+
+ /* read full bufq empty */
+ nread = 0;
+ while(!Curl_bufq_is_empty(&q)) {
+ n = Curl_bufq_read(&q, test_data, rsize, &result);
+ if(n >= 0) {
+ nread += (size_t)n;
+ }
+ else if(result != CURLE_AGAIN) {
+ fail_unless(result == CURLE_AGAIN, "read-loop: unexpected result");
+ break;
+ }
+ }
+ if(nread != max_len) {
+ fprintf(stderr, "%zu bytes read, but max_len=%zu\n",
+ nwritten, max_len);
+ dump_bufq(&q, "after reading empty");
+ fail_if(TRUE, "read: bufq empty but nread wrong");
+ }
+ if(q.tail) {
+ dump_bufq(&q, "after reading empty");
+ fail_if(TRUE, "read empty, but tail is not NULL");
+ }
+
+ for(i = 0; i < 1000; ++i) {
+ n = Curl_bufq_write(&q, test_data, wsize, &result);
+ if(n < 0 && result != CURLE_AGAIN) {
+ fail_unless(result == CURLE_AGAIN, "rw-loop: unexpected write result");
+ break;
+ }
+ n = Curl_bufq_read(&q, test_data, rsize, &result);
+ if(n < 0 && result != CURLE_AGAIN) {
+ fail_unless(result == CURLE_AGAIN, "rw-loop: unexpected read result");
+ break;
+ }
+ }
+
+ /* Test SOFT_LIMIT option */
+ Curl_bufq_free(&q);
+ Curl_bufq_init2(&q, chunk_size, max_chunks, (opts|BUFQ_OPT_SOFT_LIMIT));
+ nwritten = 0;
+ while(!Curl_bufq_is_full(&q)) {
+ n = Curl_bufq_write(&q, test_data, wsize, &result);
+ if(n < 0 || (size_t)n != wsize) {
+ fail_unless(n > 0 && (size_t)n == wsize, "write should be complete");
+ break;
+ }
+ nwritten += (size_t)n;
+ }
+ if(nwritten < max_len) {
+ fprintf(stderr, "%zu bytes written, but max_len=%zu\n",
+ nwritten, max_len);
+ dump_bufq(&q, "after writing full");
+ fail_if(TRUE, "write: bufq full but nwritten wrong");
+ }
+ /* do one more write on a full bufq, should work */
+ n = Curl_bufq_write(&q, test_data, wsize, &result);
+ fail_unless(n > 0 && (size_t)n == wsize, "write should be complete");
+ nwritten += (size_t)n;
+ /* see that we get all out again */
+ nread = 0;
+ while(!Curl_bufq_is_empty(&q)) {
+ n = Curl_bufq_read(&q, test_data, rsize, &result);
+ if(n <= 0) {
+ fail_unless(n > 0, "read-loop: unexpected fail");
+ break;
+ }
+ nread += (size_t)n;
+ }
+ fail_unless(nread == nwritten, "did not get the same out as put in");
+
+ dump_bufq(&q, "at end of test");
+ Curl_bufq_free(&q);
+ if(pool_spares > 0)
+ Curl_bufcp_free(&pool);
+}
+
+UNITTEST_START
+ struct bufq q;
+ ssize_t n;
+ CURLcode result;
+ unsigned char buf[16*1024];
+
+ Curl_bufq_init(&q, 8*1024, 12);
+ n = Curl_bufq_read(&q, buf, 128, &result);
+ fail_unless(n < 0 && result == CURLE_AGAIN, "read empty fail");
+ Curl_bufq_free(&q);
+
+ check_bufq(0, 1024, 4, 128, 128, BUFQ_OPT_NONE);
+ check_bufq(0, 1024, 4, 129, 127, BUFQ_OPT_NONE);
+ check_bufq(0, 1024, 4, 2000, 16000, BUFQ_OPT_NONE);
+ check_bufq(0, 1024, 4, 16000, 3000, BUFQ_OPT_NONE);
+
+ check_bufq(0, 8000, 10, 1234, 1234, BUFQ_OPT_NONE);
+ check_bufq(0, 8000, 10, 8*1024, 4*1024, BUFQ_OPT_NONE);
+
+ check_bufq(0, 1024, 4, 128, 128, BUFQ_OPT_NO_SPARES);
+ check_bufq(0, 1024, 4, 129, 127, BUFQ_OPT_NO_SPARES);
+ check_bufq(0, 1024, 4, 2000, 16000, BUFQ_OPT_NO_SPARES);
+ check_bufq(0, 1024, 4, 16000, 3000, BUFQ_OPT_NO_SPARES);
+
+ check_bufq(8, 1024, 4, 128, 128, BUFQ_OPT_NONE);
+ check_bufq(8, 8000, 10, 1234, 1234, BUFQ_OPT_NONE);
+ check_bufq(8, 1024, 4, 129, 127, BUFQ_OPT_NO_SPARES);
+
+UNITTEST_STOP
diff --git a/tests/unit/unit2602.c b/tests/unit/unit2602.c
new file mode 100644
index 0000000..e596f8a
--- /dev/null
+++ b/tests/unit/unit2602.c
@@ -0,0 +1,148 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 "curlcheck.h"
+
+#include "urldata.h"
+#include "dynbuf.h"
+#include "dynhds.h"
+#include "curl_log.h"
+
+static CURLcode unit_setup(void)
+{
+ return CURLE_OK;
+}
+
+static void unit_stop(void)
+{
+}
+
+
+UNITTEST_START
+
+ struct dynhds hds;
+ struct dynbuf dbuf;
+ CURLcode result;
+ size_t i;
+
+ /* add 1 more header than allowed */
+ Curl_dynhds_init(&hds, 2, 128);
+ fail_if(Curl_dynhds_count(&hds), "should be empty");
+ fail_if(Curl_dynhds_add(&hds, "test1", 5, "123", 3), "add failed");
+ fail_if(Curl_dynhds_add(&hds, "test2", 5, "456", 3), "add failed");
+ /* remove and add without exceeding limits */
+ for(i = 0; i < 100; ++i) {
+ if(Curl_dynhds_remove(&hds, "test2", 5) != 1) {
+ fail_if(TRUE, "should");
+ break;
+ }
+ if(Curl_dynhds_add(&hds, "test2", 5, "456", 3)) {
+ fail_if(TRUE, "add failed");
+ break;
+ }
+ }
+ fail_unless(Curl_dynhds_count(&hds) == 2, "should hold 2");
+ /* set, replacing previous entry without exceeding limits */
+ for(i = 0; i < 100; ++i) {
+ if(Curl_dynhds_set(&hds, "test2", 5, "456", 3)) {
+ fail_if(TRUE, "add failed");
+ break;
+ }
+ }
+ fail_unless(Curl_dynhds_count(&hds) == 2, "should hold 2");
+ /* exceed limit on # of entries */
+ result = Curl_dynhds_add(&hds, "test3", 5, "789", 3);
+ fail_unless(result, "add should have failed");
+
+ fail_unless(Curl_dynhds_count_name(&hds, "test", 4) == 0, "false positive");
+ fail_unless(Curl_dynhds_count_name(&hds, "test1", 4) == 0, "false positive");
+ fail_if(Curl_dynhds_get(&hds, "test1", 4), "false positive");
+ fail_unless(Curl_dynhds_get(&hds, "test1", 5), "false negative");
+ fail_unless(Curl_dynhds_count_name(&hds, "test1", 5) == 1, "should");
+ fail_unless(Curl_dynhds_ccount_name(&hds, "test2") == 1, "should");
+ fail_unless(Curl_dynhds_cget(&hds, "test2"), "should");
+ fail_unless(Curl_dynhds_ccount_name(&hds, "TEST2") == 1, "should");
+ fail_unless(Curl_dynhds_ccontains(&hds, "TesT2"), "should");
+ fail_unless(Curl_dynhds_contains(&hds, "TeSt2", 5), "should");
+ Curl_dynhds_free(&hds);
+
+ /* add header exceeding max overall length */
+ Curl_dynhds_init(&hds, 128, 10);
+ fail_if(Curl_dynhds_add(&hds, "test1", 5, "123", 3), "add failed");
+ fail_unless(Curl_dynhds_add(&hds, "test2", 5, "456", 3), "should fail");
+ fail_if(Curl_dynhds_add(&hds, "t", 1, "1", 1), "add failed");
+ Curl_dynhds_reset(&hds);
+ Curl_dynhds_free(&hds);
+
+ Curl_dynhds_init(&hds, 128, 4*1024);
+ fail_if(Curl_dynhds_add(&hds, "test1", 5, "123", 3), "add failed");
+ fail_if(Curl_dynhds_add(&hds, "test1", 5, "123", 3), "add failed");
+ fail_if(Curl_dynhds_cadd(&hds, "blablabla", "thingies"), "add failed");
+ fail_if(Curl_dynhds_h1_cadd_line(&hds, "blablabla: thingies"), "add failed");
+ fail_unless(Curl_dynhds_ccount_name(&hds, "blablabla") == 2, "should");
+ fail_unless(Curl_dynhds_cremove(&hds, "blablabla") == 2, "should");
+ fail_if(Curl_dynhds_ccontains(&hds, "blablabla"), "should not");
+
+ result = Curl_dynhds_h1_cadd_line(&hds, "blablabla thingies");
+ fail_unless(result, "add should have failed");
+ if(!result) {
+ fail_unless(Curl_dynhds_ccount_name(&hds, "bLABlaBlA") == 0, "should");
+ fail_if(Curl_dynhds_cadd(&hds, "Bla-Bla", "thingies"), "add failed");
+
+ Curl_dyn_init(&dbuf, 32*1024);
+ fail_if(Curl_dynhds_h1_dprint(&hds, &dbuf), "h1 print failed");
+ if(Curl_dyn_ptr(&dbuf)) {
+ fail_if(strcmp(Curl_dyn_ptr(&dbuf),
+ "test1: 123\r\ntest1: 123\r\nBla-Bla: thingies\r\n"),
+ "h1 format differs");
+ }
+ Curl_dyn_free(&dbuf);
+ }
+
+ Curl_dynhds_free(&hds);
+ Curl_dynhds_init(&hds, 128, 4*1024);
+ /* continuation without previous header fails */
+ result = Curl_dynhds_h1_cadd_line(&hds, " indented value");
+ fail_unless(result, "add should have failed");
+
+ /* continuation with previous header must succeed */
+ fail_if(Curl_dynhds_h1_cadd_line(&hds, "ti1: val1"), "add");
+ fail_if(Curl_dynhds_h1_cadd_line(&hds, " val2"), "add indent");
+ fail_if(Curl_dynhds_h1_cadd_line(&hds, "ti2: val1"), "add");
+ fail_if(Curl_dynhds_h1_cadd_line(&hds, "\tval2"), "add indent");
+ fail_if(Curl_dynhds_h1_cadd_line(&hds, "ti3: val1"), "add");
+ fail_if(Curl_dynhds_h1_cadd_line(&hds, " val2"), "add indent");
+
+ Curl_dyn_init(&dbuf, 32*1024);
+ fail_if(Curl_dynhds_h1_dprint(&hds, &dbuf), "h1 print failed");
+ if(Curl_dyn_ptr(&dbuf)) {
+ fprintf(stderr, "indent concat: %s\n", Curl_dyn_ptr(&dbuf));
+ fail_if(strcmp(Curl_dyn_ptr(&dbuf),
+ "ti1: val1 val2\r\nti2: val1 val2\r\nti3: val1 val2\r\n"),
+ "wrong format");
+ }
+ Curl_dyn_free(&dbuf);
+
+ Curl_dynhds_free(&hds);
+
+UNITTEST_STOP
diff --git a/tests/unit/unit2603.c b/tests/unit/unit2603.c
new file mode 100644
index 0000000..ddd90d1
--- /dev/null
+++ b/tests/unit/unit2603.c
@@ -0,0 +1,190 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 "curlcheck.h"
+
+#include "urldata.h"
+#include "http.h"
+#include "http1.h"
+#include "curl_log.h"
+
+static CURLcode unit_setup(void)
+{
+ return CURLE_OK;
+}
+
+static void unit_stop(void)
+{
+}
+
+struct tcase {
+ const char **input;
+ const char *default_scheme;
+ const char *method;
+ const char *scheme;
+ const char *authority;
+ const char *path;
+ size_t header_count;
+ size_t input_remain;
+};
+
+static void check_eq(const char *s, const char *exp_s, const char *name)
+{
+ if(s && exp_s) {
+ if(strcmp(s, exp_s)) {
+ fprintf(stderr, "expected %s: '%s' but got '%s'\n", name, exp_s, s);
+ fail("unexpected req component");
+ }
+ }
+ else if(!s && exp_s) {
+ fprintf(stderr, "expected %s: '%s' but got NULL\n", name, exp_s);
+ fail("unexpected req component");
+ }
+ else if(s && !exp_s) {
+ fprintf(stderr, "expected %s: NULL but got '%s'\n", name, s);
+ fail("unexpected req component");
+ }
+}
+
+static void parse_success(struct tcase *t)
+{
+ struct h1_req_parser p;
+ const char *buf;
+ size_t buflen, i, in_len, in_consumed;
+ CURLcode err;
+ ssize_t nread;
+
+ Curl_h1_req_parse_init(&p, 1024);
+ in_len = in_consumed = 0;
+ for(i = 0; t->input[i]; ++i) {
+ buf = t->input[i];
+ buflen = strlen(buf);
+ in_len += buflen;
+ nread = Curl_h1_req_parse_read(&p, buf, buflen, t->default_scheme,
+ 0, &err);
+ if(nread < 0) {
+ fprintf(stderr, "got err %d parsing: '%s'\n", err, buf);
+ fail("error consuming");
+ }
+ in_consumed += (size_t)nread;
+ if((size_t)nread != buflen) {
+ if(!p.done) {
+ fprintf(stderr, "only %zd/%zu consumed for: '%s'\n",
+ nread, buflen, buf);
+ fail("not all consumed");
+ }
+ }
+ }
+
+ fail_if(!p.done, "end not detected");
+ fail_if(!p.req, "not request created");
+ if(t->input_remain != (in_len - in_consumed)) {
+ fprintf(stderr, "expected %zu input bytes to remain, but got %zu\n",
+ t->input_remain, in_len - in_consumed);
+ fail("unexpected input consumption");
+ }
+ if(p.req) {
+ check_eq(p.req->method, t->method, "method");
+ check_eq(p.req->scheme, t->scheme, "scheme");
+ check_eq(p.req->authority, t->authority, "authority");
+ check_eq(p.req->path, t->path, "path");
+ if(Curl_dynhds_count(&p.req->headers) != t->header_count) {
+ fprintf(stderr, "expected %zu headers but got %zu\n", t->header_count,
+ Curl_dynhds_count(&p.req->headers));
+ fail("unexpected req header count");
+ }
+ }
+
+ Curl_h1_req_parse_free(&p);
+}
+
+static const char *T1_INPUT[] = {
+ "GET /path HTTP/1.1\r\nHost: test.curl.se\r\n\r\n",
+ NULL,
+};
+static struct tcase TEST1a = {
+ T1_INPUT, NULL, "GET", NULL, NULL, "/path", 1, 0
+};
+static struct tcase TEST1b = {
+ T1_INPUT, "https", "GET", "https", NULL, "/path", 1, 0
+};
+
+static const char *T2_INPUT[] = {
+ "GET /path HTT",
+ "P/1.1\r\nHost: te",
+ "st.curl.se\r\n\r",
+ "\n12345678",
+ NULL,
+};
+static struct tcase TEST2 = {
+ T2_INPUT, NULL, "GET", NULL, NULL, "/path", 1, 8
+};
+
+static const char *T3_INPUT[] = {
+ "GET ftp://ftp.curl.se/xxx?a=2 HTTP/1.1\r\nContent-Length: 0\r",
+ "\nUser-Agent: xxx\r\n\r\n",
+ NULL,
+};
+static struct tcase TEST3a = {
+ T3_INPUT, NULL, "GET", "ftp", "ftp.curl.se", "/xxx?a=2", 2, 0
+};
+
+static const char *T4_INPUT[] = {
+ "CONNECT ftp.curl.se:123 HTTP/1.1\r\nContent-Length: 0\r\n",
+ "User-Agent: xxx\r\n",
+ "nothing: \r\n\r\n\n\n",
+ NULL,
+};
+static struct tcase TEST4a = {
+ T4_INPUT, NULL, "CONNECT", NULL, "ftp.curl.se:123", NULL, 3, 2
+};
+
+static const char *T5_INPUT[] = {
+ "OPTIONS * HTTP/1.1\r\nContent-Length: 0\r\nBlabla: xxx.yyy\r",
+ "\n\tzzzzzz\r\n\r\n",
+ "123",
+ NULL,
+};
+static struct tcase TEST5a = {
+ T5_INPUT, NULL, "OPTIONS", NULL, NULL, "*", 2, 3
+};
+
+static const char *T6_INPUT[] = {
+ "PUT /path HTTP/1.1\nHost: test.curl.se\n\n123",
+ NULL,
+};
+static struct tcase TEST6a = {
+ T6_INPUT, NULL, "PUT", NULL, NULL, "/path", 1, 3
+};
+
+UNITTEST_START
+
+ parse_success(&TEST1a);
+ parse_success(&TEST1b);
+ parse_success(&TEST2);
+ parse_success(&TEST3a);
+ parse_success(&TEST4a);
+ parse_success(&TEST5a);
+ parse_success(&TEST6a);
+
+UNITTEST_STOP
diff --git a/tests/unit/unit3200.c b/tests/unit/unit3200.c
new file mode 100644
index 0000000..58eaff9
--- /dev/null
+++ b/tests/unit/unit3200.c
@@ -0,0 +1,159 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the 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 "curlcheck.h"
+#include "curl_get_line.h"
+
+/* The test XML does not supply a way to write files without newlines
+ * so we write our own
+ */
+
+#define C64 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
+#define C256 C64 C64 C64 C64
+#define C1024 C256 C256 C256 C256
+#define C4096 C1024 C1024 C1024 C1024
+
+static CURLcode unit_setup(void)
+{
+ return CURLE_OK;
+}
+
+static CURLcode unit_stop(void)
+{
+ return CURLE_OK;
+}
+
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Woverlength-strings"
+#endif
+
+#define NUMTESTS 6
+static const char *filecontents[] = {
+ /* Both should be read */
+ "LINE1\n"
+ "LINE2 NEWLINE\n",
+
+ /* Both should be read */
+ "LINE1\n"
+ "LINE2 NONEWLINE",
+
+ /* Only first should be read */
+ "LINE1\n"
+ C4096,
+
+ /* First line should be read */
+ "LINE1\n"
+ C4096 "SOME EXTRA TEXT",
+
+ /* First and third line should be read */
+ "LINE1\n"
+ C4096 "SOME EXTRA TEXT\n"
+ "LINE3\n",
+
+ "LINE1\x1aTEST"
+};
+
+#ifdef __GNUC__
+#pragma GCC diagnostic warning "-Woverlength-strings"
+#endif
+
+
+UNITTEST_START
+ size_t i;
+ for(i = 0; i < NUMTESTS; i++) {
+ FILE *fp;
+ char buf[4096];
+ int len = 4096;
+ char *line;
+
+ fp = fopen(arg, "wb");
+ abort_unless(fp != NULL, "Cannot open testfile");
+ fwrite(filecontents[i], 1, strlen(filecontents[i]), fp);
+ fclose(fp);
+
+ fp = fopen(arg, "rb");
+ abort_unless(fp != NULL, "Cannot open testfile");
+
+ fprintf(stderr, "Test %d...", i);
+ switch(i) {
+ case 0:
+ line = Curl_get_line(buf, len, fp);
+ fail_unless(line && !strcmp("LINE1\n", line),
+ "First line failed (1)");
+ line = Curl_get_line(buf, len, fp);
+ fail_unless(line && !strcmp("LINE2 NEWLINE\n", line),
+ "Second line failed (1)");
+ line = Curl_get_line(buf, len, fp);
+ abort_unless(line == NULL, "Missed EOF (1)");
+ break;
+ case 1:
+ line = Curl_get_line(buf, len, fp);
+ fail_unless(line && !strcmp("LINE1\n", line),
+ "First line failed (2)");
+ line = Curl_get_line(buf, len, fp);
+ fail_unless(line && !strcmp("LINE2 NONEWLINE\n", line),
+ "Second line failed (2)");
+ line = Curl_get_line(buf, len, fp);
+ abort_unless(line == NULL, "Missed EOF (2)");
+ break;
+ case 2:
+ line = Curl_get_line(buf, len, fp);
+ fail_unless(line && !strcmp("LINE1\n", line),
+ "First line failed (3)");
+ line = Curl_get_line(buf, len, fp);
+ fail_unless(line == NULL,
+ "Did not detect max read on EOF (3)");
+ break;
+ case 3:
+ line = Curl_get_line(buf, len, fp);
+ fail_unless(line && !strcmp("LINE1\n", line),
+ "First line failed (4)");
+ line = Curl_get_line(buf, len, fp);
+ fail_unless(line == NULL,
+ "Did not ignore partial on EOF (4)");
+ break;
+ case 4:
+ line = Curl_get_line(buf, len, fp);
+ fail_unless(line && !strcmp("LINE1\n", line),
+ "First line failed (5)");
+ line = Curl_get_line(buf, len, fp);
+ fail_unless(line && !strcmp("LINE3\n", line),
+ "Third line failed (5)");
+ line = Curl_get_line(buf, len, fp);
+ abort_unless(line == NULL, "Missed EOF (5)");
+ break;
+ case 5:
+ line = Curl_get_line(buf, len, fp);
+ fail_unless(line && !strcmp("LINE1\x1aTEST\n", line),
+ "Missed/Misinterpreted ^Z (6)");
+ line = Curl_get_line(buf, len, fp);
+ abort_unless(line == NULL, "Missed EOF (6)");
+ break;
+ default:
+ abort_unless(1, "Unknown case");
+ break;
+ }
+ fclose(fp);
+ fprintf(stderr, "OK\n");
+ }
+UNITTEST_STOP
diff --git a/tests/util.py b/tests/util.py
index b8c4ebd..051c693 100755
--- a/tests/util.py
+++ b/tests/util.py
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2017 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
diff --git a/tests/valgrind.pm b/tests/valgrind.pm
index 8916b59..a0bce30 100644
--- a/tests/valgrind.pm
+++ b/tests/valgrind.pm
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -22,14 +22,28 @@
#
###########################################################################
+package valgrind;
+
+use strict;
+use warnings;
+
+BEGIN {
+ use base qw(Exporter);
+
+ our @EXPORT = qw(
+ valgrindparse
+ );
+}
+
+
use File::Basename;
sub valgrindparse {
my ($file) = @_;
my @o;
- open(VAL, "<$file");
- @o = <VAL>;
- close(VAL);
+ open(my $val, "<", "$file");
+ @o = <$val>;
+ close($val);
return @o;
}
diff --git a/tests/version-scan.pl b/tests/version-scan.pl
index b52459d..3c055d9 100755
--- a/tests/version-scan.pl
+++ b/tests/version-scan.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2010 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -32,25 +32,39 @@
my $manpage=$ARGV[0];
my $header=$ARGV[1];
+my $source=$ARGV[2];
my %manversion;
my %headerversion;
-my $error;
+my %manname;
+my %sourcename;
+my $error=0;
-open(M, "<$manpage");
-while(<M>) {
- if($_ =~ /^.ip (CURL_VERSION_[A-Z0-9_]+)/i) {
+open(my $m, "<", "$manpage");
+while(<$m>) {
+ if($_ =~ / mask bit: (CURL_VERSION_[A-Z0-9_]+)/i) {
$manversion{$1}++;
}
+ if($_ =~ /^\.ip """([^"]+)"""/i) {
+ $manname{$1}++;
+ }
}
-close(M);
+close($m);
-open(H, "<$header");
-while(<H>) {
+open(my $h, "<", "$header");
+while(<$h>) {
if($_ =~ /^\#define (CURL_VERSION_[A-Z0-9_]+)/i) {
$headerversion{$1}++;
}
}
-close(H);
+close($h);
+
+open(my $s, "<", "$source");
+while(<$s>) {
+ if($_ =~ /FEATURE\("([^"]*)"/) {
+ $sourcename{$1}++;
+ }
+}
+close($s);
for my $h (keys %headerversion) {
if(!$manversion{$h}) {
@@ -64,5 +78,17 @@
$error++;
}
}
+for my $n (keys %sourcename) {
+ if(!$manname{$n}) {
+ print STDERR "$manpage: missing feature name $n\n";
+ $error++;
+ }
+}
+for my $n (keys %manname) {
+ if(!$sourcename{$n}) {
+ print STDERR "$manpage: $n is not in the source!\n";
+ $error++;
+ }
+}
exit $error;
diff --git a/winbuild/.gitignore b/winbuild/.gitignore
index c3e10a0..0d7f2b2 100644
--- a/winbuild/.gitignore
+++ b/winbuild/.gitignore
@@ -1,4 +1,4 @@
-# Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
diff --git a/winbuild/Makefile.vc b/winbuild/Makefile.vc
index 594b16f..44d9604 100644
--- a/winbuild/Makefile.vc
+++ b/winbuild/Makefile.vc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1999 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -265,6 +265,10 @@
!MESSAGE configuration name: $(CONFIG_NAME_LIB)
+# Note these directories are removed by this makefile's 'clean' so they should
+# not be changed to point to user-specified directories that may contain other
+# data. MakefileBuild.vc uses the same variable names but allows some user
+# changes and therefore does not remove the directories.
BUILD_DIR=../builds/$(CONFIG_NAME_LIB)
LIBCURL_DIROBJ = ..\builds\$(CONFIG_NAME_LIB)-obj-lib
CURL_DIROBJ = ..\builds\$(CONFIG_NAME_LIB)-obj-curl
@@ -300,4 +304,7 @@
FOR %%i IN ($(CURLX_CFILES:/=\)) DO copy %%i ..\src\
clean:
+ @if exist $(LIBCURL_DIROBJ) rd /s /q $(LIBCURL_DIROBJ)
+ @if exist $(CURL_DIROBJ) rd /s /q $(CURL_DIROBJ)
+ @if exist $(DIRDIST) rd /s /q $(DIRDIST)
$(MAKE) /NOLOGO /F MakefileBuild.vc $@
diff --git a/winbuild/MakefileBuild.vc b/winbuild/MakefileBuild.vc
index 1bdbf79..5cf65dc 100644
--- a/winbuild/MakefileBuild.vc
+++ b/winbuild/MakefileBuild.vc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1999 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -275,7 +275,7 @@
!ENDIF
!IFDEF USE_ZLIB
-ZLIB_CFLAGS = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ $(ADDITIONAL_ZLIB_CFLAGS) /I"$(ZLIB_INC_DIR)"
+ZLIB_CFLAGS = /DHAVE_LIBZ $(ADDITIONAL_ZLIB_CFLAGS) /I"$(ZLIB_INC_DIR)"
!ENDIF
@@ -305,8 +305,8 @@
!ENDIF
!IFDEF USE_SSH2
-SSH2_CFLAGS = /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /DUSE_LIBSSH2
-SSH2_CFLAGS = $(SSH2_CFLAGS) /I$(SSH2_INC_DIR)
+SSH2_CFLAGS = /DUSE_LIBSSH2
+SSH2_CFLAGS = $(SSH2_CFLAGS) /I"$(SSH2_INC_DIR)"
!ENDIF
@@ -326,8 +326,8 @@
!ENDIF
!IFDEF USE_SSH
-SSH_CFLAGS = /DHAVE_LIBSSH /DHAVE_LIBSSH_LIBSSH_H /DLIBSSH_WIN32 /DLIBSSH_LIBRARY /DUSE_LIBSSH /DCURL_USE_LIBSSH
-SSH_CFLAGS = $(SSH_CFLAGS) /I$(SSH_INC_DIR)
+SSH_CFLAGS = /DUSE_LIBSSH
+SSH_CFLAGS = $(SSH_CFLAGS) /I"$(SSH_INC_DIR)"
!ENDIF
@@ -338,7 +338,7 @@
!ENDIF
!IF "$(USE_IDN)"=="true"
-IDN_CFLAGS = $(IDN_CFLAGS) /DUSE_WIN32_IDN /DWANT_IDN_PROTOTYPES
+IDN_CFLAGS = $(IDN_CFLAGS) /DUSE_WIN32_IDN
WIN_LIBS = $(WIN_LIBS) Normaliz.lib
!ENDIF
@@ -621,20 +621,20 @@
.SUFFIXES: .c .obj .res
-{$(LIBCURL_SRC_DIR)\}.c{$(LIB_DIROBJ)\}.obj:
- $(CURL_CC) $(CFLAGS) /Fo"$@" $<
+{$(LIBCURL_SRC_DIR)\}.c{$(LIB_DIROBJ)\}.obj::
+ $(CURL_CC) $(CFLAGS) /Fo"$(LIB_DIROBJ)\\" $<
-{$(LIBCURL_SRC_DIR)\vauth\}.c{$(LIB_DIROBJ)\vauth\}.obj:
- $(CURL_CC) $(CFLAGS) /Fo"$@" $<
+{$(LIBCURL_SRC_DIR)\vauth\}.c{$(LIB_DIROBJ)\vauth\}.obj::
+ $(CURL_CC) $(CFLAGS) /Fo"$(LIB_DIROBJ)\vauth\\" $<
-{$(LIBCURL_SRC_DIR)\vtls\}.c{$(LIB_DIROBJ)\vtls\}.obj:
- $(CURL_CC) $(CFLAGS) /Fo"$@" $<
+{$(LIBCURL_SRC_DIR)\vtls\}.c{$(LIB_DIROBJ)\vtls\}.obj::
+ $(CURL_CC) $(CFLAGS) /Fo"$(LIB_DIROBJ)\vtls\\" $<
-{$(LIBCURL_SRC_DIR)\vssh\}.c{$(LIB_DIROBJ)\vssh\}.obj:
- $(CURL_CC) $(CFLAGS) /Fo"$@" $<
+{$(LIBCURL_SRC_DIR)\vssh\}.c{$(LIB_DIROBJ)\vssh\}.obj::
+ $(CURL_CC) $(CFLAGS) /Fo"$(LIB_DIROBJ)\vssh\\" $<
-{$(LIBCURL_SRC_DIR)\vquic\}.c{$(LIB_DIROBJ)\vquic\}.obj:
- $(CURL_CC) $(CFLAGS) /Fo"$@" $<
+{$(LIBCURL_SRC_DIR)\vquic\}.c{$(LIB_DIROBJ)\vquic\}.obj::
+ $(CURL_CC) $(CFLAGS) /Fo"$(LIB_DIROBJ)\vquic\\" $<
$(LIB_DIROBJ)\libcurl.res: $(LIBCURL_SRC_DIR)\libcurl.rc
$(RC) $(RC_FLAGS)
@@ -662,7 +662,6 @@
$(CURL_DIROBJ)\nonblock.obj \
$(CURL_DIROBJ)\strtoofft.obj \
$(CURL_DIROBJ)\warnless.obj \
- $(CURL_DIROBJ)\curl_ctype.obj \
$(CURL_DIROBJ)\curl_multibyte.obj \
$(CURL_DIROBJ)\version_win32.obj \
$(CURL_DIROBJ)\dynbuf.obj
@@ -671,8 +670,8 @@
$(CURL_LINK) $(CURL_LFLAGS) $(CURL_LIBCURL_LIBNAME) $(WIN_LIBS) $(CURL_FROM_LIBCURL) $(EXE_OBJS)
$(MANIFESTTOOL)
-{$(CURL_SRC_DIR)\}.c{$(CURL_DIROBJ)\}.obj:
- $(CURL_CC) $(CURL_CFLAGS) /Fo"$@" $<
+{$(CURL_SRC_DIR)\}.c{$(CURL_DIROBJ)\}.obj::
+ $(CURL_CC) $(CURL_CFLAGS) /Fo"$(CURL_DIROBJ)\\" $<
$(CURL_DIROBJ)\tool_hugehelp.obj: $(CURL_SRC_DIR)\tool_hugehelp.c
$(CURL_CC) $(CURL_CFLAGS) /Zm200 /Fo"$@" $(CURL_SRC_DIR)\tool_hugehelp.c
@@ -682,8 +681,6 @@
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/strtoofft.c
$(CURL_DIROBJ)\warnless.obj: ../lib/warnless.c
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/warnless.c
-$(CURL_DIROBJ)\curl_ctype.obj: ../lib/curl_ctype.c
- $(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/curl_ctype.c
$(CURL_DIROBJ)\curl_multibyte.obj: ../lib/curl_multibyte.c
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/curl_multibyte.c
$(CURL_DIROBJ)\version_win32.obj: ../lib/version_win32.c
@@ -695,6 +692,12 @@
!ENDIF # End of case where a config was provided.
+# Makefile.vc's clean removes (LIB)CURL_DIROBJ and DIRDIST dirs then calls
+# this clean. Note those are the original directories we control and not the
+# directories possibly modified by this makefile to point to user-specified
+# directories.
+# For example, don't remove DIRDIST here since it may contain user files if it
+# has been changed by WITH_PREFIX to a different output dir (eg C:\usr\local).
clean:
@-erase /s *.dll 2> NUL
@-erase /s *.exp 2> NUL
@@ -704,6 +707,3 @@
@-erase /s *.pch 2> NUL
@-erase /s *.pdb 2> NUL
@-erase /s *.res 2> NUL
- @if exist $(LIB_DIROBJ) rd /s/q $(LIB_DIROBJ)
- @if exist $(CURL_DIROBJ)rd /s/q $(CURL_DIROBJ)
- @if exist $(DIRDIST) rd /s/q $(DIRDIST)
diff --git a/winbuild/README.md b/winbuild/README.md
index 22ecfe4..1ecde7c 100644
--- a/winbuild/README.md
+++ b/winbuild/README.md
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2000 - 2022 Daniel Stenberg, <daniel@haxx.se>, et al.
+Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
@@ -21,8 +21,8 @@
## Prerequisites
- If you wish to support zlib, openssl, c-ares, ssh2, you will have to download
- them separately and copy them to the deps directory as shown below:
+ If you wish to support zlib, OpenSSL, c-ares, ssh2, you will have to download
+ them separately and copy them to the `deps` directory as shown below:
somedirectory\
|_curl-src
@@ -33,8 +33,8 @@
|_ include
|_ bin
- It is also possible to create the deps directory in some other random places
- and tell the Makefile its location using the WITH_DEVEL option.
+ It is also possible to create the `deps` directory in some other random places
+ and tell the `Makefile` its location using the `WITH_DEVEL` option.
## Building straight from git
@@ -59,7 +59,7 @@
Using the **'VS [version] [platform] [type] Command Prompt'** menu entry:
where [version] is the Visual Studio version, [platform] is e.g. x64 and
- [type] Native of Cross platform build. This type of command prompt may not
+ [type] Native of Cross platform build. This type of command prompt may not
exist in all Visual Studio versions.
See also: [Set the Path and Environment Variables for Command-Line Builds](https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line)
@@ -81,9 +81,7 @@
- `VC=<num>` - VC version. 6 or later.
- `WITH_DEVEL=<path>` - Paths for the development files (SSL, zlib, etc.)
- Defaults to sibbling directory deps: ../deps
- Libraries can be fetched at https://windows.php.net/downloads/php-sdk/deps/
- Uncompress them into the deps folder.
+ Defaults to sibling directory: `../deps`
- `WITH_SSL=<dll/static>` - Enable OpenSSL support, DLL or static
- `WITH_NGHTTP2=<dll/static>` - Enable HTTP/2 support, DLL or static
- `WITH_MSH3=<dll/static>` - Enable (experimental) HTTP/3 support, DLL or static
@@ -106,7 +104,7 @@
- `GEN_PDB=<yes/no>` - Generate External Program Database
(debug symbols for release build)
- `DEBUG=<yes/no>` - Debug builds
- - `MACHINE=<x86/x64>` - Target architecture (default is x86)
+ - `MACHINE=<x86/x64/arm64>` - Target architecture (default is x86)
- `CARES_PATH=<path>` - Custom path for c-ares
- `MBEDTLS_PATH=<path>` - Custom path for mbedTLS
- `NGHTTP2_PATH=<path>` - Custom path for nghttp2
@@ -115,20 +113,20 @@
- `SSL_PATH=<path>` - Custom path for OpenSSL
- `ZLIB_PATH=<path>` - Custom path for zlib
-## Static linking of Microsoft's C RunTime (CRT):
+## Static linking of Microsoft's C runtime (CRT):
If you are using mode=static nmake will create and link to the static build
of libcurl but *not* the static CRT. If you must you can force nmake to link
- in the static CRT by passing RTLIBCFG=static. Typically you shouldn't use
- that option, and nmake will default to the DLL CRT. RTLIBCFG is rarely used
- and therefore rarely tested. When passing RTLIBCFG for a configuration that
+ in the static CRT by passing `RTLIBCFG=static`. Typically you shouldn't use
+ that option, and nmake will default to the DLL CRT. `RTLIBCFG` is rarely used
+ and therefore rarely tested. When passing `RTLIBCFG` for a configuration that
was already built but not with that option, or if the option was specified
differently, you must destroy the build directory containing the
configuration so that nmake can build it from scratch.
This option is not recommended unless you have enough development experience
- to know how to match the runtime library for linking (that is, the CRT).
- If RTLIBCFG=static then release builds use /MT and debug builds use /MTd.
+ to know how to match the runtime library for linking (that is, the CRT). If
+ `RTLIBCFG=static` then release builds use `/MT` and debug builds use `/MTd`.
## Building your own application with libcurl (Visual Studio example)
@@ -140,17 +138,17 @@
For example let's say you've built curl.exe and libcurl.dll from the Visual
Studio 2010 x64 Win64 Command Prompt:
- nmake /f Makefile.vc mode=dll VC=10
+ nmake /f Makefile.vc mode=dll VC=10
The output directory will have a name similar to
- ..\builds\libcurl-vc10-x64-release-dll-ipv6-sspi-schannel.
+ `..\builds\libcurl-vc10-x64-release-dll-ipv6-sspi-schannel`.
The output directory contains subdirectories bin, lib and include. Those are
the directories to set in your Visual Studio project. You can either copy the
output directory to your project or leave it in place. Following the example,
let's assume you leave it in place and your curl top source directory is
- C:\curl-7.82.0. You would set these options for configurations using the x64
- platform:
+ `C:\curl-7.82.0`. You would set these options for configurations using the
+ x64 platform:
~~~
- Configuration Properties > Debugging > Environment
@@ -169,26 +167,27 @@
For configurations using the x86 platform (aka Win32 platform) you would
need to make a separate x86 build of libcurl.
- If you build libcurl static (mode=static) or debug (DEBUG=yes) then the
+ If you build libcurl static (`mode=static`) or debug (`DEBUG=yes`) then the
library name will vary and separate builds may be necessary for separate
- configurations of your project within the same platform. This is discussed
- in the next section.
+ configurations of your project within the same platform. This is discussed in
+ the next section.
## Building your own application with a static libcurl
When building an application that uses the static libcurl library on Windows,
- you must define CURL_STATICLIB. Otherwise the linker will look for dynamic
+ you must define `CURL_STATICLIB`. Otherwise the linker will look for dynamic
import symbols.
- The static library name has an '_a' suffix in the basename and the debug
- library name has a '_debug' suffix in the basename. For example,
- libcurl_a_debug.lib is a static debug build of libcurl.
+ The static library name has an `_a` suffix in the basename and the debug
+ library name has a `_debug` suffix in the basename. For example,
+ `libcurl_a_debug.lib` is a static debug build of libcurl.
You may need a separate build of libcurl for each VC configuration combination
- (eg: Debug|Win32, Debug|x64, Release|Win32, Release|x64).
+ (for example: Debug|Win32, Debug|x64, Release|Win32, Release|x64).
You must specify any additional dependencies needed by your build of static
- libcurl (eg: advapi32.lib;crypt32.lib;normaliz.lib;ws2_32.lib;wldap32.lib).
+ libcurl (for example:
+ `advapi32.lib;crypt32.lib;normaliz.lib;ws2_32.lib;wldap32.lib`).
## Legacy Windows and SSL
diff --git a/winbuild/gen_resp_file.bat b/winbuild/gen_resp_file.bat
index 70332e7..157a1d9 100755
--- a/winbuild/gen_resp_file.bat
+++ b/winbuild/gen_resp_file.bat
@@ -6,7 +6,7 @@
rem * | (__| |_| | _ <| |___
rem * \___|\___/|_| \_\_____|
rem *
-rem * Copyright (C) 2011 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+rem * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
rem *
rem * This software is licensed as described in the file COPYING, which
rem * you should have received as part of this distribution. The terms
diff --git a/winbuild/makedebug.cmd b/winbuild/makedebug.cmd
index e7de73d..39acd58 100644
--- a/winbuild/makedebug.cmd
+++ b/winbuild/makedebug.cmd
@@ -6,7 +6,7 @@
rem * | (__| |_| | _ <| |___
rem * \___|\___/|_| \_\_____|
rem *
-rem * Copyright (C) 2018 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+rem * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
rem *
rem * This software is licensed as described in the file COPYING, which
rem * you should have received as part of this distribution. The terms
diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml
deleted file mode 100644
index 6947aae..0000000
--- a/zuul.d/jobs.yaml
+++ /dev/null
@@ -1,330 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 2021 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-
-# The results of each of these jobs can be found at
-# https://curl.zuul.vexxhost.dev/builds. As of November 2021 they are not being
-# propagated to the Github "checks" UI, you need to check for them manually.
-
----
-- job:
- name: curl-base
- abstract: true
- pre-run: zuul.d/playbooks/pre.yaml
- run: zuul.d/playbooks/run.yaml
- post-run: zuul.d/playbooks/post.yaml
- nodeset: ubuntu-bionic
- timeout: 3600
- vars:
- curl_env:
- LD_LIBRARY_PATH: /usr/local/lib
- # NOTE(mnaser): Workaround to keep existing Travis scripts compatible
- TRAVIS_OS_NAME: linux
-
-- job:
- name: curl-normal-with-openssl-gssapi-libssh2-checksrc
- parent: curl-base
- vars:
- curl_env:
- T: normal
- C: --with-openssl --with-gssapi --with-libssh2
- CHECKSRC: 1
- curl_apt_packages:
- - krb5-user
- - libssh2-1-dev
- - libbrotli-dev
- - libzstd-dev
-
-- job:
- name: curl-novalgrind-boringssl-with-openssl
- parent: curl-base
- vars:
- gimme_stable: true
- curl_env:
- CC: gcc-8
- CXX: g++-8
- T: novalgrind
- BORINGSSL: "yes"
- C: >-
- --with-openssl={{ ansible_user_dir }}/boringssl
- LD_LIBRARY_PATH: "{{ ansible_user_dir }}/boringssl/lib:/usr/local/lib"
-
-- job:
- name: curl-novalgrind-boringssl-with-openssl-quiche
- parent: curl-base
- vars:
- curl_apt_packages:
- - libpsl-dev
- - libbrotli-dev
- - libzstd-dev
- curl_env:
- CC: gcc-8
- CXX: g++-8
- T: novalgrind
- QUICHE: "yes"
- C: >-
- --with-openssl={{ ansible_user_dir }}/quiche/quiche/deps/boringssl/src
- --with-quiche={{ ansible_user_dir }}/quiche/target/release
- LD_LIBRARY_PATH: "{{ ansible_user_dir }}/quiche/target/release:/usr/local/lib"
-
-- job:
- name: curl-novalgrind-libressl
- parent: curl-base
- vars:
- curl_env:
- CC: gcc-8
- CXX: g++-8
- T: novalgrind
- LIBRESSL: "yes"
- C: >-
- --with-openssl={{ ansible_user_dir }}/libressl
- LD_LIBRARY_PATH: "{{ ansible_user_dir }}/libressl/lib:/usr/local/lib"
-
-- job:
- name: curl-novalgrind-ngtcp2-with-openssl
- parent: curl-base
- vars:
- curl_apt_packages:
- - libpsl-dev
- - libbrotli-dev
- - libzstd-dev
- curl_env:
- CC: gcc-8
- CXX: g++-8
- T: novalgrind
- NGTCP2: "yes"
- C: >-
- --with-openssl={{ ansible_user_dir }}/ngbuild
- --with-ngtcp2={{ ansible_user_dir }}/ngbuild
- --with-nghttp3={{ ansible_user_dir }}/ngbuild
- NOTESTS:
-
-- job:
- name: curl-novalgrind-ngtcp2-gnutls
- parent: curl-base
- vars:
- curl_apt_packages:
- - libpsl-dev
- - libbrotli-dev
- - libzstd-dev
- - zlib1g-dev
- - autogen
- - automake
- - autopoint
- - bison
- - gperf
- - libgmp-dev
- - libopts25-dev
- - libp11-kit-dev
- - libtasn1-6-dev
- - nettle-dev
- - gtk-doc-tools
- - gnulib
- - libtasn1-bin
- curl_env:
- CC: gcc-8
- CXX: g++-8
- T: novalgrind
- NGTCP2: "yes"
- GNUTLS: "yes"
- C: >-
- PKG_CONFIG_PATH={{ ansible_user_dir }}/ngbuild
- --with-gnutls={{ ansible_user_dir }}/ngbuild
- --with-ngtcp2={{ ansible_user_dir }}/ngbuild
- --with-nghttp3={{ ansible_user_dir }}/ngbuild
- NOTESTS:
-
-- job:
- name: curl-debug-clang-disable-alt-svc-with-openssl
- parent: curl-base
- vars:
- curl_apt_packages:
- - clang-9
- - libpsl-dev
- - libbrotli-dev
- - libzstd-dev
- curl_env:
- CC: clang-9
- CXX: clang++-9
- T: debug
- C: >-
- --with-openssl
- --disable-alt-svc
-
-- job:
- name: curl-debug-clang-with-gnutls
- parent: curl-base
- vars:
- curl_apt_packages:
- - clang-9
- - libpsl-dev
- - libbrotli-dev
- - libzstd-dev
- - libgnutls28-dev
- curl_env:
- CC: clang-9
- CXX: clang++-9
- T: debug
- C: >-
- --with-gnutls
-
-- job:
- name: curl-cmake-boringssl-quiche
- parent: curl-base
- vars:
- gimme_stable: true
- curl_apt_packages:
- - libpsl-dev
- - libbrotli-dev
- - libzstd-dev
- curl_env:
- BORINGSSL: "yes"
- QUICHE: "yes"
- CC: gcc-8
- CXX: g++-8
- T: cmake
- C: >-
- -GNinja
- -DUSE_QUICHE=1
- -DOPENSSL_ROOT_DIR={{ ansible_user_dir }}/boringssl
- -DCURL_BROTLI=1
- -DCURL_ZSTD=1
- TFLAGS: https ftps
- PKG_CONFIG_PATH: "{{ ansible_user_dir }}/quiche/target/release"
-
-- job:
- name: curl-cmake-ngtcp2
- parent: curl-base
- vars:
- curl_apt_packages:
- - clang-9
- - libpsl-dev
- - libbrotli-dev
- - libzstd-dev
- - libnss3-dev
- curl_env:
- NGTCP2: "yes"
- CC: clang-9
- CXX: clang++-9
- T: cmake
- C: >-
- -GNinja
- -DUSE_NGTCP2=ON
- -DCURL_BROTLI=1
- -DCURL_ZSTD=1
- PKG_CONFIG_PATH: "{{ ansible_user_dir }}/ngbuild/lib/pkgconfig"
-
-- job:
- name: curl-torture
- parent: curl-base
- vars:
- curl_apt_packages:
- - lcov
- - libpsl-dev
- - libssl-dev
- - libbrotli-dev
- - libzstd-dev
- - libssh2-1-dev
- curl_env:
- CC: gcc-8
- CXX: g++-8
- T: torture
-
-- job:
- name: curl-fuzzer
- parent: curl-base
- vars:
- curl_apt_packages:
- - clang
- - clang-9
- - libpsl-dev
- - libbrotli-dev
- - libzstd-dev
- curl_env:
- CC: clang-9
- CXX: clang++-9
- T: fuzzer
-
-- job:
- name: curl-tidy
- parent: curl-base
- vars:
- curl_apt_packages:
- - clang
- - clang-tidy
- - clang-9
- - clang-tidy-9
- - libpsl-dev
- - libbrotli-dev
- - libzstd-dev
- curl_env:
- CC: clang-9
- CXX: clang++-9
- T: tidy
- C: --with-openssl
-
-- job:
- name: curl-debug-clang-with-openssl-dl-ubsan
- parent: curl-base
- vars:
- curl_apt_packages:
- - clang-9
- - libpsl-dev
- - libbrotli-dev
- - libzstd-dev
- curl_env:
- CC: clang-9
- CXX: clang++-9
- T: debug
- CFLAGS: >-
- -fsanitize=address,undefined,signed-integer-overflow
- -fno-sanitize-recover=undefined,integer
- -Wformat
- -Werror=format-security
- -Werror=array-bounds
- -g
- LDFLAGS: >-
- -fsanitize=address,undefined
- -fno-sanitize-recover=undefined,integer
- LIBS: -ldl -lubsan
- TFLAGS: -n
- C: --with-openssl
-
-- project:
- check:
- jobs:
- - curl-normal-with-openssl-gssapi-libssh2-checksrc
- - curl-novalgrind-boringssl-with-openssl
- - curl-novalgrind-boringssl-with-openssl-quiche
- - curl-novalgrind-libressl
- - curl-novalgrind-ngtcp2-with-openssl
- - curl-novalgrind-ngtcp2-gnutls
- - curl-debug-clang-disable-alt-svc-with-openssl
- - curl-debug-clang-with-gnutls
- - curl-cmake-boringssl-quiche
- - curl-cmake-ngtcp2
- - curl-torture
- - curl-fuzzer
- - curl-tidy
- - curl-debug-clang-with-openssl-dl-ubsan
-...
diff --git a/zuul.d/playbooks/post.yaml b/zuul.d/playbooks/post.yaml
deleted file mode 100644
index 52248d9..0000000
--- a/zuul.d/playbooks/post.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 2021 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
----
-- hosts: all
- tasks:
- - name: Pull down logs to executor
- ignore_errors: True
- synchronize:
- src: "{{ zuul.project.src_dir }}/config.log"
- dest: "{{ zuul.executor.log_root }}/config.log"
- mode: pull
- owner: false
- group: false
-...
diff --git a/zuul.d/playbooks/pre.yaml b/zuul.d/playbooks/pre.yaml
deleted file mode 100644
index 1ea967c..0000000
--- a/zuul.d/playbooks/pre.yaml
+++ /dev/null
@@ -1,93 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 2021 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
----
-- hosts: all
- tasks:
-
- - name: Install latest stable release of go
- when: gimme_stable|default(false)
- block:
- - name: Find latest stable version
- register: go_stable
- uri:
- url: https://golang.org/VERSION?m=text
- return_content: true
- - name: Install Go
- include_role:
- name: ensure-go
- vars:
- go_version: "{{ go_stable.content | regex_replace('^go', '') }}"
-
- - name: Symlink /usr/local/go/bin/go to /usr/bin/go
- become: true
- file:
- src: /usr/local/go/bin/go
- dest: /usr/bin/go
- state: link
-
- - name: Install common dependencies
- become: true
- apt:
- update_cache: true
- pkg:
- - autoconf
- - automake
- - cmake
- - valgrind
- - libev-dev
- - libc-ares-dev
- - libssl-dev
- - libtool
- - g++
- - g++-8
- - stunnel4
- - libidn2-dev
- - gnutls-bin
- - python-impacket
- - ninja-build
- - libgsasl7-dev
- - libnghttp2-dev
-
- - name: Install job-specific packages
- when: curl_apt_packages is defined
- become: true
- apt:
- pkg: "{{ curl_apt_packages }}"
-
- - name: Symlink /usr/bin/scan-build-10 to /usr/bin/scan-build
- when:
- - curl_apt_packages is defined
- - '"clang-tools-10" in curl_apt_packages'
- become: true
- file:
- src: /usr/bin/scan-build-10
- dest: /usr/bin/scan-build
- state: link
-
- - name: Run before script
- shell: "./scripts/zuul/before_script.sh"
- args:
- chdir: "{{ zuul.project.src_dir }}"
- environment: "{{ curl_env }}"
-...
diff --git a/zuul.d/playbooks/run.yaml b/zuul.d/playbooks/run.yaml
deleted file mode 100644
index 473f997..0000000
--- a/zuul.d/playbooks/run.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 2021 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
----
-- hosts: all
- tasks:
- - name: Print environment variables
- debug:
- var: curl_env
-
- - name: Run tests
- environment: "{{ curl_env }}"
- shell: "./scripts/zuul/script.sh"
- args:
- chdir: "{{ zuul.project.src_dir }}"